diff --git a/Android-APP/app/src/main/assets/server_bundle/server.cjs b/Android-APP/app/src/main/assets/server_bundle/server.cjs index 3ccf257..402cf88 100644 --- a/Android-APP/app/src/main/assets/server_bundle/server.cjs +++ b/Android-APP/app/src/main/assets/server_bundle/server.cjs @@ -7369,103651 +7369,454 @@ var require_dist = __commonJS({ } }); -// src/proxy/identity.ts -function resolveAppVersion(raw) { - if (typeof raw !== "string") return void 0; - const v = raw.trim(); - return v.length > 0 && ASCII_PRINTABLE2.test(v) ? v : void 0; +// src/config/loader.ts +function loadConfig(path2) { + if (!(0, import_node_fs.existsSync)(path2)) { + throw new Error(`Config file not found: ${path2}`); + } + const raw = (0, import_node_fs.readFileSync)(path2, "utf-8"); + const parsed = (0, import_yaml.parse)(raw) ?? {}; + const port = resolvePort(process.env[ENV.PORT] ?? parsed?.server?.port); + const host2 = typeof parsed?.server?.host === "string" ? parsed.server.host : DEFAULTS.HOST; + const proxyApiKey = process.env[ENV.PROXY_API_KEY] ?? parsed?.auth?.proxyApiKey; + const oauthCredentialsPath = parsed?.auth?.oauthCredentialsPath; + const provider = resolveProvider(process.env[ENV.PROVIDER] ?? parsed?.provider); + const plan = resolvePlan(parsed?.plan); + const zai = { + anthropicBase: parsed?.providers?.zai?.anthropicBase ?? DEFAULTS.ZAI_ANTHROPIC_BASE, + openaiBase: parsed?.providers?.zai?.openaiBase ?? DEFAULTS.ZAI_OPENAI_BASE + }; + const bigmodel = { + anthropicBase: parsed?.providers?.bigmodel?.anthropicBase ?? DEFAULTS.BIGMODEL_ANTHROPIC_BASE, + openaiBase: parsed?.providers?.bigmodel?.openaiBase ?? DEFAULTS.BIGMODEL_OPENAI_BASE + }; + const defaultModel = typeof parsed?.defaultModel === "string" ? parsed.defaultModel : DEFAULTS.DEFAULT_MODEL; + const models = Array.isArray(parsed?.models) ? parsed.models : [defaultModel]; + const logLevel = resolveLogLevel(parsed?.logging?.level); + const identity = resolveIdentity({ + appVersionEnv: process.env[ENV.APP_VERSION], + appVersionYaml: parsed?.identity?.appVersion, + sourceTitleEnv: process.env[ENV.SOURCE_TITLE], + sourceTitleYaml: parsed?.identity?.sourceTitle, + refererEnv: process.env[ENV.REFERER_ORIGIN], + refererYaml: parsed?.identity?.refererOrigin, + deviceMidYaml: parsed?.identity?.deviceMid + }); + const clientIdentity = resolveClientIdentity(parsed?.clientIdentity); + const responses = resolveResponsesConfig(parsed?.responses); + const mcp = resolveMcpConfig(parsed?.mcp); + const asyncCfg = resolveAsyncConfig(parsed?.async); + const claimCfg = resolveClaimConfig(parsed?.claim); + const endpointRouting = resolveEndpointRoutingConfig(parsed?.endpointRouting); + const clientSigning = resolveClientSigningConfig(parsed?.clientSigning); + const config = { + server: { port, host: host2 }, + auth: { proxyApiKey, oauthCredentialsPath }, + provider, + plan, + providers: { zai, bigmodel }, + defaultModel, + models, + identity, + clientIdentity, + responses, + endpointRouting, + clientSigning, + mcp, + async: asyncCfg, + claim: claimCfg, + logging: { level: logLevel } + }; + validate(config); + return config; } -function normalizePrintableHeaderValue(raw) { - if (typeof raw !== "string") return void 0; - const v = raw.trim(); - return v.length > 0 && ASCII_PRINTABLE2.test(v) ? v : void 0; +function resolveClientIdentity(raw) { + const obj = raw && typeof raw === "object" ? raw : {}; + const mode2 = resolveClientIdentityMode(obj.mode); + const ttlSeconds = resolvePositiveInt(obj.ttlSeconds, DEFAULTS.CLIENT_IDENTITY_TTL_SECONDS, "clientIdentity.ttlSeconds"); + const maxSessions = resolvePositiveInt(obj.maxSessions, DEFAULTS.CLIENT_IDENTITY_MAX_SESSIONS, "clientIdentity.maxSessions"); + return { mode: mode2, ttlSeconds, maxSessions }; } -function normalizeOsCategory(platform) { - switch (platform) { - case "darwin": - return "macos"; - case "win32": - return "windows"; - default: - return "linux"; - } +function resolveClientIdentityMode(raw) { + if (raw === void 0 || raw === null) return DEFAULTS.CLIENT_IDENTITY_MODE; + if (raw === "off" || raw === "observe" || raw === "enforce") return raw; + throw new Error(`Invalid clientIdentity.mode "${String(raw)}": must be "off", "observe", or "enforce"`); } -function resolveClientLanguage() { - const override = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_CLIENT_LANGUAGE); - if (override) return override; +function resolveResponsesConfig(raw) { + const obj = raw && typeof raw === "object" ? raw : {}; + const storeRaw = obj.store && typeof obj.store === "object" ? obj.store : {}; + return { + enabled: resolveBool(obj.enabled, DEFAULTS.RESPONSES_ENABLED), + storeMaxEntries: resolvePositiveInt(storeRaw.maxEntries, DEFAULTS.RESPONSES_STORE_MAX_ENTRIES, "responses.store.maxEntries"), + storeTtlMs: resolvePositiveInt(storeRaw.ttlMs, DEFAULTS.RESPONSES_STORE_TTL_MS, "responses.store.ttlMs") + }; +} +function resolveMcpConfig(raw) { + const obj = raw && typeof raw === "object" ? raw : {}; + return { + enabled: resolveBool(obj.enabled, DEFAULTS.MCP_ENABLED), + webSearch: resolveBool(obj.webSearch ?? obj.web_search, DEFAULTS.MCP_WEB_SEARCH), + webReader: resolveBool(obj.webReader ?? obj.web_reader, DEFAULTS.MCP_WEB_READER), + zread: resolveBool(obj.zread, DEFAULTS.MCP_ZREAD) + }; +} +function resolveAsyncConfig(raw) { + const obj = raw && typeof raw === "object" ? raw : {}; + const enabledEnv = process.env[ENV.ASYNC_ENABLED]; + const originEnv = process.env[ENV.ASYNC_ORIGIN]; + const maxRetriesEnv = process.env[ENV.ASYNC_MAX_RETRIES]; + const maxWaitMsEnv = process.env[ENV.ASYNC_MAX_WAIT_MS]; + const origin = (originEnv ?? (typeof obj.origin === "string" ? obj.origin : DEFAULTS.ASYNC_ORIGIN)).trim() || DEFAULTS.ASYNC_ORIGIN; + validateOrigin(origin, "async.origin"); + return { + enabled: enabledEnv !== void 0 ? resolveBool(enabledEnv, DEFAULTS.ASYNC_ENABLED) : resolveBool(obj.enabled, DEFAULTS.ASYNC_ENABLED), + origin, + pollIntervalMs: resolvePositiveInt(obj.pollIntervalMs ?? obj.poll_interval_ms, DEFAULTS.ASYNC_POLL_INTERVAL_MS, "async.pollIntervalMs"), + keepAliveIntervalMs: resolvePositiveInt(obj.keepAliveIntervalMs ?? obj.keepalive_interval_ms, DEFAULTS.ASYNC_KEEPALIVE_INTERVAL_MS, "async.keepAliveIntervalMs"), + maxWaitMs: resolveNonNegativeInt(maxWaitMsEnv ?? obj.maxWaitMs ?? obj.max_wait_ms, DEFAULTS.ASYNC_MAX_WAIT_MS, "async.maxWaitMs"), + maxRetries: resolveNonNegativeInt(maxRetriesEnv ?? obj.maxRetries ?? obj.max_retries, DEFAULTS.ASYNC_MAX_RETRIES, "async.maxRetries"), + settleTimeoutMs: resolvePositiveInt(obj.settleTimeoutMs ?? obj.settle_timeout_ms, DEFAULTS.ASYNC_SETTLE_TIMEOUT_MS, "async.settleTimeoutMs"), + controlTimeoutMs: resolvePositiveInt(obj.controlTimeoutMs ?? obj.control_timeout_ms, DEFAULTS.ASYNC_CONTROL_TIMEOUT_MS, "async.controlTimeoutMs"), + defaultModel: typeof obj.defaultModel === "string" ? obj.defaultModel : DEFAULTS.ASYNC_DEFAULT_MODEL + }; +} +function validateOrigin(origin, name2) { + let parsed; try { - return Intl.DateTimeFormat().resolvedOptions().locale || void 0; + parsed = new URL(origin); } catch { - return void 0; + throw new Error(`${name2} "${origin}" is not a valid URL`); + } + if (parsed.protocol !== "https:" && parsed.protocol !== "http:") { + throw new Error(`${name2} must use http: or https: scheme (got ${parsed.protocol})`); + } + const hostname = parsed.hostname.replace(/^\[|\]$/g, ""); + const isLoopback2 = hostname === "127.0.0.1" || hostname === "localhost" || hostname === "::1"; + if (parsed.protocol === "http:" && !isLoopback2) { + throw new Error(`${name2} http:// is only allowed for loopback hosts (got ${hostname}). Use https:// for remote origins.`); + } + if (parsed.username || parsed.password) { + throw new Error(`${name2} must not contain userinfo`); + } + if (parsed.hash) { + throw new Error(`${name2} must not contain a fragment`); + } + if (parsed.pathname !== "/" && parsed.pathname !== "") { + throw new Error(`${name2} must not contain a path (got "${parsed.pathname}"); clients append their own paths`); + } + if (parsed.search) { + throw new Error(`${name2} must not contain a query string`); } } -function resolveClientTimezone() { - const override = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_CLIENT_TIMEZONE); - if (override) return override; - try { - return Intl.DateTimeFormat().resolvedOptions().timeZone || void 0; - } catch { - return void 0; +function resolveEndpointRoutingConfig(raw) { + const obj = raw && typeof raw === "object" ? raw : {}; + const enabledEnv = process.env[ENV.ENDPOINT_ROUTING_ENABLED]; + const origin = (typeof obj.origin === "string" ? obj.origin : DEFAULTS.ENDPOINT_ROUTING_ORIGIN).trim() || DEFAULTS.ENDPOINT_ROUTING_ORIGIN; + validateOrigin(origin, "endpointRouting.origin"); + return { + enabled: enabledEnv !== void 0 ? resolveBool(enabledEnv, DEFAULTS.ENDPOINT_ROUTING_ENABLED) : resolveBool(obj.enabled, DEFAULTS.ENDPOINT_ROUTING_ENABLED), + origin + }; +} +function resolveClientSigningConfig(raw) { + const obj = raw && typeof raw === "object" ? raw : {}; + const enabledEnv = process.env[ENV.CLIENT_SIGNING_ENABLED]; + const origin = (typeof obj.origin === "string" ? obj.origin : DEFAULTS.CLIENT_SIGNING_ORIGIN).trim() || DEFAULTS.CLIENT_SIGNING_ORIGIN; + validateOrigin(origin, "clientSigning.origin"); + return { + enabled: enabledEnv !== void 0 ? resolveBool(enabledEnv, DEFAULTS.CLIENT_SIGNING_ENABLED) : resolveBool(obj.enabled, DEFAULTS.CLIENT_SIGNING_ENABLED), + origin + }; +} +function resolveBool(raw, fallback) { + if (typeof raw === "boolean") return raw; + if (typeof raw === "string") return raw === "true" || raw === "1"; + return fallback; +} +function resolvePositiveInt(raw, fallback, name2) { + if (raw === void 0 || raw === null) return fallback; + const n = typeof raw === "number" ? raw : parseInt(String(raw), 10); + if (!Number.isInteger(n) || n < 1) { + throw new Error(`${name2} must be a positive integer`); } + return n; } -function buildIdentityHeaders(id2) { - const n = resolveAppVersion(id2.appVersion); - const platform = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_PLATFORM ?? process.platform); - const arch = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_ARCH ?? import_node_os.default.arch()); - const release = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_RELEASE ?? import_node_os.default.release()); - const platformForCategory = process.env.ZCODE_IDENTITY_PLATFORM ?? process.platform; - const releaseChannel = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_RELEASE_CHANNEL) ?? (process.env.ZCODE_ENV?.trim().toLowerCase() === "test" ? "test" : "production"); - const clientLanguage = resolveClientLanguage(); - const clientTimezone = resolveClientTimezone(); - const deviceMid = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_DEVICE_MID) ?? normalizePrintableHeaderValue(id2.deviceMid); - const headers2 = { - "HTTP-Referer": id2.refererOrigin, - "User-Agent": `ZCode/${n ?? "unknown"}`, - ...n ? { "X-ZCode-App-Version": n } : {}, - "X-Title": `Z Code@${id2.sourceTitle}`, - "X-ZCode-Agent": "glm", - ...platform && arch ? { "X-Platform": `${platform}-${arch}` } : {}, - ...releaseChannel ? { "X-Release-Channel": releaseChannel } : {}, - ...clientLanguage ? { "X-Client-Language": clientLanguage } : {}, - ...clientTimezone ? { "X-Client-Timezone": clientTimezone } : {}, - ...platform ? { "X-Os-Category": normalizeOsCategory(platformForCategory) } : {}, - ...release ? { "X-Os-Version": release } : {}, - ...deviceMid ? { "X-Device-Mid": deviceMid } : {} +function resolveNonNegativeInt(raw, fallback, name2) { + if (raw === void 0 || raw === null) return fallback; + const n = typeof raw === "number" ? raw : parseInt(String(raw), 10); + if (!Number.isInteger(n) || n < 0) { + throw new Error(`${name2} must be a non-negative integer`); + } + return n; +} +function resolvePort(raw) { + if (raw === void 0 || raw === null) return DEFAULTS.PORT; + const n = typeof raw === "number" ? raw : parseInt(String(raw), 10); + if (!Number.isFinite(n)) { + throw new Error("server.port must be a valid number"); + } + return n; +} +function resolveProvider(raw) { + const v = typeof raw === "string" ? raw : DEFAULTS.PROVIDER; + if (v !== "zai" && v !== "bigmodel") { + throw new Error(`Invalid provider "${v}": must be "zai" or "bigmodel"`); + } + return v; +} +function resolvePlan(raw) { + if (raw === "start-plan") return "start-plan"; + return DEFAULTS.PLAN; +} +function resolveLogLevel(raw) { + const levels = ["debug", "info", "warn", "error"]; + if (typeof raw === "string" && levels.includes(raw)) { + return raw; + } + return DEFAULTS.LOG_LEVEL; +} +function resolveIdentity(inp) { + const rawVersion = (inp.appVersionEnv ?? inp.appVersionYaml ?? DEFAULTS.APP_VERSION).trim(); + const appVersion = ASCII_PRINTABLE.test(rawVersion) ? rawVersion : DEFAULTS.APP_VERSION; + const sourceTitle = (inp.sourceTitleEnv ?? inp.sourceTitleYaml ?? DEFAULTS.SOURCE_TITLE).trim() || DEFAULTS.SOURCE_TITLE; + const refererOrigin = (inp.refererEnv ?? inp.refererYaml ?? DEFAULTS.REFERER_ORIGIN).trim() || DEFAULTS.REFERER_ORIGIN; + const deviceMid = typeof inp.deviceMidYaml === "string" ? inp.deviceMidYaml.trim() : ""; + return { appVersion, sourceTitle, refererOrigin, ...deviceMid ? { deviceMid } : {} }; +} +function resolveClaimConfig(raw) { + const obj = raw && typeof raw === "object" ? raw : {}; + const enabledEnv = process.env[ENV.CLAIM_ENABLED]; + const autoEnv = process.env[ENV.CLAIM_AUTO]; + const originEnv = process.env[ENV.CLAIM_ORIGIN]; + const pollIntervalEnv = process.env[ENV.CLAIM_POLL_INTERVAL_MS]; + const origin = (originEnv ?? (typeof obj.origin === "string" ? obj.origin : DEFAULTS.CLAIM_ORIGIN)).trim() || DEFAULTS.CLAIM_ORIGIN; + validateOrigin(origin, "claim.origin"); + return { + enabled: enabledEnv !== void 0 ? resolveBool(enabledEnv, DEFAULTS.CLAIM_ENABLED) : resolveBool(obj.enabled, DEFAULTS.CLAIM_ENABLED), + auto: autoEnv !== void 0 ? resolveBool(autoEnv, DEFAULTS.CLAIM_AUTO) : resolveBool(obj.auto, DEFAULTS.CLAIM_AUTO), + origin, + pollIntervalMs: resolvePositiveInt(pollIntervalEnv ?? obj.pollIntervalMs ?? obj.poll_interval_ms, DEFAULTS.CLAIM_POLL_INTERVAL_MS, "claim.pollIntervalMs"), + cooldownMs: resolvePositiveInt(obj.cooldownMs ?? obj.cooldown_ms, DEFAULTS.CLAIM_COOLDOWN_MS, "claim.cooldownMs"), + planId: typeof obj.planId === "string" ? obj.planId.trim() : DEFAULTS.CLAIM_PLAN_ID }; - return headers2; } -var import_node_os, ASCII_PRINTABLE2; -var init_identity = __esm({ - "src/proxy/identity.ts"() { +function validate(config) { + if (config.server.port < 1 || config.server.port > 65535) { + throw new Error(`server.port ${config.server.port} is out of range (1-65535)`); + } + if (!config.models.includes(config.defaultModel)) { + config.models.push(config.defaultModel); + } +} +var import_node_fs, import_yaml, ENV, DEFAULTS, ASCII_PRINTABLE; +var init_loader = __esm({ + "src/config/loader.ts"() { "use strict"; - import_node_os = __toESM(require("node:os"), 1); - ASCII_PRINTABLE2 = /^[\x20-\x7e]+$/; + import_node_fs = require("node:fs"); + import_yaml = __toESM(require_dist(), 1); + ENV = { + PORT: "ZCODE_PROXY_PORT", + PROXY_API_KEY: "ZCODE_PROXY_API_KEY", + PROVIDER: "ZCODE_PROVIDER", + APP_VERSION: "ZCODE_APP_VERSION", + SOURCE_TITLE: "ZCODE_SOURCE_TITLE", + REFERER_ORIGIN: "ZCODE_REFERER_ORIGIN", + ASYNC_ENABLED: "ZCODE_ASYNC_ENABLED", + ASYNC_ORIGIN: "ZCODE_ASYNC_ORIGIN", + ASYNC_MAX_RETRIES: "ZCODE_ASYNC_MAX_RETRIES", + ASYNC_MAX_WAIT_MS: "ZCODE_ASYNC_MAX_WAIT_MS", + CLAIM_ENABLED: "ZCODE_CLAIM_ENABLED", + CLAIM_AUTO: "ZCODE_CLAIM_AUTO", + CLAIM_ORIGIN: "ZCODE_CLAIM_ORIGIN", + CLAIM_POLL_INTERVAL_MS: "ZCODE_CLAIM_POLL_INTERVAL_MS", + ENDPOINT_ROUTING_ENABLED: "ZCODE_ENDPOINT_ROUTING", + CLIENT_SIGNING_ENABLED: "ZCODE_CLIENT_SIGNING" + }; + DEFAULTS = { + PORT: 8080, + HOST: "0.0.0.0", + PROVIDER: "zai", + PLAN: "coding-plan", + DEFAULT_MODEL: "glm-4.6", + LOG_LEVEL: "info", + ZAI_ANTHROPIC_BASE: "https://api.z.ai/api/anthropic", + ZAI_OPENAI_BASE: "https://api.z.ai/api/coding/paas/v4", + BIGMODEL_ANTHROPIC_BASE: "https://open.bigmodel.cn/api/anthropic", + BIGMODEL_OPENAI_BASE: "https://open.bigmodel.cn/api/coding/paas/v4", + APP_VERSION: "3.10.0", + SOURCE_TITLE: "cli", + REFERER_ORIGIN: "https://zcode.z.ai", + CLIENT_IDENTITY_MODE: "observe", + CLIENT_IDENTITY_TTL_SECONDS: 900, + CLIENT_IDENTITY_MAX_SESSIONS: 1024, + RESPONSES_ENABLED: true, + RESPONSES_STORE_MAX_ENTRIES: 1e3, + RESPONSES_STORE_TTL_MS: 24 * 60 * 60 * 1e3, + MCP_ENABLED: true, + MCP_WEB_SEARCH: true, + MCP_WEB_READER: false, + MCP_ZREAD: false, + ASYNC_ENABLED: false, + ASYNC_ORIGIN: "https://zcode.z.ai", + ASYNC_POLL_INTERVAL_MS: 5e3, + ASYNC_KEEPALIVE_INTERVAL_MS: 3e3, + ASYNC_MAX_WAIT_MS: 0, + ASYNC_MAX_RETRIES: 3, + ASYNC_SETTLE_TIMEOUT_MS: 8e3, + ASYNC_CONTROL_TIMEOUT_MS: 15e3, + ASYNC_DEFAULT_MODEL: "", + CLAIM_ENABLED: false, + CLAIM_AUTO: true, + CLAIM_ORIGIN: "https://zcode.z.ai", + CLAIM_POLL_INTERVAL_MS: 3e5, + CLAIM_COOLDOWN_MS: 6e5, + CLAIM_PLAN_ID: "", + ENDPOINT_ROUTING_ENABLED: true, + ENDPOINT_ROUTING_ORIGIN: "https://zcode.z.ai", + CLIENT_SIGNING_ENABLED: true, + CLIENT_SIGNING_ORIGIN: "https://zcode.z.ai" + }; + ASCII_PRINTABLE = /^[\x20-\x7e]+$/; } }); -// node_modules/happy-dom/lib/PropertySymbol.js -var PropertySymbol_exports = {}; -__export(PropertySymbol_exports, { - abort: () => abort, - aborted: () => aborted, - accessKey: () => accessKey, - accessKeyLabel: () => accessKeyLabel, - activeCues: () => activeCues, - activeElement: () => activeElement, - adoptedStyleSheets: () => adoptedStyleSheets, - affectsCache: () => affectsCache, - affectsComputedStyleCache: () => affectsComputedStyleCache, - amplitude: () => amplitude, - angle: () => angle, - animVal: () => animVal, - animatedPoints: () => animatedPoints, - appendChild: () => appendChild, - areas: () => areas, - assignedNodes: () => assignedNodes, - assignedToSlot: () => assignedToSlot, - asyncTaskManager: () => asyncTaskManager, - attributeName: () => attributeName, - attributeValue: () => attributeValue, - attributes: () => attributes, - attributesProxy: () => attributesProxy, - azimuth: () => azimuth, - baseFrequencyX: () => baseFrequencyX, - baseFrequencyY: () => baseFrequencyY, - baseVal: () => baseVal, - bias: () => bias, - bindMethods: () => bindMethods, - blocking: () => blocking, - body: () => body, - bodyBuffer: () => bodyBuffer, - bodyUsed: () => bodyUsed, - browserFrames: () => browserFrames, - bubbles: () => bubbles, - buffer: () => buffer, - buffered: () => buffered, - cache: () => cache, - cachedResponse: () => cachedResponse, - callbacks: () => callbacks, - cancelable: () => cancelable, - canvas: () => canvas, - capabilities: () => capabilities, - cells: () => cells, - checked: () => checked, - childNodes: () => childNodes, - children: () => children, - classList: () => classList, - classRegistry: () => classRegistry, - clearCache: () => clearCache, - clientHeight: () => clientHeight, - clientLeft: () => clientLeft, - clientTop: () => clientTop, - clientWidth: () => clientWidth, - clipPathUnits: () => clipPathUnits, - clonable: () => clonable, - clone: () => clone, - cloneNode: () => cloneNode, - complete: () => complete, - composed: () => composed, - computedStyle: () => computedStyle, - conditionText: () => conditionText, - connectedToDocument: () => connectedToDocument, - connectedToNode: () => connectedToNode, - constraints: () => constraints, - content: () => content, - contentLength: () => contentLength, - contentType: () => contentType, - context: () => context, - controlsList: () => controlsList, - cookieStore: () => cookieStore, - credentials: () => credentials, - crossOrigin: () => crossOrigin, - cssParser: () => cssParser, - cssRule: () => cssRule, - cssRules: () => cssRules, - cssText: () => cssText, - cues: () => cues, - currentNode: () => currentNode, - currentScale: () => currentScale, - currentScript: () => currentScript, - currentTarget: () => currentTarget, - currentTime: () => currentTime, - customElementReactionStack: () => customElementReactionStack, - cx: () => cx, - cy: () => cy, - data: () => data, - dataset: () => dataset, - defaultChecked: () => defaultChecked, - defaultMuted: () => defaultMuted, - defaultPlaybackRate: () => defaultPlaybackRate, - defaultPrevented: () => defaultPrevented, - defaultValue: () => defaultValue, - defaultView: () => defaultView, - delegatesFocus: () => delegatesFocus, - destroy: () => destroy, - destroyed: () => destroyed, - detail: () => detail, - diffuseConstant: () => diffuseConstant, - dirtyness: () => dirtyness, - disableEvaluation: () => disableEvaluation, - disabled: () => disabled, - disconnectedFromDocument: () => disconnectedFromDocument, - disconnectedFromNode: () => disconnectedFromNode, - dispatchError: () => dispatchError, - dispatching: () => dispatching, - divisor: () => divisor, - domMatrix: () => domMatrix, - duration: () => duration, - dx: () => dx, - dy: () => dy, - edgeMode: () => edgeMode, - elementArray: () => elementArray, - elementIdMap: () => elementIdMap, - elements: () => elements, - elevation: () => elevation, - end: () => end, - ended: () => ended, - entries: () => entries, - error: () => error, - evaluateCSS: () => evaluateCSS, - evaluateScript: () => evaluateScript, - eventPhase: () => eventPhase, - exceptionObserver: () => exceptionObserver, - exponent: () => exponent, - files: () => files, - filterNode: () => filterNode, - filterUnits: () => filterUnits, - flipXSelf: () => flipXSelf, - flipYSelf: () => flipYSelf, - formNode: () => formNode, - forms: () => forms, - frames: () => frames, - fromArray: () => fromArray, - fromString: () => fromString, - fx: () => fx, - fy: () => fy, - getAttribute: () => getAttribute, - getDOMMatrix: () => getDOMMatrix, - getFormControlItems: () => getFormControlItems, - getFormControlNamedItem: () => getFormControlNamedItem, - getItemList: () => getItemList, - getLength: () => getLength, - getNamedItemKey: () => getNamedItemKey, - getNamespaceItemKey: () => getNamespaceItemKey, - getTokenList: () => getTokenList, - globalObject: () => globalObject, - gradientTransform: () => gradientTransform, - gradientUnits: () => gradientUnits, - headers: () => headers, - height: () => height, - history: () => history, - host: () => host, - href: () => href, - id: () => id, - illegalConstructor: () => illegalConstructor, - immediatePropagationStopped: () => immediatePropagationStopped, - implementation: () => implementation, - in1: () => in1, - in2: () => in2, - indeterminate: () => indeterminate, - insertBefore: () => insertBefore, - intercept: () => intercept, - internalId: () => internalId, - invertSelf: () => invertSelf, - isConnected: () => isConnected, - isFirstWrite: () => isFirstWrite, - isFirstWriteAfterOpen: () => isFirstWriteAfterOpen, - isInPassiveEventListener: () => isInPassiveEventListener, - isValue: () => isValue, - items: () => items, - itemsByName: () => itemsByName, - itemsByNamespaceURI: () => itemsByNamespaceURI, - kernelMatrix: () => kernelMatrix, - kernelUnitLengthX: () => kernelUnitLengthX, - kernelUnitLengthY: () => kernelUnitLengthY, - keyText: () => keyText, - kind: () => kind, - label: () => label, - language: () => language, - length: () => length, - lengthAdjust: () => lengthAdjust, - limitingConeAngle: () => limitingConeAngle, - links: () => links, - listenerOptions: () => listenerOptions, - listeners: () => listeners, - loading: () => loading, - localName: () => localName, - localStorage: () => localStorage, - location: () => location, - m11: () => m11, - m12: () => m12, - m13: () => m13, - m14: () => m14, - m21: () => m21, - m22: () => m22, - m23: () => m23, - m24: () => m24, - m31: () => m31, - m32: () => m32, - m33: () => m33, - m34: () => m34, - m41: () => m41, - m42: () => m42, - m43: () => m43, - m44: () => m44, - markerHeight: () => markerHeight, - markerUnits: () => markerUnits, - markerWidth: () => markerWidth, - maskContentUnits: () => maskContentUnits, - maskUnits: () => maskUnits, - matrix: () => matrix, - media: () => media, - mediaKeys: () => mediaKeys, - method: () => method, - mode: () => mode, - moduleCache: () => moduleCache, - moduleImportMap: () => moduleImportMap, - modules: () => modules, - multiplySelf: () => multiplySelf, - mutationListeners: () => mutationListeners, - mutationObservers: () => mutationObservers, - muted: () => muted, - name: () => name, - namespaceURI: () => namespaceURI, - naturalHeight: () => naturalHeight, - naturalWidth: () => naturalWidth, - navigator: () => navigator, - networkState: () => networkState, - nextActiveElement: () => nextActiveElement, - nodeArray: () => nodeArray, - nodeStream: () => nodeStream, - nodeType: () => nodeType, - numOctaves: () => numOctaves, - observeMutations: () => observeMutations, - offset: () => offset, - offsetHeight: () => offsetHeight, - offsetLeft: () => offsetLeft, - offsetTop: () => offsetTop, - offsetWidth: () => offsetWidth, - onRemoveAttribute: () => onRemoveAttribute, - onSetAttribute: () => onSetAttribute, - openWebSockets: () => openWebSockets, - openerFrame: () => openerFrame, - openerWindow: () => openerWindow, - operator: () => operator, - options: () => options, - orderX: () => orderX, - orderY: () => orderY, - orientAngle: () => orientAngle, - orientType: () => orientType, - ownerDocument: () => ownerDocument, - ownerElement: () => ownerElement, - parent: () => parent, - parentNode: () => parentNode, - parentRule: () => parentRule, - parentStyleSheet: () => parentStyleSheet, - pathLength: () => pathLength, - patternContentUnits: () => patternContentUnits, - patternTransform: () => patternTransform, - patternUnits: () => patternUnits, - paused: () => paused, - playbackRate: () => playbackRate, - played: () => played, - pointerCaptures: () => pointerCaptures, - points: () => points, - pointsAtX: () => pointsAtX, - pointsAtY: () => pointsAtY, - pointsAtZ: () => pointsAtZ, - popoverTargetElement: () => popoverTargetElement, - popup: () => popup, - prefix: () => prefix, - preloads: () => preloads, - preserveAlpha: () => preserveAlpha, - preserveAspectRatio: () => preserveAspectRatio, - preservesPitch: () => preservesPitch, - primitiveUnits: () => primitiveUnits, - propagationStopped: () => propagationStopped, - propertyEventListeners: () => propertyEventListeners, - proxy: () => proxy, - publicId: () => publicId, - query: () => query, - querySelectorCache: () => querySelectorCache, - r: () => r, - radiusX: () => radiusX, - radiusY: () => radiusY, - readOnly: () => readOnly, - readyState: () => readyState, - readyStateManager: () => readyStateManager, - reason: () => reason, - redirect: () => redirect, - refX: () => refX, - refY: () => refY, - referrer: () => referrer, - referrerPolicy: () => referrerPolicy, - registry: () => registry, - relList: () => relList, - remote: () => remote, - removeChild: () => removeChild, - removeNamedItem: () => removeNamedItem, - replaceChild: () => replaceChild, - reportMutation: () => reportMutation, - requiredExtensions: () => requiredExtensions, - resetSelection: () => resetSelection, - result: () => result2, - returnValue: () => returnValue, - root: () => root, - rootNode: () => rootNode, - rotate: () => rotate, - rotateAxisAngleSelf: () => rotateAxisAngleSelf, - rotateFromVectorSelf: () => rotateFromVectorSelf, - rotateSelf: () => rotateSelf, - rows: () => rows, - rulePrefix: () => rulePrefix, - rx: () => rx, - ry: () => ry, - sandbox: () => sandbox, - scale: () => scale, - scale3dSelf: () => scale3dSelf, - scaleNonUniformSelf: () => scaleNonUniformSelf, - scaleSelf: () => scaleSelf, - screen: () => screen, - scrollHeight: () => scrollHeight, - scrollLeft: () => scrollLeft, - scrollTop: () => scrollTop, - scrollWidth: () => scrollWidth, - seed: () => seed, - seekable: () => seekable, - seeking: () => seeking, - selectNode: () => selectNode, - selectedIndex: () => selectedIndex, - selectedOptions: () => selectedOptions, - selectedness: () => selectedness, - selection: () => selection, - selectorText: () => selectorText, - self: () => self, - serializable: () => serializable, - sessionStorage: () => sessionStorage, - setAttribute: () => setAttribute, - setDOMMatrix: () => setDOMMatrix, - setMatrixValue: () => setMatrixValue, - setNamedItem: () => setNamedItem, - setURL: () => setURL, - settings: () => settings, - setupVMContext: () => setupVMContext, - shadowRoot: () => shadowRoot, - sheet: () => sheet, - signal: () => signal, - sinkId: () => sinkId, - skewXSelf: () => skewXSelf, - skewYSelf: () => skewYSelf, - slope: () => slope, - slotAssignment: () => slotAssignment, - spacing: () => spacing, - specified: () => specified, - specularConstant: () => specularConstant, - specularExponent: () => specularExponent, - spreadMethod: () => spreadMethod, - srcObject: () => srcObject, - start: () => start, - startOffset: () => startOffset, - state: () => state, - stdDeviationX: () => stdDeviationX, - stdDeviationY: () => stdDeviationY, - stitchTiles: () => stitchTiles, - style: () => style, - styleMap: () => styleMap, - styleNode: () => styleNode, - supports: () => supports, - surfaceScale: () => surfaceScale, - systemId: () => systemId, - systemLanguage: () => systemLanguage, - tBodies: () => tBodies, - tableValues: () => tableValues, - tagName: () => tagName, - target: () => target, - targetX: () => targetX, - targetY: () => targetY, - textAreaNode: () => textAreaNode, - textLength: () => textLength, - textTracks: () => textTracks, - timeStamp: () => timeStamp, - toArray: () => toArray, - top: () => top, - track: () => track, - tracks: () => tracks, - transform: () => transform, - translateSelf: () => translateSelf, - type: () => type, - unitType: () => unitType, - unobserveMutations: () => unobserveMutations, - updateSelectedness: () => updateSelectedness, - updateSheet: () => updateSheet, - url: () => url, - validateJavaScriptExecutionEnvironment: () => validateJavaScriptExecutionEnvironment, - validationMessage: () => validationMessage, - validity: () => validity, - value: () => value, - values: () => values, - viewBox: () => viewBox, - virtualServerFile: () => virtualServerFile, - volume: () => volume, - w: () => w, - webSocket: () => webSocket, - width: () => width, - window: () => window, - windowInternalId: () => windowInternalId, - windowResizeListener: () => windowResizeListener, - x: () => x, - x1: () => x1, - x2: () => x2, - xChannelSelector: () => xChannelSelector, - xmlProcessingInstruction: () => xmlProcessingInstruction, - y: () => y, - y1: () => y1, - y2: () => y2, - yChannelSelector: () => yChannelSelector, - z: () => z -}); -var abort, activeElement, asyncTaskManager, bodyBuffer, buffer, cachedResponse, callbacks, checked, childNodes, children, classList, connectedToNode, disconnectedFromNode, connectedToDocument, disconnectedFromDocument, contentLength, contentType, cssText, currentScript, currentTarget, data, defaultView, destroy, dirtyness, end, entries, evaluateCSS, evaluateScript, exceptionObserver, formNode, internalId, height, immediatePropagationStopped, indeterminate, isFirstWrite, isFirstWriteAfterOpen, isInPassiveEventListener, isValue, listenerOptions, listeners, itemsByName, nextActiveElement, observeMutations, mutationListeners, ownerDocument, ownerElement, propagationStopped, readyStateManager, referrer, registry, relList, resetSelection, rootNode, selectNode, selectedness, selection, setupVMContext, shadowRoot, start, style, target, textAreaNode, unobserveMutations, reportMutation, updateSelectedness, url, value, width, window, windowResizeListener, mutationObservers, openerFrame, openerWindow, pointerCaptures, popup, isConnected, parentNode, nodeType, tagName, prefix, scrollHeight, scrollWidth, scrollTop, scrollLeft, attributes, attributesProxy, namespaceURI, accessKey, accessKeyLabel, offsetHeight, offsetWidth, offsetLeft, offsetTop, clientHeight, clientWidth, clientLeft, clientTop, name, specified, adoptedStyleSheets, implementation, readyState, publicId, systemId, validationMessage, validity, returnValue, elements, length, complete, naturalHeight, naturalWidth, loading, x, y, defaultChecked, files, sheet, volume, paused, currentTime, playbackRate, defaultPlaybackRate, muted, defaultMuted, preservesPitch, buffered, duration, error, ended, networkState, textTracks, seeking, seekable, played, options, content, mode, host, setURL, localName, classRegistry, nodeStream, location, history, navigator, screen, sessionStorage, localStorage, sandbox, cloneNode, appendChild, removeChild, insertBefore, replaceChild, tracks, constraints, capabilities, settings, clone, removeNamedItem, items, selectedOptions, styleNode, updateSheet, clearCache, onSetAttribute, onRemoveAttribute, nodeArray, elementArray, cache, affectsCache, forms, links, affectsComputedStyleCache, query, computedStyle, getFormControlItems, getFormControlNamedItem, dataset, getNamespaceItemKey, getNamedItemKey, itemsByNamespaceURI, proxy, setNamedItem, getTokenList, attributeName, selectedIndex, self, parent, top, areas, defaultValue, elementIdMap, clonable, delegatesFocus, serializable, slotAssignment, assignedNodes, assignedToSlot, cells, rows, headers, tBodies, track, controlsList, mediaKeys, remote, sinkId, srcObject, cues, activeCues, kind, label, language, id, illegalConstructor, state, canvas, popoverTargetElement, composed, bubbles, cancelable, defaultPrevented, eventPhase, timeStamp, type, detail, globalObject, destroyed, aborted, browserFrames, windowInternalId, getItemList, requiredExtensions, systemLanguage, transform, baseVal, animVal, pathLength, unitType, viewBox, markerUnits, markerWidth, markerHeight, values, orientType, orientAngle, refX, refY, readOnly, preserveAspectRatio, animatedPoints, points, rx, ry, cx, cy, r, clipPathUnits, maskUnits, maskContentUnits, filterUnits, primitiveUnits, href, x1, y1, x2, y2, gradientUnits, gradientTransform, spreadMethod, patternUnits, patternContentUnits, patternTransform, fx, fy, offset, disabled, textLength, lengthAdjust, getAttribute, setAttribute, z, w, toArray, fromString, fromArray, angle, m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44, setMatrixValue, translateSelf, rotateSelf, rotateAxisAngleSelf, scaleSelf, scale3dSelf, scaleNonUniformSelf, skewXSelf, skewYSelf, multiplySelf, matrix, domMatrix, getDOMMatrix, setDOMMatrix, attributeValue, startOffset, method, spacing, in1, in2, result2, bias, divisor, edgeMode, kernelMatrix, kernelUnitLengthX, kernelUnitLengthY, orderX, orderY, preserveAlpha, targetX, targetY, diffuseConstant, surfaceScale, scale, xChannelSelector, yChannelSelector, azimuth, elevation, dx, dy, stdDeviationX, stdDeviationY, tableValues, slope, intercept, amplitude, exponent, crossOrigin, operator, radiusX, radiusY, specularConstant, specularExponent, pointsAtX, pointsAtY, pointsAtZ, limitingConeAngle, baseFrequencyX, baseFrequencyY, numOctaves, seed, stitchTiles, rotateFromVectorSelf, flipXSelf, flipYSelf, invertSelf, getLength, currentScale, rotate, bindMethods, xmlProcessingInstruction, root, filterNode, customElementReactionStack, dispatching, modules, preloads, body, redirect, referrerPolicy, signal, bodyUsed, credentials, blocking, moduleImportMap, dispatchError, supports, reason, propertyEventListeners, cssRules, parentRule, parentStyleSheet, conditionText, keyText, media, styleMap, selectorText, cssParser, cssRule, rulePrefix, virtualServerFile, frames, disableEvaluation, validateJavaScriptExecutionEnvironment, currentNode, openWebSockets, webSocket, moduleCache, cookieStore, context, querySelectorCache; -var init_PropertySymbol = __esm({ - "node_modules/happy-dom/lib/PropertySymbol.js"() { - abort = /* @__PURE__ */ Symbol("abort"); - activeElement = /* @__PURE__ */ Symbol("activeElement"); - asyncTaskManager = /* @__PURE__ */ Symbol("asyncTaskManager"); - bodyBuffer = /* @__PURE__ */ Symbol("bodyBuffer"); - buffer = /* @__PURE__ */ Symbol("buffer"); - cachedResponse = /* @__PURE__ */ Symbol("cachedResponse"); - callbacks = /* @__PURE__ */ Symbol("callbacks"); - checked = /* @__PURE__ */ Symbol("checked"); - childNodes = /* @__PURE__ */ Symbol("childNodes"); - children = /* @__PURE__ */ Symbol("children"); - classList = /* @__PURE__ */ Symbol("classList"); - connectedToNode = /* @__PURE__ */ Symbol("connectedToNode"); - disconnectedFromNode = /* @__PURE__ */ Symbol("disconnectedFromNode"); - connectedToDocument = /* @__PURE__ */ Symbol("connectedToDocument"); - disconnectedFromDocument = /* @__PURE__ */ Symbol("disconnectedFromDocument"); - contentLength = /* @__PURE__ */ Symbol("contentLength"); - contentType = /* @__PURE__ */ Symbol("contentType"); - cssText = /* @__PURE__ */ Symbol("cssText"); - currentScript = /* @__PURE__ */ Symbol("currentScript"); - currentTarget = /* @__PURE__ */ Symbol("currentTarget"); - data = /* @__PURE__ */ Symbol("data"); - defaultView = /* @__PURE__ */ Symbol("defaultView"); - destroy = /* @__PURE__ */ Symbol("destroy"); - dirtyness = /* @__PURE__ */ Symbol("dirtyness"); - end = /* @__PURE__ */ Symbol("end"); - entries = /* @__PURE__ */ Symbol("entries"); - evaluateCSS = /* @__PURE__ */ Symbol("evaluateCSS"); - evaluateScript = /* @__PURE__ */ Symbol("evaluateScript"); - exceptionObserver = /* @__PURE__ */ Symbol("exceptionObserver"); - formNode = /* @__PURE__ */ Symbol("formNode"); - internalId = /* @__PURE__ */ Symbol("internalId"); - height = /* @__PURE__ */ Symbol("height"); - immediatePropagationStopped = /* @__PURE__ */ Symbol("immediatePropagationStopped"); - indeterminate = /* @__PURE__ */ Symbol("indeterminate"); - isFirstWrite = /* @__PURE__ */ Symbol("isFirstWrite"); - isFirstWriteAfterOpen = /* @__PURE__ */ Symbol("isFirstWriteAfterOpen"); - isInPassiveEventListener = /* @__PURE__ */ Symbol("isInPassiveEventListener"); - isValue = /* @__PURE__ */ Symbol("isValue"); - listenerOptions = /* @__PURE__ */ Symbol("listenerOptions"); - listeners = /* @__PURE__ */ Symbol("listeners"); - itemsByName = /* @__PURE__ */ Symbol("itemsByName"); - nextActiveElement = /* @__PURE__ */ Symbol("nextActiveElement"); - observeMutations = /* @__PURE__ */ Symbol("observeMutations"); - mutationListeners = /* @__PURE__ */ Symbol("mutationListeners"); - ownerDocument = /* @__PURE__ */ Symbol("ownerDocument"); - ownerElement = /* @__PURE__ */ Symbol("ownerElement"); - propagationStopped = /* @__PURE__ */ Symbol("propagationStopped"); - readyStateManager = /* @__PURE__ */ Symbol("readyStateManager"); - referrer = /* @__PURE__ */ Symbol("referrer"); - registry = /* @__PURE__ */ Symbol("registry"); - relList = /* @__PURE__ */ Symbol("relList"); - resetSelection = /* @__PURE__ */ Symbol("resetSelection"); - rootNode = /* @__PURE__ */ Symbol("rootNode"); - selectNode = /* @__PURE__ */ Symbol("selectNode"); - selectedness = /* @__PURE__ */ Symbol("selectedness"); - selection = /* @__PURE__ */ Symbol("selection"); - setupVMContext = /* @__PURE__ */ Symbol("setupVMContext"); - shadowRoot = /* @__PURE__ */ Symbol("shadowRoot"); - start = /* @__PURE__ */ Symbol("start"); - style = /* @__PURE__ */ Symbol("style"); - target = /* @__PURE__ */ Symbol("target"); - textAreaNode = /* @__PURE__ */ Symbol("textAreaNode"); - unobserveMutations = /* @__PURE__ */ Symbol("unobserveMutations"); - reportMutation = /* @__PURE__ */ Symbol("reportMutation"); - updateSelectedness = /* @__PURE__ */ Symbol("updateSelectedness"); - url = /* @__PURE__ */ Symbol("url"); - value = /* @__PURE__ */ Symbol("value"); - width = /* @__PURE__ */ Symbol("width"); - window = /* @__PURE__ */ Symbol("window"); - windowResizeListener = /* @__PURE__ */ Symbol("windowResizeListener"); - mutationObservers = /* @__PURE__ */ Symbol("mutationObservers"); - openerFrame = /* @__PURE__ */ Symbol("openerFrame"); - openerWindow = /* @__PURE__ */ Symbol("openerWindow"); - pointerCaptures = /* @__PURE__ */ Symbol("pointerCaptures"); - popup = /* @__PURE__ */ Symbol("popup"); - isConnected = /* @__PURE__ */ Symbol("isConnected"); - parentNode = /* @__PURE__ */ Symbol("parentNode"); - nodeType = /* @__PURE__ */ Symbol("nodeType"); - tagName = /* @__PURE__ */ Symbol("tagName"); - prefix = /* @__PURE__ */ Symbol("prefix"); - scrollHeight = /* @__PURE__ */ Symbol("scrollHeight"); - scrollWidth = /* @__PURE__ */ Symbol("scrollWidth"); - scrollTop = /* @__PURE__ */ Symbol("scrollTop"); - scrollLeft = /* @__PURE__ */ Symbol("scrollLeft"); - attributes = /* @__PURE__ */ Symbol("attributes"); - attributesProxy = /* @__PURE__ */ Symbol("attributesProxy"); - namespaceURI = /* @__PURE__ */ Symbol("namespaceURI"); - accessKey = /* @__PURE__ */ Symbol("accessKey"); - accessKeyLabel = /* @__PURE__ */ Symbol("accessKeyLabel"); - offsetHeight = /* @__PURE__ */ Symbol("offsetHeight"); - offsetWidth = /* @__PURE__ */ Symbol("offsetWidth"); - offsetLeft = /* @__PURE__ */ Symbol("offsetLeft"); - offsetTop = /* @__PURE__ */ Symbol("offsetTop"); - clientHeight = /* @__PURE__ */ Symbol("clientHeight"); - clientWidth = /* @__PURE__ */ Symbol("clientWidth"); - clientLeft = /* @__PURE__ */ Symbol("clientLeft"); - clientTop = /* @__PURE__ */ Symbol("clientTop"); - name = /* @__PURE__ */ Symbol("name"); - specified = /* @__PURE__ */ Symbol("specified"); - adoptedStyleSheets = /* @__PURE__ */ Symbol("adoptedStyleSheets"); - implementation = /* @__PURE__ */ Symbol("implementation"); - readyState = /* @__PURE__ */ Symbol("readyState"); - publicId = /* @__PURE__ */ Symbol("publicId"); - systemId = /* @__PURE__ */ Symbol("systemId"); - validationMessage = /* @__PURE__ */ Symbol("validationMessage"); - validity = /* @__PURE__ */ Symbol("validity"); - returnValue = /* @__PURE__ */ Symbol("returnValue"); - elements = /* @__PURE__ */ Symbol("elements"); - length = /* @__PURE__ */ Symbol("length"); - complete = /* @__PURE__ */ Symbol("complete"); - naturalHeight = /* @__PURE__ */ Symbol("naturalHeight"); - naturalWidth = /* @__PURE__ */ Symbol("naturalWidth"); - loading = /* @__PURE__ */ Symbol("loading"); - x = /* @__PURE__ */ Symbol("x"); - y = /* @__PURE__ */ Symbol("y"); - defaultChecked = /* @__PURE__ */ Symbol("defaultChecked"); - files = /* @__PURE__ */ Symbol("files"); - sheet = /* @__PURE__ */ Symbol("sheet"); - volume = /* @__PURE__ */ Symbol("volume"); - paused = /* @__PURE__ */ Symbol("paused"); - currentTime = /* @__PURE__ */ Symbol("currentTime"); - playbackRate = /* @__PURE__ */ Symbol("playbackRate"); - defaultPlaybackRate = /* @__PURE__ */ Symbol("defaultPlaybackRate"); - muted = /* @__PURE__ */ Symbol("muted"); - defaultMuted = /* @__PURE__ */ Symbol("defaultMuted"); - preservesPitch = /* @__PURE__ */ Symbol("preservesPitch"); - buffered = /* @__PURE__ */ Symbol("buffered"); - duration = /* @__PURE__ */ Symbol("duration"); - error = /* @__PURE__ */ Symbol("error"); - ended = /* @__PURE__ */ Symbol("ended"); - networkState = /* @__PURE__ */ Symbol("networkState"); - textTracks = /* @__PURE__ */ Symbol("textTracks"); - seeking = /* @__PURE__ */ Symbol("seeking"); - seekable = /* @__PURE__ */ Symbol("seekable"); - played = /* @__PURE__ */ Symbol("played"); - options = /* @__PURE__ */ Symbol("options"); - content = /* @__PURE__ */ Symbol("content"); - mode = /* @__PURE__ */ Symbol("mode"); - host = /* @__PURE__ */ Symbol("host"); - setURL = /* @__PURE__ */ Symbol("setURL"); - localName = /* @__PURE__ */ Symbol("localName"); - classRegistry = /* @__PURE__ */ Symbol("classRegistry"); - nodeStream = /* @__PURE__ */ Symbol("nodeStream"); - location = /* @__PURE__ */ Symbol("location"); - history = /* @__PURE__ */ Symbol("history"); - navigator = /* @__PURE__ */ Symbol("navigator"); - screen = /* @__PURE__ */ Symbol("screen"); - sessionStorage = /* @__PURE__ */ Symbol("sessionStorage"); - localStorage = /* @__PURE__ */ Symbol("localStorage"); - sandbox = /* @__PURE__ */ Symbol("sandbox"); - cloneNode = /* @__PURE__ */ Symbol("cloneNode"); - appendChild = /* @__PURE__ */ Symbol("appendChild"); - removeChild = /* @__PURE__ */ Symbol("removeChild"); - insertBefore = /* @__PURE__ */ Symbol("insertBefore"); - replaceChild = /* @__PURE__ */ Symbol("replaceChild"); - tracks = /* @__PURE__ */ Symbol("tracks"); - constraints = /* @__PURE__ */ Symbol("constraints"); - capabilities = /* @__PURE__ */ Symbol("capabilities"); - settings = /* @__PURE__ */ Symbol("settings"); - clone = /* @__PURE__ */ Symbol("clone"); - removeNamedItem = /* @__PURE__ */ Symbol("removeNamedItem"); - items = /* @__PURE__ */ Symbol("items"); - selectedOptions = /* @__PURE__ */ Symbol("selectedOptions"); - styleNode = /* @__PURE__ */ Symbol("styleNode"); - updateSheet = /* @__PURE__ */ Symbol("updateSheet"); - clearCache = /* @__PURE__ */ Symbol("clearCache"); - onSetAttribute = /* @__PURE__ */ Symbol("onSetAttribute"); - onRemoveAttribute = /* @__PURE__ */ Symbol("onRemoveAttribute"); - nodeArray = /* @__PURE__ */ Symbol("nodeArray"); - elementArray = /* @__PURE__ */ Symbol("elementArray"); - cache = /* @__PURE__ */ Symbol("cache"); - affectsCache = /* @__PURE__ */ Symbol("affectsCache"); - forms = /* @__PURE__ */ Symbol("forms"); - links = /* @__PURE__ */ Symbol("links"); - affectsComputedStyleCache = /* @__PURE__ */ Symbol("affectsComputedStyleCache"); - query = /* @__PURE__ */ Symbol("query"); - computedStyle = /* @__PURE__ */ Symbol("computedStyle"); - getFormControlItems = /* @__PURE__ */ Symbol("getFormControlItems"); - getFormControlNamedItem = /* @__PURE__ */ Symbol("getFormControlNamedItem"); - dataset = /* @__PURE__ */ Symbol("dataset"); - getNamespaceItemKey = /* @__PURE__ */ Symbol("getNamespaceItemKey"); - getNamedItemKey = /* @__PURE__ */ Symbol("getNamedItemKey"); - itemsByNamespaceURI = /* @__PURE__ */ Symbol("itemsByNamespaceURI"); - proxy = /* @__PURE__ */ Symbol("proxy"); - setNamedItem = /* @__PURE__ */ Symbol("setNamedItem"); - getTokenList = /* @__PURE__ */ Symbol("getTokenList"); - attributeName = /* @__PURE__ */ Symbol("attributeName"); - selectedIndex = /* @__PURE__ */ Symbol("selectedIndex"); - self = /* @__PURE__ */ Symbol("self"); - parent = /* @__PURE__ */ Symbol("parent"); - top = /* @__PURE__ */ Symbol("top"); - areas = /* @__PURE__ */ Symbol("areas"); - defaultValue = /* @__PURE__ */ Symbol("defaultValue"); - elementIdMap = /* @__PURE__ */ Symbol("elementIdMap"); - clonable = /* @__PURE__ */ Symbol("clonable"); - delegatesFocus = /* @__PURE__ */ Symbol("delegatesFocus"); - serializable = /* @__PURE__ */ Symbol("serializable"); - slotAssignment = /* @__PURE__ */ Symbol("slotAssignment"); - assignedNodes = /* @__PURE__ */ Symbol("assignedNodes"); - assignedToSlot = /* @__PURE__ */ Symbol("assignedToSlot"); - cells = /* @__PURE__ */ Symbol("cells"); - rows = /* @__PURE__ */ Symbol("rows"); - headers = /* @__PURE__ */ Symbol("headers"); - tBodies = /* @__PURE__ */ Symbol("tBodies"); - track = /* @__PURE__ */ Symbol("track"); - controlsList = /* @__PURE__ */ Symbol("controlsList"); - mediaKeys = /* @__PURE__ */ Symbol("mediaKeys"); - remote = /* @__PURE__ */ Symbol("remote"); - sinkId = /* @__PURE__ */ Symbol("sinkId"); - srcObject = /* @__PURE__ */ Symbol("srcObject"); - cues = /* @__PURE__ */ Symbol("cues"); - activeCues = /* @__PURE__ */ Symbol("activeCues"); - kind = /* @__PURE__ */ Symbol("kind"); - label = /* @__PURE__ */ Symbol("label"); - language = /* @__PURE__ */ Symbol("language"); - id = /* @__PURE__ */ Symbol("id"); - illegalConstructor = /* @__PURE__ */ Symbol("illegalConstructor"); - state = /* @__PURE__ */ Symbol("state"); - canvas = /* @__PURE__ */ Symbol("canvas"); - popoverTargetElement = /* @__PURE__ */ Symbol("popoverTargetElement"); - composed = /* @__PURE__ */ Symbol("composed"); - bubbles = /* @__PURE__ */ Symbol("bubbles"); - cancelable = /* @__PURE__ */ Symbol("cancelable"); - defaultPrevented = /* @__PURE__ */ Symbol("defaultPrevented"); - eventPhase = /* @__PURE__ */ Symbol("eventPhase"); - timeStamp = /* @__PURE__ */ Symbol("timeStamp"); - type = /* @__PURE__ */ Symbol("type"); - detail = /* @__PURE__ */ Symbol("detail"); - globalObject = /* @__PURE__ */ Symbol("globalObject"); - destroyed = /* @__PURE__ */ Symbol("destroyed"); - aborted = /* @__PURE__ */ Symbol("aborted"); - browserFrames = /* @__PURE__ */ Symbol("browserFrames"); - windowInternalId = /* @__PURE__ */ Symbol("windowInternalId"); - getItemList = /* @__PURE__ */ Symbol("getItemList"); - requiredExtensions = /* @__PURE__ */ Symbol("requiredExtensions"); - systemLanguage = /* @__PURE__ */ Symbol("systemLanguage"); - transform = /* @__PURE__ */ Symbol("transform"); - baseVal = /* @__PURE__ */ Symbol("baseVal"); - animVal = /* @__PURE__ */ Symbol("animVal"); - pathLength = /* @__PURE__ */ Symbol("pathLength"); - unitType = /* @__PURE__ */ Symbol("unitType"); - viewBox = /* @__PURE__ */ Symbol("viewBox"); - markerUnits = /* @__PURE__ */ Symbol("markerUnits"); - markerWidth = /* @__PURE__ */ Symbol("markerWidth"); - markerHeight = /* @__PURE__ */ Symbol("markerHeight"); - values = /* @__PURE__ */ Symbol("values"); - orientType = /* @__PURE__ */ Symbol("orientType"); - orientAngle = /* @__PURE__ */ Symbol("orientAngle"); - refX = /* @__PURE__ */ Symbol("refX"); - refY = /* @__PURE__ */ Symbol("refY"); - readOnly = /* @__PURE__ */ Symbol("readOnly"); - preserveAspectRatio = /* @__PURE__ */ Symbol("preserveAspectRatio"); - animatedPoints = /* @__PURE__ */ Symbol("animatedPoints"); - points = /* @__PURE__ */ Symbol("points"); - rx = /* @__PURE__ */ Symbol("rx"); - ry = /* @__PURE__ */ Symbol("ry"); - cx = /* @__PURE__ */ Symbol("cx"); - cy = /* @__PURE__ */ Symbol("cy"); - r = /* @__PURE__ */ Symbol("r"); - clipPathUnits = /* @__PURE__ */ Symbol("clipPathUnits"); - maskUnits = /* @__PURE__ */ Symbol("maskUnits"); - maskContentUnits = /* @__PURE__ */ Symbol("maskContentUnits"); - filterUnits = /* @__PURE__ */ Symbol("filterUnits"); - primitiveUnits = /* @__PURE__ */ Symbol("primitiveUnits"); - href = /* @__PURE__ */ Symbol("href"); - x1 = /* @__PURE__ */ Symbol("x1"); - y1 = /* @__PURE__ */ Symbol("y1"); - x2 = /* @__PURE__ */ Symbol("x2"); - y2 = /* @__PURE__ */ Symbol("y2"); - gradientUnits = /* @__PURE__ */ Symbol("gradientUnits"); - gradientTransform = /* @__PURE__ */ Symbol("gradientTransform"); - spreadMethod = /* @__PURE__ */ Symbol("spreadMethod"); - patternUnits = /* @__PURE__ */ Symbol("patternUnits"); - patternContentUnits = /* @__PURE__ */ Symbol("patternContentUnits"); - patternTransform = /* @__PURE__ */ Symbol("patternTransform"); - fx = /* @__PURE__ */ Symbol("fx"); - fy = /* @__PURE__ */ Symbol("fy"); - offset = /* @__PURE__ */ Symbol("offset"); - disabled = /* @__PURE__ */ Symbol("disabled"); - textLength = /* @__PURE__ */ Symbol("textLength"); - lengthAdjust = /* @__PURE__ */ Symbol("lengthAdjust"); - getAttribute = /* @__PURE__ */ Symbol("getAttribute"); - setAttribute = /* @__PURE__ */ Symbol("setAttribute"); - z = /* @__PURE__ */ Symbol("z"); - w = /* @__PURE__ */ Symbol("w"); - toArray = /* @__PURE__ */ Symbol("toArray"); - fromString = /* @__PURE__ */ Symbol("fromString"); - fromArray = /* @__PURE__ */ Symbol("fromArray"); - angle = /* @__PURE__ */ Symbol("angle"); - m11 = /* @__PURE__ */ Symbol("m11"); - m12 = /* @__PURE__ */ Symbol("m12"); - m13 = /* @__PURE__ */ Symbol("m13"); - m14 = /* @__PURE__ */ Symbol("m14"); - m21 = /* @__PURE__ */ Symbol("m21"); - m22 = /* @__PURE__ */ Symbol("m22"); - m23 = /* @__PURE__ */ Symbol("m23"); - m24 = /* @__PURE__ */ Symbol("m24"); - m31 = /* @__PURE__ */ Symbol("m31"); - m32 = /* @__PURE__ */ Symbol("m32"); - m33 = /* @__PURE__ */ Symbol("m33"); - m34 = /* @__PURE__ */ Symbol("m34"); - m41 = /* @__PURE__ */ Symbol("m41"); - m42 = /* @__PURE__ */ Symbol("m42"); - m43 = /* @__PURE__ */ Symbol("m43"); - m44 = /* @__PURE__ */ Symbol("m44"); - setMatrixValue = /* @__PURE__ */ Symbol("setMatrixValue"); - translateSelf = /* @__PURE__ */ Symbol("translateSelf"); - rotateSelf = /* @__PURE__ */ Symbol("rotateSelf"); - rotateAxisAngleSelf = /* @__PURE__ */ Symbol("rotateAxisAngleSelf"); - scaleSelf = /* @__PURE__ */ Symbol("scaleSelf"); - scale3dSelf = /* @__PURE__ */ Symbol("scale3dSelf"); - scaleNonUniformSelf = /* @__PURE__ */ Symbol("scaleNonUniformSelf"); - skewXSelf = /* @__PURE__ */ Symbol("skewXSelf"); - skewYSelf = /* @__PURE__ */ Symbol("skewYSelf"); - multiplySelf = /* @__PURE__ */ Symbol("multiplySelf"); - matrix = /* @__PURE__ */ Symbol("matrix"); - domMatrix = /* @__PURE__ */ Symbol("domMatrix"); - getDOMMatrix = /* @__PURE__ */ Symbol("getDOMMatrix"); - setDOMMatrix = /* @__PURE__ */ Symbol("setDOMMatrix"); - attributeValue = /* @__PURE__ */ Symbol("attributeValue"); - startOffset = /* @__PURE__ */ Symbol("startOffset"); - method = /* @__PURE__ */ Symbol("method"); - spacing = /* @__PURE__ */ Symbol("spacing"); - in1 = /* @__PURE__ */ Symbol("in1"); - in2 = /* @__PURE__ */ Symbol("in2"); - result2 = /* @__PURE__ */ Symbol("result"); - bias = /* @__PURE__ */ Symbol("bias"); - divisor = /* @__PURE__ */ Symbol("divisor"); - edgeMode = /* @__PURE__ */ Symbol("edgeMode"); - kernelMatrix = /* @__PURE__ */ Symbol("kernelMatrix"); - kernelUnitLengthX = /* @__PURE__ */ Symbol("kernelUnitLengthX"); - kernelUnitLengthY = /* @__PURE__ */ Symbol("kernelUnitLengthY"); - orderX = /* @__PURE__ */ Symbol("orderX"); - orderY = /* @__PURE__ */ Symbol("orderY"); - preserveAlpha = /* @__PURE__ */ Symbol("preserveAlpha"); - targetX = /* @__PURE__ */ Symbol("targetX"); - targetY = /* @__PURE__ */ Symbol("targetY"); - diffuseConstant = /* @__PURE__ */ Symbol("diffuseConstant"); - surfaceScale = /* @__PURE__ */ Symbol("surfaceScale"); - scale = /* @__PURE__ */ Symbol("scale"); - xChannelSelector = /* @__PURE__ */ Symbol("xChannelSelector"); - yChannelSelector = /* @__PURE__ */ Symbol("yChannelSelector"); - azimuth = /* @__PURE__ */ Symbol("azimuth"); - elevation = /* @__PURE__ */ Symbol("elevation"); - dx = /* @__PURE__ */ Symbol("dx"); - dy = /* @__PURE__ */ Symbol("dy"); - stdDeviationX = /* @__PURE__ */ Symbol("stdDeviationX"); - stdDeviationY = /* @__PURE__ */ Symbol("stdDeviationY"); - tableValues = /* @__PURE__ */ Symbol("tableValues"); - slope = /* @__PURE__ */ Symbol("slope"); - intercept = /* @__PURE__ */ Symbol("intercept"); - amplitude = /* @__PURE__ */ Symbol("amplitude"); - exponent = /* @__PURE__ */ Symbol("exponent"); - crossOrigin = /* @__PURE__ */ Symbol("crossOrigin"); - operator = /* @__PURE__ */ Symbol("operator"); - radiusX = /* @__PURE__ */ Symbol("radiusX"); - radiusY = /* @__PURE__ */ Symbol("radiusY"); - specularConstant = /* @__PURE__ */ Symbol("specularConstant"); - specularExponent = /* @__PURE__ */ Symbol("specularExponent"); - pointsAtX = /* @__PURE__ */ Symbol("pointsAtX"); - pointsAtY = /* @__PURE__ */ Symbol("pointsAtY"); - pointsAtZ = /* @__PURE__ */ Symbol("pointsAtZ"); - limitingConeAngle = /* @__PURE__ */ Symbol("limitingConeAngle"); - baseFrequencyX = /* @__PURE__ */ Symbol("baseFrequencyX"); - baseFrequencyY = /* @__PURE__ */ Symbol("baseFrequencyY"); - numOctaves = /* @__PURE__ */ Symbol("numOctaves"); - seed = /* @__PURE__ */ Symbol("seed"); - stitchTiles = /* @__PURE__ */ Symbol("stitchTiles"); - rotateFromVectorSelf = /* @__PURE__ */ Symbol("rotateFromVectorSelf"); - flipXSelf = /* @__PURE__ */ Symbol("flipXSelf"); - flipYSelf = /* @__PURE__ */ Symbol("flipYSelf"); - invertSelf = /* @__PURE__ */ Symbol("invertSelf"); - getLength = /* @__PURE__ */ Symbol("getLength"); - currentScale = /* @__PURE__ */ Symbol("currentScale"); - rotate = /* @__PURE__ */ Symbol("rotate"); - bindMethods = /* @__PURE__ */ Symbol("bindMethods"); - xmlProcessingInstruction = /* @__PURE__ */ Symbol("xmlProcessingInstruction"); - root = /* @__PURE__ */ Symbol("root"); - filterNode = /* @__PURE__ */ Symbol("filterNode"); - customElementReactionStack = /* @__PURE__ */ Symbol("customElementReactionStack"); - dispatching = /* @__PURE__ */ Symbol("dispatching"); - modules = /* @__PURE__ */ Symbol("modules"); - preloads = /* @__PURE__ */ Symbol("preloads"); - body = /* @__PURE__ */ Symbol("body"); - redirect = /* @__PURE__ */ Symbol("redirect"); - referrerPolicy = /* @__PURE__ */ Symbol("referrerPolicy"); - signal = /* @__PURE__ */ Symbol("signal"); - bodyUsed = /* @__PURE__ */ Symbol("bodyUsed"); - credentials = /* @__PURE__ */ Symbol("credentials"); - blocking = /* @__PURE__ */ Symbol("blocking"); - moduleImportMap = /* @__PURE__ */ Symbol("moduleImportMap"); - dispatchError = /* @__PURE__ */ Symbol("dispatchError"); - supports = /* @__PURE__ */ Symbol("supports"); - reason = /* @__PURE__ */ Symbol("reason"); - propertyEventListeners = /* @__PURE__ */ Symbol("propertyEventListeners"); - cssRules = /* @__PURE__ */ Symbol("cssRules"); - parentRule = /* @__PURE__ */ Symbol("parentRule"); - parentStyleSheet = /* @__PURE__ */ Symbol("parentStyleSheet"); - conditionText = /* @__PURE__ */ Symbol("conditionText"); - keyText = /* @__PURE__ */ Symbol("keyText"); - media = /* @__PURE__ */ Symbol("media"); - styleMap = /* @__PURE__ */ Symbol("styleMap"); - selectorText = /* @__PURE__ */ Symbol("selectorText"); - cssParser = /* @__PURE__ */ Symbol("cssParser"); - cssRule = /* @__PURE__ */ Symbol("cssRule"); - rulePrefix = /* @__PURE__ */ Symbol("rulePrefix"); - virtualServerFile = /* @__PURE__ */ Symbol("virtualServerFile"); - frames = /* @__PURE__ */ Symbol("frames"); - disableEvaluation = /* @__PURE__ */ Symbol("disableEvaluation"); - validateJavaScriptExecutionEnvironment = /* @__PURE__ */ Symbol("validateJavaScriptExecutionEnvironment"); - currentNode = /* @__PURE__ */ Symbol("currentNode"); - openWebSockets = /* @__PURE__ */ Symbol("openWebSockets"); - webSocket = /* @__PURE__ */ Symbol("webSocket"); - moduleCache = /* @__PURE__ */ Symbol("moduleCache"); - cookieStore = /* @__PURE__ */ Symbol("cookieStore"); - context = /* @__PURE__ */ Symbol("context"); - querySelectorCache = /* @__PURE__ */ Symbol("querySelectorCache"); - } -}); - -// node_modules/happy-dom/lib/cookie/enums/CookieSameSiteEnum.js -var CookieSameSiteEnum, CookieSameSiteEnum_default; -var init_CookieSameSiteEnum = __esm({ - "node_modules/happy-dom/lib/cookie/enums/CookieSameSiteEnum.js"() { - (function(CookieSameSiteEnum2) { - CookieSameSiteEnum2["strict"] = "Strict"; - CookieSameSiteEnum2["lax"] = "Lax"; - CookieSameSiteEnum2["none"] = "None"; - })(CookieSameSiteEnum || (CookieSameSiteEnum = {})); - CookieSameSiteEnum_default = CookieSameSiteEnum; - } -}); - -// node_modules/happy-dom/lib/cookie/DefaultCookie.js -var DefaultCookie_default; -var init_DefaultCookie = __esm({ - "node_modules/happy-dom/lib/cookie/DefaultCookie.js"() { - init_CookieSameSiteEnum(); - DefaultCookie_default = { - // Required - key: null, - originURL: null, - // Optional - value: null, - domain: "", - path: "", - expires: null, - httpOnly: false, - secure: false, - sameSite: CookieSameSiteEnum_default.lax - }; - } -}); - -// node_modules/happy-dom/lib/cookie/urilities/CookieExpireUtility.js -var CookieExpireUtility; -var init_CookieExpireUtility = __esm({ - "node_modules/happy-dom/lib/cookie/urilities/CookieExpireUtility.js"() { - CookieExpireUtility = class { - /** - * Returns "true" if cookie has expired. - * - * @param cookie Cookie. - * @returns "true" if cookie has expired. - */ - static hasExpired(cookie) { - return cookie.expires && cookie.expires.getTime() < Date.now(); - } - }; - } -}); - -// node_modules/happy-dom/lib/cookie/urilities/CookieURLUtility.js -var CookieURLUtility; -var init_CookieURLUtility = __esm({ - "node_modules/happy-dom/lib/cookie/urilities/CookieURLUtility.js"() { - init_CookieSameSiteEnum(); - CookieURLUtility = class { - /** - * Returns "true" if cookie matches URL. - * - * @param cookie Cookie. - * @param url URL. - * @returns "true" if cookie matches URL. - */ - static cookieMatchesURL(cookie, url2) { - const isLocalhost = url2.hostname === "localhost" || url2.hostname?.endsWith(".localhost"); - return (!cookie.secure || url2.protocol === "https:" || isLocalhost) && (!cookie.domain || url2.hostname?.endsWith(cookie.domain)) && (!cookie.path || url2.pathname?.startsWith(cookie.path)) && // @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value - (cookie.sameSite === CookieSameSiteEnum_default.none && cookie.secure || cookie.originURL?.hostname === url2.hostname); - } - }; - } +// src/config/template.ts +var EXAMPLE_CONFIG_YAML; +var init_template = __esm({ + "src/config/template.ts"() { + "use strict"; + EXAMPLE_CONFIG_YAML = `server: + port: 8080 + host: "0.0.0.0" + +auth: + # Key that clients must provide to use the proxy. + # Set to null/omit to disable client auth. + proxyApiKey: "your-proxy-secret" + + # Upstream credentials come from the OAuth login flow \u2014 run this first: + # bun run src/index.ts auth login + # Path to the stored credentials (default shown): + # oauthCredentialsPath: "~/.zcode-proxy/credentials.json" + +# Which upstream provider to use: "zai" or "bigmodel" +provider: zai + +# Which plan tier to use: +# "coding-plan" (default) \u2014 direct upstream endpoints, permanent API key +# "start-plan" \u2014 routes through zcode.z.ai with JWT auth (requires \`auth login\`) +plan: coding-plan + +providers: + zai: + anthropicBase: "https://api.z.ai/api/anthropic" + openaiBase: "https://api.z.ai/api/coding/paas/v4" + bigmodel: + anthropicBase: "https://open.bigmodel.cn/api/anthropic" + openaiBase: "https://open.bigmodel.cn/api/coding/paas/v4" + +defaultModel: glm-4.6 + +models: + - glm-4.5-air + - glm-4.6 + - glm-4.6v + - glm-4.7 + - glm-5 + - glm-5-turbo + - glm-5v-turbo + - glm-5.1 + - glm-5.2 + - glm-5.3 + +# Configurable identity headers injected on every upstream request to mimic the +# ZCode desktop client (User-Agent, X-ZCode-App-Version, X-Title, +# X-ZCode-Agent, HTTP-Referer). Runtime platform headers (X-Platform, +# X-Os-Category, X-Os-Version) are detected dynamically and are not configured +# here. All fields below are optional; env vars override YAML, which overrides +# defaults. +identity: + # Mirrors process.env.ZCODE_APP_VERSION in the ZCode bundle. + # Must be printable ASCII; non-conforming values fall back to the default. + # Default: "3.10.0" (current ZCode release). Override to match your real client. + appVersion: "3.10.0" + # X-Title suffix \u2192 "Z Code@{sourceTitle}". Default "cli". + sourceTitle: "cli" + # HTTP-Referer URL. Default "https://zcode.z.ai". + refererOrigin: "https://zcode.z.ai" + # Device identity (X-Device-Mid) \u2014 random UUIDv4, generated ONCE and reused + # forever (mirrors ZCode's telemetry deviceMid; no hardware values involved). + # Auto-generated into this file at first \`auth login\` or config creation. + # Leave empty on Android \u2014 the app injects ZCODE_IDENTITY_DEVICE_MID instead. + deviceMid: "" + +# Local client-session inference for cache-affinity experiments. +# "observe" (default) logs inferred sessions in debug mode but does not change +# upstream x-session-id. "enforce" reuses a stable x-session-id for inferred +# coding-plan sessions. "off" disables inference entirely. +clientIdentity: + mode: observe + ttlSeconds: 900 + maxSessions: 1024 + +# Server-controlled upstream URL remapping (mirrors the ZCode client's +# ProviderEndpointRoutingService). The proxy periodically fetches +# {origin}/api/v1/agent/configs and rewrites matching upstream URLs per the +# returned proxyEndpoint.mapping table (currently the coding-plan Anthropic +# endpoints -> zcode.z.ai ultra endpoints). Fail-open: any fetch/parse error +# keeps the original URLs. Env override: ZCODE_ENDPOINT_ROUTING=false. +endpointRouting: + enabled: true + origin: "https://zcode.z.ai" + +# Client request signing V4 (mirrors the ZCode 3.9.1 ClientRequestSigningV4Signer). +# When enabled, the proxy probes {origin}/api/v1/agent/configs (cached 1h) and, +# only if the server sets data.codingPlanSignature.enable=true, signs coding-plan +# requests: handshake against {provider}/api/paas/c1f3a7e2/v2/client, Ed25519 +# signature + proof-of-work headers on every request, fail-open retry ladder +# (two 401 VERIFY rejections -> permanent unsigned bypass). Start-plan and +# off-peak paths are never signed. Env override: ZCODE_CLIENT_SIGNING=false. +clientSigning: + enabled: true + origin: "https://zcode.z.ai" + +logging: + level: info +`; + } }); -// node_modules/happy-dom/lib/cookie/CookieContainer.js -var CookieContainer; -var init_CookieContainer = __esm({ - "node_modules/happy-dom/lib/cookie/CookieContainer.js"() { - init_DefaultCookie(); - init_CookieExpireUtility(); - init_CookieURLUtility(); - CookieContainer = class { - #cookies = []; - /** - * Adds or replaces cookies. - * - * @param cookies Cookies. - * @returns Changed cookies. - */ - addCookies(cookies) { - const changedCookies = { - changed: [], - deleted: [] - }; - const allCookies = this.#cookies; - for (const cookie of cookies) { - const newCookie = Object.assign({}, DefaultCookie_default, cookie); - if (newCookie && newCookie.key && newCookie.originURL) { - const hasExpired = CookieExpireUtility.hasExpired(newCookie); - for (let i = 0, max = allCookies.length; i < max; i++) { - const existingCookie = allCookies[i]; - if (existingCookie.key === newCookie.key && existingCookie.originURL.hostname === newCookie.originURL.hostname && existingCookie.path === newCookie.path && typeof existingCookie.value === typeof newCookie.value) { - if (hasExpired) { - changedCookies.deleted.push(existingCookie); - } - allCookies.splice(i, 1); - break; - } - } - if (!hasExpired) { - allCookies.push(newCookie); - changedCookies.changed.push(newCookie); - } - } - } - return changedCookies; - } - /** - * Returns cookies. - * - * @param [url] URL. - * @param [clientSide] "true" if "httpOnly" cookies should be filtered out. - * @returns Cookies. - */ - getCookies(url2 = null, clientSide = false) { - const cookies = []; - for (const cookie of this.#cookies) { - if (!CookieExpireUtility.hasExpired(cookie) && (!clientSide || !cookie.httpOnly) && (!url2 || CookieURLUtility.cookieMatchesURL(cookie, url2))) { - cookies.push(cookie); +// src/auth/manager.ts +var AuthManager; +var init_manager = __esm({ + "src/auth/manager.ts"() { + "use strict"; + AuthManager = class { + oauthCred = null; + /** Returns the current credential, refreshing if necessary. */ + async getCredential() { + if (this.oauthCred) { + if (this.oauthCred.expiresAt && Date.now() >= this.oauthCred.expiresAt) { + this.oauthCred = null; + throw new Error("OAuth credential expired; re-authentication required \u2014 run: zcode-proxy auth login"); } + return this.oauthCred; } - return cookies; - } - /** - * Clears all cookies. - */ - clearCookies() { - this.#cookies = []; + throw new Error("OAuth credential not available \u2014 run: zcode-proxy auth login"); } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/cache/response/CachedResponseStateEnum.js -var CachedResponseStateEnum, CachedResponseStateEnum_default; -var init_CachedResponseStateEnum = __esm({ - "node_modules/happy-dom/lib/fetch/cache/response/CachedResponseStateEnum.js"() { - (function(CachedResponseStateEnum2) { - CachedResponseStateEnum2["fresh"] = "fresh"; - CachedResponseStateEnum2["stale"] = "stale"; - })(CachedResponseStateEnum || (CachedResponseStateEnum = {})); - CachedResponseStateEnum_default = CachedResponseStateEnum; - } -}); - -// node_modules/happy-dom/lib/exception/DOMExceptionNameEnum.js -var DOMExceptionNameEnum, DOMExceptionNameEnum_default; -var init_DOMExceptionNameEnum = __esm({ - "node_modules/happy-dom/lib/exception/DOMExceptionNameEnum.js"() { - (function(DOMExceptionNameEnum2) { - DOMExceptionNameEnum2["invalidStateError"] = "InvalidStateError"; - DOMExceptionNameEnum2["indexSizeError"] = "IndexSizeError"; - DOMExceptionNameEnum2["syntaxError"] = "SyntaxError"; - DOMExceptionNameEnum2["hierarchyRequestError"] = "HierarchyRequestError"; - DOMExceptionNameEnum2["notSupportedError"] = "NotSupportedError"; - DOMExceptionNameEnum2["wrongDocumentError"] = "WrongDocumentError"; - DOMExceptionNameEnum2["invalidNodeTypeError"] = "InvalidNodeTypeError"; - DOMExceptionNameEnum2["invalidCharacterError"] = "InvalidCharacterError"; - DOMExceptionNameEnum2["notFoundError"] = "NotFoundError"; - DOMExceptionNameEnum2["securityError"] = "SecurityError"; - DOMExceptionNameEnum2["networkError"] = "NetworkError"; - DOMExceptionNameEnum2["domException"] = "DOMException"; - DOMExceptionNameEnum2["invalidAccessError"] = "InvalidAccessError"; - DOMExceptionNameEnum2["unknownError"] = "UnknownError"; - DOMExceptionNameEnum2["abortError"] = "AbortError"; - DOMExceptionNameEnum2["timeoutError"] = "TimeoutError"; - DOMExceptionNameEnum2["encodingError"] = "EncodingError"; - DOMExceptionNameEnum2["uriMismatchError"] = "URIMismatchError"; - DOMExceptionNameEnum2["inUseAttributeError"] = "InUseAttributeError"; - DOMExceptionNameEnum2["namespaceError"] = "NamespaceError"; - })(DOMExceptionNameEnum || (DOMExceptionNameEnum = {})); - DOMExceptionNameEnum_default = DOMExceptionNameEnum; - } -}); - -// node_modules/happy-dom/lib/exception/DOMException.js -var DOMException2; -var init_DOMException = __esm({ - "node_modules/happy-dom/lib/exception/DOMException.js"() { - init_DOMExceptionNameEnum(); - DOMException2 = class extends Error { - /** - * Constructor. - * - * @param message Message. - * @param name Name. - */ - constructor(message, name2 = null) { - super(message); - this.name = name2 || DOMExceptionNameEnum_default.domException; + /** Set the OAuth credential (used by the `auth login` flow). */ + setOAuthCredential(cred) { + this.oauthCred = cred; } }; } }); -// node_modules/happy-dom/lib/fetch/Headers.js -var Headers2; -var init_Headers = __esm({ - "node_modules/happy-dom/lib/fetch/Headers.js"() { - init_DOMException(); - init_PropertySymbol(); - init_DOMExceptionNameEnum(); - Headers2 = class _Headers { - [entries] = {}; - /** - * Constructor. - * - * @param init Headers init. - */ - constructor(init) { - if (init) { - if (init instanceof _Headers) { - this[entries] = JSON.parse(JSON.stringify(init[entries])); - } else if (Array.isArray(init)) { - for (const entry of init) { - if (entry.length !== 2) { - throw new DOMException2('Failed to construct "Headers": The provided init is not a valid array.', DOMExceptionNameEnum_default.invalidStateError); - } - this.append(entry[0], entry[1]); - } - } else { - for (const name2 of Object.keys(init)) { - this.set(name2, init[name2]); - } - } - } - } - /** - * Appends a new value onto an existing header inside a Headers object, or adds the header if it does not already exist. - * - * @param name Name. - * @param value Value. - */ - append(name2, value2) { - const lowerName = name2.toLowerCase(); - if (this[entries][lowerName]) { - this[entries][lowerName].value.push(value2); - } else { - this[entries][lowerName] = { - name: name2, - value: [value2] - }; - } - } - /** - * Removes an header. - * - * @param name Name. - */ - delete(name2) { - delete this[entries][name2.toLowerCase()]; - } - /** - * Returns header value. - * - * @param name Name. - * @returns Value. - */ - get(name2) { - return this[entries][name2.toLowerCase()]?.value.join(", ") ?? null; - } - /** - * Sets a new value for an existing header inside a Headers object, or adds the header if it does not already exist. - * - * @param name Name. - * @param value Value. - */ - set(name2, value2) { - this[entries][name2.toLowerCase()] = { - name: name2, - value: [value2] - }; - } - /** - * Returns an array containing the values of all Set-Cookie headers associated with a response. - * - * @returns An array of strings representing the values of all the different Set-Cookie headers. - */ - getSetCookie() { - const entry = this[entries]["set-cookie"]; - if (!entry) { - return []; - } - return entry.value; - } - /** - * Returns whether an Headers object contains a certain key. - * - * @param name Name. - * @returns "true" if the Headers object contains the key. - */ - has(name2) { - return !!this[entries][name2.toLowerCase()]; - } - /** - * Executes a callback function once per each key/value pair in the Headers object. - * - * @param callback Callback. - * @param thisArg thisArg. - */ - forEach(callback, thisArg) { - const thisArgValue = thisArg ?? this[window]; - for (const header of Object.values(this[entries])) { - callback.call(thisArgValue, header.value.join(", "), header.name, this); - } - } - /** - * Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object. - * - * @returns Iterator. - */ - *keys() { - for (const header of Object.values(this[entries])) { - yield header.name; - } - } - /** - * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. - * - * @returns Iterator. - */ - *values() { - for (const header of Object.values(this[entries])) { - yield header.value.join(", "); - } - } - /** - * Returns an iterator, allowing you to go through all key/value pairs contained in this object. - * - * @returns Iterator. - */ - *entries() { - for (const header of Object.values(this[entries])) { - yield [header.name, header.value.join(", ")]; - } - } - /** - * Iterator. - * - * @returns Iterator. - */ - *[Symbol.iterator]() { - for (const header of Object.values(this[entries])) { - yield [header.name, header.value.join(", ")]; - } - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/cache/response/ResponseCacheFileSystem.js -var import_fs, import_path, import_crypto, ResponseCacheFileSystem; -var init_ResponseCacheFileSystem = __esm({ - "node_modules/happy-dom/lib/fetch/cache/response/ResponseCacheFileSystem.js"() { - init_Headers(); - import_fs = __toESM(require("fs"), 1); - import_path = __toESM(require("path"), 1); - import_crypto = __toESM(require("crypto"), 1); - ResponseCacheFileSystem = class { - #createdDirectories = /* @__PURE__ */ new Set(); - #hashes = /* @__PURE__ */ new Set(); - #entries; - /** - * Constructor. - * - * @param entries Map of URL to cached responses. - */ - constructor(entries2) { - this.#entries = entries2; - } - /** - * Loads cache from file system. - * - * @param directory Directory to load from. - */ - async load(directory) { - if (!directory) { - throw new Error("Failed to execute 'load' on 'ResponseCacheFileSystem': Directory is not specified."); - } - const absoluteDirectory = import_path.default.resolve(directory); - let files2 = []; - try { - files2 = await import_fs.default.promises.readdir(absoluteDirectory); - } catch (error2) { - return; - } - const promises = []; - const entries2 = this.#entries; - for (const file of files2) { - if (file.endsWith(".json")) { - promises.push(import_fs.default.promises.readFile(import_path.default.join(absoluteDirectory, file), "utf8").then((content2) => { - const cachedResponse2 = JSON.parse(content2); - if (cachedResponse2.response && cachedResponse2.request && !cachedResponse2.virtual) { - cachedResponse2.response.headers = new Headers2(cachedResponse2.response.headers); - cachedResponse2.request.headers = new Headers2(cachedResponse2.request.headers); - return import_fs.default.promises.readFile(import_path.default.join(absoluteDirectory, file.split(".")[0] + ".data")).then((body2) => { - cachedResponse2.response.body = body2; - let entry = entries2.get(cachedResponse2.response.url); - if (!entry) { - entry = []; - entries2.set(cachedResponse2.response.url, entry); - } - entry.push(cachedResponse2); - }).catch(() => { - let entry = entries2.get(cachedResponse2.response.url); - if (!entry) { - entry = []; - entries2.set(cachedResponse2.response.url, entry); - } - entry.push(cachedResponse2); - }); - } - }).catch(() => { - })); - } - } - await Promise.all(promises); - } - /** - * Saves the cache to file system. - * - * @param directory Directory to store to. - */ - async save(directory) { - if (!directory) { - throw new Error("Failed to execute 'store' on 'ResponseCacheFileSystem': Directory is not specified."); - } - if (!this.#entries.size) { - return; - } - const absoluteDirectory = import_path.default.resolve(directory); - const isDirectoryCreated = this.#createdDirectories.has(absoluteDirectory); - if (!isDirectoryCreated) { - this.#createdDirectories.add(absoluteDirectory); - try { - await import_fs.default.promises.mkdir(absoluteDirectory, { - recursive: true - }); - } catch (error2) { - } - } - const entries2 = this.#entries; - const promises = []; - for (const entry of entries2.values()) { - for (const cachedResponse2 of entry) { - if (!cachedResponse2.virtual) { - const responseHeaders = {}; - const requestHeaders = {}; - for (const [key, value2] of cachedResponse2.response.headers.entries()) { - responseHeaders[key] = value2; - } - for (const [key, value2] of cachedResponse2.request.headers.entries()) { - requestHeaders[key] = value2; - } - const cacheableEntry = { - ...cachedResponse2, - response: { - ...cachedResponse2.response, - headers: responseHeaders, - body: null - }, - request: { - ...cachedResponse2.request, - headers: requestHeaders - } - }; - const json = JSON.stringify(cacheableEntry, null, 3); - const hash = import_crypto.default.createHash("md5").update(json).digest("hex"); - if (!this.#hashes.has(hash)) { - this.#hashes.add(hash); - promises.push(import_fs.default.promises.writeFile(import_path.default.join(absoluteDirectory, `${hash}.json`), json)); - if (cachedResponse2.response.body) { - promises.push(import_fs.default.promises.writeFile(import_path.default.join(absoluteDirectory, `${hash}.data`), cachedResponse2.response.body)); - } - } - } - } - } - await Promise.all(promises); - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/cache/response/ResponseCache.js -var UPDATE_RESPONSE_HEADERS, ResponseCache; -var init_ResponseCache = __esm({ - "node_modules/happy-dom/lib/fetch/cache/response/ResponseCache.js"() { - init_CachedResponseStateEnum(); - init_Headers(); - init_ResponseCacheFileSystem(); - UPDATE_RESPONSE_HEADERS = ["Cache-Control", "Last-Modified", "Vary", "ETag"]; - ResponseCache = class { - fileSystem; - #entries = /* @__PURE__ */ new Map(); - /** - * Constructor. - */ - constructor() { - this.fileSystem = new ResponseCacheFileSystem(this.#entries); - } - /** - * Returns cached response. - * - * @param request Request. - * @returns Cached response. - */ - get(request) { - if (request.headers.get("Cache-Control")?.includes("no-cache")) { - return null; - } - const url2 = request.url; - const entries2 = this.#entries.get(url2); - if (entries2) { - for (let i = 0, max = entries2.length; i < max; i++) { - const entry = entries2[i]; - let isMatch = entry.request.method === request.method; - if (isMatch) { - for (const header of Object.keys(entry.vary)) { - const requestHeader = request.headers.get(header); - if (requestHeader !== null && entry.vary[header] !== requestHeader) { - isMatch = false; - break; - } - } - } - if (isMatch) { - if (entry.expires && entry.expires < Date.now()) { - if (entry.lastModified) { - entry.state = CachedResponseStateEnum_default.stale; - } else if (!entry.etag) { - entries2.splice(i, 1); - return null; - } - } - return entry; - } - } - } - return null; - } - /** - * Adds a cache entity. - * - * @param request Request. - * @param response Response. - * @returns Cached response. - */ - add(request, response) { - if (request.method !== "GET" && request.method !== "HEAD" || request.headers.get("Cache-Control")?.includes("no-cache")) { - return null; - } - const url2 = request.url; - let cachedResponse2 = this.get(request); - if (response.status === 304) { - if (!cachedResponse2) { - throw new Error("ResponseCache: Cached response not found."); - } - for (const name2 of UPDATE_RESPONSE_HEADERS) { - if (response.headers.has(name2)) { - cachedResponse2.response.headers.set(name2, response.headers.get(name2)); - } - } - cachedResponse2.cacheUpdateTime = Date.now(); - cachedResponse2.state = CachedResponseStateEnum_default.fresh; - } else { - if (cachedResponse2) { - const entries3 = this.#entries.get(url2); - if (entries3) { - const index = entries3.indexOf(cachedResponse2); - if (index !== -1) { - entries3.splice(index, 1); - } - } - } - cachedResponse2 = { - response: { - status: response.status, - statusText: response.statusText, - url: response.url, - headers: new Headers2(response.headers), - // We need to wait for the body to be consumed and then populated if set to true (e.g. by using Response.text()). - waitingForBody: response.waitingForBody, - body: response.body ?? null - }, - request: { - headers: request.headers, - method: request.method - }, - vary: {}, - expires: null, - etag: null, - cacheUpdateTime: Date.now(), - lastModified: null, - mustRevalidate: false, - staleWhileRevalidate: false, - state: CachedResponseStateEnum_default.fresh, - virtual: response.virtual ?? false - }; - let entries2 = this.#entries.get(url2); - if (!entries2) { - entries2 = []; - this.#entries.set(url2, entries2); - } - entries2.push(cachedResponse2); - } - if (response.headers.has("Cache-Control")) { - const age = response.headers.get("Age"); - for (const part of response.headers.get("Cache-Control").split(",")) { - const [key, value2] = part.trim().split("="); - switch (key) { - case "max-age": - cachedResponse2.expires = Date.now() + parseFloat(value2) * 1e3 - (age ? parseFloat(age) * 1e3 : 0); - break; - case "no-cache": - case "no-store": - const entries2 = this.#entries.get(url2); - if (entries2) { - const index = entries2.indexOf(cachedResponse2); - if (index !== -1) { - entries2.splice(index, 1); - } - } - return null; - case "must-revalidate": - cachedResponse2.mustRevalidate = true; - break; - case "stale-while-revalidate": - cachedResponse2.staleWhileRevalidate = true; - break; - } - } - } - if (response.headers.has("Last-Modified")) { - cachedResponse2.lastModified = Date.parse(response.headers.get("Last-Modified")); - } - if (response.headers.has("Vary")) { - for (const header of response.headers.get("Vary").split(",")) { - const name2 = header.trim(); - const value2 = request.headers.get(name2); - if (value2) { - cachedResponse2.vary[name2] = value2; - } - } - } - if (response.headers.has("ETag")) { - cachedResponse2.etag = response.headers.get("ETag"); - } - if (!cachedResponse2.expires) { - const expires = response.headers.get("Expires"); - if (expires) { - cachedResponse2.expires = Date.parse(expires); - } - } - if (!cachedResponse2.etag && (!cachedResponse2.expires || cachedResponse2.expires < Date.now())) { - const entries2 = this.#entries.get(url2); - if (entries2) { - const index = entries2.indexOf(cachedResponse2); - if (index !== -1) { - entries2.splice(index, 1); - } - } - return null; - } - return cachedResponse2; - } - /** - * Clears the cache. - * - * @param [options] Options. - * @param [options.url] URL. - * @param [options.toTime] Removes all entries that are older than this time. Time in MS. - */ - clear(options2) { - if (options2) { - if (options2.toTime) { - for (const key of options2.url ? [options2.url] : this.#entries.keys()) { - const entry = this.#entries.get(key); - if (entry) { - for (let i = 0, max = entry.length; i < max; i++) { - if (entry[i].cacheUpdateTime < options2.toTime) { - entry.splice(i, 1); - i--; - max--; - } - } - } - } - } else if (options2.url) { - this.#entries.delete(options2.url); - } - } else { - this.#entries.clear(); - } - } - }; - } -}); - -// node_modules/happy-dom/lib/console/enums/VirtualConsoleLogLevelEnum.js -var VirtualConsoleLogLevelEnum, VirtualConsoleLogLevelEnum_default; -var init_VirtualConsoleLogLevelEnum = __esm({ - "node_modules/happy-dom/lib/console/enums/VirtualConsoleLogLevelEnum.js"() { - (function(VirtualConsoleLogLevelEnum2) { - VirtualConsoleLogLevelEnum2[VirtualConsoleLogLevelEnum2["log"] = 0] = "log"; - VirtualConsoleLogLevelEnum2[VirtualConsoleLogLevelEnum2["info"] = 1] = "info"; - VirtualConsoleLogLevelEnum2[VirtualConsoleLogLevelEnum2["warn"] = 2] = "warn"; - VirtualConsoleLogLevelEnum2[VirtualConsoleLogLevelEnum2["error"] = 3] = "error"; - })(VirtualConsoleLogLevelEnum || (VirtualConsoleLogLevelEnum = {})); - VirtualConsoleLogLevelEnum_default = VirtualConsoleLogLevelEnum; - } -}); - -// node_modules/happy-dom/lib/nodes/node/NodeTypeEnum.js -var NodeTypeEnum, NodeTypeEnum_default; -var init_NodeTypeEnum = __esm({ - "node_modules/happy-dom/lib/nodes/node/NodeTypeEnum.js"() { - (function(NodeTypeEnum2) { - NodeTypeEnum2[NodeTypeEnum2["elementNode"] = 1] = "elementNode"; - NodeTypeEnum2[NodeTypeEnum2["attributeNode"] = 2] = "attributeNode"; - NodeTypeEnum2[NodeTypeEnum2["textNode"] = 3] = "textNode"; - NodeTypeEnum2[NodeTypeEnum2["cdataSectionNode"] = 4] = "cdataSectionNode"; - NodeTypeEnum2[NodeTypeEnum2["commentNode"] = 8] = "commentNode"; - NodeTypeEnum2[NodeTypeEnum2["documentNode"] = 9] = "documentNode"; - NodeTypeEnum2[NodeTypeEnum2["documentTypeNode"] = 10] = "documentTypeNode"; - NodeTypeEnum2[NodeTypeEnum2["documentFragmentNode"] = 11] = "documentFragmentNode"; - NodeTypeEnum2[NodeTypeEnum2["processingInstructionNode"] = 7] = "processingInstructionNode"; - })(NodeTypeEnum || (NodeTypeEnum = {})); - NodeTypeEnum_default = NodeTypeEnum; - } -}); - -// node_modules/happy-dom/lib/event/EventPhaseEnum.js -var EventPhaseEnum, EventPhaseEnum_default; -var init_EventPhaseEnum = __esm({ - "node_modules/happy-dom/lib/event/EventPhaseEnum.js"() { - (function(EventPhaseEnum2) { - EventPhaseEnum2[EventPhaseEnum2["none"] = 0] = "none"; - EventPhaseEnum2[EventPhaseEnum2["capturing"] = 1] = "capturing"; - EventPhaseEnum2[EventPhaseEnum2["atTarget"] = 2] = "atTarget"; - EventPhaseEnum2[EventPhaseEnum2["bubbling"] = 3] = "bubbling"; - })(EventPhaseEnum || (EventPhaseEnum = {})); - EventPhaseEnum_default = EventPhaseEnum; - } -}); - -// node_modules/happy-dom/lib/event/Event.js -var Event2; -var init_Event = __esm({ - "node_modules/happy-dom/lib/event/Event.js"() { - init_PropertySymbol(); - init_NodeTypeEnum(); - init_EventPhaseEnum(); - Event2 = class _Event { - static NONE = EventPhaseEnum_default.none; - static CAPTURING_PHASE = EventPhaseEnum_default.capturing; - static AT_TARGET = EventPhaseEnum_default.atTarget; - static BUBBLING_PHASE = EventPhaseEnum_default.bubbling; - NONE = _Event.NONE; - CAPTURING_PHASE = _Event.CAPTURING_PHASE; - AT_TARGET = _Event.AT_TARGET; - BUBBLING_PHASE = _Event.BUBBLING_PHASE; - [composed] = false; - [bubbles] = false; - [cancelable] = false; - [defaultPrevented] = false; - [eventPhase] = EventPhaseEnum_default.none; - [timeStamp] = performance.now(); - [type]; - [dispatching] = false; - [immediatePropagationStopped] = false; - [propagationStopped] = false; - [target] = null; - [currentTarget] = null; - [isInPassiveEventListener] = false; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - this[type] = type2; - this[bubbles] = eventInit?.bubbles ?? false; - this[cancelable] = eventInit?.cancelable ?? false; - this[composed] = eventInit?.composed ?? false; - } - /** - * Returns composed. - * - * @returns Composed. - */ - get composed() { - return this[composed]; - } - /** - * Returns bubbles. - * - * @returns Bubbles. - */ - get bubbles() { - return this[bubbles]; - } - /** - * Returns cancelable. - * - * @returns Cancelable. - */ - get cancelable() { - return this[cancelable]; - } - /** - * Returns defaultPrevented. - * - * @returns Default prevented. - */ - get defaultPrevented() { - return this[defaultPrevented]; - } - /** - * Returns eventPhase. - * - * @returns Event phase. - */ - get eventPhase() { - return this[eventPhase]; - } - /** - * Returns timeStamp. - * - * @returns Time stamp. - */ - get timeStamp() { - return this[timeStamp]; - } - /** - * Returns type. - * - * @returns Type. - */ - get type() { - return this[type]; - } - /** - * Returns target. - * - * @returns Target. - */ - get target() { - return this[target]; - } - /** - * Returns target. - * - * @returns Target. - */ - get currentTarget() { - return this[currentTarget]; - } - /** - * Returns "true" if propagation has been stopped. - * - * @returns "true" if propagation has been stopped. - */ - get cancelBubble() { - return this[propagationStopped]; - } - /** - * Returns composed path. - * - * @returns Composed path. - */ - composedPath() { - if (!this[target]) { - return []; - } - const composedPath = []; - let eventTarget = this[target]; - while (eventTarget) { - composedPath.push(eventTarget); - if (eventTarget.parentNode) { - eventTarget = eventTarget.parentNode; - } else if (this[composed] && eventTarget[nodeType] === NodeTypeEnum_default.documentFragmentNode && eventTarget.host) { - eventTarget = eventTarget.host; - } else if (eventTarget[nodeType] === NodeTypeEnum_default.documentNode && // The "load" event is a special case. It should not bubble up to the window. - this[type] !== "load") { - eventTarget = eventTarget[window]; - } else { - break; - } - } - return composedPath; - } - /** - * Init event. - * - * @deprecated - * @param type Type. - * @param [bubbles=false] "true" if it bubbles. - * @param [cancelable=false] "true" if it cancelable. - */ - initEvent(type2, bubbles2 = false, cancelable2 = false) { - this[type] = type2; - this[bubbles] = bubbles2; - this[cancelable] = cancelable2; - this[propagationStopped] = false; - this[immediatePropagationStopped] = false; - this[defaultPrevented] = false; - } - /** - * Prevents default. - */ - preventDefault() { - if (!this[isInPassiveEventListener] && this.cancelable) { - this[defaultPrevented] = true; - } - } - /** - * Stops immediate propagation. - */ - stopImmediatePropagation() { - this[immediatePropagationStopped] = true; - } - /** - * Stops propagation. - */ - stopPropagation() { - this[propagationStopped] = true; - } - }; - } -}); - -// node_modules/happy-dom/lib/console/enums/VirtualConsoleLogTypeEnum.js -var VirtualConsoleLogTypeEnum, VirtualConsoleLogTypeEnum_default; -var init_VirtualConsoleLogTypeEnum = __esm({ - "node_modules/happy-dom/lib/console/enums/VirtualConsoleLogTypeEnum.js"() { - (function(VirtualConsoleLogTypeEnum2) { - VirtualConsoleLogTypeEnum2["log"] = "log"; - VirtualConsoleLogTypeEnum2["table"] = "table"; - VirtualConsoleLogTypeEnum2["trace"] = "trace"; - VirtualConsoleLogTypeEnum2["dir"] = "dir"; - VirtualConsoleLogTypeEnum2["dirxml"] = "dirxml"; - VirtualConsoleLogTypeEnum2["group"] = "group"; - VirtualConsoleLogTypeEnum2["groupCollapsed"] = "groupCollapsed"; - VirtualConsoleLogTypeEnum2["debug"] = "debug"; - VirtualConsoleLogTypeEnum2["timeLog"] = "timeLog"; - VirtualConsoleLogTypeEnum2["info"] = "info"; - VirtualConsoleLogTypeEnum2["count"] = "count"; - VirtualConsoleLogTypeEnum2["timeEnd"] = "timeEnd"; - VirtualConsoleLogTypeEnum2["warn"] = "warn"; - VirtualConsoleLogTypeEnum2["countReset"] = "countReset"; - VirtualConsoleLogTypeEnum2["error"] = "error"; - VirtualConsoleLogTypeEnum2["assert"] = "assert"; - })(VirtualConsoleLogTypeEnum || (VirtualConsoleLogTypeEnum = {})); - VirtualConsoleLogTypeEnum_default = VirtualConsoleLogTypeEnum; - } -}); - -// node_modules/happy-dom/lib/console/utilities/VirtualConsoleLogEntryStringifier.js -var VirtualConsoleLogEntryStringifier; -var init_VirtualConsoleLogEntryStringifier = __esm({ - "node_modules/happy-dom/lib/console/utilities/VirtualConsoleLogEntryStringifier.js"() { - init_VirtualConsoleLogTypeEnum(); - VirtualConsoleLogEntryStringifier = class { - /** - * Stringifies a log entry. - * - * @param logEntry Log entry. - * @returns Stringified message. - */ - static toString(logEntry) { - if (this.isLogEntryCollapsed(logEntry)) { - return ""; - } - const tabbing = this.getLogEntryGroupTabbing(logEntry); - let output = tabbing; - for (const part of logEntry.message) { - output += output !== "" && output !== tabbing ? " " : ""; - if (typeof part === "object" && (part === null || part.constructor.name === "Object" || Array.isArray(part))) { - try { - output += JSON.stringify(part); - } catch (error2) { - output += new Error("Failed to JSON stringify object in log entry.").stack.replace(/\n at/gm, "\n " + tabbing + "at"); - } - } else if (typeof part === "object" && part["message"] && part["stack"]) { - output += part["stack"].replace(/\n at/gm, "\n " + tabbing + "at"); - } else { - output += this.getLogEntryIcon(logEntry) + String(part); - } - } - return output + "\n"; - } - /** - * Gets the log entry icon. - * - * @param logEntry Log entry. - * @returns Icon. - */ - static getLogEntryIcon(logEntry) { - switch (logEntry.type) { - case VirtualConsoleLogTypeEnum_default.group: - return "\u25BC "; - case VirtualConsoleLogTypeEnum_default.groupCollapsed: - return "\u25B6 "; - } - return ""; - } - /** - * Gets the log entry group tabbing. - * - * @param logEntry Log entry. - * @returns Tabbing. - */ - static getLogEntryGroupTabbing(logEntry) { - let tabs = ""; - let group = logEntry.type === VirtualConsoleLogTypeEnum_default.group || logEntry.type === VirtualConsoleLogTypeEnum_default.groupCollapsed ? logEntry.group?.parent : logEntry.group; - while (group) { - tabs += " "; - group = group.parent; - } - return tabs; - } - /** - * Checks if the log entry content is collapsed. - * - * @param logEntry Log entry. - * @returns True if collapsed. - */ - static isLogEntryCollapsed(logEntry) { - let group = logEntry.type === VirtualConsoleLogTypeEnum_default.group || logEntry.type === VirtualConsoleLogTypeEnum_default.groupCollapsed ? logEntry.group?.parent : logEntry.group; - while (group) { - if (group.collapsed) { - return true; - } - group = group.parent; - } - return false; - } - }; - } -}); - -// node_modules/happy-dom/lib/console/VirtualConsolePrinter.js -var VirtualConsolePrinter; -var init_VirtualConsolePrinter = __esm({ - "node_modules/happy-dom/lib/console/VirtualConsolePrinter.js"() { - init_VirtualConsoleLogLevelEnum(); - init_Event(); - init_VirtualConsoleLogEntryStringifier(); - VirtualConsolePrinter = class { - #logEntries = []; - #listeners = { print: [], clear: [] }; - #closed = false; - /** - * Returns closed state. - * - * @returns True if the printer is closed. - */ - get closed() { - return this.#closed; - } - /** - * Writes to the output. - * - * @param logEntry Log entry. - */ - print(logEntry) { - if (this.#closed) { - return; - } - this.#logEntries.push(logEntry); - this.dispatchEvent(new Event2("print")); - } - /** - * Clears the output. - */ - clear() { - if (this.#closed) { - return; - } - this.#logEntries = []; - this.dispatchEvent(new Event2("clear")); - } - /** - * Clears and closes the virtual console printer. - */ - close() { - if (this.#closed) { - return; - } - this.#logEntries = []; - this.#listeners = { print: [], clear: [] }; - this.#closed = true; - } - /** - * Adds an event listener. - * - * @param eventType Event type ("print" or "clear"). - * @param listener Listener. - */ - addEventListener(eventType, listener) { - if (this.#closed) { - return; - } - if (!this.#listeners[eventType]) { - throw new Error(`Event type "${eventType}" is not supported.`); - } - this.#listeners[eventType].push(listener); - } - /** - * Removes an event listener. - * - * @param eventType Event type ("print" or "clear"). - * @param listener Listener. - */ - removeEventListener(eventType, listener) { - if (this.#closed) { - return; - } - if (!this.#listeners[eventType]) { - throw new Error(`Event type "${eventType}" is not supported.`); - } - const index = this.#listeners[eventType].indexOf(listener); - if (index !== -1) { - this.#listeners[eventType].splice(index, 1); - } - } - /** - * Dispatches an event. - * - * @param event Event. - */ - dispatchEvent(event) { - if (this.#closed) { - return; - } - switch (event.type) { - case "print": - case "clear": - for (const listener of this.#listeners[event.type]) { - listener(event); - } - break; - default: - throw new Error(`Event type "${event.type}" is not supported.`); - } - } - /** - * Reads the buffer. - * - * @returns Console log entries. - */ - read() { - const logEntries = this.#logEntries; - this.#logEntries = []; - return logEntries; - } - /** - * Returns the buffer as a string. - * - * @param [logLevel] Log level. - * @returns Buffer as a string of concatenated log entries. - */ - readAsString(logLevel = VirtualConsoleLogLevelEnum_default.log) { - const logEntries = this.read(); - let output = ""; - for (const logEntry of logEntries) { - if (logEntry.level >= logLevel) { - output += VirtualConsoleLogEntryStringifier.toString(logEntry); - } - } - return output; - } - }; - } -}); - -// node_modules/happy-dom/lib/async-task-manager/AsyncTaskManagerDebugError.js -var AsyncTaskManagerDebugError; -var init_AsyncTaskManagerDebugError = __esm({ - "node_modules/happy-dom/lib/async-task-manager/AsyncTaskManagerDebugError.js"() { - AsyncTaskManagerDebugError = class extends Error { - /** - * Constructor. - * - * @param message Message. - */ - constructor(message) { - super(message); - this.name = "AsyncTaskManagerDebugError"; - } - }; - } -}); - -// node_modules/happy-dom/lib/async-task-manager/AsyncTaskManager.js -var TIMER, AsyncTaskManager; -var init_AsyncTaskManager = __esm({ - "node_modules/happy-dom/lib/async-task-manager/AsyncTaskManager.js"() { - init_AsyncTaskManagerDebugError(); - TIMER = { - setTimeout: globalThis.setTimeout.bind(globalThis), - clearTimeout: globalThis.clearTimeout.bind(globalThis), - clearImmediate: globalThis.clearImmediate.bind(globalThis) - }; - AsyncTaskManager = class { - static taskID = 0; - runningTasks = {}; - runningTaskCount = 0; - runningTimers = []; - runningImmediates = []; - debugTrace = /* @__PURE__ */ new Map(); - waitUntilCompleteTimer = null; - waitUntilCompleteResolvers = []; - destroyed = false; - #debugTimeout = null; - #browserFrame; - /** - * Constructor. - * - * @param browserFrame Browser frame. - */ - constructor(browserFrame) { - this.#browserFrame = browserFrame; - } - /** - * Returns a promise that is resolved when async tasks are complete. - * - * @returns Promise. - */ - waitUntilComplete() { - return new Promise((resolve, reject) => { - this.waitUntilCompleteResolvers.push({ resolve, reject }); - this.resolveWhenComplete(); - }); - } - /** - * Aborts all tasks. - */ - abort() { - if (this.destroyed) { - return new Promise((resolve, reject) => { - this.waitUntilCompleteResolvers.push({ resolve, reject }); - this.resolveWhenComplete(); - }); - } - return this.abortAll(false); - } - /** - * Destroys the manager. - */ - destroy() { - if (this.destroyed) { - return new Promise((resolve, reject) => { - this.waitUntilCompleteResolvers.push({ resolve, reject }); - this.resolveWhenComplete(); - }); - } - return this.abortAll(true); - } - /** - * Starts a timer. - * - * @param timerID Timer ID. - */ - startTimer(timerID) { - if (this.destroyed) { - TIMER.clearTimeout(timerID); - return; - } - if (this.waitUntilCompleteTimer) { - TIMER.clearTimeout(this.waitUntilCompleteTimer); - this.waitUntilCompleteTimer = null; - } - this.runningTimers.push(timerID); - if (this.#browserFrame.page.context.browser.settings.debug.traceWaitUntilComplete > 0) { - this.debugTrace.set(timerID, new AsyncTaskManagerDebugError().stack); - } - } - /** - * Ends a timer. - * - * @param timerID Timer ID. - */ - endTimer(timerID) { - if (this.destroyed) { - TIMER.clearTimeout(timerID); - return; - } - const index = this.runningTimers.indexOf(timerID); - if (index !== -1) { - this.runningTimers.splice(index, 1); - this.resolveWhenComplete(); - } - if (this.#browserFrame.page.context.browser.settings.debug.traceWaitUntilComplete > 0) { - this.debugTrace.delete(timerID); - } - } - /** - * Starts an immediate. - * - * @param immediateID Immediate ID. - */ - startImmediate(immediateID) { - if (this.destroyed) { - TIMER.clearImmediate(immediateID); - return; - } - if (this.waitUntilCompleteTimer) { - TIMER.clearTimeout(this.waitUntilCompleteTimer); - this.waitUntilCompleteTimer = null; - } - this.runningImmediates.push(immediateID); - if (this.#browserFrame.page?.context?.browser?.settings?.debug?.traceWaitUntilComplete > 0) { - this.debugTrace.set(immediateID, new AsyncTaskManagerDebugError().stack); - } - } - /** - * Ends an immediate. - * - * @param immediateID Immediate ID. - */ - endImmediate(immediateID) { - if (this.destroyed) { - TIMER.clearImmediate(immediateID); - return; - } - const index = this.runningImmediates.indexOf(immediateID); - if (index !== -1) { - this.runningImmediates.splice(index, 1); - this.resolveWhenComplete(); - } - if (this.#browserFrame.page.context.browser.settings.debug.traceWaitUntilComplete > 0) { - this.debugTrace.delete(immediateID); - } - } - /** - * Starts an async task. - * - * @param abortHandler Abort handler. - * @returns Task ID. - */ - startTask(abortHandler) { - if (this.destroyed) { - if (abortHandler) { - abortHandler(this.destroyed); - } - throw new this.#browserFrame.window.Error(`Failed to execute 'startTask()' on 'AsyncTaskManager': The asynchronous task manager has been destroyed. This error can be thrown if scripts continue to run while a browser frame is closed.`); - } - if (this.waitUntilCompleteTimer) { - TIMER.clearTimeout(this.waitUntilCompleteTimer); - this.waitUntilCompleteTimer = null; - } - const taskID = this.newTaskID(); - this.runningTasks[taskID] = abortHandler ? abortHandler : () => { - }; - this.runningTaskCount++; - if (this.#browserFrame.page.context.browser.settings.debug.traceWaitUntilComplete > 0) { - this.debugTrace.set(taskID, new AsyncTaskManagerDebugError().stack); - } - return taskID; - } - /** - * Ends an async task. - * - * @param taskID Task ID. - */ - endTask(taskID) { - if (this.destroyed) { - return; - } - if (this.runningTasks[taskID]) { - delete this.runningTasks[taskID]; - this.runningTaskCount--; - this.resolveWhenComplete(); - } - if (this.#browserFrame.page.context.browser.settings.debug.traceWaitUntilComplete > 0) { - this.debugTrace.delete(taskID); - } - } - /** - * Returns the amount of running tasks. - * - * @returns Count. - */ - getTaskCount() { - return this.runningTaskCount; - } - /** - * Returns a new task ID. - * - * @returns Task ID. - */ - newTaskID() { - this.constructor.taskID++; - return this.constructor.taskID; - } - /** - * Resolves when complete. - */ - resolveWhenComplete() { - this.applyDebugging(); - if (this.runningTaskCount || this.runningTimers.length || this.runningImmediates.length) { - return; - } - if (this.waitUntilCompleteTimer) { - TIMER.clearTimeout(this.waitUntilCompleteTimer); - this.waitUntilCompleteTimer = null; - } - this.waitUntilCompleteTimer = TIMER.setTimeout(() => { - this.waitUntilCompleteTimer = null; - if (!this.runningTaskCount && !this.runningTimers.length && !this.runningImmediates.length) { - if (this.#debugTimeout) { - TIMER.clearTimeout(this.#debugTimeout); - } - const resolvers = this.waitUntilCompleteResolvers; - this.waitUntilCompleteResolvers = []; - for (const resolver of resolvers) { - resolver.resolve(); - } - this.destroyed = false; - } else { - this.applyDebugging(); - } - }, 1); - } - /** - * Applies debugging. - */ - applyDebugging() { - const debug = this.#browserFrame.page.context.browser.settings.debug; - if (!debug?.traceWaitUntilComplete || debug.traceWaitUntilComplete < 1) { - return; - } - if (this.#debugTimeout) { - return; - } - this.#debugTimeout = TIMER.setTimeout(() => { - this.#debugTimeout = null; - let errorMessage = `The maximum time was reached for "waitUntilComplete()". - -${this.debugTrace.size} task${this.debugTrace.size === 1 ? "" : "s"} did not end in time. - -The following traces were recorded: - -`; - let number = 1; - for (const [key, value2] of this.debugTrace.entries()) { - const type2 = typeof key === "number" ? "Task" : "Timer"; - errorMessage += `${type2} #${number} -\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E${value2.replace(/AsyncTaskManagerDebugError:{0,1}/, "").replace(/\s+at /gm, "\n> ")} - -`; - number++; - } - const error2 = new Error(errorMessage); - for (const resolver of this.waitUntilCompleteResolvers) { - resolver.reject(error2); - } - this.abortAll(true); - }, debug.traceWaitUntilComplete); - } - /** - * Aborts all tasks. - * - * @param destroy Destroy. - */ - abortAll(destroy2) { - const runningTimers = this.runningTimers; - const runningImmediates = this.runningImmediates; - const runningTasks = this.runningTasks; - if (destroy2) { - this.destroyed = true; - } - this.runningTasks = {}; - this.runningTaskCount = 0; - this.runningImmediates = []; - this.runningTimers = []; - this.debugTrace = /* @__PURE__ */ new Map(); - if (this.waitUntilCompleteTimer) { - TIMER.clearTimeout(this.waitUntilCompleteTimer); - this.waitUntilCompleteTimer = null; - } - for (const immediate of runningImmediates) { - TIMER.clearImmediate(immediate); - } - for (const timer of runningTimers) { - TIMER.clearTimeout(timer); - } - for (const key of Object.keys(runningTasks)) { - runningTasks[key](destroy2); - } - return new Promise((resolve, reject) => { - this.waitUntilCompleteResolvers.push({ resolve, reject }); - this.resolveWhenComplete(); - }); - } - }; - } -}); - -// node_modules/happy-dom/lib/base64/Base64.js -var BASE64_CHARS, Base64; -var init_Base64 = __esm({ - "node_modules/happy-dom/lib/base64/Base64.js"() { - init_DOMException(); - init_DOMExceptionNameEnum(); - BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; - Base64 = class { - /** - * Creates a Base64-encoded ASCII string from a binary string (i.e., a string in which each character in the string is treated as a byte of binary data). - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/btoa - * @param data Binay data. - * @returns Base64-encoded string. - */ - static btoa(data2) { - const str = data2.toString(); - if (/[^\u0000-\u00ff]/.test(str)) { - throw new DOMException2("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.", DOMExceptionNameEnum_default.invalidCharacterError); - } - let t = ""; - let p = -6; - let a = 0; - let i = 0; - let v = 0; - let c; - while (i < str.length || p > -6) { - if (p < 0) { - if (i < str.length) { - c = str.charCodeAt(i++); - v += 8; - } else { - c = 0; - } - a = (a & 255) << 8 | c & 255; - p += 8; - } - t += BASE64_CHARS.charAt(v > 0 ? a >> p & 63 : 64); - p -= 6; - v -= 6; - } - return t; - } - /** - * Decodes a string of data which has been encoded using Base64 encoding. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/atob - * @see https://infra.spec.whatwg.org/#forgiving-base64-encode. - * @see Https://html.spec.whatwg.org/multipage/webappapis.html#btoa. - * @param data Binay string. - * @returns An ASCII string containing decoded data from encodedData. - */ - static atob(data2) { - const str = data2.toString(); - if (/[^\u0000-\u00ff]/.test(str)) { - throw new DOMException2("Failed to execute 'atob' on 'Window': The string to be decoded contains characters outside of the Latin1 range.", DOMExceptionNameEnum_default.invalidCharacterError); - } - if (/[^A-Za-z\d+/=]/.test(str) || str.length % 4 == 1) { - throw new DOMException2("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.", DOMExceptionNameEnum_default.invalidCharacterError); - } - let t = ""; - let p = -8; - let a = 0; - let c; - let d; - for (let i = 0; i < str.length; i++) { - if ((c = BASE64_CHARS.indexOf(str.charAt(i))) < 0) { - continue; - } - a = a << 6 | c & 63; - if ((p += 6) >= 0) { - d = a >> p & 255; - if (c !== 64) { - t += String.fromCharCode(d); - } - a &= 63; - p -= 8; - } - } - return t; - } - }; - } -}); - -// node_modules/happy-dom/lib/browser/enums/BrowserErrorCaptureEnum.js -var BrowserErrorCaptureEnum, BrowserErrorCaptureEnum_default; -var init_BrowserErrorCaptureEnum = __esm({ - "node_modules/happy-dom/lib/browser/enums/BrowserErrorCaptureEnum.js"() { - (function(BrowserErrorCaptureEnum2) { - BrowserErrorCaptureEnum2["tryAndCatch"] = "tryAndCatch"; - BrowserErrorCaptureEnum2["processLevel"] = "processLevel"; - BrowserErrorCaptureEnum2["disabled"] = "disabled"; - })(BrowserErrorCaptureEnum || (BrowserErrorCaptureEnum = {})); - BrowserErrorCaptureEnum_default = BrowserErrorCaptureEnum; - } -}); - -// node_modules/happy-dom/lib/file/Blob.js -var import_buffer, import_web, Blob2; -var init_Blob = __esm({ - "node_modules/happy-dom/lib/file/Blob.js"() { - import_buffer = require("buffer"); - import_web = require("stream/web"); - init_PropertySymbol(); - Blob2 = class _Blob { - type = ""; - [buffer]; - /** - * Constructor. - * - * @param [bits] Bits. - * @param [options] Options. - * @param [options.type] MIME type. - */ - constructor(bits, options2) { - const buffers = []; - if (bits) { - for (const bit of bits) { - let buffer2; - if (bit instanceof ArrayBuffer) { - buffer2 = import_buffer.Buffer.from(new Uint8Array(bit)); - } else if (bit instanceof _Blob) { - buffer2 = bit[buffer]; - } else if (bit instanceof import_buffer.Buffer) { - buffer2 = bit; - } else if (ArrayBuffer.isView(bit)) { - buffer2 = import_buffer.Buffer.from(new Uint8Array(bit.buffer, bit.byteOffset, bit.byteLength)); - } else { - buffer2 = import_buffer.Buffer.from(typeof bit === "string" ? bit : String(bit)); - } - buffers.push(buffer2); - } - } - this[buffer] = import_buffer.Buffer.concat(buffers); - if (options2 && options2.type && options2.type.match(/^[\u0020-\u007E]*$/)) { - this.type = String(options2.type).toLowerCase(); - } - } - /** - * Returns size. - * - * @returns Size. - */ - get size() { - return this[buffer].length; - } - /** - * Slices the blob. - * - * @param start Start. - * @param end End. - * @param contentType Content type. - * @returns New Blob. - */ - slice(start2 = 0, end2 = null, contentType2 = "") { - const size = this.size; - let relativeStart; - let relativeEnd; - let relativeContentType; - if (start2 === void 0) { - relativeStart = 0; - } else if (start2 < 0) { - relativeStart = Math.max(size + start2, 0); - } else { - relativeStart = Math.min(start2, size); - } - if (end2 === null) { - relativeEnd = size; - } else if (end2 < 0) { - relativeEnd = Math.max(size + end2, 0); - } else { - relativeEnd = Math.min(end2, size); - } - if (contentType2 === void 0) { - relativeContentType = ""; - } else { - relativeContentType = contentType2; - } - const span = Math.max(relativeEnd - relativeStart, 0); - const buffer2 = this[buffer]; - const slicedBuffer = buffer2.slice(relativeStart, relativeStart + span); - const blob = new _Blob([], { type: relativeContentType }); - blob[buffer] = slicedBuffer; - return blob; - } - /** - * Returns a Promise that resolves to a ArrayBuffer. - * - * @returns ArrayBuffer. - */ - // Reference: - // https://github.com/web-std/io/blob/c88170bf24f064adfbb3586a21fb76650ca5a9ab/packages/blob/src/blob.js#L139-L148 - // https://stackoverflow.com/questions/8609289/convert-a-binary-nodejs-buffer-to-javascript-arraybuffer - /** - * - */ - async arrayBuffer() { - return new Uint8Array(this[buffer]).buffer; - } - /** - * Returns a Promise that resolves to a text. - * - * @returns Text. - */ - async text() { - return this[buffer].toString(); - } - /** - * Returns returns a ReadableStream which upon reading returns the data contained within the Blob. - * - * @returns ReadableStream - */ - stream() { - const buffer2 = this[buffer]; - return new import_web.ReadableStream({ - start(controller) { - controller.enqueue(buffer2); - controller.close(); - } - }); - } - /** - * Returns the object converted to string. - * - * @returns String. - */ - toString() { - return "[object Blob]"; - } - }; - } -}); - -// node_modules/happy-dom/lib/clipboard/Clipboard.js -var Clipboard; -var init_Clipboard = __esm({ - "node_modules/happy-dom/lib/clipboard/Clipboard.js"() { - init_Blob(); - Clipboard = class { - #window; - #data = []; - /** - * Constructor. - * - * @param window Owner window. - */ - constructor(window2) { - if (!window2) { - throw new TypeError("Illegal constructor"); - } - this.#window = window2; - } - /** - * Returns data. - * - * @returns Data. - */ - async read() { - const permissionStatus = await this.#window.navigator.permissions.query({ - name: "clipboard-read" - }); - if (permissionStatus.state === "denied") { - throw new this.#window.DOMException(`Failed to execute 'read' on 'Clipboard': The request is not allowed`); - } - return this.#data; - } - /** - * Returns text. - * - * @returns Text. - */ - async readText() { - const permissionStatus = await this.#window.navigator.permissions.query({ - name: "clipboard-read" - }); - if (permissionStatus.state === "denied") { - throw new this.#window.DOMException(`Failed to execute 'readText' on 'Clipboard': The request is not allowed`); - } - let text = ""; - for (const item of this.#data) { - if (item.types.includes("text/plain")) { - const data2 = await item.getType("text/plain"); - if (typeof data2 === "string") { - text += data2; - } else { - text += await data2.text(); - } - } - } - return text; - } - /** - * Writes data. - * - * @param data Data. - */ - async write(data2) { - const permissionStatus = await this.#window.navigator.permissions.query({ - name: "clipboard-write" - }); - if (permissionStatus.state === "denied") { - throw new this.#window.DOMException(`Failed to execute 'write' on 'Clipboard': The request is not allowed`); - } - this.#data = data2; - } - /** - * Writes text. - * - * @param text Text. - */ - async writeText(text) { - const permissionStatus = await this.#window.navigator.permissions.query({ - name: "clipboard-write" - }); - if (permissionStatus.state === "denied") { - throw new this.#window.DOMException(`Failed to execute 'writeText' on 'Clipboard': The request is not allowed`); - } - this.#data = [ - new this.#window.ClipboardItem({ "text/plain": new Blob2([text], { type: "text/plain" }) }) - ]; - } - }; - } -}); - -// node_modules/happy-dom/lib/clipboard/ClipboardItem.js -var ClipboardItem; -var init_ClipboardItem = __esm({ - "node_modules/happy-dom/lib/clipboard/ClipboardItem.js"() { - init_DOMException(); - init_Blob(); - ClipboardItem = class { - presentationStyle = "unspecified"; - #data; - /** - * Constructor. - * - * @param data Data. - * @param [options] Options. - * @param [options.presentationStyle] Presentation style. - */ - constructor(data2, options2) { - this.#data = data2; - if (options2?.presentationStyle) { - this.presentationStyle = options2.presentationStyle; - } - } - /** - * Returns types. - * - * @returns Types. - */ - get types() { - return Object.keys(this.#data); - } - /** - * Returns data by type. - * - * @param type Type. - * @returns Data. - */ - async getType(type2) { - if (!this.#data[type2]) { - throw new DOMException2(`Failed to execute 'getType' on 'ClipboardItem': The type '${type2}' was not found`); - } - if (this.#data[type2] instanceof Blob2) { - return this.#data[type2]; - } - return new Blob2([await this.#data[type2]], { type: type2 }); - } - }; - } -}); - -// node_modules/happy-dom/lib/window/WindowBrowserContext.js -var WindowBrowserContext; -var init_WindowBrowserContext = __esm({ - "node_modules/happy-dom/lib/window/WindowBrowserContext.js"() { - init_PropertySymbol(); - WindowBrowserContext = class { - static [browserFrames] = /* @__PURE__ */ new Map(); - static [windowInternalId] = 0; - #window; - /** - * Browser window. - * - * @param window Window. - */ - constructor(window2) { - this.#window = window2; - } - /** - * Returns the browser settings of the window. - * - * @returns Browser settings. - */ - getSettings() { - return this.getBrowserFrame()?.page.context.browser.settings || null; - } - /** - * Returns the browser. - * - * @returns Browser. - */ - getBrowser() { - return this.getBrowserFrame()?.page.context.browser || null; - } - /** - * Returns the browser page. - * - * @returns Browser page. - */ - getBrowserPage() { - return this.getBrowserFrame()?.page || null; - } - /** - * Returns the browser context. - * - * @returns Browser context. - */ - getBrowserContext() { - return this.getBrowserFrame()?.page.context || null; - } - /** - * Returns the browser frame of the window. - * - * @returns Browser frame. - */ - getBrowserFrame() { - if (!this.#window) { - return null; - } - return this.constructor[browserFrames].get(this.#window[internalId]) || null; - } - /** - * Returns the async task manager of the window. - * - * @returns Async task manager. - */ - getAsyncTaskManager() { - return this.getBrowserFrame()?.[asyncTaskManager] || null; - } - /** - * Assigns the window to a browser frame. - * - * @param window Window. - * @param browserFrame Browser frame. - */ - static setWindowBrowserFrameRelation(window2, browserFrame) { - const browserFrames2 = this[browserFrames]; - if (window2[internalId] === -1) { - window2[internalId] = this[windowInternalId]; - this[windowInternalId]++; - } - browserFrames2.set(window2[internalId], browserFrame); - } - /** - * Assigns the window to a browser frame. - * - * @param window Window. - * @param browserFrame Browser frame. - */ - static removeWindowBrowserFrameRelation(window2) { - this[browserFrames].delete(window2[internalId]); - } - }; - } -}); - -// node_modules/happy-dom/lib/event/EventTarget.js -var EventTarget2; -var init_EventTarget = __esm({ - "node_modules/happy-dom/lib/event/EventTarget.js"() { - init_PropertySymbol(); - init_Event(); - init_EventPhaseEnum(); - init_WindowBrowserContext(); - init_BrowserErrorCaptureEnum(); - EventTarget2 = class { - [listeners] = { - capturing: /* @__PURE__ */ new Map(), - bubbling: /* @__PURE__ */ new Map() - }; - [listenerOptions] = { - capturing: /* @__PURE__ */ new Map(), - bubbling: /* @__PURE__ */ new Map() - }; - /** - * Return a default description for the EventTarget class. - */ - get [Symbol.toStringTag]() { - return "EventTarget"; - } - /** - * Adds an event listener. - * - * @param type Event type. - * @param listener Listener. - * @param options An object that specifies characteristics about the event listener.(currently only once) - * @param options.once - * @param options.signal An AbortSignal. The listener will be removed when the given AbortSignal object's abort() method is called. - */ - addEventListener(type2, listener, options2) { - options2 = typeof options2 === "boolean" ? { capture: options2 } : options2 || {}; - const eventPhase2 = options2.capture ? "capturing" : "bubbling"; - let listeners2 = this[listeners][eventPhase2].get(type2); - let listenerOptions2; - if (listeners2) { - listenerOptions2 = this[listenerOptions][eventPhase2].get(type2); - } else { - listeners2 = []; - listenerOptions2 = []; - this[listeners][eventPhase2].set(type2, listeners2); - this[listenerOptions][eventPhase2].set(type2, listenerOptions2); - } - if (listeners2.includes(listener)) { - return; - } - listeners2.push(listener); - listenerOptions2.push(options2); - if (options2.signal && !options2.signal.aborted) { - options2.signal.addEventListener("abort", () => { - this.removeEventListener(type2, listener); - }); - } - } - /** - * Adds an event listener. - * - * @param type Event type. - * @param listener Listener. - */ - removeEventListener(type2, listener) { - const bubblingListeners = this[listeners].bubbling.get(type2); - if (bubblingListeners) { - const index = bubblingListeners.indexOf(listener); - if (index !== -1) { - bubblingListeners.splice(index, 1); - this[listenerOptions].bubbling.get(type2).splice(index, 1); - return; - } - } - const capturingListeners = this[listeners].capturing.get(type2); - if (capturingListeners) { - const index = capturingListeners.indexOf(listener); - if (index !== -1) { - capturingListeners.splice(index, 1); - this[listenerOptions].capturing.get(type2).splice(index, 1); - } - } - } - /** - * Dispatches an event. - * - * @see https://www.w3.org/TR/DOM-Level-3-Events/#event-flow - * @see https://www.quirksmode.org/js/events_order.html#link4 - * @param event Event. - * @returns The return value is false if event is cancelable and at least one of the event handlers which handled this event called Event.preventDefault(). - */ - dispatchEvent(event) { - if (!(event instanceof Event2)) { - throw new this[window].TypeError(`Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'.`); - } - if (!event[dispatching] && (event[type] !== "load" || !event[target])) { - event[dispatching] = true; - event[target] = this[proxy] || this; - this.#goThroughDispatchEventPhases(event); - event[dispatching] = false; - return !(event[cancelable] && event[defaultPrevented]); - } - this.#callDispatchEventListeners(event); - return !(event[cancelable] && event[defaultPrevented]); - } - /** - * Adds an event listener. - * - * TODO: - * Was used by with IE8- and Opera. React believed Happy DOM was a legacy browser and used them, but that is no longer the case, so we should remove this method after that this is verified. - * - * @deprecated - * @param type Event type. - * @param listener Listener. - */ - attachEvent(type2, listener) { - this.addEventListener(type2.replace("on", ""), listener); - } - /** - * Removes an event listener. - * - * TODO: - * Was used by IE8- and Opera. React believed Happy DOM was a legacy browser and used them, but that is no longer the case, so we should remove this method after that this is verified. - * - * @deprecated - * @param type Event type. - * @param listener Listener. - */ - detachEvent(type2, listener) { - this.removeEventListener(type2.replace("on", ""), listener); - } - /** - * Destroys the node. - */ - [destroy]() { - this[listeners].capturing.clear(); - this[listeners].bubbling.clear(); - this[listenerOptions].capturing.clear(); - this[listenerOptions].bubbling.clear(); - } - /** - * Goes through dispatch event phases. - * - * @param event Event. - */ - #goThroughDispatchEventPhases(event) { - const composedPath = event.composedPath(); - event[eventPhase] = EventPhaseEnum_default.capturing; - for (let i = composedPath.length - 1; i >= 0; i--) { - event[currentTarget] = composedPath[i]; - composedPath[i].dispatchEvent(event); - if (event[propagationStopped] || event[immediatePropagationStopped]) { - event[eventPhase] = EventPhaseEnum_default.none; - event[currentTarget] = null; - return; - } - } - event[eventPhase] = EventPhaseEnum_default.atTarget; - event[currentTarget] = this[proxy] || this; - event[target].dispatchEvent(event); - event[eventPhase] = EventPhaseEnum_default.bubbling; - if (event[bubbles] && !event[propagationStopped] && !event[immediatePropagationStopped]) { - for (let i = 1, max = composedPath.length; i < max; i++) { - event[currentTarget] = composedPath[i]; - composedPath[i].dispatchEvent(event); - if (event[propagationStopped] || event[immediatePropagationStopped]) { - event[eventPhase] = EventPhaseEnum_default.none; - event[currentTarget] = null; - return; - } - } - } - event[eventPhase] = EventPhaseEnum_default.none; - event[currentTarget] = null; - } - /** - * Handles dispatch event listeners. - * - * @param event Event. - */ - #callDispatchEventListeners(event) { - const window2 = this[window]; - const browserSettings = window2 ? new WindowBrowserContext(window2).getSettings() : null; - const eventPhase2 = event.eventPhase === EventPhaseEnum_default.capturing ? "capturing" : "bubbling"; - const listeners2 = this[listeners][eventPhase2].get(event.type)?.slice(); - if (listeners2 && listeners2.length) { - const listenerOptions2 = this[listenerOptions][eventPhase2].get(event.type).slice(); - for (let i = 0, max = listeners2.length; i < max; i++) { - const listener = listeners2[i]; - const options2 = listenerOptions2[i]; - if (options2?.passive) { - event[isInPassiveEventListener] = true; - } - if (window2 && (this !== window2 || event.type !== "error") && !browserSettings?.disableErrorCapturing && browserSettings?.errorCapture === BrowserErrorCaptureEnum_default.tryAndCatch) { - if (listener.handleEvent) { - let result3; - try { - result3 = listener.handleEvent.call(listener, event); - } catch (error2) { - window2[dispatchError](error2); - } - if (result3 instanceof Promise) { - result3.catch((error2) => window2[dispatchError](error2)); - } - } else { - let result3; - try { - result3 = listener.call(this, event); - } catch (error2) { - window2[dispatchError](error2); - } - if (result3 instanceof Promise) { - result3.catch((error2) => window2[dispatchError](error2)); - } - } - } else { - if (listener.handleEvent) { - listener.handleEvent.call(listener, event); - } else { - listener.call(this, event); - } - } - event[isInPassiveEventListener] = false; - if (options2?.once) { - listeners2.splice(i, 1); - listenerOptions2.splice(i, 1); - this.removeEventListener(event.type, listener); - i--; - max--; - } - if (event[immediatePropagationStopped]) { - return; - } - } - } - if (event.eventPhase !== EventPhaseEnum_default.capturing) { - const onEventName = "on" + event.type.toLowerCase(); - const propertyEventListeners2 = this[propertyEventListeners]; - const hasClassDefinedHandler = !propertyEventListeners2 && Object.hasOwn(this, onEventName) && this.constructor.name !== "EventTarget"; - if (propertyEventListeners2 || hasClassDefinedHandler) { - const eventListener = propertyEventListeners2?.get(onEventName) ?? this[onEventName]; - if (typeof eventListener === "function") { - if (window2 && (this !== window2 || event.type !== "error") && !browserSettings?.disableErrorCapturing && browserSettings?.errorCapture === BrowserErrorCaptureEnum_default.tryAndCatch) { - let result3; - try { - result3 = eventListener(event); - } catch (error2) { - window2[dispatchError](error2); - } - if (result3 instanceof Promise) { - result3.catch((error2) => window2[dispatchError](error2)); - } - } else { - eventListener(event); - } - } - } - } - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/CookieChangeEvent.js -var CookieChangeEvent; -var init_CookieChangeEvent = __esm({ - "node_modules/happy-dom/lib/event/events/CookieChangeEvent.js"() { - init_Event(); - CookieChangeEvent = class extends Event2 { - changed; - deleted; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.changed = eventInit?.changed ?? []; - this.deleted = eventInit?.deleted ?? []; - } - }; - } -}); - -// node_modules/happy-dom/lib/url/URL.js -var import_url, import_buffer2, URL2; -var init_URL = __esm({ - "node_modules/happy-dom/lib/url/URL.js"() { - import_url = require("url"); - init_PropertySymbol(); - import_buffer2 = require("buffer"); - init_Blob(); - URL2 = class extends import_url.URL { - /** - * Constructor. - * - * @param url URL. - * @param [base] Base URL. - */ - constructor(url2, base) { - try { - super(url2, base); - } catch (error2) { - super("about:blank"); - if (this[window]) { - throw new this[window].TypeError("Invalid URL"); - } - throw error2; - } - } - /** - * Creates a string containing a URL representing the object given in the parameter. - * - * @param object Object. - * @returns URL. - */ - static createObjectURL(object) { - if (object instanceof Blob2) { - const blob = new import_buffer2.Blob([object[buffer]], { type: object.type }); - return super.createObjectURL(blob); - } - return super.createObjectURL(object); - } - }; - } -}); - -// node_modules/happy-dom/lib/cookie-store/CookieStore.js -var CookieStore; -var init_CookieStore = __esm({ - "node_modules/happy-dom/lib/cookie-store/CookieStore.js"() { - init_EventTarget(); - init_DOMExceptionNameEnum(); - init_CookieSameSiteEnum(); - init_CookieChangeEvent(); - init_URL(); - init_WindowBrowserContext(); - init_PropertySymbol(); - CookieStore = class extends EventTarget2 { - // Internal properties - #window; - /** - * Constructor. - * - * @param illegalConstructorSymbol Illegal constructor symbol. - * @param window Window. - */ - constructor(illegalConstructorSymbol, window2) { - super(); - if (illegalConstructorSymbol !== illegalConstructor) { - throw new TypeError("Illegal constructor"); - } - this.#window = window2; - } - /** - * Returns a cookie. - * - * @param [nameOrOptions] Name or options. - * @returns Cookie. - */ - async get(nameOrOptions) { - const cookies = await this.getAll(nameOrOptions); - return cookies.length > 0 ? cookies[0] : null; - } - /** - * Returns all cookies. - * - * @param [nameOrOptions] Name or options. - * @returns Cookies. - */ - async getAll(nameOrOptions) { - const browserFrame = new WindowBrowserContext(this.#window).getBrowserFrame(); - if (!browserFrame) { - return []; - } - const options2 = typeof nameOrOptions === "string" ? { name: nameOrOptions } : nameOrOptions || {}; - let targetURL; - if (options2.url) { - targetURL = new URL2(options2.url, this.#window.location.href); - if (targetURL.origin !== this.#window.location.origin) { - throw new this.#window.DOMException(`Failed to execute 'getAll' on 'CookieStore': URL must match the document origin`, DOMExceptionNameEnum_default.securityError); - } - } else { - targetURL = this.#window.location; - } - const internalCookies = browserFrame.page.context.cookieContainer.getCookies(targetURL, true); - const result3 = []; - for (const cookie of internalCookies) { - if (!options2.name || cookie.key === options2.name) { - result3.push(this.#convertToStoreItem(cookie)); - } - } - return result3; - } - /** - * Sets a cookie. - * - * @param nameOrOptions Name or options. - * @param [value] Value. - * @returns Promise. - */ - async set(nameOrOptions, value2) { - const browserFrame = new WindowBrowserContext(this.#window).getBrowserFrame(); - if (!browserFrame) { - return; - } - let options2; - if (typeof nameOrOptions === "string") { - if (value2 === void 0) { - throw new this.#window.TypeError(`Failed to execute 'set' on 'CookieStore': Value is required when name is provided as a string.`); - } - options2 = { name: nameOrOptions, value: value2 }; - } else { - options2 = { ...nameOrOptions, value: nameOrOptions.value ?? "" }; - } - if (!options2.name) { - throw new this.#window.TypeError(`Failed to execute 'set' on 'CookieStore': Required member name is undefined.`); - } - const originURL = this.#window.location; - let expires = null; - if (options2.expires !== void 0 && options2.expires !== null) { - expires = options2.expires instanceof Date ? options2.expires : new Date(options2.expires); - } - let sameSite = CookieSameSiteEnum_default.strict; - if (options2.sameSite) { - switch (options2.sameSite.toLowerCase()) { - case "strict": - sameSite = CookieSameSiteEnum_default.strict; - break; - case "lax": - sameSite = CookieSameSiteEnum_default.lax; - break; - case "none": - sameSite = CookieSameSiteEnum_default.none; - break; - } - } - const cookie = { - key: options2.name, - value: options2.value ?? "", - originURL, - domain: options2.domain || "", - path: options2.path || "/", - expires, - httpOnly: false, - // CookieStore API cannot set httpOnly cookies - secure: true, - sameSite - }; - const cookieContainer = browserFrame.page.context.cookieContainer; - const changedCookies = cookieContainer.addCookies([cookie]); - if (changedCookies.changed.length > 0 || changedCookies.deleted.length > 0) { - this.dispatchEvent(new CookieChangeEvent("change", { - changed: changedCookies.changed.map((cookie2) => this.#convertToStoreItem(cookie2)), - deleted: changedCookies.deleted.map((cookie2) => this.#convertToStoreItem(cookie2)) - })); - } - } - /** - * Deletes a cookie. - * - * @param nameOrOptions Name or options. - * @returns Promise. - */ - async delete(nameOrOptions) { - const options2 = typeof nameOrOptions === "string" ? { name: nameOrOptions } : nameOrOptions; - await this.set({ - name: options2.name, - value: "", - domain: options2.domain ?? void 0, - path: options2.path, - partitioned: options2.partitioned, - expires: /* @__PURE__ */ new Date(0) - }); - } - /** - * Converts an internal cookie to a CookieStore item. - * - * @param cookie Internal cookie. - * @returns CookieStore item. - */ - #convertToStoreItem(cookie) { - let sameSite = "lax"; - switch (cookie.sameSite) { - case CookieSameSiteEnum_default.strict: - sameSite = "strict"; - break; - case CookieSameSiteEnum_default.lax: - sameSite = "lax"; - break; - case CookieSameSiteEnum_default.none: - sameSite = "none"; - break; - } - return { - name: cookie.key, - value: cookie.value ?? "", - domain: cookie.domain, - path: cookie.path, - expires: cookie.expires ? cookie.expires.getTime() : null, - secure: cookie.secure, - sameSite, - partitioned: false - // Not supported yet - }; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/utilities/CSSEscaper.js -var CSSEscaper; -var init_CSSEscaper = __esm({ - "node_modules/happy-dom/lib/css/utilities/CSSEscaper.js"() { - CSSEscaper = class { - /** - * Escapes CSS. - * - * Based on: - * https://github.com/mathiasbynens/CSS.escape - * - * @param cssText CSS. - * @returns Escaped CSS. - */ - static escape(cssText2) { - if (arguments.length == 0) { - throw new TypeError("`CSS.escape` requires an argument."); - } - const returnValue2 = String(cssText2); - const length2 = returnValue2.length; - let index = -1; - let codeUnit; - let result3 = ""; - const firstCodeUnit = returnValue2.charCodeAt(0); - if ( - // If the character is the first character and is a `-` (U+002D), and - // There is no second character, […] - length2 == 1 && firstCodeUnit == 45 - ) { - return "\\" + returnValue2; - } - while (++index < length2) { - codeUnit = returnValue2.charCodeAt(index); - if (codeUnit == 0) { - result3 += "\uFFFD"; - continue; - } - if ( - // If the character is in the range [\1-\1F] (U+0001 to U+001F) or is - // U+007F, […] - codeUnit >= 1 && codeUnit <= 31 || codeUnit == 127 || // If the character is the first character and is in the range [0-9] - // (U+0030 to U+0039), […] - index == 0 && codeUnit >= 48 && codeUnit <= 57 || // If the character is the second character and is in the range [0-9] - // (U+0030 to U+0039) and the first character is a `-` (U+002D), […] - index == 1 && codeUnit >= 48 && codeUnit <= 57 && firstCodeUnit == 45 - ) { - result3 += "\\" + codeUnit.toString(16) + " "; - continue; - } - if (codeUnit >= 128 || codeUnit == 45 || codeUnit == 95 || codeUnit >= 48 && codeUnit <= 57 || codeUnit >= 65 && codeUnit <= 90 || codeUnit >= 97 && codeUnit <= 122) { - result3 += returnValue2.charAt(index); - continue; - } - result3 += "\\" + returnValue2.charAt(index); - } - return result3; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/CSSUnits.js -var CSSUnits_default; -var init_CSSUnits = __esm({ - "node_modules/happy-dom/lib/css/CSSUnits.js"() { - CSSUnits_default = [ - "Hz", - "Q", - "ch", - "cm", - "deg", - "dpcm", - "dpi", - "dppx", - "em", - "ex", - "fr", - "grad", - "in", - "kHz", - "mm", - "ms", - "number", - "pc", - "percent", - "pt", - "px", - "rad", - "rem", - "s", - "turn", - "vh", - "vmax", - "vmin", - "vw" - ]; - } -}); - -// node_modules/happy-dom/lib/css/CSSUnitValue.js -var CSSUnitValue; -var init_CSSUnitValue = __esm({ - "node_modules/happy-dom/lib/css/CSSUnitValue.js"() { - init_CSSUnits(); - CSSUnitValue = class { - unit; - value; - /** - * Constructor. - * - * @param value Value. - * @param unit Unit. - */ - constructor(value2, unit) { - if (typeof value2 !== "number") { - throw new TypeError("The provided double value is non-finite"); - } - if (!CSSUnits_default.includes(unit)) { - throw new TypeError("Invalid unit: " + unit); - } - this.value = value2; - this.unit = unit; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/CSS.js -var CSS; -var init_CSS = __esm({ - "node_modules/happy-dom/lib/css/CSS.js"() { - init_CSSEscaper(); - init_CSSUnitValue(); - CSS = class { - Hz = (value2) => new CSSUnitValue(value2, "Hz"); - Q = (value2) => new CSSUnitValue(value2, "Q"); - ch = (value2) => new CSSUnitValue(value2, "ch"); - cm = (value2) => new CSSUnitValue(value2, "cm"); - deg = (value2) => new CSSUnitValue(value2, "deg"); - dpcm = (value2) => new CSSUnitValue(value2, "dpcm"); - dpi = (value2) => new CSSUnitValue(value2, "dpi"); - dppx = (value2) => new CSSUnitValue(value2, "dppx"); - em = (value2) => new CSSUnitValue(value2, "em"); - ex = (value2) => new CSSUnitValue(value2, "ex"); - fr = (value2) => new CSSUnitValue(value2, "fr"); - grad = (value2) => new CSSUnitValue(value2, "grad"); - in = (value2) => new CSSUnitValue(value2, "in"); - kHz = (value2) => new CSSUnitValue(value2, "kHz"); - mm = (value2) => new CSSUnitValue(value2, "mm"); - ms = (value2) => new CSSUnitValue(value2, "ms"); - number = (value2) => new CSSUnitValue(value2, "number"); - pc = (value2) => new CSSUnitValue(value2, "pc"); - percent = (value2) => new CSSUnitValue(value2, "percent"); - pt = (value2) => new CSSUnitValue(value2, "pt"); - px = (value2) => new CSSUnitValue(value2, "px"); - rad = (value2) => new CSSUnitValue(value2, "rad"); - rem = (value2) => new CSSUnitValue(value2, "rem"); - s = (value2) => new CSSUnitValue(value2, "s"); - turn = (value2) => new CSSUnitValue(value2, "turn"); - vh = (value2) => new CSSUnitValue(value2, "vh"); - vmax = (value2) => new CSSUnitValue(value2, "vmax"); - vmin = (value2) => new CSSUnitValue(value2, "vmin"); - vw = (value2) => new CSSUnitValue(value2, "vw"); - /** - * Returns a Boolean indicating if the pair property-value, or the condition, given in parameter is supported. - * - * TODO: Always returns "true" for now, but it should probably be improved in the future. - * - * @param _condition Property name or condition. - * @param [_value] Value when using property name. - * @returns "true" if supported. - */ - supports(_condition, _value) { - return true; - } - /** - * Escapes a value. - * - * @param value Value to escape. - * @returns Escaped string. - */ - escape(value2) { - return CSSEscaper.escape(value2); - } - }; - } -}); - -// node_modules/happy-dom/lib/css/CSSRuleTypeEnum.js -var CSSRuleTypeEnum, CSSRuleTypeEnum_default; -var init_CSSRuleTypeEnum = __esm({ - "node_modules/happy-dom/lib/css/CSSRuleTypeEnum.js"() { - (function(CSSRuleTypeEnum2) { - CSSRuleTypeEnum2[CSSRuleTypeEnum2["containerRule"] = 0] = "containerRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["styleRule"] = 1] = "styleRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["importRule"] = 3] = "importRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["mediaRule"] = 4] = "mediaRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["fontFaceRule"] = 5] = "fontFaceRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["pageRule"] = 6] = "pageRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["keyframesRule"] = 7] = "keyframesRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["keyframeRule"] = 8] = "keyframeRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["namespaceRule"] = 10] = "namespaceRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["counterStyleRule"] = 11] = "counterStyleRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["supportsRule"] = 12] = "supportsRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["documentRule"] = 13] = "documentRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["fontFeatureValuesRule"] = 14] = "fontFeatureValuesRule"; - CSSRuleTypeEnum2[CSSRuleTypeEnum2["regionStyleRule"] = 16] = "regionStyleRule"; - })(CSSRuleTypeEnum || (CSSRuleTypeEnum = {})); - CSSRuleTypeEnum_default = CSSRuleTypeEnum; - } -}); - -// node_modules/happy-dom/lib/css/CSSRule.js -var CSSRule; -var init_CSSRule = __esm({ - "node_modules/happy-dom/lib/css/CSSRule.js"() { - init_CSSRuleTypeEnum(); - init_PropertySymbol(); - CSSRule = class { - // Static properties - static CONTAINER_RULE = CSSRuleTypeEnum_default.containerRule; - static STYLE_RULE = CSSRuleTypeEnum_default.styleRule; - static IMPORT_RULE = CSSRuleTypeEnum_default.importRule; - static MEDIA_RULE = CSSRuleTypeEnum_default.mediaRule; - static FONT_FACE_RULE = CSSRuleTypeEnum_default.fontFaceRule; - static PAGE_RULE = CSSRuleTypeEnum_default.pageRule; - static KEYFRAMES_RULE = CSSRuleTypeEnum_default.keyframesRule; - static KEYFRAME_RULE = CSSRuleTypeEnum_default.keyframeRule; - static NAMESPACE_RULE = CSSRuleTypeEnum_default.namespaceRule; - static COUNTER_STYLE_RULE = CSSRuleTypeEnum_default.counterStyleRule; - static SUPPORTS_RULE = CSSRuleTypeEnum_default.supportsRule; - static DOCUMENT_RULE = CSSRuleTypeEnum_default.documentRule; - static FONT_FEATURE_VALUES_RULE = CSSRuleTypeEnum_default.fontFeatureValuesRule; - static REGION_STYLE_RULE = CSSRuleTypeEnum_default.regionStyleRule; - // Internal properties - [window]; - [cssParser]; - // Public properties - [parentRule] = null; - [parentStyleSheet] = null; - /** - * Constructor. - * - * @param illegalConstructorSymbol Illegal constructor symbol. - * @param window Window. - * @param cssParser CSS parser. - */ - constructor(illegalConstructorSymbol, window2, cssParser2) { - if (illegalConstructorSymbol !== illegalConstructor) { - throw new TypeError("Illegal constructor"); - } - this[window] = window2; - this[cssParser] = cssParser2; - } - /** - * Returns parent rule. - * - * @returns Parent rule. - */ - get parentRule() { - return this[parentRule]; - } - /** - * Returns parent style sheet. - * - * @returns Parent style sheet. - */ - get parentStyleSheet() { - return this[parentStyleSheet]; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationValueUtility.js -var SPLIT_BY_COMMA_REGEXP, SPLIT_BY_SPACE_REGEXP, CSSStyleDeclarationValueUtility; -var init_CSSStyleDeclarationValueUtility = __esm({ - "node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationValueUtility.js"() { - SPLIT_BY_COMMA_REGEXP = /[,()]/gm; - SPLIT_BY_SPACE_REGEXP = /[()]|\s+/gm; - CSSStyleDeclarationValueUtility = class { - /** - * Splits by comma while respecting nested parentheses. - * - * @param value Value to split. - * @returns Array of parts. - */ - static splitByComma(value2) { - const parts = []; - const regexp = new RegExp(SPLIT_BY_COMMA_REGEXP); - let match; - let depth = 0; - let lastIndex = 0; - while (match = regexp.exec(value2)) { - switch (match[0]) { - case "(": - depth++; - break; - case ")": - depth--; - break; - case ",": - if (depth === 0) { - const part = value2.substring(lastIndex, match.index).trim(); - if (part) { - parts.push(part); - } - lastIndex = regexp.lastIndex; - } - break; - } - } - if (lastIndex < value2.length) { - parts.push(value2.substring(lastIndex).trim()); - } - return parts; - } - /** - * Splits by space while respecting nested parentheses. - * - * @param value Value to split. - * @returns Array of parts. - */ - static splitBySpace(value2) { - const parts = []; - const regexp = new RegExp(SPLIT_BY_SPACE_REGEXP); - let match; - let depth = 0; - let lastIndex = 0; - while (match = regexp.exec(value2)) { - switch (match[0]) { - case "(": - depth++; - break; - case ")": - depth--; - break; - default: - if (depth === 0) { - const part = value2.substring(lastIndex, match.index).trim(); - if (part) { - parts.push(part); - } - lastIndex = regexp.lastIndex; - } - break; - } - } - if (lastIndex < value2.length) { - const part = value2.substring(lastIndex).trim(); - if (part) { - parts.push(part); - } - } - return parts; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationValueParser.js -var COLOR_REGEXP, LENGTH_REGEXP, PERCENTAGE_REGEXP, DEGREE_REGEXP, URL_REGEXP, INTEGER_REGEXP, FLOAT_REGEXP, CALC_REGEXP, CSS_VARIABLE_REGEXP, FIT_CONTENT_REGEXP, GRADIENT_REGEXP, GLOBALS, COLORS, CSSStyleDeclarationValueParser; -var init_CSSStyleDeclarationValueParser = __esm({ - "node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationValueParser.js"() { - init_CSSStyleDeclarationValueUtility(); - COLOR_REGEXP = /^#([0-9a-fA-F]{3,4}){1,2}$|^rgb\(([^)]*)\)$|^rgba\(([^)]*)\)$|^hsla?\(\s*(-?\d+|-?\d*.\d+)\s*,\s*(-?\d+|-?\d*.\d+)%\s*,\s*(-?\d+|-?\d*.\d+)%\s*(,\s*(-?\d+|-?\d*.\d+)\s*)?\)|(?:(rgba?|hsla?)\((var\(\s*(--[^)\s]+)\))\))/; - LENGTH_REGEXP = /^(0|[-+]?[0-9]*\.?[0-9]+)(in|cm|em|mm|pt|pc|px|ex|rem|vh|vw|ch|vw|vh|vmin|vmax|Q)$/; - PERCENTAGE_REGEXP = /^[-+]?[0-9]*\.?[0-9]+%$/; - DEGREE_REGEXP = /^[0-9]+deg$/; - URL_REGEXP = /^url\(\s*([^)]*)\s*\)$/; - INTEGER_REGEXP = /^[0-9]+$/; - FLOAT_REGEXP = /^[0-9.]+$/; - CALC_REGEXP = /^calc\([^^)]+\)$/; - CSS_VARIABLE_REGEXP = /^var\(\s*(--[^)\s]+)\)$/; - FIT_CONTENT_REGEXP = /^fit-content\([^^)]+\)$/; - GRADIENT_REGEXP = /^((repeating-linear|linear|radial|repeating-radial|conic|repeating-conic)-gradient)\(((?:[^()]|\([^()]*\))*)\)$/; - GLOBALS = ["inherit", "initial", "unset", "revert"]; - COLORS = [ - "none", - "currentcolor", - "transparent", - "silver", - "gray", - "white", - "maroon", - "red", - "purple", - "fuchsia", - "green", - "lime", - "olive", - "yellow", - "navy", - "blue", - "teal", - "aliceblue", - "aqua", - "antiquewhite", - "aquamarine", - "azure", - "beige", - "bisque", - "black", - "blanchedalmond", - "blueviolet", - "brown", - "burlywood", - "cadetblue", - "chartreuse", - "chocolate", - "coral", - "cornflowerblue", - "cornsilk", - "crimson", - "cyan", - "darkblue", - "darkcyan", - "darkgoldenrod", - "darkgray", - "darkgreen", - "darkgrey", - "darkkhaki", - "darkmagenta", - "darkolivegreen", - "darkorange", - "darkorchid", - "darkred", - "darksalmon", - "darkseagreen", - "darkslateblue", - "darkslategray", - "darkslategrey", - "darkturquoise", - "darkviolet", - "deeppink", - "deepskyblue", - "dimgray", - "dimgrey", - "dodgerblue", - "firebrick", - "floralwhite", - "forestgreen", - "gainsboro", - "ghostwhite", - "gold", - "goldenrod", - "greenyellow", - "grey", - "honeydew", - "hotpink", - "indianred", - "indigo", - "ivory", - "khaki", - "lavender", - "lavenderblush", - "lawngreen", - "lemonchiffon", - "lightblue", - "lightcoral", - "lightcyan", - "lightgoldenrodyellow", - "lightgray", - "lightgreen", - "lightgrey", - "lightpink", - "lightsalmon", - "lightseagreen", - "lightskyblue", - "lightslategray", - "lightslategrey", - "lightsteelblue", - "lightyellow", - "limegreen", - "linen", - "magenta", - "mediumaquamarine", - "mediumblue", - "mediumorchid", - "mediumpurple", - "mediumseagreen", - "mediumslateblue", - "mediumspringgreen", - "mediumturquoise", - "mediumvioletred", - "midnightblue", - "mintcream", - "mistyrose", - "moccasin", - "navajowhite", - "oldlace", - "olivedrab", - "orange", - "orangered", - "orchid", - "palegoldenrod", - "palegreen", - "paleturquoise", - "palevioletred", - "papayawhip", - "peachpuff", - "peru", - "pink", - "plum", - "powderblue", - "rebeccapurple", - "rosybrown", - "royalblue", - "saddlebrown", - "salmon", - "sandybrown", - "seagreen", - "seashell", - "sienna", - "skyblue", - "slateblue", - "slategray", - "slategrey", - "snow", - "springgreen", - "steelblue", - "tan", - "thistle", - "tomato", - "turquoise", - "violet", - "wheat", - "whitesmoke", - "yellowgreen" - ]; - CSSStyleDeclarationValueParser = class { - /** - * Returns length. - * - * @param value Value. - * @returns Parsed value. - */ - static getLength(value2) { - if (value2 === "0") { - return "0px"; - } - const match = value2.match(LENGTH_REGEXP); - if (match) { - const number = parseFloat(match[1]); - if (isNaN(number)) { - return null; - } - const unit = match[2]; - return `${Math.round(number * 1e6) / 1e6}${unit}`; - } - return null; - } - /** - * Returns percentance. - * - * @param value Value. - * @returns Parsed value. - */ - static getPercentage(value2) { - if (value2 === "0") { - return "0%"; - } - if (PERCENTAGE_REGEXP.test(value2)) { - return value2; - } - return null; - } - /** - * Returns degree. - * - * @param value Value. - * @returns Parsed value. - */ - static getDegree(value2) { - if (value2 === "0") { - return "0deg"; - } - if (DEGREE_REGEXP.test(value2)) { - return value2; - } - return null; - } - /** - * Returns calc. - * - * @param value Value. - * @returns Parsed value. - */ - static getCalc(value2) { - if (CALC_REGEXP.test(value2)) { - return value2; - } - return null; - } - /** - * Returns fit content. - * - * @param value Value. - * @returns Parsed value. - */ - static getFitContent(value2) { - const lowerValue = value2.toLowerCase(); - if (lowerValue === "auto" || lowerValue === "max-content" || lowerValue === "min-content" || lowerValue === "fit-content") { - return lowerValue; - } - if (FIT_CONTENT_REGEXP.test(lowerValue)) { - return lowerValue; - } - return null; - } - /** - * Returns measurement. - * - * @param value Value. - * @returns Parsed value. - */ - static getMeasurement(value2) { - return this.getLength(value2) || this.getPercentage(value2) || this.getCalc(value2); - } - /** - * Returns measurement or auto, min-content, max-content or fit-content. - * - * @param value Value. - * @returns Parsed value. - */ - static getContentMeasurement(value2) { - return this.getFitContent(value2) || this.getMeasurement(value2); - } - /** - * Returns measurement or auto, min-content, max-content or fit-content. - * - * @param value Value. - * @returns Parsed value. - */ - static getAutoMeasurement(value2) { - if (value2.toLocaleLowerCase() === "auto") { - return "auto"; - } - return this.getMeasurement(value2); - } - /** - * Returns integer. - * - * @param value Value. - * @returns Parsed value. - */ - static getInteger(value2) { - if (INTEGER_REGEXP.test(value2)) { - return value2; - } - return null; - } - /** - * Returns float. - * - * @param value Value. - * @returns Parsed value. - */ - static getFloat(value2) { - if (FLOAT_REGEXP.test(value2)) { - const number = parseFloat(value2); - if (isNaN(number)) { - return null; - } - return String(Math.round(number * 1e6) / 1e6); - } - return null; - } - /** - * Returns gradient. - * - * @param value Value. - * @returns Parsed value. - */ - static getGradient(value2) { - const match = value2.match(GRADIENT_REGEXP); - if (match) { - const args = match[3].trim(); - const parts = CSSStyleDeclarationValueUtility.splitByComma(args); - return `${match[1]}(${parts.join(", ")})`; - } - return null; - } - /** - * Returns color. - * - * @param value Value. - * @returns Parsed value. - */ - static getColor(value2) { - const lowerValue = value2.toLowerCase(); - if (COLORS.includes(lowerValue)) { - return lowerValue; - } - if (COLOR_REGEXP.test(value2)) { - return value2.replace(/,([^ ])/g, ", $1"); - } - return null; - } - /** - * Returns URL. - * - * Based on: - * https://github.com/jsdom/cssstyle/blob/master/lib/parsers.js#L222 - * - * @param value Value. - * @returns Parsed value. - */ - static getURL(value2) { - if (!value2) { - return null; - } - if (value2.toLowerCase() === "none") { - return "none"; - } - const result3 = URL_REGEXP.exec(value2); - if (!result3) { - return null; - } - let url2 = result3[1].trim(); - if ((url2[0] === '"' || url2[0] === "'") && url2[0] !== url2[url2.length - 1]) { - return null; - } - if (url2[0] === '"' || url2[0] === "'") { - url2 = url2.substring(1, url2.length - 1); - } - for (let i = 0; i < url2.length; i++) { - switch (url2[i]) { - case "(": - case ")": - case " ": - case " ": - case "\n": - case "'": - case '"': - return null; - case "\\": - i++; - break; - } - } - return `url("${url2}")`; - } - /** - * Returns global initial value. - * - * @param value Value. - * @returns Parsed value. - */ - static getInitial(value2) { - return value2.toLowerCase() === "initial" ? "initial" : null; - } - /** - * Returns CSS variable. - * - * @param value Value. - * @returns Parsed value. - */ - static getVariable(value2) { - const cssVariableMatch = value2.match(CSS_VARIABLE_REGEXP); - if (cssVariableMatch) { - return `var(${cssVariableMatch[1]})`; - } - return null; - } - /** - * Returns global. - * - * @param value Value. - * @returns Parsed value. - */ - static getGlobal(value2) { - const lowerValue = value2.toLowerCase(); - return GLOBALS.includes(lowerValue) ? lowerValue : null; - } - /** - * Returns global, unless it is not set to 'initial' as it is sometimes treated different. - * - * @param value Value. - * @returns Parsed value. - */ - static getGlobalExceptInitial(value2) { - const lowerValue = value2.toLowerCase(); - return lowerValue !== "initial" && GLOBALS.includes(lowerValue) ? lowerValue : null; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertySetParser.js -var RECT_REGEXP, SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP, SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP, WHITE_SPACE_GLOBAL_REGEXP, BORDER_STYLE, BORDER_WIDTH, BORDER_COLLAPSE, BACKGROUND_REPEAT, BACKGROUND_ORIGIN, BACKGROUND_CLIP, BACKGROUND_ATTACHMENT, FLEX_BASIS, CLEAR, FLOAT, SYSTEM_FONT, FONT_WEIGHT, FONT_STYLE, FONT_SIZE, FONT_STRETCH, DISPLAY, BORDER_IMAGE_REPEAT, TEXT_TRANSFORM, VISIBILITY, CSSStyleDeclarationPropertySetParser; -var init_CSSStyleDeclarationPropertySetParser = __esm({ - "node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertySetParser.js"() { - init_CSSStyleDeclarationValueParser(); - init_CSSStyleDeclarationValueUtility(); - RECT_REGEXP = /^rect\((.*)\)$/i; - SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP = /,(?=(?:(?:(?!\))[\s\S])*\()|[^\(\)]*$)/; - SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP = /\s+(?=(?:(?:(?!\))[\s\S])*\()|[^\(\)]*$)/; - WHITE_SPACE_GLOBAL_REGEXP = /\s+/gm; - BORDER_STYLE = [ - "none", - "hidden", - "dotted", - "dashed", - "solid", - "double", - "groove", - "ridge", - "inset", - "outset" - ]; - BORDER_WIDTH = ["thin", "medium", "thick"]; - BORDER_COLLAPSE = ["separate", "collapse"]; - BACKGROUND_REPEAT = ["repeat", "repeat-x", "repeat-y", "no-repeat"]; - BACKGROUND_ORIGIN = ["border-box", "padding-box", "content-box"]; - BACKGROUND_CLIP = ["border-box", "padding-box", "content-box"]; - BACKGROUND_ATTACHMENT = ["scroll", "fixed"]; - FLEX_BASIS = ["auto", "fill", "content"]; - CLEAR = ["none", "left", "right", "both"]; - FLOAT = ["none", "left", "right", "inline-start", "inline-end"]; - SYSTEM_FONT = ["caption", "icon", "menu", "message-box", "small-caption", "status-bar"]; - FONT_WEIGHT = ["normal", "bold", "bolder", "lighter"]; - FONT_STYLE = ["normal", "italic", "oblique"]; - FONT_SIZE = [ - "xx-small", - "x-small", - "small", - "medium", - "large", - "x-large", - "xx-large", - "xxx-large", - "smaller", - "larger" - ]; - FONT_STRETCH = [ - "ultra-condensed", - "extra-condensed", - "condensed", - "semi-condensed", - "normal", - "semi-expanded", - "expanded", - "extra-expanded", - "ultra-expanded" - ]; - DISPLAY = [ - /* Legacy values */ - "block", - "inline", - "inline-block", - "flex", - "inline-flex", - "grid", - "inline-grid", - "flow-root", - /* Box generation */ - "none", - "contents", - /* Two-value syntax */ - "block flow", - "inline flow", - "inline flow-root", - "block flex", - "inline flex", - "block grid", - "inline grid", - "block flow-root", - /* Other values */ - "table", - "table-row", - "list-item" - ]; - BORDER_IMAGE_REPEAT = ["stretch", "repeat", "round", "space"]; - TEXT_TRANSFORM = [ - "capitalize", - "uppercase", - "lowercase", - "none", - "full-width", - "full-size-kana" - ]; - VISIBILITY = ["visible", "hidden", "collapse"]; - CSSStyleDeclarationPropertySetParser = class { - /** - * Returns border collapse. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderCollapse(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-collapse": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_COLLAPSE.includes(lowerValue)) { - return { "border-collapse": { value: lowerValue, important } }; - } - return null; - } - /** - * Returns display. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getDisplay(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { display: { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || DISPLAY.includes(lowerValue)) { - return { display: { value: lowerValue, important } }; - } - return null; - } - /** - * Returns direction. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getDirection(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { direction: { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "ltr" || lowerValue === "rtl") { - return { direction: { value: lowerValue, important } }; - } - return null; - } - /** - * Returns letter spacing. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getLetterSpacing(value2, important) { - const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); - return parsedValue ? { "letter-spacing": { value: parsedValue, important } } : null; - } - /** - * Returns word spacing. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getWordSpacing(value2, important) { - const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); - return parsedValue ? { "word-spacing": { value: parsedValue, important } } : null; - } - /** - * Returns text indent. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getTextIndent(value2, important) { - const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); - return parsedValue ? { "text-indent": { value: parsedValue, important } } : null; - } - /** - * Returns width. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getWidth(value2, important) { - const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); - return parsedValue ? { width: { value: parsedValue, important } } : null; - } - /** - * Returns height. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getHeight(value2, important) { - const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); - return parsedValue ? { height: { value: parsedValue, important } } : null; - } - /** - * Returns top. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getTop(value2, important) { - const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); - return parsedValue ? { top: { value: parsedValue, important } } : null; - } - /** - * Returns top. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getRight(value2, important) { - const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); - return parsedValue ? { right: { value: parsedValue, important } } : null; - } - /** - * Returns top. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBottom(value2, important) { - const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); - return parsedValue ? { bottom: { value: parsedValue, important } } : null; - } - /** - * Returns top. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getLeft(value2, important) { - const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); - return parsedValue ? { left: { value: parsedValue, important } } : null; - } - /** - * Returns clear. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getClear(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { clear: { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || CLEAR.includes(lowerValue)) { - return { clear: { value: lowerValue, important } }; - } - return null; - } - /** - * Returns clip - * - * Based on: - * https://github.com/jsdom/cssstyle/blob/master/lib/properties/clip.js - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getClip(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { clip: { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "auto") { - return { clip: { value: lowerValue, important } }; - } - const matches = lowerValue.match(RECT_REGEXP); - if (!matches) { - return null; - } - const parts = matches[1].split(/\s*,\s*/); - if (parts.length !== 4) { - return null; - } - for (const part of parts) { - if (!CSSStyleDeclarationValueParser.getMeasurement(part)) { - return null; - } - } - return { clip: { value: value2, important } }; - } - /** - * Returns float. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFloat(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { float: { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FLOAT.includes(lowerValue)) { - return { float: { value: lowerValue, important } }; - } - return null; - } - /** - * Returns float. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getCSSFloat(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "css-float": { value: variable, important } }; - } - const float = this.getFloat(value2, important); - return float ? { "css-float": float["float"] } : null; - } - /** - * Returns outline. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getOutline(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { outline: { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getOutlineColor(globalValue, important), - ...this.getOutlineStyle(globalValue, important), - ...this.getOutlineWidth(globalValue, important) - }; - } - const properties = { - ...this.getOutlineColor("initial", important), - ...this.getOutlineStyle("initial", important), - ...this.getOutlineWidth("initial", important) - }; - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - for (const part of parts) { - const width2 = this.getOutlineWidth(part, important); - const style2 = this.getOutlineStyle(part, important); - const color = this.getOutlineColor(part, important); - if (width2 === null && style2 === null && color === null) { - return null; - } - Object.assign(properties, width2, style2, color); - } - return properties; - } - /** - * Returns outline color. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getOutlineColor(value2, important) { - const color = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); - return color ? { - "outline-color": { value: color, important } - } : null; - } - /** - * Returns outline offset. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getOutlineOffset(value2, important) { - const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getLength(value2); - return parsedValue ? { "outline-offset": { value: parsedValue, important } } : null; - } - /** - * Returns outline style. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getOutlineStyle(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "outline-style": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_STYLE.includes(lowerValue)) { - return { - "outline-style": { value: lowerValue, important } - }; - } - return null; - } - /** - * Returns outline width. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getOutlineWidth(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "outline-width": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - const parsedValue = BORDER_WIDTH.includes(lowerValue) || CSSStyleDeclarationValueParser.getGlobal(lowerValue) ? lowerValue : CSSStyleDeclarationValueParser.getLength(value2); - if (parsedValue) { - return { - "outline-width": { value: parsedValue, important } - }; - } - return null; - } - /** - * Returns border. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBorder(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { border: { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBorderWidth(globalValue, important), - ...this.getBorderStyle(globalValue, important), - ...this.getBorderColor(globalValue, important), - ...this.getBorderImage(globalValue, important) - }; - } - const properties = { - ...this.getBorderWidth("initial", important), - ...this.getBorderStyle("initial", important), - ...this.getBorderColor("initial", important), - ...this.getBorderImage("initial", important) - }; - const parts = value2.replace(/\s*,\s*/g, ",").split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - for (const part of parts) { - const width2 = this.getBorderWidth(part, important); - const style2 = this.getBorderStyle(part, important); - const color = this.getBorderColor(part, important); - if (width2 === null && style2 === null && color === null) { - return null; - } - Object.assign(properties, width2, style2, color); - } - return properties; - } - /** - * Returns border width. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderWidth(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-width": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBorderTopWidth(globalValue, important), - ...this.getBorderRightWidth(globalValue, important), - ...this.getBorderBottomWidth(globalValue, important), - ...this.getBorderLeftWidth(globalValue, important) - }; - } - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - const top2 = this.getBorderTopWidth(parts[0], important); - const right = this.getBorderRightWidth(parts[1] || parts[0], important); - const bottom = this.getBorderBottomWidth(parts[2] || parts[0], important); - const left = this.getBorderLeftWidth(parts[3] || parts[1] || parts[0], important); - if (!top2 || !right || !bottom || !left) { - return null; - } - return { - ...top2, - ...right, - ...bottom, - ...left - }; - } - /** - * Returns border style. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderStyle(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-style": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBorderTopStyle(globalValue, important), - ...this.getBorderRightStyle(globalValue, important), - ...this.getBorderBottomStyle(globalValue, important), - ...this.getBorderLeftStyle(globalValue, important) - }; - } - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - const top2 = this.getBorderTopStyle(parts[0], important); - const right = this.getBorderRightStyle(parts[1] || parts[0], important); - const bottom = this.getBorderBottomStyle(parts[2] || parts[0], important); - const left = this.getBorderLeftStyle(parts[3] || parts[1] || parts[0], important); - if (!top2 || !right || !bottom || !left) { - return null; - } - return { - ...top2, - ...right, - ...bottom, - ...left - }; - } - /** - * Returns border color. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderColor(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-color": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBorderTopColor(globalValue, important), - ...this.getBorderRightColor(globalValue, important), - ...this.getBorderBottomColor(globalValue, important), - ...this.getBorderLeftColor(globalValue, important) - }; - } - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - const top2 = this.getBorderTopColor(parts[0], important); - const right = this.getBorderRightColor(parts[1] || parts[0], important); - const bottom = this.getBorderBottomColor(parts[2] || parts[0], important); - const left = this.getBorderLeftColor(parts[3] || parts[1] || parts[0], important); - if (!top2 || !right || !bottom || !left) { - return null; - } - return { - ...top2, - ...right, - ...bottom, - ...left - }; - } - /** - * Returns border image. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderImage(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-image": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBorderImageSource(globalValue, important), - ...this.getBorderImageSlice(globalValue, important), - ...this.getBorderImageWidth(globalValue, important), - ...this.getBorderImageOutset(globalValue, important), - ...this.getBorderImageRepeat(globalValue, important) - }; - } - let parsedValue = value2.replace(/\s\/\s/g, "/"); - const sourceMatch = parsedValue.match(/\s*([a-zA-Z-]+\([^)]*\))\s*/); - if (sourceMatch) { - parsedValue = parsedValue.replace(sourceMatch[0], ""); - } - const parts = parsedValue.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - if (sourceMatch) { - parts.push(sourceMatch[1]); - } - const properties = { - ...this.getBorderImageSource("none", important), - ...this.getBorderImageSlice("100%", important), - ...this.getBorderImageWidth("1", important), - ...this.getBorderImageOutset("0", important), - ...this.getBorderImageRepeat("stretch", important) - }; - for (let i = 0, max = parts.length; i < max; i++) { - const part = parts[i]; - const previousPart = i > 0 ? parts[i - 1] : ""; - if (!part.startsWith("url") && part.includes("/")) { - const [slice, width2, outset] = part.split("/"); - const borderImageSlice = this.getBorderImageSlice(`${previousPart} ${slice}`, important) || this.getBorderImageSlice(slice, important); - const borderImageWidth = this.getBorderImageWidth(width2, important); - const borderImageOutset = outset && this.getBorderImageOutset(outset, important); - if (!borderImageSlice || !borderImageWidth || borderImageOutset === null) { - return null; - } - Object.assign(properties, borderImageSlice, borderImageWidth, borderImageOutset); - } else { - const slice = this.getBorderImageSlice(`${previousPart} ${part}`, important) || this.getBorderImageSlice(part, important); - const source = this.getBorderImageSource(part, important); - const repeat = this.getBorderImageRepeat(part, important); - if (!slice && !source && !repeat) { - return null; - } - Object.assign(properties, slice, source, repeat); - } - } - return properties; - } - /** - * Returns border source. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderImageSource(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-image-source": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "none") { - return { - "border-image-source": { - important, - value: lowerValue - } - }; - } - const parsedValue = CSSStyleDeclarationValueParser.getURL(value2) || CSSStyleDeclarationValueParser.getGradient(value2); - if (!parsedValue) { - return null; - } - return { - "border-image-source": { - important, - value: parsedValue - } - }; - } - /** - * Returns border slice. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderImageSlice(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-image-slice": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { - return { - "border-image-slice": { - important, - value: lowerValue - } - }; - } - if (lowerValue !== lowerValue.trim()) { - return null; - } - const regexp = /(fill)|(calc\([^^)]+\))|([0-9]+%)|([0-9]+)/g; - const values2 = []; - let match; - while (match = regexp.exec(lowerValue)) { - const previousCharacter = lowerValue[match.index - 1]; - const nextCharacter = lowerValue[match.index + match[0].length]; - if (previousCharacter && previousCharacter !== " " || nextCharacter && nextCharacter !== " ") { - return null; - } - const fill = match[1] && "fill"; - const calc = match[2] && CSSStyleDeclarationValueParser.getCalc(match[2]); - const percentage = match[3] && CSSStyleDeclarationValueParser.getPercentage(match[3]); - const integer = match[4] && CSSStyleDeclarationValueParser.getInteger(match[4]); - if (!fill && !calc && !percentage && !integer) { - return null; - } - values2.push(fill || calc || percentage || integer); - } - if (!values2.length || values2.length > 4) { - return null; - } - return { - "border-image-slice": { - important, - value: values2.join(" ") - } - }; - } - /** - * Returns border width. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderImageWidth(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-image-width": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { - return { - "border-image-width": { - important, - value: lowerValue - } - }; - } - const parts = lowerValue.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - if (parts.length > 4) { - return null; - } - for (const part of parts) { - if (!CSSStyleDeclarationValueParser.getInteger(part) && !CSSStyleDeclarationValueParser.getAutoMeasurement(part)) { - return null; - } - } - return { - "border-image-width": { - important, - value: value2 - } - }; - } - /** - * Returns border outset. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderImageOutset(value2, important) { - if (value2 === "0") { - return { - "border-image-outset": { - important, - value: value2 - } - }; - } - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-image-outset": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { - return { - "border-image-outset": { - important, - value: lowerValue - } - }; - } - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - if (parts.length > 4) { - return null; - } - const newParts = []; - for (const part of parts) { - const parsedValue = CSSStyleDeclarationValueParser.getLength(part) || CSSStyleDeclarationValueParser.getFloat(part); - if (!parsedValue) { - return null; - } - newParts.push(parsedValue === "0px" ? "0" : parsedValue); - } - return { - "border-image-outset": { - important, - value: newParts.join(" ") - } - }; - } - /** - * Returns border repeat. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderImageRepeat(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-image-repeat": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { - return { - "border-image-repeat": { - important, - value: lowerValue - } - }; - } - const parts = lowerValue.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - if (parts.length > 2) { - return null; - } - for (const part of parts) { - if (!BORDER_IMAGE_REPEAT.includes(part)) { - return null; - } - } - return { - "border-image-repeat": { - important, - value: value2 - } - }; - } - /** - * Returns border width. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderTopWidth(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-top-width": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - const parsedValue = BORDER_WIDTH.includes(lowerValue) || CSSStyleDeclarationValueParser.getGlobal(lowerValue) ? lowerValue : CSSStyleDeclarationValueParser.getLength(value2); - if (parsedValue) { - return { - "border-top-width": { value: parsedValue, important } - }; - } - return null; - } - /** - * Returns border width. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderRightWidth(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-right-width": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - const parsedValue = BORDER_WIDTH.includes(lowerValue) || CSSStyleDeclarationValueParser.getGlobal(lowerValue) ? lowerValue : CSSStyleDeclarationValueParser.getLength(value2); - if (parsedValue) { - return { - "border-right-width": { value: parsedValue, important } - }; - } - return null; - } - /** - * Returns border width. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderBottomWidth(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-bottom-width": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - const parsedValue = BORDER_WIDTH.includes(lowerValue) || CSSStyleDeclarationValueParser.getGlobal(lowerValue) ? lowerValue : CSSStyleDeclarationValueParser.getLength(value2); - if (parsedValue) { - return { - "border-bottom-width": { value: parsedValue, important } - }; - } - return null; - } - /** - * Returns border width. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderLeftWidth(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-left-width": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - const parsedValue = BORDER_WIDTH.includes(lowerValue) || CSSStyleDeclarationValueParser.getGlobal(lowerValue) ? lowerValue : CSSStyleDeclarationValueParser.getLength(value2); - if (parsedValue) { - return { - "border-left-width": { value: parsedValue, important } - }; - } - return null; - } - /** - * Returns border style. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderTopStyle(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-top-style": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_STYLE.includes(lowerValue)) { - return { - "border-top-style": { value: lowerValue, important } - }; - } - return null; - } - /** - * Returns border style. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderRightStyle(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-right-style": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_STYLE.includes(lowerValue)) { - return { - "border-right-style": { value: lowerValue, important } - }; - } - return null; - } - /** - * Returns border style. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderBottomStyle(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-bottom-style": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_STYLE.includes(lowerValue)) { - return { - "border-bottom-style": { value: lowerValue, important } - }; - } - return null; - } - /** - * Returns border style. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderLeftStyle(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-left-style": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_STYLE.includes(lowerValue)) { - return { - "border-left-style": { value: lowerValue, important } - }; - } - return null; - } - /** - * Returns border color. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderTopColor(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-top-color": { value: variable, important } }; - } - const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); - return color ? { - "border-top-color": { value: color, important } - } : null; - } - /** - * Returns border color. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderRightColor(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-right-color": { value: variable, important } }; - } - const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); - return color ? { - "border-right-color": { value: color, important } - } : null; - } - /** - * Returns border color. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderBottomColor(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-bottom-color": { value: variable, important } }; - } - const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); - return color ? { - "border-bottom-color": { value: color, important } - } : null; - } - /** - * Returns border color. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBorderLeftColor(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-left-color": { value: variable, important } }; - } - const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); - return color ? { - "border-left-color": { value: color, important } - } : null; - } - /** - * Returns border radius. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBorderRadius(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-radius": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBorderTopLeftRadius(globalValue, important), - ...this.getBorderTopRightRadius(globalValue, important), - ...this.getBorderBottomRightRadius(globalValue, important), - ...this.getBorderBottomLeftRadius(globalValue, important) - }; - } - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - const topLeft = this.getBorderTopLeftRadius(parts[0], important); - const topRight = this.getBorderTopRightRadius(parts[1] || parts[0], important); - const bottomRight = this.getBorderBottomRightRadius(parts[2] || parts[0], important); - const bottomLeft = this.getBorderBottomLeftRadius(parts[3] || parts[1] || parts[0], important); - if (!topLeft || !topRight || !bottomRight || !bottomLeft) { - return null; - } - return { - ...topLeft, - ...topRight, - ...bottomRight, - ...bottomLeft - }; - } - /** - * Returns border radius. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBorderTopLeftRadius(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-top-left-radius": { value: variable, important } }; - } - const radius = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); - return radius ? { "border-top-left-radius": { important, value: radius } } : null; - } - /** - * Returns border radius. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBorderTopRightRadius(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-top-right-radius": { value: variable, important } }; - } - const radius = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); - return radius ? { "border-top-right-radius": { important, value: radius } } : null; - } - /** - * Returns border radius. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBorderBottomRightRadius(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-bottom-right-radius": { value: variable, important } }; - } - const radius = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); - return radius ? { "border-bottom-right-radius": { important, value: radius } } : null; - } - /** - * Returns border radius. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBorderBottomLeftRadius(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-bottom-left-radius": { value: variable, important } }; - } - const radius = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); - return radius ? { "border-bottom-left-radius": { important, value: radius } } : null; - } - /** - * Returns border top, right, bottom or left. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBorderTop(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-top": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBorderTopWidth(globalValue, important), - ...this.getBorderTopStyle(globalValue, important), - ...this.getBorderTopColor(globalValue, important) - }; - } - const properties = { - ...this.getBorderTopWidth("initial", important), - ...this.getBorderTopStyle("initial", important), - ...this.getBorderTopColor("initial", important) - }; - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - for (const part of parts) { - const width2 = this.getBorderTopWidth(part, important); - const style2 = this.getBorderTopStyle(part, important); - const color = this.getBorderTopColor(part, important); - if (width2 === null && style2 === null && color === null) { - return null; - } - Object.assign(properties, width2, style2, color); - } - return properties; - } - /** - * Returns border top, right, bottom or left. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBorderRight(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-right": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBorderRightWidth(globalValue, important), - ...this.getBorderRightStyle(globalValue, important), - ...this.getBorderRightColor(globalValue, important) - }; - } - const properties = { - ...this.getBorderRightWidth("initial", important), - ...this.getBorderRightStyle("initial", important), - ...this.getBorderRightColor("initial", important) - }; - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - for (const part of parts) { - const width2 = this.getBorderRightWidth(part, important); - const style2 = this.getBorderRightStyle(part, important); - const color = this.getBorderRightColor(part, important); - if (width2 === null && style2 === null && color === null) { - return null; - } - Object.assign(properties, width2, style2, color); - } - return properties; - } - /** - * Returns border top, right, bottom or left. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBorderBottom(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-bottom": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBorderBottomWidth(globalValue, important), - ...this.getBorderBottomStyle(globalValue, important), - ...this.getBorderBottomColor(globalValue, important) - }; - } - const properties = { - ...this.getBorderBottomWidth("initial", important), - ...this.getBorderBottomStyle("initial", important), - ...this.getBorderBottomColor("initial", important) - }; - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - for (const part of parts) { - const width2 = this.getBorderBottomWidth(part, important); - const style2 = this.getBorderBottomStyle(part, important); - const color = this.getBorderBottomColor(part, important); - if (width2 === null && style2 === null && color === null) { - return null; - } - Object.assign(properties, width2, style2, color); - } - return properties; - } - /** - * Returns border top, right, bottom or left. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBorderLeft(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "border-left": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBorderLeftWidth(globalValue, important), - ...this.getBorderLeftStyle(globalValue, important), - ...this.getBorderLeftColor(globalValue, important) - }; - } - const properties = { - ...this.getBorderLeftWidth("initial", important), - ...this.getBorderLeftStyle("initial", important), - ...this.getBorderLeftColor("initial", important) - }; - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - for (const part of parts) { - const width2 = this.getBorderLeftWidth(part, important); - const style2 = this.getBorderLeftStyle(part, important); - const color = this.getBorderLeftColor(part, important); - if (width2 === null && style2 === null && color === null) { - return null; - } - Object.assign(properties, width2, style2, color); - } - return properties; - } - /** - * Returns padding. - * - * @param value Value. - * @param important Important. - */ - static getPadding(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { padding: { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getPaddingTop(globalValue, important), - ...this.getPaddingRight(globalValue, important), - ...this.getPaddingBottom(globalValue, important), - ...this.getPaddingLeft(globalValue, important) - }; - } - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - const top2 = this.getPaddingTop(parts[0], important); - const right = this.getPaddingRight(parts[1] || parts[0], important); - const bottom = this.getPaddingBottom(parts[2] || parts[0], important); - const left = this.getPaddingLeft(parts[3] || parts[1] || parts[0], important); - if (!top2 || !right || !bottom || !left) { - return null; - } - return { - ...top2, - ...right, - ...bottom, - ...left - }; - } - /** - * Returns padding top. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getPaddingTop(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "padding-top": { value: variable, important } }; - } - const padding = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); - return padding ? { "padding-top": { value: padding, important } } : null; - } - /** - * Returns padding right. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getPaddingRight(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "padding-right": { value: variable, important } }; - } - const padding = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); - return padding ? { "padding-right": { value: padding, important } } : null; - } - /** - * Returns padding bottom. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getPaddingBottom(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "padding-bottom": { value: variable, important } }; - } - const padding = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); - return padding ? { "padding-bottom": { value: padding, important } } : null; - } - /** - * Returns padding left. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getPaddingLeft(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "padding-left": { value: variable, important } }; - } - const padding = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); - return padding ? { "padding-left": { value: padding, important } } : null; - } - /** - * Returns margin. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getMargin(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { margin: { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getMarginTop(globalValue, important), - ...this.getMarginRight(globalValue, important), - ...this.getMarginBottom(globalValue, important), - ...this.getMarginLeft(globalValue, important) - }; - } - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - const top2 = this.getMarginTop(parts[0], important); - const right = this.getMarginRight(parts[1] || parts[0], important); - const bottom = this.getMarginBottom(parts[2] || parts[0], important); - const left = this.getMarginLeft(parts[3] || parts[1] || parts[0], important); - if (!top2 || !right || !bottom || !left) { - return null; - } - return { - ...top2, - ...right, - ...bottom, - ...left - }; - } - /** - * Returns margin top. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getMarginTop(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "margin-top": { value: variable, important } }; - } - const margin = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getAutoMeasurement(value2); - return margin ? { "margin-top": { value: margin, important } } : null; - } - /** - * Returns margin right. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getMarginRight(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "margin-right": { value: variable, important } }; - } - const margin = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getAutoMeasurement(value2); - return margin ? { "margin-right": { value: margin, important } } : null; - } - /** - * Returns margin right. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getMarginBottom(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "margin-bottom": { value: variable, important } }; - } - const margin = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getAutoMeasurement(value2); - return margin ? { "margin-bottom": { value: margin, important } } : null; - } - /** - * Returns margin left. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getMarginLeft(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "margin-left": { value: variable, important } }; - } - const margin = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getAutoMeasurement(value2); - return margin ? { "margin-left": { value: margin, important } } : null; - } - /** - * Returns flex. - * - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getFlex(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { flex: { value: variable, important } }; - } - const lowerValue = value2.trim().toLowerCase(); - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getFlexGrow(globalValue, important), - ...this.getFlexShrink(globalValue, important), - ...this.getFlexBasis(globalValue, important) - }; - } - switch (lowerValue) { - case "none": - return { - ...this.getFlexGrow("0", important), - ...this.getFlexShrink("0", important), - ...this.getFlexBasis("auto", important) - }; - case "auto": - return { - ...this.getFlexGrow("1", important), - ...this.getFlexShrink("1", important), - ...this.getFlexBasis("auto", important) - }; - } - const measurement = CSSStyleDeclarationValueParser.getContentMeasurement(lowerValue); - if (measurement) { - return { - ...this.getFlexGrow("1", important), - ...this.getFlexShrink("1", important), - ...this.getFlexBasis(measurement, important) - }; - } - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - const flexGrow = this.getFlexGrow(parts[0], important); - const flexShrink = this.getFlexShrink(parts[1] || "1", important); - const flexBasis = this.getFlexBasis(parts[2] || "0%", important); - if (!flexGrow || !flexShrink || !flexBasis) { - return null; - } - return { - ...flexGrow, - ...flexShrink, - ...flexBasis - }; - } - /** - * Returns flex basis. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFlexBasis(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "flex-basis": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FLEX_BASIS.includes(lowerValue)) { - return { "flex-basis": { value: lowerValue, important } }; - } - const measurement = CSSStyleDeclarationValueParser.getContentMeasurement(lowerValue); - return measurement ? { "flex-basis": { value: measurement, important } } : null; - } - /** - * Returns flex shrink. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFlexShrink(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "flex-shrink": { value: variable, important } }; - } - const parsedValue = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getFloat(value2); - return parsedValue ? { "flex-shrink": { value: parsedValue, important } } : null; - } - /** - * Returns flex grow. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFlexGrow(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "flex-grow": { value: variable, important } }; - } - const parsedValue = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getFloat(value2); - return parsedValue ? { "flex-grow": { value: parsedValue, important } } : null; - } - /** - * Returns background. - * - * @param name Name. - * @param value Value. - * @param important Important. - * @returns Property values. - */ - static getBackground(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { background: { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBackgroundImage(globalValue, important), - ...this.getBackgroundPosition(globalValue, important), - ...this.getBackgroundSize(globalValue, important), - ...this.getBackgroundRepeat(globalValue, important), - ...this.getBackgroundAttachment(globalValue, important), - ...this.getBackgroundOrigin(globalValue, important), - ...this.getBackgroundClip(globalValue, important), - ...this.getBackgroundColor(globalValue, important) - }; - } - const properties = { - ...this.getBackgroundImage("initial", important), - ...this.getBackgroundPosition("initial", important), - ...this.getBackgroundSize("initial", important), - ...this.getBackgroundRepeat("initial", important), - ...this.getBackgroundAttachment("initial", important), - ...this.getBackgroundOrigin("initial", important), - ...this.getBackgroundClip("initial", important), - ...this.getBackgroundColor("initial", important) - }; - const parts = CSSStyleDeclarationValueUtility.splitBySpace(value2.replace(/\s+\/\s+/g, "/")); - const backgroundPositions = []; - for (const part of parts) { - if (!part.startsWith("url") && part.includes("/")) { - const [position, size] = part.split("/"); - const backgroundPositionX = this.getBackgroundPositionX(position, important); - const backgroundPositionY = this.getBackgroundPositionY(position, important); - const backgroundSize = this.getBackgroundSize(size, important); - if (!backgroundPositionX && !backgroundPositionY || !backgroundSize) { - return null; - } - if (backgroundPositionY) { - backgroundPositions.push(backgroundPositionY["background-position-y"].value); - } else if (backgroundPositionX) { - backgroundPositions.push(backgroundPositionX["background-position-x"].value); - } - Object.assign(properties, backgroundSize); - } else { - const backgroundImage = this.getBackgroundImage(part, important); - const backgroundRepeat = this.getBackgroundRepeat(part, important); - const backgroundAttachment = this.getBackgroundAttachment(part, important); - const backgroundPositionX = this.getBackgroundPositionX(part, important); - const backgroundPositionY = this.getBackgroundPositionY(part, important); - const backgroundColor = this.getBackgroundColor(part, important); - const backgroundOrigin = this.getBackgroundOrigin(part, important); - const backgroundClip = this.getBackgroundClip(part, important); - if (!backgroundImage && !backgroundRepeat && !backgroundAttachment && !backgroundPositionX && !backgroundPositionY && !backgroundColor && !backgroundOrigin && !backgroundClip) { - return null; - } - if (backgroundPositionX) { - backgroundPositions.push(backgroundPositionX["background-position-x"].value); - } else if (backgroundPositionY) { - backgroundPositions.push(backgroundPositionY["background-position-y"].value); - } - Object.assign(properties, backgroundImage, backgroundRepeat, backgroundAttachment, backgroundColor, backgroundOrigin, backgroundClip); - } - } - if (backgroundPositions.length) { - Object.assign(properties, this.getBackgroundPosition(backgroundPositions.join(" "), important)); - } - return properties; - } - /** - * Returns background size. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBackgroundSize(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "background-size": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { - return { "background-size": { value: lowerValue, important } }; - } - const imageParts = lowerValue.split(SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP); - const parsed = []; - for (const imagePart of imageParts) { - const parts = imagePart.trim().split(" "); - if (parts.length !== 1 && parts.length !== 2) { - return null; - } - if (parts.length === 1) { - if (parts[0] !== "cover" && parts[0] !== "contain" && !CSSStyleDeclarationValueParser.getAutoMeasurement(parts[0])) { - return null; - } - parsed.push(parts[0]); - } else { - if (!CSSStyleDeclarationValueParser.getAutoMeasurement(parts[0]) || !CSSStyleDeclarationValueParser.getAutoMeasurement(parts[1])) { - return null; - } - parsed.push(`${parts[0]} ${parts[1]}`); - } - } - if (parsed.length === 1) { - return { "background-size": { value: parsed.join(", "), important } }; - } - return null; - } - /** - * Returns background origin. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBackgroundOrigin(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "background-origin": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BACKGROUND_ORIGIN.includes(lowerValue)) { - return { "background-origin": { value: lowerValue, important } }; - } - return null; - } - /** - * Returns background clip. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBackgroundClip(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "background-clip": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BACKGROUND_CLIP.includes(lowerValue)) { - return { "background-clip": { value: lowerValue, important } }; - } - return null; - } - /** - * Returns background repeat. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBackgroundRepeat(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "background-repeat": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BACKGROUND_REPEAT.includes(lowerValue)) { - return { "background-repeat": { value: lowerValue, important } }; - } - return null; - } - /** - * Returns background attachment. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBackgroundAttachment(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "background-attachment": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BACKGROUND_ATTACHMENT.includes(lowerValue)) { - return { "background-attachment": { value: lowerValue, important } }; - } - return null; - } - /** - * Returns background position. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBackgroundPosition(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "background-position": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { - ...this.getBackgroundPositionX(globalValue, important), - ...this.getBackgroundPositionY(globalValue, important) - }; - } - const imageParts = value2.split(SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP); - let x3 = ""; - let y3 = ""; - for (const imagePart of imageParts) { - const parts = imagePart.trim().split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - if (x3) { - x3 += ","; - y3 += ","; - } - switch (parts.length) { - case 1: - if (parts[0] === "top" || parts[0] === "bottom") { - x3 += "center"; - y3 += parts[0]; - } else if (parts[0] === "left" || parts[0] === "right") { - x3 += parts[0]; - y3 += "center"; - } else if (parts[0] === "center") { - x3 += "center"; - y3 += "center"; - } - break; - case 2: - x3 += parts[0] === "top" || parts[0] === "bottom" ? parts[1] : parts[0]; - y3 += parts[0] === "top" || parts[0] === "bottom" ? parts[0] : parts[1]; - break; - case 3: - if (parts[0] === "top" || parts[0] === "bottom" || parts[1] === "left" || parts[1] === "right" || parts[2] === "left" || parts[2] === "right") { - if (CSSStyleDeclarationValueParser.getMeasurement(parts[1])) { - x3 += parts[2]; - y3 += `${parts[0]} ${parts[1]}`; - } else { - x3 += `${parts[1]} ${parts[2]}`; - y3 += parts[0]; - } - } else { - if (CSSStyleDeclarationValueParser.getMeasurement(parts[1])) { - x3 += `${parts[0]} ${parts[1]}`; - y3 += parts[2]; - } else { - x3 += parts[0]; - y3 += `${parts[1]} ${parts[2]}`; - } - } - break; - case 4: - x3 += parts[0] === "top" || parts[0] === "bottom" || parts[1] === "top" || parts[1] === "bottom" ? `${parts[2]} ${parts[3]}` : `${parts[0]} ${parts[1]}`; - y3 += parts[0] === "top" || parts[0] === "bottom" || parts[1] === "top" || parts[1] === "bottom" ? `${parts[0]} ${parts[1]}` : `${parts[2]} ${parts[3]}`; - break; - default: - return null; - } - } - const xValue = this.getBackgroundPositionX(x3, important); - const yValue = this.getBackgroundPositionY(y3, important); - if (xValue && yValue) { - return { - ...xValue, - ...yValue - }; - } - return null; - } - /** - * Returns background position. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBackgroundPositionX(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "background-position-x": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { - return { "background-position-x": { value: lowerValue, important } }; - } - const imageParts = lowerValue.split(SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP); - let parsedValue = ""; - for (const imagePart of imageParts) { - const parts = imagePart.trim().split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - if (parsedValue) { - parsedValue += ","; - } - for (const part of parts) { - const measurement = CSSStyleDeclarationValueParser.getMeasurement(part); - if (!measurement && part !== "left" && part !== "right" && part !== "center") { - return null; - } - if (parsedValue) { - parsedValue += " "; - } - parsedValue += measurement || part; - } - } - return { "background-position-x": { value: parsedValue, important } }; - } - /** - * Returns background position. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getBackgroundPositionY(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "background-position-y": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { - return { "background-position-y": { value: lowerValue, important } }; - } - const imageParts = lowerValue.split(SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP); - let parsedValue = ""; - for (const imagePart of imageParts) { - const parts = imagePart.trim().split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - if (parsedValue) { - parsedValue += ","; - } - for (const part of parts) { - const measurement = CSSStyleDeclarationValueParser.getMeasurement(part); - if (!measurement && part !== "top" && part !== "bottom" && part !== "center") { - return null; - } - if (parsedValue) { - parsedValue += " "; - } - parsedValue += measurement || part; - } - } - return { "background-position-y": { value: parsedValue, important } }; - } - /** - * Returns background color. - * - * @param value Value. - * @param important Important. - * @returns Property value. - */ - static getBackgroundColor(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "background-color": { value: variable, important } }; - } - const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); - return color ? { - ["background-color"]: { important, value: color } - } : null; - } - /** - * Returns background image. - * - * @param value Value. - * @param important Important. - * @returns Property value. - */ - static getBackgroundImage(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "background-image": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "none") { - return { "background-image": { value: lowerValue, important } }; - } - const parts = CSSStyleDeclarationValueUtility.splitByComma(value2); - const parsed = []; - for (const part of parts) { - const parsedValue = CSSStyleDeclarationValueParser.getURL(part.trim()) || CSSStyleDeclarationValueParser.getGradient(part.trim()); - if (!parsedValue) { - return null; - } - parsed.push(parsedValue); - } - if (parsed.length) { - return { "background-image": { value: parsed.join(", "), important } }; - } - return null; - } - /** - * Returns color. - * - * @param value Value. - * @param important Important. - * @returns Property value. - */ - static getColor(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { color: { value: variable, important } }; - } - const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); - return color ? { color: { important, value: color } } : null; - } - /** - * Returns color. - * - * @param value Value. - * @param important Important. - * @returns Property value. - */ - static getFloodColor(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "flood-color": { value: variable, important } }; - } - const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); - return color ? { "flood-color": { important, value: color } } : null; - } - /** - * Returns font. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFont(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { font: { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { - return { - ...this.getFontStyle(lowerValue, important), - ...this.getFontVariant(lowerValue, important), - ...this.getFontWeight(lowerValue, important), - ...this.getFontStretch(lowerValue, important), - ...this.getFontSize(lowerValue, important), - ...this.getLineHeight(lowerValue, important), - ...this.getFontFamily(lowerValue, important) - }; - } - if (SYSTEM_FONT.includes(lowerValue)) { - return { font: { value: lowerValue, important } }; - } - const properties = { - ...this.getFontStyle("normal", important), - ...this.getFontVariant("normal", important), - ...this.getFontWeight("normal", important), - ...this.getFontStretch("normal", important), - ...this.getLineHeight("normal", important) - }; - const parts = value2.replace(/\s*\/\s*/g, "/").split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - for (let i = 0, max = parts.length; i < max; i++) { - const part = parts[i]; - if (part.includes("/")) { - const [size, height2] = part.split("/"); - const fontSize = this.getFontSize(size, important); - const lineHeight = this.getLineHeight(height2, important); - if (!fontSize || !lineHeight) { - return null; - } - Object.assign(properties, fontSize, lineHeight); - } else { - const fontStyle = this.getFontStyle(part, important); - const fontVariant = this.getFontVariant(part, important); - const fontWeight = this.getFontWeight(part, important); - const fontSize = this.getFontSize(part, important); - const fontStretch = this.getFontStretch(part, important); - if (fontStyle) { - Object.assign(properties, fontStyle); - } else if (fontVariant) { - Object.assign(properties, fontVariant); - } else if (fontWeight) { - Object.assign(properties, fontWeight); - } else if (fontSize) { - Object.assign(properties, fontSize); - } else if (fontStretch) { - Object.assign(properties, fontStretch); - } else { - const fontFamilyValue = parts.slice(i).join(" "); - const fontFamily = this.getFontFamily(fontFamilyValue, important); - if (!fontFamily) { - return null; - } - Object.assign(properties, fontFamily); - break; - } - } - } - return properties; - } - /** - * Returns font style. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFontStyle(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "font-style": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FONT_STYLE.includes(lowerValue)) { - return { "font-style": { value: lowerValue, important } }; - } - const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); - if (parts.length === 2 && parts[0] === "oblique") { - const degree = CSSStyleDeclarationValueParser.getDegree(parts[1]); - return degree ? { "font-style": { value: lowerValue, important } } : null; - } - return null; - } - /** - * Returns font variant. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFontVariant(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "font-variant": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - return CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "normal" || lowerValue === "small-caps" ? { "font-variant": { value: lowerValue, important } } : null; - } - /** - * Returns font strech. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFontStretch(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "font-stretch": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FONT_STRETCH.includes(lowerValue)) { - return { "font-stretch": { value: lowerValue, important } }; - } - const percentage = CSSStyleDeclarationValueParser.getPercentage(value2); - return percentage ? { "font-stretch": { value: percentage, important } } : null; - } - /** - * Returns font weight. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFontWeight(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "font-weight": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FONT_WEIGHT.includes(lowerValue)) { - return { "font-weight": { value: lowerValue, important } }; - } - const integer = CSSStyleDeclarationValueParser.getInteger(value2); - return integer ? { "font-weight": { value: integer, important } } : null; - } - /** - * Returns font size. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFontSize(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "font-size": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FONT_SIZE.includes(lowerValue)) { - return { "font-size": { value: lowerValue, important } }; - } - const measurement = CSSStyleDeclarationValueParser.getMeasurement(value2); - return measurement ? { "font-size": { value: measurement, important } } : null; - } - /** - * Returns line height. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getLineHeight(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "line-height": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "normal") { - return { "line-height": { value: lowerValue, important } }; - } - const lineHeight = CSSStyleDeclarationValueParser.getFloat(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); - return lineHeight ? { "line-height": { value: lineHeight, important } } : null; - } - /** - * Returns font family. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getFontFamily(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "font-family": { value: variable, important } }; - } - const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); - if (globalValue) { - return { "font-family": { value: globalValue, important } }; - } - const parts = value2.split(","); - let parsedValue = ""; - let endWithApostroph = false; - for (let i = 0, max = parts.length; i < max; i++) { - let trimmedPart = parts[i].trim().replace(/'/g, '"'); - if (!trimmedPart) { - return null; - } - if (trimmedPart.includes(" ")) { - const apostrophCount = (trimmedPart.match(/"/g) || []).length; - if ((trimmedPart[0] !== '"' || i !== 0) && apostrophCount !== 2 && apostrophCount !== 0) { - return null; - } - if (trimmedPart[0] === '"' && trimmedPart[trimmedPart.length - 1] !== '"') { - endWithApostroph = true; - } else if (trimmedPart[0] !== '"' && trimmedPart[trimmedPart.length - 1] !== '"') { - trimmedPart = `"${trimmedPart}"`; - } - } else { - trimmedPart = trimmedPart.replace(/"/g, ""); - } - if (i > 0) { - parsedValue += ", "; - } - parsedValue += trimmedPart; - } - if (endWithApostroph) { - parsedValue += '"'; - } - if (!parsedValue) { - return null; - } - return { - "font-family": { - important, - value: parsedValue - } - }; - } - /** - * Returns font family. - * - * @param value Value. - * @param important Important. - * @returns Property values - */ - static getTextTransform(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "text-transform": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - const parsedValue = CSSStyleDeclarationValueParser.getGlobal(lowerValue) || TEXT_TRANSFORM.includes(lowerValue) && lowerValue; - if (parsedValue) { - return { - "text-transform": { value: parsedValue, important } - }; - } - return null; - } - /** - * Returns visibility. - * - * @param value Value. - * @param important Important. - * @returns Property - */ - static getVisibility(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { visibility: { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - const parsedValue = CSSStyleDeclarationValueParser.getGlobal(lowerValue) || VISIBILITY.includes(lowerValue) && lowerValue; - if (parsedValue) { - return { - visibility: { value: parsedValue, important } - }; - } - return null; - } - /** - * Returns aspect ratio. - * - * @param value Value. - * @param important Important. - * @returns Property - */ - static getAspectRatio(value2, important) { - const variable = CSSStyleDeclarationValueParser.getVariable(value2); - if (variable) { - return { "aspect-ratio": { value: variable, important } }; - } - const lowerValue = value2.toLowerCase(); - if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { - return { "aspect-ratio": { value: lowerValue, important } }; - } - let parsedValue = value2; - const hasAuto = parsedValue.includes("auto"); - if (hasAuto) { - parsedValue = parsedValue.replace("auto", ""); - } - parsedValue = parsedValue.replace(WHITE_SPACE_GLOBAL_REGEXP, ""); - if (!parsedValue) { - return { "aspect-ratio": { value: "auto", important } }; - } - const aspectRatio = parsedValue.split("/"); - if (aspectRatio.length > 3) { - return null; - } - const width2 = Number(aspectRatio[0]); - const height2 = aspectRatio[1] ? Number(aspectRatio[1]) : 1; - if (isNaN(width2) || isNaN(height2)) { - return null; - } - if (hasAuto) { - return { "aspect-ratio": { value: `auto ${width2} / ${height2}`, important } }; - } - return { "aspect-ratio": { value: `${width2} / ${height2}`, important } }; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyGetParser.js -var CSSStyleDeclarationPropertyGetParser; -var init_CSSStyleDeclarationPropertyGetParser = __esm({ - "node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyGetParser.js"() { - init_CSSStyleDeclarationValueParser(); - CSSStyleDeclarationPropertyGetParser = class { - /** - * Returns margin. - * - * @param properties Properties. - * @returns Property value - */ - static getMargin(properties) { - return this.getPaddingLikeProperty(["margin-top", "margin-right", "margin-bottom", "margin-left"], properties); - } - /** - * Returns padding. - * - * @param properties Properties. - * @returns Property value - */ - static getPadding(properties) { - return this.getPaddingLikeProperty(["padding-top", "padding-right", "padding-bottom", "padding-left"], properties); - } - /** - * Returns outline. - * - * @param properties Properties. - * @returns Property value - */ - static getOutline(properties) { - if (!properties["outline-color"]?.value || !properties["outline-style"]?.value || !properties["outline-width"]?.value) { - return null; - } - const important = properties["outline-color"].important && properties["outline-style"].important && properties["outline-width"].important; - if (CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["outline-width"].value) && properties["outline-width"].value === properties["outline-style"].value && properties["outline-width"].value === properties["outline-color"].value) { - return { - important, - value: properties["outline-width"].value - }; - } - const values2 = []; - if (!CSSStyleDeclarationValueParser.getInitial(properties["outline-color"]?.value)) { - values2.push(properties["outline-color"].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties["outline-style"]?.value)) { - values2.push(properties["outline-style"].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties["outline-width"].value)) { - values2.push(properties["outline-width"].value); - } - return { - important, - value: values2.join(" ") - }; - } - /** - * Returns border. - * - * @param properties Properties. - * @returns Property value - */ - static getBorder(properties) { - if (!properties["border-top-width"]?.value || properties["border-top-width"]?.value !== properties["border-right-width"]?.value || properties["border-top-width"]?.value !== properties["border-bottom-width"]?.value || properties["border-top-width"]?.value !== properties["border-left-width"]?.value || !properties["border-top-style"]?.value || properties["border-top-style"]?.value !== properties["border-right-style"]?.value || properties["border-top-style"]?.value !== properties["border-bottom-style"]?.value || properties["border-top-style"]?.value !== properties["border-left-style"]?.value || !properties["border-top-color"]?.value || properties["border-top-color"]?.value !== properties["border-right-color"]?.value || properties["border-top-color"]?.value !== properties["border-bottom-color"]?.value || properties["border-top-color"]?.value !== properties["border-left-color"]?.value || !properties["border-image-source"]?.value || !properties["border-image-slice"]?.value || !properties["border-image-width"]?.value || !properties["border-image-outset"]?.value || !properties["border-image-repeat"]?.value) { - return null; - } - const important = properties["border-top-width"].important && properties["border-right-width"].important && properties["border-bottom-width"].important && properties["border-left-width"].important && properties["border-top-style"].important && properties["border-right-style"].important && properties["border-bottom-style"].important && properties["border-left-style"].important && properties["border-top-color"].important && properties["border-right-color"].important && properties["border-bottom-color"].important && properties["border-left-color"].important && properties["border-image-source"].important && properties["border-image-slice"].important && properties["border-image-width"].important && properties["border-image-outset"].important && properties["border-image-repeat"].important; - if (CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-top-width"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-top-style"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-top-color"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-image-source"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-image-slice"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-image-width"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-image-outset"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-image-repeat"].value)) { - if (properties["border-top-width"].value !== properties["border-top-style"].value || properties["border-top-width"].value !== properties["border-top-color"].value || properties["border-top-width"].value !== properties["border-image-source"].value || properties["border-top-width"].value !== properties["border-image-slice"].value || properties["border-top-width"].value !== properties["border-image-width"].value || properties["border-top-width"].value !== properties["border-image-outset"].value || properties["border-top-width"].value !== properties["border-image-repeat"].value) { - return null; - } - return { - important, - value: properties["border-top-width"].value - }; - } - const values2 = []; - if (!CSSStyleDeclarationValueParser.getInitial(properties["border-top-width"].value)) { - values2.push(properties["border-top-width"].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties["border-top-style"].value)) { - values2.push(properties["border-top-style"].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties["border-top-color"].value)) { - values2.push(properties["border-top-color"].value); - } - return { - important, - value: values2.join(" ") - }; - } - /** - * Returns border. - * - * @param properties Properties. - * @returns Property value - */ - static getBorderTop(properties) { - return this.getBorderTopRightBottomLeft("top", properties); - } - /** - * Returns border. - * - * @param properties Properties. - * @returns Property value - */ - static getBorderRight(properties) { - return this.getBorderTopRightBottomLeft("right", properties); - } - /** - * Returns border. - * - * @param properties Properties. - * @returns Property value - */ - static getBorderBottom(properties) { - return this.getBorderTopRightBottomLeft("bottom", properties); - } - /** - * Returns border. - * - * @param properties Properties. - * @returns Property value - */ - static getBorderLeft(properties) { - return this.getBorderTopRightBottomLeft("left", properties); - } - /** - * Returns border. - * - * @param properties Properties. - * @returns Property value - */ - static getBorderColor(properties) { - return this.getPaddingLikeProperty(["border-top-color", "border-right-color", "border-bottom-color", "border-left-color"], properties); - } - /** - * Returns border. - * - * @param properties Properties. - * @returns Property value - */ - static getBorderWidth(properties) { - return this.getPaddingLikeProperty(["border-top-width", "border-right-width", "border-bottom-width", "border-left-width"], properties); - } - /** - * Returns border. - * - * @param properties Properties. - * @returns Property value - */ - static getBorderStyle(properties) { - return this.getPaddingLikeProperty(["border-top-style", "border-right-style", "border-bottom-style", "border-left-style"], properties); - } - /** - * Returns border radius. - * - * @param properties Properties. - * @returns Property value - */ - static getBorderRadius(properties) { - return this.getPaddingLikeProperty([ - "border-top-left-radius", - "border-top-right-radius", - "border-bottom-right-radius", - "border-bottom-left-radius" - ], properties); - } - /** - * Returns border image. - * - * @param properties Properties. - * @returns Property value - */ - static getBorderImage(properties) { - if (!properties["border-image-source"]?.value || !properties["border-image-slice"]?.value || !properties["border-image-width"]?.value || !properties["border-image-outset"]?.value || !properties["border-image-repeat"]?.value) { - return null; - } - const important = properties["border-image-source"].important && properties["border-image-slice"].important && properties["border-image-width"].important && properties["border-image-outset"].important && properties["border-image-repeat"].important; - if (CSSStyleDeclarationValueParser.getGlobal(properties["border-image-source"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["border-image-slice"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["border-image-width"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["border-image-outset"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["border-image-repeat"].value)) { - if (properties["border-image-source"].value !== properties["border-image-slice"].value || properties["border-image-source"].value !== properties["border-image-width"].value || properties["border-image-source"].value !== properties["border-image-outset"].value || properties["border-image-source"].value !== properties["border-image-repeat"].value) { - return null; - } - return { - important, - value: properties["border-image-source"].value - }; - } - return { - important, - value: `${properties["border-image-source"].value} ${properties["border-image-slice"].value} / ${properties["border-image-width"].value} / ${properties["border-image-outset"].value} ${properties["border-image-repeat"].value}` - }; - } - /** - * Returns background. - * - * @param properties Properties. - * @returns Property value - */ - static getBackground(properties) { - if (!properties["background-image"]?.value || !properties["background-repeat"]?.value || !properties["background-attachment"]?.value || !properties["background-position-x"]?.value || !properties["background-position-y"]?.value || !properties["background-color"]?.value || !properties["background-size"]?.value || !properties["background-origin"]?.value || !properties["background-clip"]?.value) { - return null; - } - const important = properties["background-image"].important && properties["background-repeat"].important && properties["background-attachment"].important && properties["background-position-x"].important && properties["background-position-y"].important && properties["background-color"].important && properties["background-size"].important && properties["background-origin"].important && properties["background-clip"].important; - if (CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-image"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-repeat"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-attachment"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-position-x"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-position-y"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-color"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-size"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-origin"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-clip"].value)) { - if (properties["background-image"].value !== properties["background-repeat"].value || properties["background-image"].value !== properties["background-attachment"].value || properties["background-image"].value !== properties["background-position-x"].value || properties["background-image"].value !== properties["background-position-y"].value || properties["background-image"].value !== properties["background-color"].value || properties["background-image"].value !== properties["background-size"].value || properties["background-image"].value !== properties["background-origin"].value || properties["background-image"].value !== properties["background-clip"].value) { - return null; - } - return { - important, - value: properties["background-image"].value - }; - } - const values2 = []; - if (!CSSStyleDeclarationValueParser.getInitial(properties["background-image"].value)) { - values2.push(properties["background-image"].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties["background-position-x"].value) && !CSSStyleDeclarationValueParser.getInitial(properties["background-position-y"].value) && !CSSStyleDeclarationValueParser.getInitial(properties["background-size"].value)) { - values2.push(`${properties["background-position-x"].value} ${properties["background-position-y"].value} / ${properties["background-size"].value}`); - } else if (!CSSStyleDeclarationValueParser.getInitial(properties["background-position-x"].value) && !CSSStyleDeclarationValueParser.getInitial(properties["background-position-y"].value)) { - values2.push(`${properties["background-position-x"].value} ${properties["background-position-y"].value}`); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties["background-repeat"].value)) { - values2.push(properties["background-repeat"].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties["background-attachment"].value)) { - values2.push(properties["background-attachment"].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties["background-origin"].value)) { - values2.push(properties["background-origin"].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties["background-clip"].value)) { - values2.push(properties["background-clip"].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties["background-color"].value)) { - values2.push(properties["background-color"].value); - } - return { - important, - value: values2.join(" ") - }; - } - /** - * Returns background position. - * - * @param properties Properties. - * @returns Property value - */ - static getBackgroundPosition(properties) { - if (!properties["background-position-x"]?.value || !properties["background-position-y"]?.value) { - return null; - } - const important = properties["background-position-x"].important && properties["background-position-y"].important; - if (CSSStyleDeclarationValueParser.getGlobal(properties["background-position-x"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["background-position-y"].value)) { - if (properties["background-position-x"].value !== properties["background-position-y"].value) { - return null; - } - return { - important, - value: properties["background-position-x"].value - }; - } - const positionX = properties["background-position-x"].value.replace(/ *, */g, ",").split(","); - const positionY = properties["background-position-y"].value.replace(/ *, */g, ",").split(","); - const parts = []; - for (let i = 0; i < positionX.length; i++) { - parts.push(`${positionX[i]} ${positionY[i]}`); - } - return { - important, - value: parts.join(", ") - }; - } - /** - * Returns flex. - * - * @param properties Properties. - * @returns Property value - */ - static getFlex(properties) { - if (!properties["flex-grow"]?.value || !properties["flex-shrink"]?.value || !properties["flex-basis"]?.value) { - return null; - } - const important = properties["flex-grow"].important && properties["flex-shrink"].important && properties["flex-basis"].important; - if (CSSStyleDeclarationValueParser.getGlobal(properties["flex-grow"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["flex-shrink"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["flex-basis"].value)) { - if (properties["flex-grow"].value !== properties["flex-shrink"].value || properties["flex-grow"].value !== properties["flex-basis"].value) { - return null; - } - return { - important, - value: properties["flex-grow"].value - }; - } - return { - important, - value: `${properties["flex-grow"].value} ${properties["flex-shrink"].value} ${properties["flex-basis"].value}` - }; - } - /** - * Returns flex. - * - * @param properties Properties. - * @returns Property value - */ - static getFont(properties) { - if (!properties["font-size"]?.value || !properties["font-family"]?.value || !properties["font-weight"]?.value || !properties["font-style"]?.value || !properties["font-variant"]?.value || !properties["font-stretch"]?.value || !properties["line-height"]?.value) { - return null; - } - const important = properties["font-size"].important && properties["font-family"].important && properties["font-weight"].important && properties["font-style"].important && properties["font-variant"].important && properties["font-stretch"].important && properties["line-height"].important; - if (CSSStyleDeclarationValueParser.getGlobal(properties["font-size"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["font-family"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["font-weight"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["font-style"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["font-variant"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["font-stretch"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["line-height"].value)) { - if (properties["font-size"].value !== properties["font-family"].value || properties["font-size"].value !== properties["font-weight"].value || properties["font-size"].value !== properties["font-style"].value || properties["font-size"].value !== properties["font-variant"].value || properties["font-size"].value !== properties["font-stretch"].value || properties["font-size"].value !== properties["line-height"].value) { - return null; - } - return { - important, - value: properties["font-size"].value - }; - } - const values2 = []; - if (properties["font-style"].value !== "normal") { - values2.push(properties["font-style"].value); - } - if (properties["font-variant"].value !== "normal") { - values2.push(properties["font-variant"].value); - } - if (properties["font-weight"].value !== "normal") { - values2.push(properties["font-weight"].value); - } - if (properties["font-stretch"].value !== "normal") { - values2.push(properties["font-stretch"].value); - } - if (properties["line-height"].value !== "normal") { - values2.push(`${properties["font-size"].value} / ${properties["line-height"].value}`); - } else { - values2.push(properties["font-size"].value); - } - values2.push(properties["font-family"].value); - return { - important, - value: values2.join(" ") - }; - } - /** - * Returns border. - * - * @param properties Properties. - * @param position - * @returns Property value - */ - static getBorderTopRightBottomLeft(position, properties) { - if (!properties[`border-${position}-width`]?.value || !properties[`border-${position}-style`]?.value || !properties[`border-${position}-color`]?.value) { - return null; - } - const important = properties[`border-${position}-width`].important && properties[`border-${position}-style`].important && properties[`border-${position}-color`].important; - if (CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties[`border-${position}-width`].value) && properties[`border-${position}-width`].value === properties[`border-${position}-style`].value && properties[`border-${position}-width`].value === properties[`border-${position}-color`].value) { - return { - important, - value: properties[`border-${position}-width`].value - }; - } - const values2 = []; - if (!CSSStyleDeclarationValueParser.getInitial(properties[`border-${position}-width`].value)) { - values2.push(properties[`border-${position}-width`].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties[`border-${position}-style`]?.value)) { - values2.push(properties[`border-${position}-style`].value); - } - if (!CSSStyleDeclarationValueParser.getInitial(properties[`border-${position}-color`]?.value)) { - values2.push(properties[`border-${position}-color`].value); - } - return { - important, - value: values2.join(" ") - }; - } - /** - * Returns a padding like property. - * - * @param properties Properties. - * @param position - * @param propertyNames - * @returns Property value - */ - static getPaddingLikeProperty(propertyNames, properties) { - if (!properties[propertyNames[0]]?.value || !properties[propertyNames[1]]?.value || !properties[propertyNames[2]]?.value || !properties[propertyNames[3]]?.value) { - return null; - } - const important = properties[propertyNames[0]].important && properties[propertyNames[1]].important && properties[propertyNames[2]].important && properties[propertyNames[3]].important; - if (CSSStyleDeclarationValueParser.getGlobal(properties[propertyNames[0]].value) || CSSStyleDeclarationValueParser.getGlobal(properties[propertyNames[1]].value) || CSSStyleDeclarationValueParser.getGlobal(properties[propertyNames[2]].value) || CSSStyleDeclarationValueParser.getGlobal(properties[propertyNames[3]].value)) { - if (properties[propertyNames[0]].value !== properties[propertyNames[1]].value || properties[propertyNames[0]].value !== properties[propertyNames[2]].value || properties[propertyNames[0]].value !== properties[propertyNames[3]].value) { - return null; - } - return { - important, - value: properties[propertyNames[0]].value - }; - } - const values2 = [properties[propertyNames[0]].value]; - if (properties[propertyNames[1]].value !== properties[propertyNames[0]].value || properties[propertyNames[2]].value !== properties[propertyNames[0]].value || properties[propertyNames[3]].value !== properties[propertyNames[1]].value) { - values2.push(properties[propertyNames[1]].value); - } - if (properties[propertyNames[2]].value !== properties[propertyNames[0]].value || properties[propertyNames[3]].value !== properties[propertyNames[1]].value) { - values2.push(properties[propertyNames[2]].value); - } - if (properties[propertyNames[3]].value !== properties[propertyNames[1]].value) { - values2.push(properties[propertyNames[3]].value); - } - return { - important, - value: values2.join(" ") - }; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/css-parser/CSSStyleDeclarationCSSParser.js -var SPLIT_RULES_REGEXP, CSSStyleDeclarationCSSParser; -var init_CSSStyleDeclarationCSSParser = __esm({ - "node_modules/happy-dom/lib/css/declaration/css-parser/CSSStyleDeclarationCSSParser.js"() { - SPLIT_RULES_REGEXP = /\s*([^:;]+?)\s*:\s*((?:[^(;]*?(?:\([^)]*\))?)*?)\s*(!important)?\s*(?:$|;)/g; - CSSStyleDeclarationCSSParser = class { - /** - * Class construtor. - * - * @param cssText CSS string. - * @param callback Callback. - */ - static parse(cssText2) { - const properties = {}; - const rules = []; - const regexp = new RegExp(SPLIT_RULES_REGEXP); - let match; - while (match = regexp.exec(cssText2)) { - const name2 = (match[1] ?? "").trim(); - const value2 = (match[2] ?? "").trim(); - const important = match[3] ? true : false; - if (name2 && value2) { - if (name2.startsWith("--")) { - properties[name2] = value2; - } - rules.push({ name: name2, value: value2, important }); - } - } - return { rules, properties }; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.js -var TO_STRING_SHORTHAND_PROPERTIES, CSSStyleDeclarationPropertyManager; -var init_CSSStyleDeclarationPropertyManager = __esm({ - "node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.js"() { - init_CSSStyleDeclarationPropertySetParser(); - init_CSSStyleDeclarationValueParser(); - init_CSSStyleDeclarationPropertyGetParser(); - init_CSSStyleDeclarationCSSParser(); - TO_STRING_SHORTHAND_PROPERTIES = [ - ["margin"], - ["padding"], - ["border", ["border-width", "border-style", "border-color", "border-image"]], - ["border-radius"], - ["background", "background-position"], - ["font"] - ]; - CSSStyleDeclarationPropertyManager = class { - properties = {}; - definedPropertyNames = {}; - /** - * Class construtor. - * - * @param [options] Options. - * @param [options.cssText] CSS string. - */ - constructor(options2) { - if (options2?.cssText) { - const { rules } = CSSStyleDeclarationCSSParser.parse(options2.cssText); - for (const rule of rules) { - if (rule.important || !this.get(rule.name)?.important) { - this.set(rule.name, rule.value, rule.important); - } - } - } - } - /** - * Returns property value. - * - * @param name Property name. - * @returns Property value. - */ - get(name2) { - if (this.properties[name2]) { - return this.properties[name2]; - } - switch (name2) { - case "margin": - return CSSStyleDeclarationPropertyGetParser.getMargin(this.properties); - case "padding": - return CSSStyleDeclarationPropertyGetParser.getPadding(this.properties); - case "border": - return CSSStyleDeclarationPropertyGetParser.getBorder(this.properties); - case "border-top": - return CSSStyleDeclarationPropertyGetParser.getBorderTop(this.properties); - case "border-right": - return CSSStyleDeclarationPropertyGetParser.getBorderRight(this.properties); - case "border-bottom": - return CSSStyleDeclarationPropertyGetParser.getBorderBottom(this.properties); - case "border-left": - return CSSStyleDeclarationPropertyGetParser.getBorderLeft(this.properties); - case "border-color": - return CSSStyleDeclarationPropertyGetParser.getBorderColor(this.properties); - case "border-style": - return CSSStyleDeclarationPropertyGetParser.getBorderStyle(this.properties); - case "border-width": - return CSSStyleDeclarationPropertyGetParser.getBorderWidth(this.properties); - case "border-radius": - return CSSStyleDeclarationPropertyGetParser.getBorderRadius(this.properties); - case "border-image": - return CSSStyleDeclarationPropertyGetParser.getBorderImage(this.properties); - case "outline": - return CSSStyleDeclarationPropertyGetParser.getOutline(this.properties); - case "background": - return CSSStyleDeclarationPropertyGetParser.getBackground(this.properties); - case "background-position": - return CSSStyleDeclarationPropertyGetParser.getBackgroundPosition(this.properties); - case "flex": - return CSSStyleDeclarationPropertyGetParser.getFlex(this.properties); - case "font": - return CSSStyleDeclarationPropertyGetParser.getFont(this.properties); - } - return this.properties[name2] || null; - } - /** - * Removes a property. - * - * @param name Property name. - */ - remove(name2) { - delete this.properties[name2]; - delete this.definedPropertyNames[name2]; - switch (name2) { - case "border": - delete this.properties["border-top-width"]; - delete this.properties["border-right-width"]; - delete this.properties["border-bottom-width"]; - delete this.properties["border-left-width"]; - delete this.properties["border-top-style"]; - delete this.properties["border-right-style"]; - delete this.properties["border-bottom-style"]; - delete this.properties["border-left-style"]; - delete this.properties["border-top-color"]; - delete this.properties["border-right-color"]; - delete this.properties["border-bottom-color"]; - delete this.properties["border-left-color"]; - delete this.properties["border-image-source"]; - delete this.properties["border-image-slice"]; - delete this.properties["border-image-width"]; - delete this.properties["border-image-outset"]; - delete this.properties["border-image-repeat"]; - break; - case "border-top": - delete this.properties["border-top-width"]; - delete this.properties["border-top-style"]; - delete this.properties["border-top-color"]; - delete this.properties["border-image-source"]; - delete this.properties["border-image-slice"]; - delete this.properties["border-image-width"]; - delete this.properties["border-image-outset"]; - delete this.properties["border-image-repeat"]; - break; - case "border-right": - delete this.properties["border-right-width"]; - delete this.properties["border-right-style"]; - delete this.properties["border-right-color"]; - delete this.properties["border-image-source"]; - delete this.properties["border-image-slice"]; - delete this.properties["border-image-width"]; - delete this.properties["border-image-outset"]; - delete this.properties["border-image-repeat"]; - break; - case "border-bottom": - delete this.properties["border-bottom-width"]; - delete this.properties["border-bottom-style"]; - delete this.properties["border-bottom-color"]; - delete this.properties["border-image-source"]; - delete this.properties["border-image-slice"]; - delete this.properties["border-image-width"]; - delete this.properties["border-image-outset"]; - delete this.properties["border-image-repeat"]; - break; - case "border-left": - delete this.properties["border-left-width"]; - delete this.properties["border-left-style"]; - delete this.properties["border-left-color"]; - delete this.properties["border-image-source"]; - delete this.properties["border-image-slice"]; - delete this.properties["border-image-width"]; - delete this.properties["border-image-outset"]; - delete this.properties["border-image-repeat"]; - break; - case "border-width": - delete this.properties["border-top-width"]; - delete this.properties["border-right-width"]; - delete this.properties["border-bottom-width"]; - delete this.properties["border-left-width"]; - break; - case "border-style": - delete this.properties["border-top-style"]; - delete this.properties["border-right-style"]; - delete this.properties["border-bottom-style"]; - delete this.properties["border-left-style"]; - break; - case "border-color": - delete this.properties["border-top-color"]; - delete this.properties["border-right-color"]; - delete this.properties["border-bottom-color"]; - delete this.properties["border-left-color"]; - break; - case "border-image": - delete this.properties["border-image-source"]; - delete this.properties["border-image-slice"]; - delete this.properties["border-image-width"]; - delete this.properties["border-image-outset"]; - delete this.properties["border-image-repeat"]; - break; - case "border-radius": - delete this.properties["border-top-left-radius"]; - delete this.properties["border-top-right-radius"]; - delete this.properties["border-bottom-right-radius"]; - delete this.properties["border-bottom-left-radius"]; - break; - case "outline": - delete this.properties["outline-color"]; - delete this.properties["outline-style"]; - delete this.properties["outline-width"]; - break; - case "background": - delete this.properties["background-color"]; - delete this.properties["background-image"]; - delete this.properties["background-repeat"]; - delete this.properties["background-attachment"]; - delete this.properties["background-position-x"]; - delete this.properties["background-position-y"]; - delete this.properties["background-size"]; - delete this.properties["background-origin"]; - delete this.properties["background-clip"]; - break; - case "background-position": - delete this.properties["background-position-x"]; - delete this.properties["background-position-y"]; - break; - case "flex": - delete this.properties["flex-grow"]; - delete this.properties["flex-shrink"]; - delete this.properties["flex-basis"]; - break; - case "font": - delete this.properties["font-style"]; - delete this.properties["font-variant"]; - delete this.properties["font-weight"]; - delete this.properties["font-stretch"]; - delete this.properties["font-size"]; - delete this.properties["line-height"]; - delete this.properties["font-family"]; - break; - case "padding": - delete this.properties["padding-top"]; - delete this.properties["padding-right"]; - delete this.properties["padding-bottom"]; - delete this.properties["padding-left"]; - break; - case "margin": - delete this.properties["margin-top"]; - delete this.properties["margin-right"]; - delete this.properties["margin-bottom"]; - delete this.properties["margin-left"]; - break; - } - } - /** - * Sets a property - * - * @param name Name. - * @param value Value. - * @param important Important. - */ - set(name2, value2, important) { - if (value2 === null) { - this.remove(name2); - return; - } - let properties = null; - switch (name2) { - case "border": - properties = CSSStyleDeclarationPropertySetParser.getBorder(value2, important); - break; - case "border-top": - properties = CSSStyleDeclarationPropertySetParser.getBorderTop(value2, important); - break; - case "border-right": - properties = CSSStyleDeclarationPropertySetParser.getBorderRight(value2, important); - break; - case "border-bottom": - properties = CSSStyleDeclarationPropertySetParser.getBorderBottom(value2, important); - break; - case "border-left": - properties = CSSStyleDeclarationPropertySetParser.getBorderLeft(value2, important); - break; - case "border-width": - properties = CSSStyleDeclarationPropertySetParser.getBorderWidth(value2, important); - break; - case "border-style": - properties = CSSStyleDeclarationPropertySetParser.getBorderStyle(value2, important); - break; - case "border-color": - properties = CSSStyleDeclarationPropertySetParser.getBorderColor(value2, important); - break; - case "border-image": - properties = CSSStyleDeclarationPropertySetParser.getBorderImage(value2, important); - break; - case "border-image-source": - properties = CSSStyleDeclarationPropertySetParser.getBorderImageSource(value2, important); - break; - case "border-image-slice": - properties = CSSStyleDeclarationPropertySetParser.getBorderImageSlice(value2, important); - break; - case "border-image-width": - properties = CSSStyleDeclarationPropertySetParser.getBorderImageWidth(value2, important); - break; - case "border-image-outset": - properties = CSSStyleDeclarationPropertySetParser.getBorderImageOutset(value2, important); - break; - case "border-image-repeat": - properties = CSSStyleDeclarationPropertySetParser.getBorderImageRepeat(value2, important); - break; - case "border-top-width": - properties = CSSStyleDeclarationPropertySetParser.getBorderTopWidth(value2, important); - break; - case "border-right-width": - properties = CSSStyleDeclarationPropertySetParser.getBorderRightWidth(value2, important); - break; - case "border-bottom-width": - properties = CSSStyleDeclarationPropertySetParser.getBorderBottomWidth(value2, important); - break; - case "border-left-width": - properties = CSSStyleDeclarationPropertySetParser.getBorderLeftWidth(value2, important); - break; - case "border-top-color": - properties = CSSStyleDeclarationPropertySetParser.getBorderTopColor(value2, important); - break; - case "border-right-color": - properties = CSSStyleDeclarationPropertySetParser.getBorderRightColor(value2, important); - break; - case "border-bottom-color": - properties = CSSStyleDeclarationPropertySetParser.getBorderBottomColor(value2, important); - break; - case "border-left-color": - properties = CSSStyleDeclarationPropertySetParser.getBorderLeftColor(value2, important); - break; - case "border-top-style": - properties = CSSStyleDeclarationPropertySetParser.getBorderTopStyle(value2, important); - break; - case "border-right-style": - properties = CSSStyleDeclarationPropertySetParser.getBorderRightStyle(value2, important); - break; - case "border-bottom-style": - properties = CSSStyleDeclarationPropertySetParser.getBorderBottomStyle(value2, important); - break; - case "border-left-style": - properties = CSSStyleDeclarationPropertySetParser.getBorderLeftStyle(value2, important); - break; - case "border-radius": - properties = CSSStyleDeclarationPropertySetParser.getBorderRadius(value2, important); - break; - case "border-top-left-radius": - properties = CSSStyleDeclarationPropertySetParser.getBorderTopLeftRadius(value2, important); - break; - case "border-top-right-radius": - properties = CSSStyleDeclarationPropertySetParser.getBorderTopRightRadius(value2, important); - break; - case "border-bottom-right-radius": - properties = CSSStyleDeclarationPropertySetParser.getBorderBottomRightRadius(value2, important); - break; - case "border-bottom-left-radius": - properties = CSSStyleDeclarationPropertySetParser.getBorderBottomLeftRadius(value2, important); - break; - case "border-collapse": - properties = CSSStyleDeclarationPropertySetParser.getBorderCollapse(value2, important); - break; - case "outline": - properties = CSSStyleDeclarationPropertySetParser.getOutline(value2, important); - break; - case "outline-width": - properties = CSSStyleDeclarationPropertySetParser.getOutlineWidth(value2, important); - break; - case "outline-style": - properties = CSSStyleDeclarationPropertySetParser.getOutlineStyle(value2, important); - break; - case "outline-color": - properties = CSSStyleDeclarationPropertySetParser.getOutlineColor(value2, important); - break; - case "letter-spacing": - properties = CSSStyleDeclarationPropertySetParser.getLetterSpacing(value2, important); - break; - case "word-spacing": - properties = CSSStyleDeclarationPropertySetParser.getWordSpacing(value2, important); - break; - case "clear": - properties = CSSStyleDeclarationPropertySetParser.getClear(value2, important); - break; - case "clip": - properties = CSSStyleDeclarationPropertySetParser.getClip(value2, important); - break; - case "css-float": - properties = CSSStyleDeclarationPropertySetParser.getCSSFloat(value2, important); - break; - case "float": - properties = CSSStyleDeclarationPropertySetParser.getFloat(value2, important); - break; - case "display": - properties = CSSStyleDeclarationPropertySetParser.getDisplay(value2, important); - break; - case "direction": - properties = CSSStyleDeclarationPropertySetParser.getDirection(value2, important); - break; - case "flex": - properties = CSSStyleDeclarationPropertySetParser.getFlex(value2, important); - break; - case "flex-shrink": - properties = CSSStyleDeclarationPropertySetParser.getFlexShrink(value2, important); - break; - case "flex-grow": - properties = CSSStyleDeclarationPropertySetParser.getFlexGrow(value2, important); - break; - case "flex-basis": - properties = CSSStyleDeclarationPropertySetParser.getFlexBasis(value2, important); - break; - case "padding": - properties = CSSStyleDeclarationPropertySetParser.getPadding(value2, important); - break; - case "padding-top": - properties = CSSStyleDeclarationPropertySetParser.getPaddingTop(value2, important); - break; - case "padding-right": - properties = CSSStyleDeclarationPropertySetParser.getPaddingRight(value2, important); - break; - case "padding-bottom": - properties = CSSStyleDeclarationPropertySetParser.getPaddingBottom(value2, important); - break; - case "padding-left": - properties = CSSStyleDeclarationPropertySetParser.getPaddingLeft(value2, important); - break; - case "margin": - properties = CSSStyleDeclarationPropertySetParser.getMargin(value2, important); - break; - case "margin-top": - properties = CSSStyleDeclarationPropertySetParser.getMarginTop(value2, important); - break; - case "margin-right": - properties = CSSStyleDeclarationPropertySetParser.getMarginRight(value2, important); - break; - case "margin-bottom": - properties = CSSStyleDeclarationPropertySetParser.getMarginBottom(value2, important); - break; - case "margin-left": - properties = CSSStyleDeclarationPropertySetParser.getMarginLeft(value2, important); - break; - case "background": - properties = CSSStyleDeclarationPropertySetParser.getBackground(value2, important); - break; - case "background-image": - properties = CSSStyleDeclarationPropertySetParser.getBackgroundImage(value2, important); - break; - case "background-color": - properties = CSSStyleDeclarationPropertySetParser.getBackgroundColor(value2, important); - break; - case "background-repeat": - properties = CSSStyleDeclarationPropertySetParser.getBackgroundRepeat(value2, important); - break; - case "background-attachment": - properties = CSSStyleDeclarationPropertySetParser.getBackgroundAttachment(value2, important); - break; - case "background-position": - properties = CSSStyleDeclarationPropertySetParser.getBackgroundPosition(value2, important); - break; - case "width": - properties = CSSStyleDeclarationPropertySetParser.getWidth(value2, important); - break; - case "height": - properties = CSSStyleDeclarationPropertySetParser.getHeight(value2, important); - break; - case "top": - properties = CSSStyleDeclarationPropertySetParser.getTop(value2, important); - break; - case "right": - properties = CSSStyleDeclarationPropertySetParser.getRight(value2, important); - break; - case "bottom": - properties = CSSStyleDeclarationPropertySetParser.getBottom(value2, important); - break; - case "left": - properties = CSSStyleDeclarationPropertySetParser.getLeft(value2, important); - break; - case "font": - properties = CSSStyleDeclarationPropertySetParser.getFont(value2, important); - break; - case "font-style": - properties = CSSStyleDeclarationPropertySetParser.getFontStyle(value2, important); - break; - case "font-variant": - properties = CSSStyleDeclarationPropertySetParser.getFontVariant(value2, important); - break; - case "font-weight": - properties = CSSStyleDeclarationPropertySetParser.getFontWeight(value2, important); - break; - case "font-stretch": - properties = CSSStyleDeclarationPropertySetParser.getFontStretch(value2, important); - break; - case "font-size": - properties = CSSStyleDeclarationPropertySetParser.getFontSize(value2, important); - break; - case "line-height": - properties = CSSStyleDeclarationPropertySetParser.getLineHeight(value2, important); - break; - case "text-indent": - properties = CSSStyleDeclarationPropertySetParser.getTextIndent(value2, important); - break; - case "font-family": - properties = CSSStyleDeclarationPropertySetParser.getFontFamily(value2, important); - break; - case "color": - properties = CSSStyleDeclarationPropertySetParser.getColor(value2, important); - break; - case "flood-color": - properties = CSSStyleDeclarationPropertySetParser.getFloodColor(value2, important); - break; - case "text-transform": - properties = CSSStyleDeclarationPropertySetParser.getTextTransform(value2, important); - break; - case "visibility": - properties = CSSStyleDeclarationPropertySetParser.getVisibility(value2, important); - break; - case "aspect-ratio": - properties = CSSStyleDeclarationPropertySetParser.getAspectRatio(value2, important); - break; - default: - const trimmedValue = value2.trim(); - if (trimmedValue) { - const globalValue = CSSStyleDeclarationValueParser.getGlobal(trimmedValue); - properties = { - [name2]: { value: globalValue || trimmedValue, important } - }; - } - break; - } - if (properties !== null && Object.keys(properties).length > 0) { - this.definedPropertyNames[name2] = true; - Object.assign(this.properties, properties); - } - } - /** - * Returns a clone. - * - * @returns Clone. - */ - clone() { - const _class = this.constructor; - const clone2 = new _class(); - clone2.properties = JSON.parse(JSON.stringify(this.properties)); - clone2.definedPropertyNames = Object.assign({}, this.definedPropertyNames); - return clone2; - } - /** - * Returns size. - * - * @returns Size. - */ - size() { - return Object.keys(this.properties).length; - } - /** - * Returns property name. - * - * @param index Index. - * @returns Property name. - */ - item(index) { - return Object.keys(this.properties)[index] || ""; - } - /** - * Converts properties to string. - * - * @returns String. - */ - toString() { - const result3 = []; - const clone2 = this.clone(); - const properties = {}; - for (const shorthandPropertyGroup of TO_STRING_SHORTHAND_PROPERTIES) { - for (const shorthandProperty of shorthandPropertyGroup) { - if (Array.isArray(shorthandProperty)) { - let isMatch = false; - for (const childShorthandProperty of shorthandProperty) { - const property = clone2.get(childShorthandProperty); - if (property) { - properties[childShorthandProperty] = property; - clone2.remove(childShorthandProperty); - isMatch = true; - } - } - if (isMatch) { - break; - } - } else { - const property = clone2.get(shorthandProperty); - if (property) { - properties[shorthandProperty] = property; - clone2.remove(shorthandProperty); - break; - } - } - } - } - for (const name2 of Object.keys(clone2.properties)) { - properties[name2] = clone2.get(name2); - } - for (const definedPropertyName of Object.keys(this.definedPropertyNames)) { - const property = properties[definedPropertyName]; - if (property) { - result3.push(`${definedPropertyName}: ${property.value}${property.important ? " !important" : ""};`); - delete properties[definedPropertyName]; - } - } - for (const propertyName of Object.keys(properties)) { - const property = properties[propertyName]; - if (property) { - result3.push(`${propertyName}: ${property.value}${property.important ? " !important" : ""};`); - } - } - return result3.join(" "); - } - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementDefaultCSS.js -var CSSStyleDeclarationElementDefaultCSS_default; -var init_CSSStyleDeclarationElementDefaultCSS = __esm({ - "node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementDefaultCSS.js"() { - CSSStyleDeclarationElementDefaultCSS_default = { - default: "display: inline;", - A: "", - ABBR: "", - ADDRESS: "display: block;", - AREA: "", - ARTICLE: "display: block;", - ASIDE: "display: block;", - AUDIO: "display: none;", - B: "", - BASE: "display: none;", - BDI: "", - BDO: "", - BLOCKQUAOTE: "", - BODY: "display: block;", - TEMPLATE: "display: none;", - FORM: "display: block;", - INPUT: "display: inline-block;", - TEXTAREA: "display: inline-block;", - SCRIPT: "display: none;", - IMG: "", - LINK: "display: none;", - STYLE: "display: none;", - LABEL: "", - SLOT: "display: contents;", - SVG: "", - CIRCLE: "", - ELLIPSE: "", - LINE: "", - PATH: "", - POLYGON: "", - POLYLINE: "", - RECT: "", - STOP: "", - USE: "", - META: "display: none;", - BLOCKQUOTE: "display: block;", - BR: "", - BUTTON: "display: inline-block;", - CANVAS: "", - CAPTION: "display: table-caption;", - CITE: "", - CODE: "", - COL: "display: table-column;", - COLGROUP: "display: table-column-group;", - DATA: "", - DATALIST: "display: none;", - DD: "display: block;", - DEL: "", - DETAILS: "display: block;", - DFN: "", - DIALOG: { - default: "display: none;", - open: "display: block;" - }, - DIV: "display: block;", - DL: "display: block;", - DT: "display: block;", - EM: "", - EMBED: "", - FIELDSET: "display: block;", - FIGCAPTION: "display: block;", - FIGURE: "display: block;", - FOOTER: "display: block;", - H1: "display: block;", - H2: "display: block;", - H3: "display: block;", - H4: "display: block;", - H5: "display: block;", - H6: "display: block;", - HEAD: "display: none;", - HEADER: "display: block;", - HGROUP: "display: block;", - HR: "display: block;", - HTML: 'display: block;direction: ltr;font: 16px "Times New Roman";', - I: "", - IFRAME: "", - INS: "", - KBD: "", - LEGEND: "display: block;", - LI: "display: list-item;", - MAIN: "display: block;", - MAP: "", - MARK: "", - MATH: "", - MENU: "display: block;", - MENUITEM: "", - METER: "display: inline-block;", - NAV: "display: block;", - NOSCRIPT: "", - OBJECT: "", - OL: "display: block;", - OPTGROUP: "display: block;", - OPTION: "display: block;", - OUTPUT: "unicode-bidi: isolate;", - P: "display: block;", - PARAM: "display: none;", - PICTURE: "", - PRE: "display: block;", - PROGRESS: "display: inline-block;", - Q: "", - RB: "", - RP: "display: none;", - RT: "", - RTC: "", - RUBY: "", - S: "", - SAMP: "", - SECTION: "display: block;", - SELECT: "display: inline-block;", - SMALL: "", - SOURCE: "", - SPAN: "", - STRONG: "", - SUB: "", - SUMMARY: "display: block;", - SUP: "", - TABLE: "display: table;", - TBODY: "display: table-row-group;", - TD: "display: table-cell;", - TFOOT: "display: table-footer-group;", - TH: "display: table-cell;", - THEAD: "display: table-header-group;", - TIME: "", - TITLE: "display: none;", - TR: "display: table-row;", - TRACK: "", - U: "", - UL: "display: block;", - VAR: "", - VIDEO: "", - WBR: "" - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementInheritedProperties.js -var CSSStyleDeclarationElementInheritedProperties_default; -var init_CSSStyleDeclarationElementInheritedProperties = __esm({ - "node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementInheritedProperties.js"() { - CSSStyleDeclarationElementInheritedProperties_default = { - "border-collapse": true, - "border-spacing": true, - "caption-side": true, - color: true, - cursor: true, - direction: true, - "empty-cells": true, - "font-family": true, - "font-size": true, - "font-style": true, - "font-variant": true, - "font-weight": true, - "font-size-adjust": true, - "font-stretch": true, - font: true, - "letter-spacing": true, - "line-height": true, - "list-style-image": true, - "list-style-position": true, - "list-style-type": true, - "list-style": true, - orphans: true, - quotes: true, - "tab-size": true, - "text-align": true, - "text-align-last": true, - "text-decoration-color": true, - "text-indent": true, - "text-justify": true, - "text-shadow": true, - "text-transform": true, - visibility: true, - "white-space": true, - widows: true, - "word-break": true, - "word-spacing": true, - "word-wrap": true - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementMeasurementProperties.js -var CSSStyleDeclarationElementMeasurementProperties_default; -var init_CSSStyleDeclarationElementMeasurementProperties = __esm({ - "node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementMeasurementProperties.js"() { - CSSStyleDeclarationElementMeasurementProperties_default = [ - "background-position-x", - "background-position-y", - "background-size", - "border-image-outset", - "border-top-width", - "border-right-width", - "border-bottom-width", - "border-left-width", - "border-top-left-radius", - "border-top-right-radius", - "border-bottom-right-radius", - "border-bottom-left-radius", - "border-image-width", - "clip", - "font-size", - "padding-top", - "padding-right", - "padding-bottom", - "padding-left", - "margin-top", - "margin-right", - "margin-bottom", - "margin-left", - "width", - "height", - "min-width", - "min-height", - "max-width", - "max-height", - "top", - "right", - "bottom", - "left", - "outline-width", - "outline-offset", - "letter-spacing", - "word-spacing", - "text-indent", - "line-height" - ]; - } -}); - -// node_modules/happy-dom/lib/utilities/ClassMethodBinder.js -var ClassMethodBinder; -var init_ClassMethodBinder = __esm({ - "node_modules/happy-dom/lib/utilities/ClassMethodBinder.js"() { - ClassMethodBinder = class { - target; - classes; - cache = /* @__PURE__ */ new Map(); - /** - * Constructor. - * - * @param target Target. - * @param classes Classes. - */ - constructor(target2, classes) { - this.target = target2; - this.classes = classes; - } - /** - * Binds method, getters and setters to a target. - * - * @param name Method name. - */ - bind(name2) { - if (this.cache.has(name2) || name2 === Symbol.iterator || name2 === "constructor") { - return; - } - this.cache.set(name2, true); - const target2 = this.target; - if (!(name2 in target2)) { - return; - } - for (const _class of this.classes) { - const descriptor = Object.getOwnPropertyDescriptor(_class.prototype, name2); - if (descriptor) { - if (typeof descriptor.value === "function") { - if (descriptor.value.toString().startsWith("class ")) { - return; - } - Object.defineProperty(target2, name2, { - ...descriptor, - value: descriptor.value.bind(target2) - }); - } else if (descriptor.get !== void 0) { - Object.defineProperty(target2, name2, { - ...descriptor, - get: descriptor.get?.bind(target2), - set: descriptor.set?.bind(target2) - }); - } - return; - } - } - } - /** - * Prevents a method, getter or setter from being bound. - * - * @param name Method name. - */ - preventBinding(name2) { - this.cache.set(name2, true); - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/node/NodeList.js -var NodeList, NodeList_default; -var init_NodeList = __esm({ - "node_modules/happy-dom/lib/nodes/node/NodeList.js"() { - init_ClassMethodBinder(); - init_PropertySymbol(); - NodeList = class _NodeList { - [items]; - [proxy]; - /** - * Constructor. - * - * @param illegalConstructorSymbol Illegal constructor symbol. - * @param items Items. - */ - constructor(illegalConstructorSymbol, items2) { - if (illegalConstructorSymbol !== illegalConstructor) { - throw new TypeError("Illegal constructor"); - } - this[items] = items2; - const methodBinder = new ClassMethodBinder(this, this.constructor !== _NodeList ? [this.constructor, _NodeList] : [_NodeList]); - const proxy2 = new Proxy(this, { - get: (target2, property) => { - if (property === "length") { - return items2.length; - } - if (property in target2 || typeof property === "symbol") { - methodBinder.bind(property); - return target2[property]; - } - if (property === "") { - return void 0; - } - const index = Number(property); - if (!isNaN(index)) { - return items2[index]; - } - }, - set(target2, property, newValue) { - methodBinder.bind(property); - if (typeof property === "symbol") { - target2[property] = newValue; - return true; - } - const index = Number(property); - if (isNaN(index)) { - target2[property] = newValue; - } - return true; - }, - deleteProperty(target2, property) { - if (typeof property === "symbol") { - delete target2[property]; - return true; - } - const index = Number(property); - if (isNaN(index)) { - delete target2[property]; - } - return true; - }, - ownKeys() { - return Object.keys(items2); - }, - has(target2, property) { - if (property in target2) { - return true; - } - if (typeof property === "symbol") { - return false; - } - const index = Number(property); - return !isNaN(index) && index >= 0 && index < items2.length; - }, - defineProperty(target2, property, descriptor) { - methodBinder.preventBinding(property); - if (property in target2) { - Object.defineProperty(target2, property, descriptor); - return true; - } - return false; - }, - getOwnPropertyDescriptor(target2, property) { - if (property in target2 || typeof property === "symbol") { - return; - } - const index = Number(property); - if (!isNaN(index) && items2[index]) { - return { - value: items2[index], - writable: false, - enumerable: true, - configurable: true - }; - } - } - }); - this[proxy] = proxy2; - return proxy2; - } - /** - * Returns length. - * - * @returns Length. - */ - get length() { - return this[items].length; - } - /** - * Returns `Symbol.toStringTag`. - * - * @returns `Symbol.toStringTag`. - */ - get [Symbol.toStringTag]() { - return "NodeList"; - } - /** - * Returns `[object NodeList]`. - * - * @returns `[object NodeList]`. - */ - toLocaleString() { - return "[object NodeList]"; - } - /** - * Returns `[object NodeList]`. - * - * @returns `[object NodeList]`. - */ - toString() { - return "[object NodeList]"; - } - /** - * Returns item by index. - * - * @param index Index. - */ - item(index) { - const nodes = this[items]; - return index >= 0 && nodes[index] ? nodes[index] : null; - } - /** - * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. - * - * @returns Iterator. - */ - [Symbol.iterator]() { - const items2 = this[items]; - return items2[Symbol.iterator](); - } - /** - * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. - * - * @returns Iterator. - */ - values() { - return this[items].values(); - } - /** - * Returns an iterator, allowing you to go through all key/value pairs contained in this object. - * - * @returns Iterator. - */ - entries() { - return this[items].entries(); - } - /** - * Executes a provided callback function once for each DOMTokenList element. - * - * @param callback Function. - * @param thisArg thisArg. - */ - forEach(callback, thisArg) { - const items2 = this[items]; - const proxy2 = this[proxy] ?? this; - for (let i = 0, max = items2.length; i < max; i++) { - const item = items2[i]; - callback.call(thisArg ?? item[window], item, i, proxy2); - } - } - /** - * Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object. - * - * @returns Iterator. - */ - keys() { - return this[items].keys(); - } - }; - NodeList_default = NodeList; - } -}); - -// node_modules/happy-dom/lib/query-selector/SelectorCombinatorEnum.js -var SelectorCombinatorEnum, SelectorCombinatorEnum_default; -var init_SelectorCombinatorEnum = __esm({ - "node_modules/happy-dom/lib/query-selector/SelectorCombinatorEnum.js"() { - (function(SelectorCombinatorEnum2) { - SelectorCombinatorEnum2["none"] = "none"; - SelectorCombinatorEnum2["descendant"] = "descendant"; - SelectorCombinatorEnum2["child"] = "child"; - SelectorCombinatorEnum2["adjacentSibling"] = "adjacentSibling"; - SelectorCombinatorEnum2["subsequentSibling"] = "subsequentSibling"; - })(SelectorCombinatorEnum || (SelectorCombinatorEnum = {})); - SelectorCombinatorEnum_default = SelectorCombinatorEnum; - } -}); - -// node_modules/happy-dom/lib/query-selector/SelectorItem.js -var SelectorItem; -var init_SelectorItem = __esm({ - "node_modules/happy-dom/lib/query-selector/SelectorItem.js"() { - init_PropertySymbol(); - init_SelectorCombinatorEnum(); - SelectorItem = class { - tagName; - id; - classNames; - attributes; - pseudos; - isPseudoElement; - combinator; - /** - * Constructor. - * - * @param [options] Options. - * @param [options.combinator] Combinator. - * @param [options.tagName] Tag name. - * @param [options.id] ID. - * @param [options.classNames] Class names. - * @param [options.attributes] Attributes. - * @param [options.pseudos] Pseudos. - * @param [options.isPseudoElement] Is pseudo element. - * @param [options.ignoreErrors] Ignore errors. - */ - constructor(options2) { - this.tagName = options2?.tagName || null; - this.id = options2?.id || null; - this.classNames = options2?.classNames || null; - this.attributes = options2?.attributes || null; - this.pseudos = options2?.pseudos || null; - this.isPseudoElement = options2?.isPseudoElement || false; - this.combinator = options2?.combinator || SelectorCombinatorEnum_default.none; - } - /** - * Matches a selector against an element. - * - * @param scope Scope. - * @param element HTML element. - * @param [ignoreErrors] Ignores errors. - * @returns Result. - */ - match(scope, element, ignoreErrors) { - let priorityWeight = 0; - if (this.isPseudoElement) { - return null; - } - if (this.tagName) { - if (this.tagName !== "*" && this.tagName !== element[tagName].toUpperCase()) { - return null; - } - priorityWeight += 1; - } - if (this.id) { - if (this.id !== element.id) { - return null; - } - priorityWeight += 100; - } - if (this.classNames) { - const result3 = this.matchClass(element); - if (!result3) { - return null; - } - priorityWeight += result3.priorityWeight; - } - if (this.attributes) { - const result3 = this.matchAttributes(element); - if (!result3) { - return null; - } - priorityWeight += result3.priorityWeight; - } - if (this.pseudos) { - const result3 = this.matchPseudo(scope, element, ignoreErrors); - if (!result3) { - return null; - } - priorityWeight += result3.priorityWeight; - } - return { priorityWeight }; - } - /** - * Matches a pseudo selector. - * - * @param scope Scope. - * @param element Element. - * @param [ignoreErrors] Ignores errors. - * @returns Result. - */ - matchPseudo(scope, element, ignoreErrors) { - const parent2 = element[parentNode]; - const parentChildren = element[parentNode] ? element[parentNode][elementArray] : []; - if (!this.pseudos) { - return { priorityWeight: 0 }; - } - let priorityWeight = 0; - for (const pseudo of this.pseudos) { - switch (pseudo.name) { - case "not": - case "nth-child": - case "nth-of-type": - case "nth-last-child": - case "nth-last-of-type": - case "is": - case "where": - if (!pseudo.arguments) { - if (ignoreErrors) { - return null; - } - throw new element[window].DOMException(`Failed to execute 'matches' on '${element.constructor.name}': '${this.getSelectorString()}' is not a valid selector.`); - } - break; - } - if (!parent2) { - switch (pseudo.name) { - case "first-child": - case "last-child": - case "only-child": - case "first-of-type": - case "last-of-type": - case "only-of-type": - case "nth-child": - case "nth-of-type": - case "nth-last-child": - case "nth-last-of-type": - return null; - } - } - const selectorMatch = this.matchPseudoItem(scope, element, parentChildren, pseudo, ignoreErrors); - if (!selectorMatch) { - return null; - } - priorityWeight += selectorMatch.priorityWeight; - } - return { priorityWeight }; - } - /** - * Matches a pseudo selector. - * - * @param scope Scope. - * @param element Element. - * @param parentChildren Parent children. - * @param pseudo Pseudo. - * @param [ignoreErrors] Ignores errors. - */ - matchPseudoItem(scope, element, parentChildren, pseudo, ignoreErrors) { - const root2 = this.getRootElement(scope); - switch (pseudo.name) { - case "first-child": - return parentChildren[0] === element ? { priorityWeight: 10 } : null; - case "last-child": - return parentChildren.length && parentChildren[parentChildren.length - 1] === element ? { priorityWeight: 10 } : null; - case "only-child": - return parentChildren.length === 1 && parentChildren[0] === element ? { priorityWeight: 10 } : null; - case "first-of-type": - for (const child of parentChildren) { - if (child[tagName] === element[tagName]) { - return child === element ? { priorityWeight: 10 } : null; - } - } - return null; - case "last-of-type": - for (let i = parentChildren.length - 1; i >= 0; i--) { - const child = parentChildren[i]; - if (child[tagName] === element[tagName]) { - return child === element ? { priorityWeight: 10 } : null; - } - } - return null; - case "only-of-type": - let isFound = false; - for (const child of parentChildren) { - if (child[tagName] === element[tagName]) { - if (isFound || child !== element) { - return null; - } - isFound = true; - } - } - return isFound ? { priorityWeight: 10 } : null; - case "checked": - return element[tagName] === "INPUT" && element.checked ? { priorityWeight: 10 } : null; - case "disabled": - return "disabled" in element && element.hasAttribute("disabled") ? { priorityWeight: 10 } : null; - case "empty": - return !element[elementArray].length ? { priorityWeight: 10 } : null; - case "root": - return root2 && element === root2 ? { priorityWeight: 10 } : null; - case "not": - for (const selectorItem of pseudo.selectorItems) { - if (selectorItem.match(scope, element)) { - return null; - } - } - return { priorityWeight: 10 }; - case "nth-child": - let nthChildIndex = -1; - if (pseudo.selectorItems?.[0] && !pseudo.selectorItems[0].match(scope, element)) { - return null; - } - for (let i = 0, max = parentChildren.length; i < max; i++) { - if (!pseudo.selectorItems?.[0] || pseudo.selectorItems[0].match(scope, parentChildren[i])) { - nthChildIndex++; - } - if (parentChildren[i] === element) { - return nthChildIndex !== -1 && pseudo.nthFunction(nthChildIndex + 1) ? { priorityWeight: 10 } : null; - } - } - return null; - case "nth-of-type": - let nthOfTypeIndex = -1; - for (let i = 0, max = parentChildren.length; i < max; i++) { - if (parentChildren[i][tagName] === element[tagName]) { - nthOfTypeIndex++; - } - if (parentChildren[i] === element) { - return nthOfTypeIndex !== -1 && pseudo.nthFunction(nthOfTypeIndex + 1) ? { priorityWeight: 10 } : null; - } - } - return null; - case "nth-last-child": - let nthLastChildIndex = -1; - if (pseudo.selectorItems?.[0] && !pseudo.selectorItems[0].match(scope, element)) { - return null; - } - for (let i = parentChildren.length - 1; i >= 0; i--) { - if (!pseudo.selectorItems?.[0] || pseudo.selectorItems[0].match(scope, parentChildren[i])) { - nthLastChildIndex++; - } - if (parentChildren[i] === element) { - return nthLastChildIndex !== -1 && pseudo.nthFunction(nthLastChildIndex + 1) ? { priorityWeight: 10 } : null; - } - } - return null; - case "nth-last-of-type": - let nthLastOfTypeIndex = -1; - for (let i = parentChildren.length - 1; i >= 0; i--) { - if (parentChildren[i][tagName] === element[tagName]) { - nthLastOfTypeIndex++; - } - if (parentChildren[i] === element) { - return nthLastOfTypeIndex !== -1 && pseudo.nthFunction(nthLastOfTypeIndex + 1) ? { priorityWeight: 10 } : null; - } - } - return null; - case "target": - const hash = element[ownerDocument].location.hash; - if (!hash) { - return null; - } - return element.isConnected && element.id === hash.slice(1) ? { priorityWeight: 10 } : null; - case "is": - let priorityWeightForIs = 0; - if (!pseudo.selectorItems) { - return null; - } - for (const selectorItem of pseudo.selectorItems) { - const match = selectorItem.match(scope, element); - if (match && priorityWeightForIs < match.priorityWeight) { - priorityWeightForIs = match.priorityWeight; - } - } - return priorityWeightForIs ? { priorityWeight: priorityWeightForIs } : null; - case "where": - if (!pseudo.selectorItems) { - return null; - } - for (const selectorItem of pseudo.selectorItems) { - if (selectorItem.match(scope, element)) { - return { priorityWeight: 0 }; - } - } - return null; - case "has": - let priorityWeightForHas = 0; - if (pseudo.arguments && pseudo.selectorItems) { - if (pseudo.arguments[0] === "+") { - const nextSibling = element.nextElementSibling; - if (!nextSibling) { - return null; - } - for (const selectorItem of pseudo.selectorItems) { - const match = selectorItem.match(scope, nextSibling); - if (match && priorityWeightForHas < match.priorityWeight) { - priorityWeightForHas = match.priorityWeight; - } - } - } else if (pseudo.arguments[0] === ">") { - for (const selectorItem of pseudo.selectorItems) { - for (const child of element[elementArray]) { - const match = selectorItem.match(scope, child); - if (match && priorityWeightForHas < match.priorityWeight) { - priorityWeightForHas = match.priorityWeight; - break; - } - } - } - } else { - for (const selectorItem of pseudo.selectorItems) { - const match = this.matchChildOfElement(scope, selectorItem, element, ignoreErrors); - if (match && priorityWeightForHas < match.priorityWeight) { - priorityWeightForHas = match.priorityWeight; - } - } - } - } - return priorityWeightForHas ? { priorityWeight: priorityWeightForHas } : null; - case "focus": - case "focus-visible": - return element[ownerDocument].activeElement === element ? { priorityWeight: 10 } : null; - case "scope": - return scope && scope === element ? { priorityWeight: 10 } : null; - default: - return null; - } - } - /** - * Matches attribute. - * - * @param element Element. - * @returns Result. - */ - matchAttributes(element) { - if (!this.attributes) { - return null; - } - let priorityWeight = 0; - for (const attribute of this.attributes) { - const elementAttribute = element[attributes].getNamedItem(attribute.name); - if (!elementAttribute) { - return null; - } - priorityWeight += 10; - if (attribute.value !== null && (elementAttribute[value] === null || attribute.regExp && !attribute.regExp.test(elementAttribute[value]) || !attribute.regExp && attribute.value !== elementAttribute[value])) { - return null; - } - } - return { priorityWeight }; - } - /** - * Matches class. - * - * @param element Element. - * @returns Result. - */ - matchClass(element) { - if (!this.classNames) { - return null; - } - let priorityWeight = 0; - for (const className of this.classNames) { - if (!element.classList.contains(className)) { - return null; - } - priorityWeight += 10; - } - return { priorityWeight }; - } - /** - * Matches a selector item against children of an element. - * - * @param scope Scope. - * @param selectorItem Selector item. - * @param element Element. - * @param [ignoreErrors] Ignores errors. - * @returns Result. - */ - matchChildOfElement(scope, selectorItem, element, ignoreErrors) { - for (const child of element[elementArray]) { - const match = selectorItem.match(scope, child, ignoreErrors); - if (match) { - return match; - } - const childMatch = this.matchChildOfElement(scope, selectorItem, child, ignoreErrors); - if (childMatch) { - return childMatch; - } - } - return null; - } - /** - * Returns the selector string. - * - * @returns Selector string. - */ - getSelectorString() { - return `${this.tagName ? this.tagName.toLowerCase() : ""}${this.id ? `#${this.id}` : ""}${this.classNames ? `.${this.classNames.join(".")}` : ""}${this.attributes ? this.attributes.map((attribute) => `[${attribute.name}${attribute.value ? `${attribute.operator || ""}="${attribute.value}"` : ""}]`).join("") : ""}${this.pseudos ? this.pseudos.map((pseudo) => `:${pseudo.name}${pseudo.arguments ? `(${pseudo.arguments})` : ""}`).join("") : ""}`; - } - /** - * Returns the root element. - * - * @param scope Scope. - * @returns Root element. - */ - getRootElement(scope) { - return scope?.[ownerDocument]?.documentElement || scope?.[window].document?.documentElement || null; - } - }; - } -}); - -// node_modules/happy-dom/lib/query-selector/SelectorParser.js -var SELECTOR_GROUP_REGEXP, SELECTOR_REGEXP, SELECTOR_PSEUDO_REGEXP, ESCAPED_CHARACTER_REGEXP, CSS_UNESCAPE_REGEXP, ATTRIBUTE_ESCAPE_REGEXP, NTH_FUNCTION, SPACE_REGEXP, SelectorParser; -var init_SelectorParser = __esm({ - "node_modules/happy-dom/lib/query-selector/SelectorParser.js"() { - init_SelectorItem(); - init_SelectorCombinatorEnum(); - init_NodeTypeEnum(); - init_PropertySymbol(); - SELECTOR_GROUP_REGEXP = /(\s*[\s,+>~]\s*)|([\[\]\(\)"'])/g; - SELECTOR_REGEXP = /(\*)|([a-zA-Z0-9\u00A0-\uFFFF-]+)|#(([a-zA-Z0-9\u00A0-\uFFFF_-]|\\.)+)|\.(([a-zA-Z0-9\u00A0-\uFFFF_-]|\\.)+)|\[(([a-zA-Z0-9-_]|\\.)+)\]|\[(([a-zA-Z0-9-_]|\\.)+)\s*([~|^$*]{0,1})\s*=\s*("([^"]*)"|'([^']*)')\s*(s|i){0,1}\]|\[(([a-zA-Z0-9-_]|\\.)+)\s*([~|^$*]{0,1})\s*=\s*(([a-zA-Z0-9\u00A0-\uFFFF_¤£-]|\\.)+)\]|:([a-zA-Z-]+)\s*\(.+\)|:([a-zA-Z-]+)|::([a-zA-Z-]+)/g; - SELECTOR_PSEUDO_REGEXP = /:([a-zA-Z-]+)|([()])/g; - ESCAPED_CHARACTER_REGEXP = /\\/g; - CSS_UNESCAPE_REGEXP = /\\([0-9a-fA-F]{1,6})\s?|\\(.)/g; - ATTRIBUTE_ESCAPE_REGEXP = /[.*+?^${}()|[\]\\]/g; - NTH_FUNCTION = { - odd: (n) => (n + 1) % 2 === 0, - even: (n) => (n + 1) % 2 !== 0, - alwaysFalse: () => false - }; - SPACE_REGEXP = / /g; - SelectorParser = class _SelectorParser { - window; - scope; - ignoreErrors; - /** - * Constructor. - * - * @param options - * @param options.window - * @param options.scope - * @param options.ignoreErrors - */ - constructor(options2) { - this.window = options2.window; - this.scope = options2.scope; - this.ignoreErrors = options2.ignoreErrors ?? false; - } - /** - * Parses a selector string and returns an instance of SelectorItem. - * - * @param selector Selector. - * @returns Selector item. - */ - getSelectorItem(selector) { - return this.getSelectorGroups(selector)[0][0]; - } - /** - * Parses a selector string and returns instances of SelectorItem. - * - * @param selector Selector. - * @returns Selector groups. - */ - getSelectorGroups(selector) { - selector = selector.trim(); - const cached = this.window[querySelectorCache].get(selector); - if (cached) { - return cached; - } - const groups = this.getSelectorGroupsUncached(selector); - this.window[querySelectorCache].set(selector, groups); - return groups; - } - /** - * Returns an error for an invalid selector. - * - * Constructed lazily, as creating a DOMException captures the current stack trace, which is - * expensive on hot paths such as Element.matches() and getComputedStyle() during rendering. - * - * @param selector Selector. - * @returns Error. - */ - getInvalidSelectorError(selector) { - const name2 = this.scope.nodeType === NodeTypeEnum_default.documentNode ? "Document" : "Element"; - return new this.window.DOMException(`Failed to execute 'querySelectorAll' on '${name2}': '${selector}' is not a valid selector.`); - } - /** - * Parses a selector string and returns instances of SelectorItem without using cache. - * - * @param selector Selector. - * @returns Selector groups. - */ - getSelectorGroupsUncached(selector) { - let currentGroup = []; - const groups = [currentGroup]; - const regExp = new RegExp(SELECTOR_GROUP_REGEXP); - const depth = { - parentheses: 0, - brackets: 0, - doubleApostrophe: 0, - singleApostrophe: 0 - }; - let match = null; - let lastIndex = 0; - let selectorItem = null; - let combinator = SelectorCombinatorEnum_default.none; - while (match = regExp.exec(selector)) { - if (match[1]) { - if (depth.parentheses === 0 && depth.brackets === 0 && depth.singleApostrophe === 0 && depth.doubleApostrophe === 0) { - const childSelector = selector.substring(lastIndex, match.index).trim(); - switch (match[1].trim()) { - case ",": - selectorItem = this.getSelectorGroupItem(childSelector, combinator); - if (!selectorItem) { - if (this.ignoreErrors) { - return []; - } - throw this.getInvalidSelectorError(selector); - } - currentGroup.push(selectorItem); - currentGroup = []; - groups.push(currentGroup); - combinator = SelectorCombinatorEnum_default.none; - break; - case ">": - selectorItem = this.getSelectorGroupItem(childSelector, combinator); - if (!selectorItem) { - if (this.ignoreErrors) { - return []; - } - throw this.getInvalidSelectorError(selector); - } - currentGroup.push(selectorItem); - combinator = SelectorCombinatorEnum_default.child; - break; - case "+": - selectorItem = this.getSelectorGroupItem(childSelector, combinator); - if (!selectorItem) { - if (this.ignoreErrors) { - return []; - } - throw this.getInvalidSelectorError(selector); - } - currentGroup.push(selectorItem); - combinator = SelectorCombinatorEnum_default.adjacentSibling; - break; - case "~": - selectorItem = this.getSelectorGroupItem(childSelector, combinator); - if (!selectorItem) { - if (this.ignoreErrors) { - return []; - } - throw this.getInvalidSelectorError(selector); - } - currentGroup.push(selectorItem); - combinator = SelectorCombinatorEnum_default.subsequentSibling; - break; - case "": - selectorItem = this.getSelectorGroupItem(childSelector, combinator); - if (!selectorItem) { - if (this.ignoreErrors) { - return []; - } - throw this.getInvalidSelectorError(selector); - } - currentGroup.push(selectorItem); - combinator = SelectorCombinatorEnum_default.descendant; - break; - } - lastIndex = regExp.lastIndex; - } - } else { - switch (match[2]) { - case "(": - if (depth.singleApostrophe === 0 && depth.doubleApostrophe === 0) { - depth.parentheses++; - } - break; - case ")": - if (depth.singleApostrophe === 0 && depth.doubleApostrophe === 0) { - depth.parentheses--; - } - break; - case "[": - if (depth.singleApostrophe === 0 && depth.doubleApostrophe === 0) { - depth.brackets++; - } - break; - case "]": - if (depth.singleApostrophe === 0 && depth.doubleApostrophe === 0) { - depth.brackets--; - } - break; - case '"': - if (depth.singleApostrophe === 0) { - depth.doubleApostrophe = depth.doubleApostrophe === 1 ? 0 : 1; - } - break; - case "'": - if (depth.doubleApostrophe === 0) { - depth.singleApostrophe = depth.singleApostrophe === 1 ? 0 : 1; - } - break; - } - } - } - selectorItem = this.getSelectorGroupItem(selector.substring(lastIndex), combinator); - if (!selectorItem || depth.parentheses !== 0 || depth.brackets !== 0 || depth.singleApostrophe !== 0 || depth.doubleApostrophe !== 0) { - if (this.ignoreErrors) { - return []; - } - throw this.getInvalidSelectorError(selector); - } - if (combinator === SelectorCombinatorEnum_default.none && currentGroup.length > 0) { - groups.push([selectorItem]); - } else { - currentGroup.push(selectorItem); - } - return groups; - } - /** - * Parses a selector string and returns an SelectorItem. - * - * @param selector Selector. - * @param combinator Combinator. - * @returns Selector item. - */ - getSelectorGroupItem(selector, combinator) { - selector = selector.trim(); - if (!selector) { - return null; - } - if (selector === "*") { - return new SelectorItem({ tagName: "*", combinator }); - } - const regexp = new RegExp(SELECTOR_REGEXP); - const selectorItem = new SelectorItem({ - combinator - }); - let match; - let lastIndex = 0; - while (match = regexp.exec(selector)) { - if (selector.substring(lastIndex, match.index).trim() !== "") { - return null; - } - if (match[1]) { - selectorItem.tagName = "*"; - } else if (match[2]) { - selectorItem.tagName = match[2].toUpperCase(); - } else if (match[3]) { - selectorItem.id = match[3].replace(ESCAPED_CHARACTER_REGEXP, ""); - } else if (match[5]) { - selectorItem.classNames = selectorItem.classNames || []; - selectorItem.classNames.push(match[5].replace(ESCAPED_CHARACTER_REGEXP, "")); - } else if (match[7]) { - selectorItem.attributes = selectorItem.attributes || []; - selectorItem.attributes.push({ - name: match[7].replace(ESCAPED_CHARACTER_REGEXP, ""), - operator: null, - value: null, - modifier: null, - regExp: null - }); - } else if (match[9] && (match[13] !== void 0 || match[14] !== void 0)) { - const value2 = match[13] ?? match[14]; - const unescapedValue = _SelectorParser.cssUnescape(value2); - selectorItem.attributes = selectorItem.attributes || []; - selectorItem.attributes.push({ - name: match[9].replace(ESCAPED_CHARACTER_REGEXP, ""), - operator: match[11] || null, - value: unescapedValue, - modifier: match[15] || null, - regExp: this.getAttributeRegExp({ - operator: match[11], - value: unescapedValue, - modifier: match[15] - }) - }); - } else if (match[16] && match[19] !== void 0) { - const unescapedValue = _SelectorParser.cssUnescape(match[19]); - selectorItem.attributes = selectorItem.attributes || []; - selectorItem.attributes.push({ - name: match[16].replace(ESCAPED_CHARACTER_REGEXP, ""), - operator: match[18] || null, - value: unescapedValue, - modifier: null, - regExp: this.getAttributeRegExp({ operator: match[18], value: unescapedValue }) - }); - } else if (match[21]) { - const pseudoRegExp = new RegExp(SELECTOR_PSEUDO_REGEXP); - let pseudoMatch = null; - let name2 = null; - let depth = 0; - let pseudoStartIndex = -1; - while (pseudoMatch = pseudoRegExp.exec(match[0])) { - if (pseudoMatch[1]) { - if (depth === 0) { - name2 = pseudoMatch[1]; - } - } else if (pseudoMatch[2]) { - if (pseudoMatch[2] === "(") { - if (depth === 0) { - pseudoStartIndex = pseudoRegExp.lastIndex; - } - depth++; - } else if (pseudoMatch[2] === ")") { - depth--; - if (depth < 0) { - return null; - } - if (depth === 0) { - if (pseudoStartIndex === -1 || !name2) { - return null; - } - selectorItem.pseudos = selectorItem.pseudos || []; - selectorItem.pseudos.push(this.getPseudo(name2, match[0].substring(pseudoStartIndex, pseudoMatch.index))); - name2 = null; - pseudoStartIndex = -1; - } - } - } - } - } else if (match[22]) { - selectorItem.pseudos = selectorItem.pseudos || []; - selectorItem.pseudos.push(this.getPseudo(match[22], null)); - } else if (match[23]) { - selectorItem.isPseudoElement = true; - } - lastIndex = regexp.lastIndex; - } - if (lastIndex < selector.length) { - return null; - } - return selectorItem; - } - /** - * Returns attribute RegExp. - * - * @param attribute Attribute. - * @param attribute.value Attribute value. - * @param attribute.operator Attribute operator. - * @param attribute.modifier Attribute modifier. - * @returns Attribute RegExp. - */ - getAttributeRegExp(attribute) { - const modifier = attribute.modifier === "i" ? "i" : ""; - if (!attribute.operator || !attribute.value) { - return null; - } - const escapedValue = attribute.value.replace(ATTRIBUTE_ESCAPE_REGEXP, "\\$&"); - switch (attribute.operator) { - // [attribute~="value"] - Contains a specified word. - case "~": - return new RegExp(`(^|\\s)${escapedValue}(\\s|$)`, modifier); - // [attribute|="value"] - Starts with the specified word. - case "|": - return new RegExp(`^${escapedValue}[- ]|^${escapedValue}$`, modifier); - // [attribute^="value"] - Begins with a specified value. - case "^": - return new RegExp(`^${escapedValue}`, modifier); - // [attribute$="value"] - Ends with a specified value. - case "$": - return new RegExp(`${escapedValue}$`, modifier); - // [attribute*="value"] - Contains a specified value. - case "*": - return new RegExp(`${escapedValue}`, modifier); - default: - return null; - } - } - /** - * Returns pseudo. - * - * @param name Pseudo name. - * @param args Pseudo arguments. - * @returns Pseudo. - */ - getPseudo(name2, args) { - const lowerName = name2.toLowerCase(); - if (args) { - args = args.trim(); - } - if (!args) { - return { name: lowerName, arguments: null, selectorItems: null, nthFunction: null }; - } - switch (lowerName) { - case "nth-last-child": - case "nth-child": - const nthOfIndex = args.indexOf(" of "); - const nthFunction = nthOfIndex !== -1 ? args.substring(0, nthOfIndex) : args; - const selectorItem = nthOfIndex !== -1 ? this.getSelectorItem(args.substring(nthOfIndex + 4).trim()) : null; - return { - name: lowerName, - arguments: args, - selectorItems: selectorItem ? [selectorItem] : null, - nthFunction: this.getPseudoNthFunction(nthFunction) - }; - case "nth-of-type": - case "nth-last-of-type": - return { - name: lowerName, - arguments: args, - selectorItems: null, - nthFunction: this.getPseudoNthFunction(args) - }; - case "not": - const notSelectorItems = []; - for (const group of this.getSelectorGroups(args)) { - if (group[0]) { - notSelectorItems.push(group[0]); - } - } - return { - name: lowerName, - arguments: args, - selectorItems: notSelectorItems, - nthFunction: null - }; - case "is": - case "where": - const selectorItems = []; - for (const group of this.getSelectorGroups(args)) { - if (group[0]) { - selectorItems.push(group[0]); - } - } - return { - name: lowerName, - arguments: args, - selectorItems, - nthFunction: null - }; - case "has": - const hasSelectorItems = []; - if (!args.includes(":has(")) { - let newArgs = args; - if (args[0] === "+") { - newArgs = args.replace("+", ""); - } else if (args[0] === ">") { - newArgs = args.replace(">", ""); - } - for (const group of this.getSelectorGroups(newArgs)) { - if (group[0]) { - hasSelectorItems.push(group[0]); - } - } - } - return { - name: lowerName, - arguments: args || "", - selectorItems: hasSelectorItems, - nthFunction: null - }; - case "scope": - case "root": - default: - return { name: lowerName, arguments: args, selectorItems: null, nthFunction: null }; - } - } - /** - * Returns pseudo nth function. - * - * Based on: - * https://github.com/dperini/nwsapi/blob/master/src/nwsapi.js - * - * @param args Pseudo arguments. - * @returns Pseudo nth function. - */ - getPseudoNthFunction(args) { - if (!args) { - return null; - } - if (args === "odd") { - return NTH_FUNCTION.odd; - } else if (args === "even") { - return NTH_FUNCTION.even; - } - const parts = args.replace(SPACE_REGEXP, "").split("n"); - let partA = parseInt(parts[0], 10) || 0; - if (parts[0] == "-") { - partA = -1; - } - if (parts.length === 1) { - return (n) => n == partA; - } - let partB = parseInt(parts[1], 10) || 0; - if (parts[0] == "+") { - partB = 1; - } - if (partA >= 1 || partA <= -1) { - if (partA >= 1) { - if (Math.abs(partA) === 1) { - return (n) => n > partB - 1; - } - return (n) => n > partB - 1 && (n + -1 * partB) % partA === 0; - } - if (Math.abs(partA) === 1) { - return (n) => n < partB + 1; - } - return (n) => n < partB + 1 && (n + -1 * partB) % partA === 0; - } - if (parts[0]) { - return (n) => n === partB; - } - return (n) => n > partB - 1; - } - /** - * Unescapes CSS escape sequences in a string value. - * - * Handles hex escapes (e.g. "\30 " → "0", "\0041" → "A") and character escapes (e.g. "\:" → ":"). - * - * @see https://www.w3.org/TR/css-syntax-3/#consume-escaped-code-point - * @param value Escaped CSS value. - * @returns Unescaped value. - */ - static cssUnescape(value2) { - return value2.replace(CSS_UNESCAPE_REGEXP, (_match, hex, char) => { - if (hex) { - return String.fromCodePoint(parseInt(hex, 16)); - } - return char; - }); - } - }; - } -}); - -// node_modules/happy-dom/lib/query-selector/QuerySelector.js -var INVALID_SELECTOR_REGEXP, QuerySelector; -var init_QuerySelector = __esm({ - "node_modules/happy-dom/lib/query-selector/QuerySelector.js"() { - init_PropertySymbol(); - init_NodeList(); - init_NodeTypeEnum(); - init_SelectorCombinatorEnum(); - init_SelectorParser(); - INVALID_SELECTOR_REGEXP = /^[.#\[]?\d|[.#]$/; - QuerySelector = class { - /** - * Finds elements based on a query selector. - * - * @param node Node to search in. - * @param selector Selector. - * @returns HTML elements. - */ - static querySelectorAll(node, selector) { - const window2 = node[window]; - if (selector === "") { - throw new window2.DOMException(`Failed to execute 'querySelectorAll' on '${node.constructor.name}': The provided selector is empty.`); - } - if (typeof selector === "function") { - throw new window2.DOMException(`Failed to execute 'querySelectorAll' on '${node.constructor.name}': '${selector}' is not a valid selector.`); - } - if (typeof selector === "symbol") { - throw new window2.TypeError(`Failed to execute 'querySelectorAll' on '${node.constructor.name}': Cannot convert a Symbol value to a string`); - } - selector = String(selector); - if (INVALID_SELECTOR_REGEXP.test(selector)) { - throw new window2.DOMException(`Failed to execute 'querySelectorAll' on '${node.constructor.name}': '${selector}' is not a valid selector.`); - } - const cache2 = node[cache].querySelectorAll; - const cachedResult = cache2.get(selector); - if (cachedResult) { - if (cachedResult.result !== null) { - const result3 = cachedResult.result.deref(); - if (result3) { - return result3; - } - } - cache2.delete(selector); - } - const scope = node[nodeType] === NodeTypeEnum_default.documentNode ? node.documentElement : node; - const groups = new SelectorParser({ window: window2, scope }).getSelectorGroups(selector); - const items2 = []; - const nodeList = new NodeList_default(illegalConstructor, items2); - const matchesMap = /* @__PURE__ */ new Map(); - const matchedPositions = []; - const cachedItem = { - result: new WeakRef(nodeList) - }; - node[cache].querySelectorAll.set(selector, cachedItem); - if (node[isConnected]) { - (node[ownerDocument] || node)[affectsCache].push(cachedItem); - } - for (const selectorItems of groups) { - const rootElement = node[nodeType] === NodeTypeEnum_default.elementNode ? node : null; - const children2 = node[nodeType] === NodeTypeEnum_default.elementNode ? [node] : node[elementArray]; - const matches = this.findAll({ scope, rootElement, children: children2, selectorItems, cachedItem }); - for (const match of matches) { - if (!matchesMap.has(match.documentPosition)) { - matchesMap.set(match.documentPosition, match.element); - matchedPositions.push(match.documentPosition); - } - } - } - const keys = matchedPositions.sort(); - for (let i = 0, max = keys.length; i < max; i++) { - items2.push(matchesMap.get(keys[i])); - } - return nodeList; - } - /** - * Finds an element based on a query selector. - * - * @param node Node to search in. - * @param selector Selector. - * @returns HTML element. - */ - static querySelector(node, selector) { - const window2 = node[window]; - if (selector === "") { - throw new window2.DOMException(`Failed to execute 'querySelector' on '${node.constructor.name}': The provided selector is empty.`); - } - if (typeof selector === "function") { - throw new window2.DOMException(`Failed to execute 'querySelector' on '${node.constructor.name}': '${selector}' is not a valid selector.`); - } - if (typeof selector === "symbol") { - throw new window2.TypeError(`Failed to execute 'querySelector' on '${node.constructor.name}': Cannot convert a Symbol value to a string`); - } - selector = String(selector); - if (INVALID_SELECTOR_REGEXP.test(selector)) { - throw new window2.DOMException(`Failed to execute 'querySelector' on '${node.constructor.name}': '${selector}' is not a valid selector.`); - } - const cachedResult = node[cache].querySelector.get(selector); - if (cachedResult) { - if (cachedResult.result !== null) { - if (!cachedResult.result.element) { - return null; - } - const result3 = cachedResult.result.element.deref(); - if (result3) { - return result3; - } - } - node[cache].querySelector.delete(selector); - } - const cachedItem = { - result: { element: null } - }; - node[cache].querySelector.set(selector, cachedItem); - if (node[isConnected]) { - (node[ownerDocument] || node)[affectsCache].push(cachedItem); - } - let bestMatch = null; - const matchesMap = /* @__PURE__ */ new Map(); - const scope = node[nodeType] === NodeTypeEnum_default.documentNode ? node.documentElement : node; - for (const selectorItems of new SelectorParser({ window: window2, scope }).getSelectorGroups(selector)) { - const rootElement = node[nodeType] === NodeTypeEnum_default.elementNode ? node : null; - const children2 = node[nodeType] === NodeTypeEnum_default.elementNode ? [node] : node[elementArray]; - const match = this.findFirst({ scope, rootElement, children: children2, selectorItems, cachedItem }); - if (match && !matchesMap.has(match.documentPosition)) { - matchesMap.set(match.documentPosition, true); - if (!bestMatch || match.documentPosition < bestMatch.documentPosition) { - bestMatch = match; - } - } - } - const element = bestMatch?.element || null; - cachedItem.result = { element: element ? new WeakRef(element) : null }; - return element; - } - /** - * Checks if an element matches a selector and returns priority weight. - * - * @param element Element to match. - * @param selector Selector to match with. - * @param [options] Options. - * @param [options.scope] Scope. - * @param [options.ignoreErrors] Ignores errors. - * @returns Result. - */ - static matches(element, selector, options2) { - const ignoreErrors = options2?.ignoreErrors; - const window2 = element[window]; - if (selector === "*") { - return { - priorityWeight: 1 - }; - } - if (selector === "") { - if (ignoreErrors) { - return null; - } - throw new window2.DOMException(`Failed to execute 'matches' on '${element.constructor.name}': The provided selector is empty.`); - } - if (typeof selector === "function") { - if (ignoreErrors) { - return null; - } - throw new window2.DOMException(`Failed to execute 'matches' on '${element.constructor.name}': '${selector}' is not a valid selector.`); - } - if (typeof selector === "symbol") { - if (ignoreErrors) { - return null; - } - throw new window2.TypeError(`Cannot convert a Symbol value to a string`); - } - selector = String(selector); - if (INVALID_SELECTOR_REGEXP.test(selector)) { - if (ignoreErrors) { - return null; - } - throw new window2.DOMException(`Failed to execute 'matches' on '${element.constructor.name}': '${selector}' is not a valid selector.`); - } - const cachedResult = element[cache].matches.get(selector); - if (cachedResult) { - if (cachedResult.result !== null) { - return cachedResult.result.match; - } - element[cache].matches.delete(selector); - } - const cachedItem = { - result: { match: null } - }; - element[cache].matches.set(selector, cachedItem); - if (element[isConnected]) { - (element[ownerDocument] || element)[affectsCache].push(cachedItem); - } - const scopeOrElement = options2?.scope || element; - const scope = scopeOrElement[nodeType] === NodeTypeEnum_default.documentNode ? scopeOrElement.documentElement : scopeOrElement; - for (const items2 of new SelectorParser({ - ignoreErrors: options2?.ignoreErrors, - window: window2, - scope - }).getSelectorGroups(selector)) { - const result3 = this.matchSelector({ - scope, - element, - selectorItems: items2.slice().reverse(), - cachedItem, - ignoreErrors - }); - if (result3) { - cachedItem.result.match = result3; - return result3; - } - } - return null; - } - /** - * Checks if a node matches a selector. - * - * @param options Options. - * @param options.scope Scope. - * @param options.element Target element. - * @param options.currentElement - * @param options.selectorItems Selector items. - * @param options.cachedItem Cached item. - * @param [options.ignoreErrors] Ignores errors. - * @param [previousSelectorItem] Previous selector item. - * @param [priorityWeight] Priority weight. - * @returns Result. - */ - static matchSelector(options2, previousSelectorItem = null, priorityWeight = 0) { - const { scope, element, selectorItems, cachedItem, ignoreErrors } = options2; - const selectorItem = selectorItems[0]; - if (!selectorItem) { - return null; - } - const result3 = selectorItem.match(scope, element, ignoreErrors); - if (result3) { - if (selectorItems.length === 1) { - return { - priorityWeight: priorityWeight + result3.priorityWeight - }; - } - switch (selectorItem.combinator) { - case SelectorCombinatorEnum_default.adjacentSibling: - const previousElementSibling = element.previousElementSibling; - if (previousElementSibling) { - previousElementSibling[affectsCache].push(cachedItem); - const match = this.matchSelector({ - scope, - element: previousElementSibling, - selectorItems: selectorItems.slice(1), - cachedItem, - ignoreErrors - }, selectorItem, priorityWeight + result3.priorityWeight); - if (match) { - return match; - } - } - break; - case SelectorCombinatorEnum_default.none: - case SelectorCombinatorEnum_default.child: - case SelectorCombinatorEnum_default.descendant: - const parentElement = element.parentElement; - if (parentElement) { - parentElement[affectsCache].push(cachedItem); - const match = this.matchSelector({ - scope, - element: parentElement, - selectorItems: selectorItems.slice(1), - cachedItem, - ignoreErrors - }, selectorItem, priorityWeight + result3.priorityWeight); - if (match) { - return match; - } - } - break; - case SelectorCombinatorEnum_default.subsequentSibling: - const siblingParentElement = element.parentElement; - if (siblingParentElement) { - const siblings = siblingParentElement[elementArray]; - const index = siblings.indexOf(element); - siblingParentElement[affectsCache].push(cachedItem); - for (let i = index - 1; i >= 0; i--) { - const sibling = siblings[i]; - sibling[affectsCache].push(cachedItem); - const match = this.matchSelector({ - scope, - element: sibling, - selectorItems: selectorItems.slice(1), - cachedItem, - ignoreErrors - }, selectorItem, priorityWeight + result3.priorityWeight); - if (match) { - return match; - } - } - } - break; - } - } - if (previousSelectorItem?.combinator === SelectorCombinatorEnum_default.none || previousSelectorItem?.combinator === SelectorCombinatorEnum_default.descendant) { - const parentElement = element.parentElement; - if (parentElement) { - return this.matchSelector({ - scope, - element: parentElement, - selectorItems, - cachedItem, - ignoreErrors - }, previousSelectorItem, priorityWeight); - } - } - return null; - } - /** - * Finds elements based on a query selector for a part of a list of selectors separated with comma. - * - * @param options Options. - * @param options.scope Scope. - * @param options.rootElement Root element. - * @param options.children Child elements. - * @param options.selectorItems Selector items. - * @param options.cachedItem Cached item. - * @param [documentPosition] Document position of the element. - * @returns Document position and element map. - */ - static findAll(options2, documentPosition) { - const { scope, rootElement, children: children2, selectorItems, cachedItem } = options2; - const selectorItem = selectorItems[0]; - const nextSelectorItem = selectorItems[1]; - let matched = []; - if (!selectorItem) { - return []; - } - for (let i = 0, max = children2.length; i < max; i++) { - const child = children2[i]; - const childrenOfChild = child[elementArray]; - const position = (documentPosition ? documentPosition + ">" : "") + String.fromCharCode(i); - child[affectsCache].push(cachedItem); - if (selectorItem.match(scope, child)) { - if (!nextSelectorItem) { - if (rootElement !== child) { - matched.push({ - documentPosition: position, - element: child - }); - } - } else { - switch (nextSelectorItem.combinator) { - case SelectorCombinatorEnum_default.adjacentSibling: - const nextElementSibling = child.nextElementSibling; - if (nextElementSibling) { - matched = matched.concat(this.findAll({ - scope, - rootElement, - children: [nextElementSibling], - selectorItems: selectorItems.slice(1), - cachedItem - }, position)); - } - break; - case SelectorCombinatorEnum_default.none: - case SelectorCombinatorEnum_default.descendant: - case SelectorCombinatorEnum_default.child: - matched = matched.concat(this.findAll({ - scope, - rootElement, - children: childrenOfChild, - selectorItems: selectorItems.slice(1), - cachedItem - }, position)); - break; - case SelectorCombinatorEnum_default.subsequentSibling: - const index = children2.indexOf(child); - for (let j = index + 1; j < children2.length; j++) { - const sibling = children2[j]; - matched = matched.concat(this.findAll({ - scope, - rootElement, - children: [sibling], - selectorItems: selectorItems.slice(1), - cachedItem - }, position)); - } - break; - } - } - } - if ((selectorItem.combinator === SelectorCombinatorEnum_default.none || selectorItem.combinator === SelectorCombinatorEnum_default.descendant) && childrenOfChild.length) { - matched = matched.concat(this.findAll({ - scope, - rootElement, - children: childrenOfChild, - selectorItems, - cachedItem - }, position)); - } - } - return matched; - } - /** - * Finds an element based on a query selector for a part of a list of selectors separated with comma. - * - * @param options Options. - * @param options.scope Scope. - * @param options.rootElement Root element. - * @param options.children Child elements. - * @param options.selectorItems Selector items. - * @param options.cachedItem Cached item. - * @param [documentPosition] Document position of the element. - * @returns Document position and element map. - */ - static findFirst(options2, documentPosition) { - const { scope, rootElement, children: children2, selectorItems, cachedItem } = options2; - const selectorItem = selectorItems[0]; - const nextSelectorItem = selectorItems[1]; - if (!selectorItem) { - return null; - } - for (let i = 0, max = children2.length; i < max; i++) { - const child = children2[i]; - const childrenOfChild = child[elementArray]; - const position = (documentPosition ? documentPosition + ">" : "") + String.fromCharCode(i); - child[affectsCache].push(cachedItem); - if (selectorItem.match(scope, child)) { - if (!nextSelectorItem) { - if (rootElement !== child) { - return { documentPosition: position, element: child }; - } - } else { - switch (nextSelectorItem.combinator) { - case SelectorCombinatorEnum_default.adjacentSibling: - const nextElementSibling = child.nextElementSibling; - if (nextElementSibling) { - const match2 = this.findFirst({ - scope, - rootElement, - children: [nextElementSibling], - selectorItems: selectorItems.slice(1), - cachedItem - }, position); - if (match2) { - return match2; - } - } - break; - case SelectorCombinatorEnum_default.none: - case SelectorCombinatorEnum_default.descendant: - case SelectorCombinatorEnum_default.child: - const match = this.findFirst({ - scope, - rootElement, - children: childrenOfChild, - selectorItems: selectorItems.slice(1), - cachedItem - }, position); - if (match) { - return match; - } - break; - case SelectorCombinatorEnum_default.subsequentSibling: - const index = children2.indexOf(child); - for (let i2 = index + 1; i2 < children2.length; i2++) { - const sibling = children2[i2]; - const match2 = this.findFirst({ - scope, - rootElement, - children: [sibling], - selectorItems: selectorItems.slice(1), - cachedItem - }, position); - if (match2) { - return match2; - } - } - break; - } - } - } - if ((selectorItem.combinator === SelectorCombinatorEnum_default.none || selectorItem.combinator === SelectorCombinatorEnum_default.descendant) && childrenOfChild.length) { - const match = this.findFirst({ - scope, - rootElement, - children: childrenOfChild, - selectorItems, - cachedItem - }, position); - if (match) { - return match; - } - } - } - return null; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/measurement-converter/CSSMeasurementConverter.js -var CSSMeasurementConverter; -var init_CSSMeasurementConverter = __esm({ - "node_modules/happy-dom/lib/css/declaration/measurement-converter/CSSMeasurementConverter.js"() { - CSSMeasurementConverter = class { - /** - * Returns measurement in pixels. - * - * @param options Options. - * @param options.window Owner window. - * @param options.value Measurement (e.g. "10px", "10rem" or "10em"). - * @param options.rootFontSize Root font size in pixels. - * @param options.parentFontSize Parent font size in pixels. - * @param [options.parentSize] Parent size in pixels. - * @returns Measurement in pixels. - */ - static toPixels(options2) { - const value2 = parseFloat(options2.value); - const unit = options2.value.replace(value2.toString(), ""); - if (isNaN(value2)) { - return null; - } - switch (unit) { - case "px": - return value2; - case "rem": - return this.round(value2 * parseFloat(options2.rootFontSize)); - case "em": - return this.round(value2 * parseFloat(options2.parentFontSize)); - case "vw": - return this.round(value2 * options2.window.innerWidth / 100); - case "vh": - return this.round(value2 * options2.window.innerHeight / 100); - case "%": - return options2.parentSize !== void 0 && options2.parentSize !== null ? this.round(value2 * parseFloat(options2.parentSize) / 100) : null; - case "vmin": - return this.round(value2 * Math.min(options2.window.innerWidth, options2.window.innerHeight) / 100); - case "vmax": - return value2 * Math.max(options2.window.innerWidth, options2.window.innerHeight) / 100; - case "cm": - return this.round(value2 * 37.7812); - case "mm": - return this.round(value2 * 3.7781); - case "in": - return this.round(value2 * 96); - case "pt": - return this.round(value2 * 1.3281); - case "pc": - return this.round(value2 * 16); - case "Q": - return this.round(value2 * 0.945); - default: - return null; - } - } - /** - * Rounds the number with 4 decimals. - * - * @param value Value. - * @returns Rounded value. - */ - static round(value2) { - return Math.round(value2 * 1e4) / 1e4; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/MediaQueryListEvent.js -var MediaQueryListEvent; -var init_MediaQueryListEvent = __esm({ - "node_modules/happy-dom/lib/event/events/MediaQueryListEvent.js"() { - init_Event(); - MediaQueryListEvent = class extends Event2 { - matches; - media; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.matches = eventInit?.matches ?? false; - this.media = eventInit?.media ?? ""; - } - }; - } -}); - -// node_modules/happy-dom/lib/match-media/MediaQueryTypeEnum.js -var MediaQueryTypeEnum, MediaQueryTypeEnum_default; -var init_MediaQueryTypeEnum = __esm({ - "node_modules/happy-dom/lib/match-media/MediaQueryTypeEnum.js"() { - (function(MediaQueryTypeEnum2) { - MediaQueryTypeEnum2["all"] = "all"; - MediaQueryTypeEnum2["print"] = "print"; - MediaQueryTypeEnum2["screen"] = "screen"; - })(MediaQueryTypeEnum || (MediaQueryTypeEnum = {})); - MediaQueryTypeEnum_default = MediaQueryTypeEnum; - } -}); - -// node_modules/happy-dom/lib/match-media/MediaQueryItem.js -var MediaQueryItem; -var init_MediaQueryItem = __esm({ - "node_modules/happy-dom/lib/match-media/MediaQueryItem.js"() { - init_CSSMeasurementConverter(); - init_WindowBrowserContext(); - init_MediaQueryTypeEnum(); - MediaQueryItem = class { - mediaTypes; - not; - rules; - ranges; - rootFontSize = null; - window; - /** - * Constructor. - * - * @param options Options. - * @param options.window Owner window. - * @param [options.rootFontSize] Root font size. - * @param [options.mediaTypes] Media types. - * @param [options.not] Not. - * @param [options.rules] Rules. - * @param [options.ranges] Ranges. - */ - constructor(options2) { - this.window = options2.window; - this.rootFontSize = options2.rootFontSize || null; - this.mediaTypes = options2.mediaTypes || []; - this.not = options2.not || false; - this.rules = options2.rules || []; - this.ranges = options2.ranges || []; - } - /** - * Returns media string. - */ - toString() { - return `${this.not ? "not " : ""}${this.mediaTypes.join(", ")}${(this.not || this.mediaTypes.length > 0) && !!this.ranges.length ? " and " : ""}${this.ranges.map((range) => `(${range.before ? `${range.before.value} ${range.before.operator} ` : ""}${range.type}${range.after ? ` ${range.after.operator} ${range.after.value}` : ""})`).join(" and ")}${(this.not || this.mediaTypes.length > 0) && !!this.rules.length ? " and " : ""}${this.rules.map((rule) => rule.value ? `(${rule.name}: ${rule.value})` : `(${rule.name})`).join(" and ")}`; - } - /** - * Returns "true" if the item matches. - */ - matches() { - return this.not ? !this.matchesAll() : this.matchesAll(); - } - /** - * Returns "true" if all matches. - * - * @returns "true" if all matches. - */ - matchesAll() { - if (!!this.mediaTypes.length) { - let isMediaTypeMatch = false; - for (const mediaType of this.mediaTypes) { - if (this.matchesMediaType(mediaType)) { - isMediaTypeMatch = true; - break; - } - } - if (!isMediaTypeMatch) { - return false; - } - } - for (const rule of this.rules) { - if (!this.matchesRule(rule)) { - return false; - } - } - for (const range of this.ranges) { - if (!this.matchesRange(range)) { - return false; - } - } - return true; - } - /** - * Returns "true" if the mediaType matches. - * - * @param mediaType Media type. - * @returns "true" if the mediaType matches. - */ - matchesMediaType(mediaType) { - if (mediaType === MediaQueryTypeEnum_default.all) { - return true; - } - return mediaType === new WindowBrowserContext(this.window).getSettings()?.device.mediaType; - } - /** - * Returns "true" if the range matches. - * - * @param range Range. - * @returns "true" if the range matches. - */ - matchesRange(range) { - const windowSize = range.type === "width" ? this.window.innerWidth : this.window.innerHeight; - if (range.before) { - const beforeValue = this.toPixels(range.before.value); - if (beforeValue === null) { - return false; - } - switch (range.before.operator) { - case "<": - if (beforeValue >= windowSize) { - return false; - } - break; - case "<=": - if (beforeValue > windowSize) { - return false; - } - break; - case ">": - if (beforeValue <= windowSize) { - return false; - } - break; - case ">=": - if (beforeValue < windowSize) { - return false; - } - break; - } - } - if (range.after) { - const afterValue = this.toPixels(range.after.value); - if (afterValue === null) { - return false; - } - switch (range.after.operator) { - case "<": - if (windowSize >= afterValue) { - return false; - } - break; - case "<=": - if (windowSize > afterValue) { - return false; - } - break; - case ">": - if (windowSize <= afterValue) { - return false; - } - break; - case ">=": - if (windowSize < afterValue) { - return false; - } - break; - } - } - return true; - } - /** - * Returns "true" if the rule matches. - * - * @param rule Rule. - * @returns "true" if the rule matches. - */ - matchesRule(rule) { - const settings2 = new WindowBrowserContext(this.window).getSettings(); - if (!settings2) { - return false; - } - if (!rule.value) { - switch (rule.name) { - case "min-width": - case "max-width": - case "min-height": - case "max-height": - case "width": - case "height": - case "orientation": - case "prefers-color-scheme": - case "hover": - case "any-hover": - case "any-pointer": - case "pointer": - case "display-mode": - case "min-aspect-ratio": - case "max-aspect-ratio": - case "aspect-ratio": - return true; - case "prefers-reduced-motion": - return settings2.device.prefersReducedMotion === "reduce"; - case "forced-colors": - return settings2.device.forcedColors === "active"; - } - return false; - } - switch (rule.name) { - case "min-width": - const minWidth = this.toPixels(rule.value); - return minWidth !== null && this.window.innerWidth >= minWidth; - case "max-width": - const maxWidth = this.toPixels(rule.value); - return maxWidth !== null && this.window.innerWidth <= maxWidth; - case "min-height": - const minHeight = this.toPixels(rule.value); - return minHeight !== null && this.window.innerHeight >= minHeight; - case "max-height": - const maxHeight = this.toPixels(rule.value); - return maxHeight !== null && this.window.innerHeight <= maxHeight; - case "width": - const width2 = this.toPixels(rule.value); - return width2 !== null && this.window.innerWidth === width2; - case "height": - const height2 = this.toPixels(rule.value); - return height2 !== null && this.window.innerHeight === height2; - case "orientation": - return rule.value === "landscape" ? this.window.innerWidth > this.window.innerHeight : this.window.innerWidth < this.window.innerHeight; - case "prefers-color-scheme": - return rule.value === settings2.device.prefersColorScheme; - case "prefers-reduced-motion": - return rule.value === settings2.device.prefersReducedMotion; - case "forced-colors": - return (rule.value === "none" || rule.value === "active") && rule.value === settings2.device.forcedColors; - case "any-hover": - case "hover": - if (rule.value === "none") { - return this.window.navigator.maxTouchPoints > 0; - } - if (rule.value === "hover") { - return this.window.navigator.maxTouchPoints === 0; - } - return false; - case "any-pointer": - case "pointer": - if (rule.value === "none") { - return false; - } - if (rule.value === "coarse") { - return this.window.navigator.maxTouchPoints > 0; - } - if (rule.value === "fine") { - return this.window.navigator.maxTouchPoints === 0; - } - return false; - case "display-mode": - return rule.value === "browser"; - case "min-aspect-ratio": - case "max-aspect-ratio": - case "aspect-ratio": - const aspectRatio = rule.value.split("/"); - const aspectRatioWidth = parseInt(aspectRatio[0], 10); - const aspectRatioHeight = parseInt(aspectRatio[1], 10); - if (isNaN(aspectRatioWidth) || isNaN(aspectRatioHeight)) { - return false; - } - switch (rule.name) { - case "min-aspect-ratio": - return aspectRatioWidth / aspectRatioHeight <= this.window.innerWidth / this.window.innerHeight; - case "max-aspect-ratio": - return aspectRatioWidth / aspectRatioHeight >= this.window.innerWidth / this.window.innerHeight; - case "aspect-ratio": - return aspectRatioWidth / aspectRatioHeight === this.window.innerWidth / this.window.innerHeight; - } - } - return false; - } - /** - * Convert to pixels. - * - * @param value Value. - * @returns Value in pixels. - */ - toPixels(value2) { - if (!new WindowBrowserContext(this.window).getSettings()?.disableComputedStyleRendering && value2.endsWith("em")) { - this.rootFontSize = this.rootFontSize || parseFloat(this.window.getComputedStyle(this.window.document.documentElement).fontSize); - return CSSMeasurementConverter.toPixels({ - window: this.window, - value: value2, - rootFontSize: this.rootFontSize, - parentFontSize: this.rootFontSize - }); - } - return CSSMeasurementConverter.toPixels({ - window: this.window, - value: value2, - rootFontSize: 16, - parentFontSize: 16 - }); - } - }; - } -}); - -// node_modules/happy-dom/lib/match-media/MediaQueryParser.js -var MEDIA_QUERY_REGEXP, IS_RESOLUTION_REGEXP, RESOLUTION_REGEXP, MediaQueryParser; -var init_MediaQueryParser = __esm({ - "node_modules/happy-dom/lib/match-media/MediaQueryParser.js"() { - init_MediaQueryItem(); - init_MediaQueryTypeEnum(); - MEDIA_QUERY_REGEXP = /(not|only|all|screen|print)|\(([^\)]+)(\)){0,1}|(,)| +(or|and) +/g; - IS_RESOLUTION_REGEXP = /[<>]/; - RESOLUTION_REGEXP = /(?:([0-9]+[a-z]+) *(<|<=|>|>=)){0,1} *(width|height) *(?:(<|<=|>|>=) *([0-9]+[a-z]+)){0,1}/; - MediaQueryParser = class { - /** - * Parses a media query string. - * - * @param options Options. - * @param options.window Owner window. - * @param options.mediaQuery Media query string. - * @param [options.rootFontSize] Root font size. - * @returns Media query items. - */ - static parse(options2) { - let currentMediaQueryItem = new MediaQueryItem({ - window: options2.window, - rootFontSize: options2.rootFontSize - }); - const mediaQueryItems = [currentMediaQueryItem]; - const regexp = new RegExp(MEDIA_QUERY_REGEXP); - let match = null; - while (match = regexp.exec(options2.mediaQuery.toLowerCase())) { - if (match[4] === "," || match[5] === "or") { - currentMediaQueryItem = new MediaQueryItem({ - window: options2.window, - rootFontSize: options2.rootFontSize - }); - mediaQueryItems.push(currentMediaQueryItem); - } else if (match[1] === "all" || match[1] === "screen" || match[1] === "print") { - currentMediaQueryItem.mediaTypes.push(match[1]); - } else if (match[1] === "not") { - currentMediaQueryItem.not = true; - } else if (match[2]) { - const resolutionMatch = IS_RESOLUTION_REGEXP.test(match[2]) ? match[2].match(RESOLUTION_REGEXP) : null; - if (resolutionMatch && (resolutionMatch[1] || resolutionMatch[5])) { - currentMediaQueryItem.ranges.push({ - before: resolutionMatch[1] ? { - value: resolutionMatch[1], - operator: resolutionMatch[2] - } : null, - type: resolutionMatch[3], - after: resolutionMatch[5] ? { - value: resolutionMatch[5], - operator: resolutionMatch[4] - } : null - }); - } else { - const [name2, value2] = match[2].split(":"); - const trimmedValue = value2 ? value2.trim() : null; - if (!trimmedValue && !match[3]) { - return [ - new MediaQueryItem({ - window: options2.window, - rootFontSize: options2.rootFontSize, - not: true, - mediaTypes: [MediaQueryTypeEnum_default.all] - }) - ]; - } - currentMediaQueryItem.rules.push({ - name: name2.trim(), - value: trimmedValue - }); - } - } - } - return mediaQueryItems; - } - }; - } -}); - -// node_modules/happy-dom/lib/match-media/MediaQueryList.js -var MediaQueryList; -var init_MediaQueryList = __esm({ - "node_modules/happy-dom/lib/match-media/MediaQueryList.js"() { - init_EventTarget(); - init_PropertySymbol(); - init_MediaQueryListEvent(); - init_MediaQueryParser(); - MediaQueryList = class extends EventTarget2 { - onchange = null; - #window; - #items = null; - #media; - #rootFontSize = null; - /** - * Constructor. - * - * @param options Options. - * @param options.window Owner window. - * @param options.media Media. - * @param [options.rootFontSize] Root font size. - */ - constructor(options2) { - super(); - this.#window = options2.window; - this.#media = options2.media; - this.#rootFontSize = options2.rootFontSize || null; - } - /** - * Returns media. - * - * @returns Media. - */ - get media() { - this.#items = this.#items || MediaQueryParser.parse({ - window: this.#window, - mediaQuery: this.#media, - rootFontSize: this.#rootFontSize - }); - return this.#items.map((item) => item.toString()).join(", "); - } - /** - * Returns "true" if the document matches. - * - * @returns Matches. - */ - get matches() { - this.#items = this.#items || MediaQueryParser.parse({ - window: this.#window, - mediaQuery: this.#media, - rootFontSize: this.#rootFontSize - }); - for (const item of this.#items) { - if (!item.matches()) { - return false; - } - } - return true; - } - /** - * Adds a listener. - * - * @deprecated - * @param callback Callback. - */ - addListener(callback) { - this.addEventListener("change", callback); - } - /** - * Removes listener. - * - * @deprecated - * @param callback Callback. - */ - removeListener(callback) { - this.removeEventListener("change", callback); - } - /** - * @override - */ - addEventListener(type2, listener) { - super.addEventListener(type2, listener); - if (type2 === "change") { - let matchesState = false; - const resizeListener = () => { - const matches = this.matches; - if (matches !== matchesState) { - matchesState = matches; - this.dispatchEvent(new MediaQueryListEvent("change", { matches, media: this.media })); - } - }; - listener[windowResizeListener] = resizeListener; - this.#window.addEventListener("resize", resizeListener); - } - } - /** - * @override - */ - removeEventListener(type2, listener) { - super.removeEventListener(type2, listener); - if (type2 === "change" && listener[windowResizeListener]) { - this.#window.removeEventListener("resize", listener[windowResizeListener]); - } - } - }; - } -}); - -// node_modules/happy-dom/lib/css/rules/CSSGroupingRule.js -var CSSGroupingRule; -var init_CSSGroupingRule = __esm({ - "node_modules/happy-dom/lib/css/rules/CSSGroupingRule.js"() { - init_CSSRule(); - init_DOMExceptionNameEnum(); - init_PropertySymbol(); - CSSGroupingRule = class extends CSSRule { - [cssRules] = []; - /** - * Returns CSS rules. - * - * @returns CSS rules. - */ - get cssRules() { - return this[cssRules]; - } - /** - * Inserts a new rule. - * - * @param rule Rule. - * @param [index] Index. - * @returns The index of the new rule. - */ - insertRule(rule, index) { - if (arguments.length === 0) { - throw new this[window].TypeError(`Failed to execute 'insertRule' on '${this.constructor.name}': 1 argument required, but only 0 present.`); - } - const rules = this[cssParser].parseFromString(rule); - if (rules.length === 0 || rules.length > 1) { - throw new this[window].DOMException(`Failed to execute 'insertRule' on '${this.constructor.name}': Failed to parse the rule '${rule}'.`, DOMExceptionNameEnum_default.syntaxError); - } - if (index !== void 0) { - index = Number(index); - if (isNaN(index) || index > this.cssRules.length) { - throw new this[window].DOMException(`Failed to execute 'insertRule' on '${this.constructor.name}': The index provided (${index}) is larger than the maximum index (${this.cssRules.length}).`, DOMExceptionNameEnum_default.indexSizeError); - } - this.cssRules.splice(index, 0, rules[0]); - return index; - } - const newIndex = this.cssRules.length; - this.cssRules.unshift(rules[0]); - return newIndex; - } - /** - * Removes a rule. - * - * @param index Index. - */ - deleteRule(index) { - if (arguments.length === 0) { - throw new this[window].TypeError(`Failed to execute 'deleteRule' on '${this.constructor.name}': 1 argument required, but only 0 present.`); - } - index = Number(index); - if (isNaN(index) || index < 0 || index >= this.cssRules.length) { - throw new this[window].DOMException(`Failed to execute 'deleteRule' on '${this.constructor.name}': the index (${index}) is greater than the length of the rule list.`, DOMExceptionNameEnum_default.indexSizeError); - } - this.cssRules.splice(index, 1); - } - }; - } -}); - -// node_modules/happy-dom/lib/css/rules/CSSScopeRule.js -var CSSScopeRule; -var init_CSSScopeRule = __esm({ - "node_modules/happy-dom/lib/css/rules/CSSScopeRule.js"() { - init_PropertySymbol(); - init_CSSRuleTypeEnum(); - init_CSSGroupingRule(); - CSSScopeRule = class extends CSSGroupingRule { - [start] = ""; - [end] = ""; - [rulePrefix] = ""; - /** - * @override - */ - get type() { - return CSSRuleTypeEnum_default.containerRule; - } - /** - * @override - */ - get cssText() { - let cssText2 = ""; - for (const cssRule2 of this[cssRules]) { - cssText2 += "\n " + cssRule2.cssText; - } - cssText2 += "\n"; - return `@${this[rulePrefix]}scope${this[start] ? ` (${this[start]})` : ""}${this[end] ? ` to (${this[end]})` : ""} {${cssText2}}`; - } - /** - * Returns start. - * - * @returns Start. - */ - get start() { - return this[start]; - } - /** - * Returns end. - * - * @returns End. - */ - get end() { - return this[end]; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.js -var CSS_MEASUREMENT_REGEXP, HOST_REGEXP, SINGLE_CSS_VARIABLE_REGEXP, CSS_VARIABLE_REGEXP2, CSSStyleDeclarationComputedStyle; -var init_CSSStyleDeclarationComputedStyle = __esm({ - "node_modules/happy-dom/lib/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.js"() { - init_PropertySymbol(); - init_CSSStyleDeclarationPropertyManager(); - init_NodeTypeEnum(); - init_CSSRuleTypeEnum(); - init_CSSStyleDeclarationElementDefaultCSS(); - init_CSSStyleDeclarationElementInheritedProperties(); - init_CSSStyleDeclarationElementMeasurementProperties(); - init_CSSStyleDeclarationCSSParser(); - init_QuerySelector(); - init_CSSMeasurementConverter(); - init_MediaQueryList(); - init_WindowBrowserContext(); - init_CSSScopeRule(); - CSS_MEASUREMENT_REGEXP = /[0-9.]+(px|rem|em|vw|vh|%|vmin|vmax|cm|mm|in|pt|pc|Q)/g; - HOST_REGEXP = /:host\s*\(([^)]+)\)|:host-context\s*\(([^)]+)\)/; - SINGLE_CSS_VARIABLE_REGEXP = /var\( *(--[^), ]+)\)/; - CSS_VARIABLE_REGEXP2 = /var\( *(--[^), ]+), *([^), ]+)\)/; - CSSStyleDeclarationComputedStyle = class { - element; - /** - * Constructor. - * - * @param element Element. - * @param [computed] Computed. - */ - constructor(element) { - this.element = element; - } - /** - * Returns style sheets. - * - * @param element Element. - * @returns Style sheets. - */ - getComputedStyle() { - const documentElements = []; - const parentElements = []; - let styleAndElement = { - element: this.element, - cssTexts: [] - }; - let shadowRootElements = []; - let customElements = []; - if (!this.element[isConnected]) { - return new CSSStyleDeclarationPropertyManager(); - } - const cacheResult = this.element[cache].computedStyle; - if (cacheResult?.result) { - const result3 = cacheResult.result.deref(); - if (result3) { - return result3; - } - } - while (styleAndElement.element) { - if (styleAndElement.element[nodeType] === NodeTypeEnum_default.elementNode) { - const rootNode2 = styleAndElement.element.getRootNode(); - if (rootNode2[nodeType] === NodeTypeEnum_default.documentNode) { - documentElements.unshift(styleAndElement); - } else { - shadowRootElements.unshift(styleAndElement); - } - if (styleAndElement.element.shadowRoot) { - customElements.push(styleAndElement); - } - parentElements.unshift(styleAndElement); - } - if (styleAndElement.element === this.element[ownerDocument]) { - const styleSheets = this.getStyleSheets(this.element[ownerDocument]); - for (const styleSheet of styleSheets) { - this.parseCSSRules({ - elements: documentElements, - cssRules: styleSheet.cssRules - }); - } - for (const customElement of customElements) { - const styleSheets2 = this.getStyleSheets(customElement.element.shadowRoot); - for (const styleSheet of styleSheets2) { - this.parseCSSRules({ - elements: [], - cssRules: styleSheet.cssRules, - hostElement: customElement - }); - } - } - styleAndElement = { element: null, cssTexts: [] }; - } else if (styleAndElement.element[nodeType] === NodeTypeEnum_default.documentFragmentNode && styleAndElement.element.host) { - const shadowRoot2 = styleAndElement.element; - const styleSheets = this.getStyleSheets(shadowRoot2); - styleAndElement = { - element: shadowRoot2.host, - cssTexts: [] - }; - for (const styleSheet of styleSheets) { - this.parseCSSRules({ - elements: shadowRootElements, - cssRules: styleSheet.cssRules, - hostElement: styleAndElement - }); - } - for (const customElement of customElements) { - const styleSheets2 = this.getStyleSheets(customElement.element.shadowRoot); - for (const styleSheet of styleSheets2) { - this.parseCSSRules({ - elements: [], - cssRules: styleSheet.cssRules, - hostElement: customElement - }); - } - } - customElements = []; - shadowRootElements = []; - } else { - styleAndElement = { - element: styleAndElement.element[parentNode], - cssTexts: [] - }; - } - } - const targetElement = parentElements[parentElements.length - 1]; - const propertyManager = new CSSStyleDeclarationPropertyManager(); - const cssProperties = {}; - let rootFontSize = 16; - let parentFontSize = 16; - for (const parentElement of parentElements) { - parentElement.cssTexts.sort((a, b) => a.priorityWeight - b.priorityWeight); - const defaultCSS = CSSStyleDeclarationElementDefaultCSS_default[parentElement.element[tagName]]; - let elementCSSText = ""; - if (defaultCSS) { - if (typeof defaultCSS === "string") { - elementCSSText += defaultCSS; - } else { - for (const key of Object.keys(defaultCSS)) { - if (key === "default" || !!parentElement.element[key]) { - elementCSSText += defaultCSS[key]; - } - } - } - } - for (const cssText2 of parentElement.cssTexts) { - elementCSSText += cssText2.cssText; - } - const elementStyleAttribute = parentElement.element.getAttribute("style"); - if (elementStyleAttribute) { - elementCSSText += elementStyleAttribute; - } - const rulesAndProperties = CSSStyleDeclarationCSSParser.parse(elementCSSText); - const rules = rulesAndProperties.rules; - Object.assign(cssProperties, rulesAndProperties.properties); - for (const { name: name2, value: value2, important } of rules) { - if (CSSStyleDeclarationElementInheritedProperties_default[name2] || parentElement === targetElement) { - const parsedValue = this.parseCSSVariablesInValue(value2.trim(), cssProperties); - if (parsedValue && (!propertyManager.get(name2)?.important || important)) { - propertyManager.set(name2, parsedValue, important); - if (name2 === "font" || name2 === "font-size") { - const fontSize = propertyManager.properties["font-size"]; - if (fontSize !== null) { - const parsedValue2 = this.parseMeasurementsInValue({ - value: fontSize.value, - rootFontSize, - parentFontSize, - parentSize: parentFontSize - }); - if (parentElement.element[tagName] === "HTML") { - rootFontSize = parsedValue2; - } else if (parentElement !== targetElement) { - parentFontSize = parsedValue2; - } - } - } - } - } - } - } - for (const name2 of CSSStyleDeclarationElementMeasurementProperties_default) { - const property = propertyManager.properties[name2]; - if (property) { - property.value = this.parseMeasurementsInValue({ - value: property.value, - rootFontSize, - parentFontSize, - // TODO: Only "font-size" is supported when using percentage values. Add support for other properties. - parentSize: name2 === "font-size" ? parentFontSize : null - }); - } - } - const cachedResult = { - result: new WeakRef(propertyManager) - }; - this.element[cache].computedStyle = cachedResult; - this.element[ownerDocument][affectsComputedStyleCache].push(cachedResult); - return propertyManager; - } - /** - * Returns style sheets. - * - * @param root Root element. - * @returns Style sheets. - */ - getStyleSheets(root2) { - if (!root2) { - return []; - } - const styleElements = root2.querySelectorAll('style,link[rel="stylesheet"]'); - let styleSheets = []; - for (const styleElement of styleElements) { - const sheet2 = styleElement.sheet; - if (sheet2) { - styleSheets.push(sheet2); - } - } - if (root2.adoptedStyleSheets) { - styleSheets = styleSheets.concat(root2.adoptedStyleSheets); - } - return styleSheets; - } - /** - * Applies CSS text to elements. - * - * @param options Options. - * @param options.elements Elements. - * @param options.cssRules CSS rules. - * @param [options.hostElement] Host element. - * @param [options.scopeElement] Scope element. - */ - parseCSSRules(options2) { - if (!options2.hostElement && !options2.elements.length) { - return; - } - const window2 = this.element[window]; - for (const rule of options2.cssRules) { - if (rule.type === CSSRuleTypeEnum_default.styleRule) { - const selectorText2 = rule.selectorText; - if (selectorText2) { - if (selectorText2[0] === ":" && selectorText2.startsWith(":host")) { - if (options2.hostElement) { - let isTargetHost = true; - if (selectorText2 !== ":host") { - const selectorMatch = selectorText2.match(HOST_REGEXP); - if (selectorMatch) { - const match = QuerySelector.matches(options2.hostElement.element, selectorMatch[1] || selectorMatch[2], { - ignoreErrors: true, - scope: options2.scopeElement?.element - }); - if (match) { - const hostContextSelectorText = selectorText2?.replace(HOST_REGEXP, "").trim(); - if (hostContextSelectorText && hostContextSelectorText[0] !== ":") { - isTargetHost = false; - for (const element of options2.elements) { - const match2 = QuerySelector.matches(element.element, hostContextSelectorText, { - ignoreErrors: true, - scope: options2.scopeElement?.element - }); - if (match2) { - element.cssTexts.push({ - cssText: rule[cssText], - priorityWeight: 10 + match2.priorityWeight - }); - } - } - } - } else { - isTargetHost = false; - } - } - } - if (isTargetHost) { - options2.hostElement.cssTexts.push({ - cssText: rule[cssText], - priorityWeight: 10 - }); - } - } - } else { - for (const element of options2.elements) { - const match = QuerySelector.matches(element.element, selectorText2, { - ignoreErrors: true, - scope: options2.scopeElement?.element - }); - if (match) { - element.cssTexts.push({ - cssText: rule[cssText], - priorityWeight: match.priorityWeight - }); - } - } - } - } - } else if (rule.type === CSSRuleTypeEnum_default.mediaRule && // TODO: We need to send in a predefined root font size as it will otherwise be calculated using Window.getComputedStyle(), which will cause a never ending loop. Is there another solution? - new MediaQueryList({ - window: window2, - media: rule.conditionText, - rootFontSize: this.element[tagName] === "HTML" ? 16 : null - }).matches) { - this.parseCSSRules({ - elements: options2.elements, - cssRules: rule.cssRules, - hostElement: options2.hostElement, - scopeElement: options2.scopeElement - }); - } else if (rule.type === CSSRuleTypeEnum_default.supportsRule) { - if (window2.CSS.supports(rule.conditionText)) { - this.parseCSSRules({ - elements: options2.elements, - cssRules: rule.cssRules, - hostElement: options2.hostElement, - scopeElement: options2.scopeElement - }); - } - } else if (rule.type === CSSRuleTypeEnum_default.containerRule) { - if (rule instanceof CSSScopeRule) { - const scopedElements = []; - let scope = null; - for (const element of options2.elements) { - if (scope) { - if (rule[end]) { - const match = QuerySelector.matches(element.element, rule[end], { - ignoreErrors: true, - scope: scope.element - }); - if (match) { - break; - } - } - scopedElements.push(element); - } else { - const match = QuerySelector.matches(element.element, rule[start] || ":root", { - ignoreErrors: true - }); - if (match) { - scope = element; - scopedElements.push(element); - } - } - } - if (scopedElements.length) { - this.parseCSSRules({ - elements: scopedElements, - cssRules: rule.cssRules, - hostElement: options2.hostElement, - scopeElement: scope - }); - } - } - } - } - } - /** - * Parses CSS variables in a value. - * - * @param value Value. - * @param cssVariables CSS variables. - * @returns CSS value. - */ - parseCSSVariablesInValue(value2, cssVariables) { - let newValue = value2; - let match; - while ((match = newValue.match(SINGLE_CSS_VARIABLE_REGEXP)) != null) { - newValue = newValue.replace(match[0], cssVariables[match[1]] || ""); - } - while ((match = newValue.match(CSS_VARIABLE_REGEXP2)) !== null) { - newValue = newValue.replace(match[0], cssVariables[match[1]] || match[2]); - } - return newValue; - } - /** - * Parses measurements in a value. - * - * @param options Options. - * @param options.value Value. - * @param options.rootFontSize Root font size. - * @param options.parentFontSize Parent font size. - * @param [options.parentSize] Parent width. - * @returns CSS value. - */ - parseMeasurementsInValue(options2) { - if (new WindowBrowserContext(this.element[window]).getSettings()?.disableComputedStyleRendering) { - return options2.value; - } - const regexp = new RegExp(CSS_MEASUREMENT_REGEXP); - let newValue = options2.value; - let match; - while ((match = regexp.exec(options2.value)) !== null) { - if (match[1] !== "px") { - const valueInPixels = CSSMeasurementConverter.toPixels({ - window: this.element[window], - value: match[0], - rootFontSize: options2.rootFontSize, - parentFontSize: options2.parentFontSize, - parentSize: options2.parentSize - }); - if (valueInPixels !== null) { - newValue = newValue.replace(match[0], valueInPixels + "px"); - } - } - } - return newValue; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/declaration/CSSStyleDeclaration.js -var CSSStyleDeclaration; -var init_CSSStyleDeclaration = __esm({ - "node_modules/happy-dom/lib/css/declaration/CSSStyleDeclaration.js"() { - init_DOMExceptionNameEnum(); - init_CSSStyleDeclarationPropertyManager(); - init_PropertySymbol(); - init_CSSStyleDeclarationComputedStyle(); - CSSStyleDeclaration = class { - // Public properties - parentRule = null; - // Internal properties - [window]; - // Private properties - #element; - #computed; - #cache = { - attributeValue: null, - propertyManager: null - }; - /** - * Constructor. - * - * @param illegalConstructorSymbol Illegal constructor symbol. - * @param window Window. - * @param [options] Options. - * @param [options.element] Element. - * @param [options.computed] Computed. - */ - constructor(illegalConstructorSymbol, window2, options2) { - if (illegalConstructorSymbol !== illegalConstructor) { - throw new TypeError("Illegal constructor"); - } - this[window] = window2; - this.#element = options2?.element || null; - this.#computed = options2?.element ? !!options2?.computed : false; - } - /** - * Index properties - */ - /* eslint-disable jsdoc/require-jsdoc */ - get 0() { - return this.item(0) || void 0; - } - get 1() { - return this.item(1) || void 0; - } - get 2() { - return this.item(2) || void 0; - } - get 3() { - return this.item(3) || void 0; - } - get 4() { - return this.item(4) || void 0; - } - get 5() { - return this.item(5) || void 0; - } - get 6() { - return this.item(6) || void 0; - } - get 7() { - return this.item(7) || void 0; - } - get 8() { - return this.item(8) || void 0; - } - get 9() { - return this.item(9) || void 0; - } - get 10() { - return this.item(10) || void 0; - } - get 11() { - return this.item(11) || void 0; - } - get 12() { - return this.item(12) || void 0; - } - get 13() { - return this.item(13) || void 0; - } - get 14() { - return this.item(14) || void 0; - } - get 15() { - return this.item(15) || void 0; - } - get 16() { - return this.item(16) || void 0; - } - get 17() { - return this.item(17) || void 0; - } - get 18() { - return this.item(18) || void 0; - } - get 19() { - return this.item(19) || void 0; - } - get 20() { - return this.item(20) || void 0; - } - get 21() { - return this.item(21) || void 0; - } - get 22() { - return this.item(22) || void 0; - } - get 23() { - return this.item(23) || void 0; - } - get 24() { - return this.item(24) || void 0; - } - get 25() { - return this.item(25) || void 0; - } - get 26() { - return this.item(26) || void 0; - } - get 27() { - return this.item(27) || void 0; - } - get 28() { - return this.item(28) || void 0; - } - get 29() { - return this.item(29) || void 0; - } - get 30() { - return this.item(30) || void 0; - } - get 31() { - return this.item(31) || void 0; - } - get 32() { - return this.item(32) || void 0; - } - get 33() { - return this.item(33) || void 0; - } - get 34() { - return this.item(34) || void 0; - } - get 35() { - return this.item(35) || void 0; - } - get 36() { - return this.item(36) || void 0; - } - get 37() { - return this.item(37) || void 0; - } - get 38() { - return this.item(38) || void 0; - } - get 39() { - return this.item(39) || void 0; - } - get 40() { - return this.item(40) || void 0; - } - get 41() { - return this.item(41) || void 0; - } - get 42() { - return this.item(42) || void 0; - } - get 43() { - return this.item(43) || void 0; - } - get 44() { - return this.item(44) || void 0; - } - get 45() { - return this.item(45) || void 0; - } - get 46() { - return this.item(46) || void 0; - } - get 47() { - return this.item(47) || void 0; - } - get 48() { - return this.item(48) || void 0; - } - get 49() { - return this.item(49) || void 0; - } - get 50() { - return this.item(50) || void 0; - } - get 51() { - return this.item(51) || void 0; - } - get 52() { - return this.item(52) || void 0; - } - get 53() { - return this.item(53) || void 0; - } - get 54() { - return this.item(54) || void 0; - } - get 55() { - return this.item(55) || void 0; - } - get 56() { - return this.item(56) || void 0; - } - get 57() { - return this.item(57) || void 0; - } - get 58() { - return this.item(58) || void 0; - } - get 59() { - return this.item(59) || void 0; - } - get 60() { - return this.item(60) || void 0; - } - get 61() { - return this.item(61) || void 0; - } - get 62() { - return this.item(62) || void 0; - } - get 63() { - return this.item(63) || void 0; - } - get 64() { - return this.item(64) || void 0; - } - get 65() { - return this.item(65) || void 0; - } - get 66() { - return this.item(66) || void 0; - } - get 67() { - return this.item(67) || void 0; - } - get 68() { - return this.item(68) || void 0; - } - get 69() { - return this.item(69) || void 0; - } - get 70() { - return this.item(70) || void 0; - } - get 71() { - return this.item(71) || void 0; - } - get 72() { - return this.item(72) || void 0; - } - get 73() { - return this.item(73) || void 0; - } - get 74() { - return this.item(74) || void 0; - } - get 75() { - return this.item(75) || void 0; - } - get 76() { - return this.item(76) || void 0; - } - get 77() { - return this.item(77) || void 0; - } - get 78() { - return this.item(78) || void 0; - } - get 79() { - return this.item(79) || void 0; - } - get 80() { - return this.item(80) || void 0; - } - get 81() { - return this.item(81) || void 0; - } - get 82() { - return this.item(82) || void 0; - } - get 83() { - return this.item(83) || void 0; - } - get 84() { - return this.item(84) || void 0; - } - get 85() { - return this.item(85) || void 0; - } - get 86() { - return this.item(86) || void 0; - } - get 87() { - return this.item(87) || void 0; - } - get 88() { - return this.item(88) || void 0; - } - get 89() { - return this.item(89) || void 0; - } - get 90() { - return this.item(90) || void 0; - } - get 91() { - return this.item(91) || void 0; - } - get 92() { - return this.item(92) || void 0; - } - get 93() { - return this.item(93) || void 0; - } - get 94() { - return this.item(94) || void 0; - } - get 95() { - return this.item(95) || void 0; - } - get 96() { - return this.item(96) || void 0; - } - get 97() { - return this.item(97) || void 0; - } - get 98() { - return this.item(98) || void 0; - } - get 99() { - return this.item(99) || void 0; - } - get 100() { - return this.item(100) || void 0; - } - get 101() { - return this.item(101) || void 0; - } - get 102() { - return this.item(102) || void 0; - } - get 103() { - return this.item(103) || void 0; - } - get 104() { - return this.item(104) || void 0; - } - get 105() { - return this.item(105) || void 0; - } - get 106() { - return this.item(106) || void 0; - } - get 107() { - return this.item(107) || void 0; - } - get 108() { - return this.item(108) || void 0; - } - get 109() { - return this.item(109) || void 0; - } - get 110() { - return this.item(110) || void 0; - } - get 111() { - return this.item(111) || void 0; - } - get 112() { - return this.item(112) || void 0; - } - get 113() { - return this.item(113) || void 0; - } - get 114() { - return this.item(114) || void 0; - } - get 115() { - return this.item(115) || void 0; - } - get 116() { - return this.item(116) || void 0; - } - get 117() { - return this.item(117) || void 0; - } - get 118() { - return this.item(118) || void 0; - } - get 119() { - return this.item(119) || void 0; - } - get 120() { - return this.item(120) || void 0; - } - get 121() { - return this.item(121) || void 0; - } - get 122() { - return this.item(122) || void 0; - } - get 123() { - return this.item(123) || void 0; - } - get 124() { - return this.item(124) || void 0; - } - get 125() { - return this.item(125) || void 0; - } - get 126() { - return this.item(126) || void 0; - } - get 127() { - return this.item(127) || void 0; - } - get 128() { - return this.item(128) || void 0; - } - get 129() { - return this.item(129) || void 0; - } - get 130() { - return this.item(130) || void 0; - } - get 131() { - return this.item(131) || void 0; - } - get 132() { - return this.item(132) || void 0; - } - get 133() { - return this.item(133) || void 0; - } - get 134() { - return this.item(134) || void 0; - } - get 135() { - return this.item(135) || void 0; - } - get 136() { - return this.item(136) || void 0; - } - get 137() { - return this.item(137) || void 0; - } - get 138() { - return this.item(138) || void 0; - } - get 139() { - return this.item(139) || void 0; - } - get 140() { - return this.item(140) || void 0; - } - get 141() { - return this.item(141) || void 0; - } - get 142() { - return this.item(142) || void 0; - } - get 143() { - return this.item(143) || void 0; - } - get 144() { - return this.item(144) || void 0; - } - get 145() { - return this.item(145) || void 0; - } - get 146() { - return this.item(146) || void 0; - } - get 147() { - return this.item(147) || void 0; - } - get 148() { - return this.item(148) || void 0; - } - get 149() { - return this.item(149) || void 0; - } - get 150() { - return this.item(150) || void 0; - } - get 151() { - return this.item(151) || void 0; - } - get 152() { - return this.item(152) || void 0; - } - get 153() { - return this.item(153) || void 0; - } - get 154() { - return this.item(154) || void 0; - } - get 155() { - return this.item(155) || void 0; - } - get 156() { - return this.item(156) || void 0; - } - get 157() { - return this.item(157) || void 0; - } - get 158() { - return this.item(158) || void 0; - } - get 159() { - return this.item(159) || void 0; - } - get 160() { - return this.item(160) || void 0; - } - get 161() { - return this.item(161) || void 0; - } - get 162() { - return this.item(162) || void 0; - } - get 163() { - return this.item(163) || void 0; - } - get 164() { - return this.item(164) || void 0; - } - get 165() { - return this.item(165) || void 0; - } - get 166() { - return this.item(166) || void 0; - } - get 167() { - return this.item(167) || void 0; - } - get 168() { - return this.item(168) || void 0; - } - get 169() { - return this.item(169) || void 0; - } - get 170() { - return this.item(170) || void 0; - } - get 171() { - return this.item(171) || void 0; - } - get 172() { - return this.item(172) || void 0; - } - get 173() { - return this.item(173) || void 0; - } - get 174() { - return this.item(174) || void 0; - } - get 175() { - return this.item(175) || void 0; - } - get 176() { - return this.item(176) || void 0; - } - get 177() { - return this.item(177) || void 0; - } - get 178() { - return this.item(178) || void 0; - } - get 179() { - return this.item(179) || void 0; - } - get 180() { - return this.item(180) || void 0; - } - get 181() { - return this.item(181) || void 0; - } - get 182() { - return this.item(182) || void 0; - } - get 183() { - return this.item(183) || void 0; - } - get 184() { - return this.item(184) || void 0; - } - get 185() { - return this.item(185) || void 0; - } - get 186() { - return this.item(186) || void 0; - } - get 187() { - return this.item(187) || void 0; - } - get 188() { - return this.item(188) || void 0; - } - get 189() { - return this.item(189) || void 0; - } - get 190() { - return this.item(190) || void 0; - } - get 191() { - return this.item(191) || void 0; - } - get 192() { - return this.item(192) || void 0; - } - get 193() { - return this.item(193) || void 0; - } - get 194() { - return this.item(194) || void 0; - } - get 195() { - return this.item(195) || void 0; - } - get 196() { - return this.item(196) || void 0; - } - get 197() { - return this.item(197) || void 0; - } - get 198() { - return this.item(198) || void 0; - } - get 199() { - return this.item(199) || void 0; - } - get 200() { - return this.item(200) || void 0; - } - get 201() { - return this.item(201) || void 0; - } - get 202() { - return this.item(202) || void 0; - } - get 203() { - return this.item(203) || void 0; - } - get 204() { - return this.item(204) || void 0; - } - get 205() { - return this.item(205) || void 0; - } - get 206() { - return this.item(206) || void 0; - } - get 207() { - return this.item(207) || void 0; - } - get 208() { - return this.item(208) || void 0; - } - get 209() { - return this.item(209) || void 0; - } - get 210() { - return this.item(210) || void 0; - } - get 211() { - return this.item(211) || void 0; - } - get 212() { - return this.item(212) || void 0; - } - get 213() { - return this.item(213) || void 0; - } - get 214() { - return this.item(214) || void 0; - } - get 215() { - return this.item(215) || void 0; - } - get 216() { - return this.item(216) || void 0; - } - get 217() { - return this.item(217) || void 0; - } - get 218() { - return this.item(218) || void 0; - } - get 219() { - return this.item(219) || void 0; - } - get 220() { - return this.item(220) || void 0; - } - get 221() { - return this.item(221) || void 0; - } - get 222() { - return this.item(222) || void 0; - } - get 223() { - return this.item(223) || void 0; - } - get 224() { - return this.item(224) || void 0; - } - get 225() { - return this.item(225) || void 0; - } - get 226() { - return this.item(226) || void 0; - } - get 227() { - return this.item(227) || void 0; - } - get 228() { - return this.item(228) || void 0; - } - get 229() { - return this.item(229) || void 0; - } - get 230() { - return this.item(230) || void 0; - } - get 231() { - return this.item(231) || void 0; - } - get 232() { - return this.item(232) || void 0; - } - get 233() { - return this.item(233) || void 0; - } - get 234() { - return this.item(234) || void 0; - } - get 235() { - return this.item(235) || void 0; - } - get 236() { - return this.item(236) || void 0; - } - get 237() { - return this.item(237) || void 0; - } - get 238() { - return this.item(238) || void 0; - } - get 239() { - return this.item(239) || void 0; - } - get 240() { - return this.item(240) || void 0; - } - get 241() { - return this.item(241) || void 0; - } - get 242() { - return this.item(242) || void 0; - } - get 243() { - return this.item(243) || void 0; - } - get 244() { - return this.item(244) || void 0; - } - get 245() { - return this.item(245) || void 0; - } - get 246() { - return this.item(246) || void 0; - } - get 247() { - return this.item(247) || void 0; - } - get 248() { - return this.item(248) || void 0; - } - get 249() { - return this.item(249) || void 0; - } - get 250() { - return this.item(250) || void 0; - } - get 251() { - return this.item(251) || void 0; - } - get 252() { - return this.item(252) || void 0; - } - get 253() { - return this.item(253) || void 0; - } - get 254() { - return this.item(254) || void 0; - } - get 255() { - return this.item(255) || void 0; - } - get 256() { - return this.item(256) || void 0; - } - get 257() { - return this.item(257) || void 0; - } - get 258() { - return this.item(258) || void 0; - } - get 259() { - return this.item(259) || void 0; - } - get 260() { - return this.item(260) || void 0; - } - get 261() { - return this.item(261) || void 0; - } - get 262() { - return this.item(262) || void 0; - } - get 263() { - return this.item(263) || void 0; - } - get 264() { - return this.item(264) || void 0; - } - get 265() { - return this.item(265) || void 0; - } - get 266() { - return this.item(266) || void 0; - } - get 267() { - return this.item(267) || void 0; - } - get 268() { - return this.item(268) || void 0; - } - get 269() { - return this.item(269) || void 0; - } - get 270() { - return this.item(270) || void 0; - } - get 271() { - return this.item(271) || void 0; - } - get 272() { - return this.item(272) || void 0; - } - get 273() { - return this.item(273) || void 0; - } - get 274() { - return this.item(274) || void 0; - } - get 275() { - return this.item(275) || void 0; - } - get 276() { - return this.item(276) || void 0; - } - get 277() { - return this.item(277) || void 0; - } - get 278() { - return this.item(278) || void 0; - } - get 279() { - return this.item(279) || void 0; - } - get 280() { - return this.item(280) || void 0; - } - get 281() { - return this.item(281) || void 0; - } - get 282() { - return this.item(282) || void 0; - } - get 283() { - return this.item(283) || void 0; - } - get 284() { - return this.item(284) || void 0; - } - get 285() { - return this.item(285) || void 0; - } - get 286() { - return this.item(286) || void 0; - } - get 287() { - return this.item(287) || void 0; - } - get 288() { - return this.item(288) || void 0; - } - get 289() { - return this.item(289) || void 0; - } - get 290() { - return this.item(290) || void 0; - } - get 291() { - return this.item(291) || void 0; - } - get 292() { - return this.item(292) || void 0; - } - get 293() { - return this.item(293) || void 0; - } - get 294() { - return this.item(294) || void 0; - } - get 295() { - return this.item(295) || void 0; - } - get 296() { - return this.item(296) || void 0; - } - get 297() { - return this.item(297) || void 0; - } - get 298() { - return this.item(298) || void 0; - } - get 299() { - return this.item(299) || void 0; - } - get 300() { - return this.item(300) || void 0; - } - get 301() { - return this.item(301) || void 0; - } - get 302() { - return this.item(302) || void 0; - } - get 303() { - return this.item(303) || void 0; - } - get 304() { - return this.item(304) || void 0; - } - get 305() { - return this.item(305) || void 0; - } - get 306() { - return this.item(306) || void 0; - } - get 307() { - return this.item(307) || void 0; - } - get 308() { - return this.item(308) || void 0; - } - get 309() { - return this.item(309) || void 0; - } - get 310() { - return this.item(310) || void 0; - } - get 311() { - return this.item(311) || void 0; - } - get 312() { - return this.item(312) || void 0; - } - get 313() { - return this.item(313) || void 0; - } - get 314() { - return this.item(314) || void 0; - } - get 315() { - return this.item(315) || void 0; - } - get 316() { - return this.item(316) || void 0; - } - get 317() { - return this.item(317) || void 0; - } - get 318() { - return this.item(318) || void 0; - } - get 319() { - return this.item(319) || void 0; - } - get 320() { - return this.item(320) || void 0; - } - get 321() { - return this.item(321) || void 0; - } - get 322() { - return this.item(322) || void 0; - } - get 323() { - return this.item(323) || void 0; - } - get 324() { - return this.item(324) || void 0; - } - get 325() { - return this.item(325) || void 0; - } - get 326() { - return this.item(326) || void 0; - } - get 327() { - return this.item(327) || void 0; - } - get 328() { - return this.item(328) || void 0; - } - get 329() { - return this.item(329) || void 0; - } - get 330() { - return this.item(330) || void 0; - } - get 331() { - return this.item(331) || void 0; - } - get 332() { - return this.item(332) || void 0; - } - get 333() { - return this.item(333) || void 0; - } - get 334() { - return this.item(334) || void 0; - } - get 335() { - return this.item(335) || void 0; - } - get 336() { - return this.item(336) || void 0; - } - get 337() { - return this.item(337) || void 0; - } - get 338() { - return this.item(338) || void 0; - } - get 339() { - return this.item(339) || void 0; - } - get 340() { - return this.item(340) || void 0; - } - get 341() { - return this.item(341) || void 0; - } - get 342() { - return this.item(342) || void 0; - } - get 343() { - return this.item(343) || void 0; - } - get 344() { - return this.item(344) || void 0; - } - get 345() { - return this.item(345) || void 0; - } - get 346() { - return this.item(346) || void 0; - } - get 347() { - return this.item(347) || void 0; - } - get 348() { - return this.item(348) || void 0; - } - get 349() { - return this.item(349) || void 0; - } - get 350() { - return this.item(350) || void 0; - } - get 351() { - return this.item(351) || void 0; - } - get 352() { - return this.item(352) || void 0; - } - get 353() { - return this.item(353) || void 0; - } - get 354() { - return this.item(354) || void 0; - } - get 355() { - return this.item(355) || void 0; - } - get 356() { - return this.item(356) || void 0; - } - get 357() { - return this.item(357) || void 0; - } - get 358() { - return this.item(358) || void 0; - } - get 359() { - return this.item(359) || void 0; - } - get 360() { - return this.item(360) || void 0; - } - get 361() { - return this.item(361) || void 0; - } - get 362() { - return this.item(362) || void 0; - } - get 363() { - return this.item(363) || void 0; - } - get 364() { - return this.item(364) || void 0; - } - get 365() { - return this.item(365) || void 0; - } - get 366() { - return this.item(366) || void 0; - } - get 367() { - return this.item(367) || void 0; - } - get 368() { - return this.item(368) || void 0; - } - get 369() { - return this.item(369) || void 0; - } - get 370() { - return this.item(370) || void 0; - } - get 371() { - return this.item(371) || void 0; - } - get 372() { - return this.item(372) || void 0; - } - get 373() { - return this.item(373) || void 0; - } - get 374() { - return this.item(374) || void 0; - } - get 375() { - return this.item(375) || void 0; - } - get 376() { - return this.item(376) || void 0; - } - get 377() { - return this.item(377) || void 0; - } - get 378() { - return this.item(378) || void 0; - } - get 379() { - return this.item(379) || void 0; - } - get 380() { - return this.item(380) || void 0; - } - get 381() { - return this.item(381) || void 0; - } - get 382() { - return this.item(382) || void 0; - } - get 383() { - return this.item(383) || void 0; - } - get 384() { - return this.item(384) || void 0; - } - get 385() { - return this.item(385) || void 0; - } - get 386() { - return this.item(386) || void 0; - } - get 387() { - return this.item(387) || void 0; - } - get 388() { - return this.item(388) || void 0; - } - get 389() { - return this.item(389) || void 0; - } - get 390() { - return this.item(390) || void 0; - } - get 391() { - return this.item(391) || void 0; - } - get 392() { - return this.item(392) || void 0; - } - get 393() { - return this.item(393) || void 0; - } - /** - * CSS properties - */ - get accentColor() { - return this.getPropertyValue("accent-color"); - } - set accentColor(value2) { - this.setProperty("accent-color", value2); - } - get appRegion() { - return this.getPropertyValue("app-region"); - } - set appRegion(value2) { - this.setProperty("app-region", value2); - } - get alignContent() { - return this.getPropertyValue("align-content"); - } - set alignContent(value2) { - this.setProperty("align-content", value2); - } - get alignItems() { - return this.getPropertyValue("align-items"); - } - set alignItems(value2) { - this.setProperty("align-items", value2); - } - get alignSelf() { - return this.getPropertyValue("align-self"); - } - set alignSelf(value2) { - this.setProperty("align-self", value2); - } - get alignmentBaseline() { - return this.getPropertyValue("alignment-baseline"); - } - set alignmentBaseline(value2) { - this.setProperty("alignment-baseline", value2); - } - get all() { - return this.getPropertyValue("all"); - } - set all(value2) { - this.setProperty("all", value2); - } - get animation() { - return this.getPropertyValue("animation"); - } - set animation(value2) { - this.setProperty("animation", value2); - } - get animationDelay() { - return this.getPropertyValue("animation-delay"); - } - set animationDelay(value2) { - this.setProperty("animation-delay", value2); - } - get animationDirection() { - return this.getPropertyValue("animation-direction"); - } - set animationDirection(value2) { - this.setProperty("animation-direction", value2); - } - get animationDuration() { - return this.getPropertyValue("animation-duration"); - } - set animationDuration(value2) { - this.setProperty("animation-duration", value2); - } - get animationFillMode() { - return this.getPropertyValue("animation-fill-mode"); - } - set animationFillMode(value2) { - this.setProperty("animation-fill-mode", value2); - } - get animationIterationCount() { - return this.getPropertyValue("animation-iteration-count"); - } - set animationIterationCount(value2) { - this.setProperty("animation-iteration-count", value2); - } - get animationName() { - return this.getPropertyValue("animation-name"); - } - set animationName(value2) { - this.setProperty("animation-name", value2); - } - get animationPlayState() { - return this.getPropertyValue("animation-play-state"); - } - set animationPlayState(value2) { - this.setProperty("animation-play-state", value2); - } - get animationTimingFunction() { - return this.getPropertyValue("animation-timing-function"); - } - set animationTimingFunction(value2) { - this.setProperty("animation-timing-function", value2); - } - get appearance() { - return this.getPropertyValue("appearance"); - } - set appearance(value2) { - this.setProperty("appearance", value2); - } - get backdropFilter() { - return this.getPropertyValue("backdrop-filter"); - } - set backdropFilter(value2) { - this.setProperty("backdrop-filter", value2); - } - get backfaceVisibility() { - return this.getPropertyValue("backface-visibility"); - } - set backfaceVisibility(value2) { - this.setProperty("backface-visibility", value2); - } - get background() { - return this.getPropertyValue("background"); - } - set background(value2) { - this.setProperty("background", value2); - } - get backgroundAttachment() { - return this.getPropertyValue("background-attachment"); - } - set backgroundAttachment(value2) { - this.setProperty("background-attachment", value2); - } - get backgroundBlendMode() { - return this.getPropertyValue("background-blend-mode"); - } - set backgroundBlendMode(value2) { - this.setProperty("background-blend-mode", value2); - } - get backgroundClip() { - return this.getPropertyValue("background-clip"); - } - set backgroundClip(value2) { - this.setProperty("background-clip", value2); - } - get backgroundColor() { - return this.getPropertyValue("background-color"); - } - set backgroundColor(value2) { - this.setProperty("background-color", value2); - } - get backgroundImage() { - return this.getPropertyValue("background-image"); - } - set backgroundImage(value2) { - this.setProperty("background-image", value2); - } - get backgroundOrigin() { - return this.getPropertyValue("background-origin"); - } - set backgroundOrigin(value2) { - this.setProperty("background-origin", value2); - } - get backgroundPosition() { - return this.getPropertyValue("background-position"); - } - set backgroundPosition(value2) { - this.setProperty("background-position", value2); - } - get backgroundPositionX() { - return this.getPropertyValue("background-position-x"); - } - set backgroundPositionX(value2) { - this.setProperty("background-position-x", value2); - } - get backgroundPositionY() { - return this.getPropertyValue("background-position-y"); - } - set backgroundPositionY(value2) { - this.setProperty("background-position-y", value2); - } - get backgroundRepeat() { - return this.getPropertyValue("background-repeat"); - } - set backgroundRepeat(value2) { - this.setProperty("background-repeat", value2); - } - get backgroundRepeatX() { - return this.getPropertyValue("background-repeat-x"); - } - set backgroundRepeatX(value2) { - this.setProperty("background-repeat-x", value2); - } - get backgroundRepeatY() { - return this.getPropertyValue("background-repeat-y"); - } - set backgroundRepeatY(value2) { - this.setProperty("background-repeat-y", value2); - } - get backgroundSize() { - return this.getPropertyValue("background-size"); - } - set backgroundSize(value2) { - this.setProperty("background-size", value2); - } - get baselineShift() { - return this.getPropertyValue("baseline-shift"); - } - set baselineShift(value2) { - this.setProperty("baseline-shift", value2); - } - get blockSize() { - return this.getPropertyValue("block-size"); - } - set blockSize(value2) { - this.setProperty("block-size", value2); - } - get border() { - return this.getPropertyValue("border"); - } - set border(value2) { - this.setProperty("border", value2); - } - get borderBlockEnd() { - return this.getPropertyValue("border-block-end"); - } - set borderBlockEnd(value2) { - this.setProperty("border-block-end", value2); - } - get borderBlockEndColor() { - return this.getPropertyValue("border-block-end-color"); - } - set borderBlockEndColor(value2) { - this.setProperty("border-block-end-color", value2); - } - get borderBlockEndStyle() { - return this.getPropertyValue("border-block-end-style"); - } - set borderBlockEndStyle(value2) { - this.setProperty("border-block-end-style", value2); - } - get borderBlockEndWidth() { - return this.getPropertyValue("border-block-end-width"); - } - set borderBlockEndWidth(value2) { - this.setProperty("border-block-end-width", value2); - } - get borderBlockStart() { - return this.getPropertyValue("border-block-start"); - } - set borderBlockStart(value2) { - this.setProperty("border-block-start", value2); - } - get borderBlockStartColor() { - return this.getPropertyValue("border-block-start-color"); - } - set borderBlockStartColor(value2) { - this.setProperty("border-block-start-color", value2); - } - get borderBlockStartStyle() { - return this.getPropertyValue("border-block-start-style"); - } - set borderBlockStartStyle(value2) { - this.setProperty("border-block-start-style", value2); - } - get borderBlockStartWidth() { - return this.getPropertyValue("border-block-start-width"); - } - set borderBlockStartWidth(value2) { - this.setProperty("border-block-start-width", value2); - } - get borderBottom() { - return this.getPropertyValue("border-bottom"); - } - set borderBottom(value2) { - this.setProperty("border-bottom", value2); - } - get borderBottomColor() { - return this.getPropertyValue("border-bottom-color"); - } - set borderBottomColor(value2) { - this.setProperty("border-bottom-color", value2); - } - get borderBottomLeftRadius() { - return this.getPropertyValue("border-bottom-left-radius"); - } - set borderBottomLeftRadius(value2) { - this.setProperty("border-bottom-left-radius", value2); - } - get borderBottomRightRadius() { - return this.getPropertyValue("border-bottom-right-radius"); - } - set borderBottomRightRadius(value2) { - this.setProperty("border-bottom-right-radius", value2); - } - get borderBottomStyle() { - return this.getPropertyValue("border-bottom-style"); - } - set borderBottomStyle(value2) { - this.setProperty("border-bottom-style", value2); - } - get borderBottomWidth() { - return this.getPropertyValue("border-bottom-width"); - } - set borderBottomWidth(value2) { - this.setProperty("border-bottom-width", value2); - } - get borderCollapse() { - return this.getPropertyValue("border-collapse"); - } - set borderCollapse(value2) { - this.setProperty("border-collapse", value2); - } - get borderColor() { - return this.getPropertyValue("border-color"); - } - set borderColor(value2) { - this.setProperty("border-color", value2); - } - get borderImage() { - return this.getPropertyValue("border-image"); - } - set borderImage(value2) { - this.setProperty("border-image", value2); - } - get borderImageOutset() { - return this.getPropertyValue("border-image-outset"); - } - set borderImageOutset(value2) { - this.setProperty("border-image-outset", value2); - } - get borderImageRepeat() { - return this.getPropertyValue("border-image-repeat"); - } - set borderImageRepeat(value2) { - this.setProperty("border-image-repeat", value2); - } - get borderImageSlice() { - return this.getPropertyValue("border-image-slice"); - } - set borderImageSlice(value2) { - this.setProperty("border-image-slice", value2); - } - get borderImageSource() { - return this.getPropertyValue("border-image-source"); - } - set borderImageSource(value2) { - this.setProperty("border-image-source", value2); - } - get borderImageWidth() { - return this.getPropertyValue("border-image-width"); - } - set borderImageWidth(value2) { - this.setProperty("border-image-width", value2); - } - get borderInlineEnd() { - return this.getPropertyValue("border-inline-end"); - } - set borderInlineEnd(value2) { - this.setProperty("border-inline-end", value2); - } - get borderInlineEndColor() { - return this.getPropertyValue("border-inline-end-color"); - } - set borderInlineEndColor(value2) { - this.setProperty("border-inline-end-color", value2); - } - get borderInlineEndStyle() { - return this.getPropertyValue("border-inline-end-style"); - } - set borderInlineEndStyle(value2) { - this.setProperty("border-inline-end-style", value2); - } - get borderInlineEndWidth() { - return this.getPropertyValue("border-inline-end-width"); - } - set borderInlineEndWidth(value2) { - this.setProperty("border-inline-end-width", value2); - } - get borderInlineStart() { - return this.getPropertyValue("border-inline-start"); - } - set borderInlineStart(value2) { - this.setProperty("border-inline-start", value2); - } - get borderInlineStartColor() { - return this.getPropertyValue("border-inline-start-color"); - } - set borderInlineStartColor(value2) { - this.setProperty("border-inline-start-color", value2); - } - get borderInlineStartStyle() { - return this.getPropertyValue("border-inline-start-style"); - } - set borderInlineStartStyle(value2) { - this.setProperty("border-inline-start-style", value2); - } - get borderInlineStartWidth() { - return this.getPropertyValue("border-inline-start-width"); - } - set borderInlineStartWidth(value2) { - this.setProperty("border-inline-start-width", value2); - } - get borderLeft() { - return this.getPropertyValue("border-left"); - } - set borderLeft(value2) { - this.setProperty("border-left", value2); - } - get borderLeftColor() { - return this.getPropertyValue("border-left-color"); - } - set borderLeftColor(value2) { - this.setProperty("border-left-color", value2); - } - get borderLeftStyle() { - return this.getPropertyValue("border-left-style"); - } - set borderLeftStyle(value2) { - this.setProperty("border-left-style", value2); - } - get borderLeftWidth() { - return this.getPropertyValue("border-left-width"); - } - set borderLeftWidth(value2) { - this.setProperty("border-left-width", value2); - } - get borderRadius() { - return this.getPropertyValue("border-radius"); - } - set borderRadius(value2) { - this.setProperty("border-radius", value2); - } - get borderRight() { - return this.getPropertyValue("border-right"); - } - set borderRight(value2) { - this.setProperty("border-right", value2); - } - get borderRightColor() { - return this.getPropertyValue("border-right-color"); - } - set borderRightColor(value2) { - this.setProperty("border-right-color", value2); - } - get borderRightStyle() { - return this.getPropertyValue("border-right-style"); - } - set borderRightStyle(value2) { - this.setProperty("border-right-style", value2); - } - get borderRightWidth() { - return this.getPropertyValue("border-right-width"); - } - set borderRightWidth(value2) { - this.setProperty("border-right-width", value2); - } - get borderSpacing() { - return this.getPropertyValue("border-spacing"); - } - set borderSpacing(value2) { - this.setProperty("border-spacing", value2); - } - get borderStyle() { - return this.getPropertyValue("border-style"); - } - set borderStyle(value2) { - this.setProperty("border-style", value2); - } - get borderTop() { - return this.getPropertyValue("border-top"); - } - set borderTop(value2) { - this.setProperty("border-top", value2); - } - get borderTopColor() { - return this.getPropertyValue("border-top-color"); - } - set borderTopColor(value2) { - this.setProperty("border-top-color", value2); - } - get borderTopLeftRadius() { - return this.getPropertyValue("border-top-left-radius"); - } - set borderTopLeftRadius(value2) { - this.setProperty("border-top-left-radius", value2); - } - get borderTopRightRadius() { - return this.getPropertyValue("border-top-right-radius"); - } - set borderTopRightRadius(value2) { - this.setProperty("border-top-right-radius", value2); - } - get borderTopStyle() { - return this.getPropertyValue("border-top-style"); - } - set borderTopStyle(value2) { - this.setProperty("border-top-style", value2); - } - get borderTopWidth() { - return this.getPropertyValue("border-top-width"); - } - set borderTopWidth(value2) { - this.setProperty("border-top-width", value2); - } - get borderWidth() { - return this.getPropertyValue("border-width"); - } - set borderWidth(value2) { - this.setProperty("border-width", value2); - } - get borderEndEndRadius() { - return this.getPropertyValue("border-end-end-radius"); - } - set borderEndEndRadius(value2) { - this.setProperty("border-end-end-radius", value2); - } - get borderEndStartRadius() { - return this.getPropertyValue("border-end-start-radius"); - } - set borderEndStartRadius(value2) { - this.setProperty("border-end-start-radius", value2); - } - get borderStartEndRadius() { - return this.getPropertyValue("border-start-end-radius"); - } - set borderStartEndRadius(value2) { - this.setProperty("border-start-end-radius", value2); - } - get borderStartStartRadius() { - return this.getPropertyValue("border-start-start-radius"); - } - set borderStartStartRadius(value2) { - this.setProperty("border-start-start-radius", value2); - } - get bottom() { - return this.getPropertyValue("bottom"); - } - set bottom(value2) { - this.setProperty("bottom", value2); - } - get boxShadow() { - return this.getPropertyValue("box-shadow"); - } - set boxShadow(value2) { - this.setProperty("box-shadow", value2); - } - get boxSizing() { - return this.getPropertyValue("box-sizing"); - } - set boxSizing(value2) { - this.setProperty("box-sizing", value2); - } - get breakAfter() { - return this.getPropertyValue("break-after"); - } - set breakAfter(value2) { - this.setProperty("break-after", value2); - } - get breakBefore() { - return this.getPropertyValue("break-before"); - } - set breakBefore(value2) { - this.setProperty("break-before", value2); - } - get breakInside() { - return this.getPropertyValue("break-inside"); - } - set breakInside(value2) { - this.setProperty("break-inside", value2); - } - get bufferedRendering() { - return this.getPropertyValue("buffered-rendering"); - } - set bufferedRendering(value2) { - this.setProperty("buffered-rendering", value2); - } - get captionSide() { - return this.getPropertyValue("caption-side"); - } - set captionSide(value2) { - this.setProperty("caption-side", value2); - } - get caretColor() { - return this.getPropertyValue("caret-color"); - } - set caretColor(value2) { - this.setProperty("caret-color", value2); - } - get clear() { - return this.getPropertyValue("clear"); - } - set clear(value2) { - this.setProperty("clear", value2); - } - get clip() { - return this.getPropertyValue("clip"); - } - set clip(value2) { - this.setProperty("clip", value2); - } - get clipPath() { - return this.getPropertyValue("clip-path"); - } - set clipPath(value2) { - this.setProperty("clip-path", value2); - } - get clipRule() { - return this.getPropertyValue("clip-rule"); - } - set clipRule(value2) { - this.setProperty("clip-rule", value2); - } - get color() { - return this.getPropertyValue("color"); - } - set color(value2) { - this.setProperty("color", value2); - } - get colorInterpolation() { - return this.getPropertyValue("color-interpolation"); - } - set colorInterpolation(value2) { - this.setProperty("color-interpolation", value2); - } - get colorInterpolationFilters() { - return this.getPropertyValue("color-interpolation-filters"); - } - set colorInterpolationFilters(value2) { - this.setProperty("color-interpolation-filters", value2); - } - get colorRendering() { - return this.getPropertyValue("color-rendering"); - } - set colorRendering(value2) { - this.setProperty("color-rendering", value2); - } - get colorScheme() { - return this.getPropertyValue("color-scheme"); - } - set colorScheme(value2) { - this.setProperty("color-scheme", value2); - } - get columnCount() { - return this.getPropertyValue("column-count"); - } - set columnCount(value2) { - this.setProperty("column-count", value2); - } - get columnFill() { - return this.getPropertyValue("column-fill"); - } - set columnFill(value2) { - this.setProperty("column-fill", value2); - } - get columnGap() { - return this.getPropertyValue("column-gap"); - } - set columnGap(value2) { - this.setProperty("column-gap", value2); - } - get columnRule() { - return this.getPropertyValue("column-rule"); - } - set columnRule(value2) { - this.setProperty("column-rule", value2); - } - get columnRuleColor() { - return this.getPropertyValue("column-rule-color"); - } - set columnRuleColor(value2) { - this.setProperty("column-rule-color", value2); - } - get columnRuleStyle() { - return this.getPropertyValue("column-rule-style"); - } - set columnRuleStyle(value2) { - this.setProperty("column-rule-style", value2); - } - get columnRuleWidth() { - return this.getPropertyValue("column-rule-width"); - } - set columnRuleWidth(value2) { - this.setProperty("column-rule-width", value2); - } - get columnSpan() { - return this.getPropertyValue("column-span"); - } - set columnSpan(value2) { - this.setProperty("column-span", value2); - } - get columnWidth() { - return this.getPropertyValue("column-width"); - } - set columnWidth(value2) { - this.setProperty("column-width", value2); - } - get columns() { - return this.getPropertyValue("columns"); - } - set columns(value2) { - this.setProperty("columns", value2); - } - get contain() { - return this.getPropertyValue("contain"); - } - set contain(value2) { - this.setProperty("contain", value2); - } - get containIntrinsicSize() { - return this.getPropertyValue("contain-intrinsic-size"); - } - set containIntrinsicSize(value2) { - this.setProperty("contain-intrinsic-size", value2); - } - get content() { - return this.getPropertyValue("content"); - } - set content(value2) { - this.setProperty("content", value2); - } - get contentVisibility() { - return this.getPropertyValue("content-visibility"); - } - set contentVisibility(value2) { - this.setProperty("content-visibility", value2); - } - get counterIncrement() { - return this.getPropertyValue("counter-increment"); - } - set counterIncrement(value2) { - this.setProperty("counter-increment", value2); - } - get counterReset() { - return this.getPropertyValue("counter-reset"); - } - set counterReset(value2) { - this.setProperty("counter-reset", value2); - } - get counterSet() { - return this.getPropertyValue("counter-set"); - } - set counterSet(value2) { - this.setProperty("counter-set", value2); - } - get containIntrinsicBlockSize() { - return this.getPropertyValue("contain-intrinsic-block-size"); - } - set containIntrinsicBlockSize(value2) { - this.setProperty("contain-intrinsic-block-size", value2); - } - get containIntrinsicHeight() { - return this.getPropertyValue("contain-intrinsic-height"); - } - set containIntrinsicHeight(value2) { - this.setProperty("contain-intrinsic-height", value2); - } - get containIntrinsicInlineSize() { - return this.getPropertyValue("contain-intrinsic-inline-size"); - } - set containIntrinsicInlineSize(value2) { - this.setProperty("contain-intrinsic-inline-size", value2); - } - get containIntrinsicWidth() { - return this.getPropertyValue("contain-intrinsic-width"); - } - set containIntrinsicWidth(value2) { - this.setProperty("contain-intrinsic-width", value2); - } - get cssFloat() { - return this.getPropertyValue("css-float"); - } - set cssFloat(value2) { - this.setProperty("css-float", value2); - } - get cursor() { - return this.getPropertyValue("cursor"); - } - set cursor(value2) { - this.setProperty("cursor", value2); - } - get cx() { - return this.getPropertyValue("cx"); - } - set cx(value2) { - this.setProperty("cx", value2); - } - get cy() { - return this.getPropertyValue("cy"); - } - set cy(value2) { - this.setProperty("cy", value2); - } - get d() { - return this.getPropertyValue("d"); - } - set d(value2) { - this.setProperty("d", value2); - } - get direction() { - return this.getPropertyValue("direction"); - } - set direction(value2) { - this.setProperty("direction", value2); - } - get display() { - return this.getPropertyValue("display"); - } - set display(value2) { - this.setProperty("display", value2); - } - get dominantBaseline() { - return this.getPropertyValue("dominant-baseline"); - } - set dominantBaseline(value2) { - this.setProperty("dominant-baseline", value2); - } - get emptyCells() { - return this.getPropertyValue("empty-cells"); - } - set emptyCells(value2) { - this.setProperty("empty-cells", value2); - } - get fill() { - return this.getPropertyValue("fill"); - } - set fill(value2) { - this.setProperty("fill", value2); - } - get fillOpacity() { - return this.getPropertyValue("fill-opacity"); - } - set fillOpacity(value2) { - this.setProperty("fill-opacity", value2); - } - get fillRule() { - return this.getPropertyValue("fill-rule"); - } - set fillRule(value2) { - this.setProperty("fill-rule", value2); - } - get filter() { - return this.getPropertyValue("filter"); - } - set filter(value2) { - this.setProperty("filter", value2); - } - get flex() { - return this.getPropertyValue("flex"); - } - set flex(value2) { - this.setProperty("flex", value2); - } - get flexBasis() { - return this.getPropertyValue("flex-basis"); - } - set flexBasis(value2) { - this.setProperty("flex-basis", value2); - } - get flexDirection() { - return this.getPropertyValue("flex-direction"); - } - set flexDirection(value2) { - this.setProperty("flex-direction", value2); - } - get flexFlow() { - return this.getPropertyValue("flex-flow"); - } - set flexFlow(value2) { - this.setProperty("flex-flow", value2); - } - get flexGrow() { - return this.getPropertyValue("flex-grow"); - } - set flexGrow(value2) { - this.setProperty("flex-grow", value2); - } - get flexShrink() { - return this.getPropertyValue("flex-shrink"); - } - set flexShrink(value2) { - this.setProperty("flex-shrink", value2); - } - get flexWrap() { - return this.getPropertyValue("flex-wrap"); - } - set flexWrap(value2) { - this.setProperty("flex-wrap", value2); - } - get float() { - return this.getPropertyValue("float"); - } - set float(value2) { - this.setProperty("float", value2); - } - get floodColor() { - return this.getPropertyValue("flood-color"); - } - set floodColor(value2) { - this.setProperty("flood-color", value2); - } - get floodOpacity() { - return this.getPropertyValue("flood-opacity"); - } - set floodOpacity(value2) { - this.setProperty("flood-opacity", value2); - } - get font() { - return this.getPropertyValue("font"); - } - set font(value2) { - this.setProperty("font", value2); - } - get fontDisplay() { - return this.getPropertyValue("font-display"); - } - set fontDisplay(value2) { - this.setProperty("font-display", value2); - } - get fontFamily() { - return this.getPropertyValue("font-family"); - } - set fontFamily(value2) { - this.setProperty("font-family", value2); - } - get fontFeatureSettings() { - return this.getPropertyValue("font-feature-settings"); - } - set fontFeatureSettings(value2) { - this.setProperty("font-feature-settings", value2); - } - get fontKerning() { - return this.getPropertyValue("font-kerning"); - } - set fontKerning(value2) { - this.setProperty("font-kerning", value2); - } - get fontOpticalSizing() { - return this.getPropertyValue("font-optical-sizing"); - } - set fontOpticalSizing(value2) { - this.setProperty("font-optical-sizing", value2); - } - get fontSize() { - return this.getPropertyValue("font-size"); - } - set fontSize(value2) { - this.setProperty("font-size", value2); - } - get fontStretch() { - return this.getPropertyValue("font-stretch"); - } - set fontStretch(value2) { - this.setProperty("font-stretch", value2); - } - get fontStyle() { - return this.getPropertyValue("font-style"); - } - set fontStyle(value2) { - this.setProperty("font-style", value2); - } - get fontVariant() { - return this.getPropertyValue("font-variant"); - } - set fontVariant(value2) { - this.setProperty("font-variant", value2); - } - get fontVariantCaps() { - return this.getPropertyValue("font-variant-caps"); - } - set fontVariantCaps(value2) { - this.setProperty("font-variant-caps", value2); - } - get fontVariantEastAsian() { - return this.getPropertyValue("font-variant-east-asian"); - } - set fontVariantEastAsian(value2) { - this.setProperty("font-variant-east-asian", value2); - } - get fontVariantLigatures() { - return this.getPropertyValue("font-variant-ligatures"); - } - set fontVariantLigatures(value2) { - this.setProperty("font-variant-ligatures", value2); - } - get fontVariantNumeric() { - return this.getPropertyValue("font-variant-numeric"); - } - set fontVariantNumeric(value2) { - this.setProperty("font-variant-numeric", value2); - } - get fontVariationSettings() { - return this.getPropertyValue("font-variation-settings"); - } - set fontVariationSettings(value2) { - this.setProperty("font-variation-settings", value2); - } - get fontPalette() { - return this.getPropertyValue("font-palette"); - } - set fontPalette(value2) { - this.setProperty("font-palette", value2); - } - get fontSynthesisSmallCaps() { - return this.getPropertyValue("font-synthesis-small-caps"); - } - set fontSynthesisSmallCaps(value2) { - this.setProperty("font-synthesis-small-caps", value2); - } - get fontSynthesisStyle() { - return this.getPropertyValue("font-synthesis-style"); - } - set fontSynthesisStyle(value2) { - this.setProperty("font-synthesis-style", value2); - } - get fontSynthesisWeight() { - return this.getPropertyValue("font-synthesis-weight"); - } - set fontSynthesisWeight(value2) { - this.setProperty("font-synthesis-weight", value2); - } - get fontWeight() { - return this.getPropertyValue("font-weight"); - } - set fontWeight(value2) { - this.setProperty("font-weight", value2); - } - get gap() { - return this.getPropertyValue("gap"); - } - set gap(value2) { - this.setProperty("gap", value2); - } - get grid() { - return this.getPropertyValue("grid"); - } - set grid(value2) { - this.setProperty("grid", value2); - } - get gridArea() { - return this.getPropertyValue("grid-area"); - } - set gridArea(value2) { - this.setProperty("grid-area", value2); - } - get gridAutoColumns() { - return this.getPropertyValue("grid-auto-columns"); - } - set gridAutoColumns(value2) { - this.setProperty("grid-auto-columns", value2); - } - get gridAutoFlow() { - return this.getPropertyValue("grid-auto-flow"); - } - set gridAutoFlow(value2) { - this.setProperty("grid-auto-flow", value2); - } - get gridAutoRows() { - return this.getPropertyValue("grid-auto-rows"); - } - set gridAutoRows(value2) { - this.setProperty("grid-auto-rows", value2); - } - get gridColumn() { - return this.getPropertyValue("grid-column"); - } - set gridColumn(value2) { - this.setProperty("grid-column", value2); - } - get gridColumnEnd() { - return this.getPropertyValue("grid-column-end"); - } - set gridColumnEnd(value2) { - this.setProperty("grid-column-end", value2); - } - get gridColumnGap() { - return this.getPropertyValue("grid-column-gap"); - } - set gridColumnGap(value2) { - this.setProperty("grid-column-gap", value2); - } - get gridColumnStart() { - return this.getPropertyValue("grid-column-start"); - } - set gridColumnStart(value2) { - this.setProperty("grid-column-start", value2); - } - get gridGap() { - return this.getPropertyValue("grid-gap"); - } - set gridGap(value2) { - this.setProperty("grid-gap", value2); - } - get gridRow() { - return this.getPropertyValue("grid-row"); - } - set gridRow(value2) { - this.setProperty("grid-row", value2); - } - get gridRowEnd() { - return this.getPropertyValue("grid-row-end"); - } - set gridRowEnd(value2) { - this.setProperty("grid-row-end", value2); - } - get gridRowGap() { - return this.getPropertyValue("grid-row-gap"); - } - set gridRowGap(value2) { - this.setProperty("grid-row-gap", value2); - } - get gridRowStart() { - return this.getPropertyValue("grid-row-start"); - } - set gridRowStart(value2) { - this.setProperty("grid-row-start", value2); - } - get gridTemplate() { - return this.getPropertyValue("grid-template"); - } - set gridTemplate(value2) { - this.setProperty("grid-template", value2); - } - get gridTemplateAreas() { - return this.getPropertyValue("grid-template-areas"); - } - set gridTemplateAreas(value2) { - this.setProperty("grid-template-areas", value2); - } - get gridTemplateColumns() { - return this.getPropertyValue("grid-template-columns"); - } - set gridTemplateColumns(value2) { - this.setProperty("grid-template-columns", value2); - } - get gridTemplateRows() { - return this.getPropertyValue("grid-template-rows"); - } - set gridTemplateRows(value2) { - this.setProperty("grid-template-rows", value2); - } - get height() { - return this.getPropertyValue("height"); - } - set height(value2) { - this.setProperty("height", value2); - } - get hyphens() { - return this.getPropertyValue("hyphens"); - } - set hyphens(value2) { - this.setProperty("hyphens", value2); - } - get imageOrientation() { - return this.getPropertyValue("image-orientation"); - } - set imageOrientation(value2) { - this.setProperty("image-orientation", value2); - } - get imageRendering() { - return this.getPropertyValue("image-rendering"); - } - set imageRendering(value2) { - this.setProperty("image-rendering", value2); - } - get inherits() { - return this.getPropertyValue("inherits"); - } - set inherits(value2) { - this.setProperty("inherits", value2); - } - get initialValue() { - return this.getPropertyValue("initial-value"); - } - set initialValue(value2) { - this.setProperty("initial-value", value2); - } - get inlineSize() { - return this.getPropertyValue("inline-size"); - } - set inlineSize(value2) { - this.setProperty("inline-size", value2); - } - get isolation() { - return this.getPropertyValue("isolation"); - } - set isolation(value2) { - this.setProperty("isolation", value2); - } - get insetBlockEnd() { - return this.getPropertyValue("inset-block-end"); - } - set insetBlockEnd(value2) { - this.setProperty("inset-block-end", value2); - } - get insetBlockStart() { - return this.getPropertyValue("inset-block-start"); - } - set insetBlockStart(value2) { - this.setProperty("inset-block-start", value2); - } - get insetInlineEnd() { - return this.getPropertyValue("inset-inline-end"); - } - set insetInlineEnd(value2) { - this.setProperty("inset-inline-end", value2); - } - get insetInlineStart() { - return this.getPropertyValue("inset-inline-start"); - } - set insetInlineStart(value2) { - this.setProperty("inset-inline-start", value2); - } - get justifyContent() { - return this.getPropertyValue("justify-content"); - } - set justifyContent(value2) { - this.setProperty("justify-content", value2); - } - get justifyItems() { - return this.getPropertyValue("justify-items"); - } - set justifyItems(value2) { - this.setProperty("justify-items", value2); - } - get justifySelf() { - return this.getPropertyValue("justify-self"); - } - set justifySelf(value2) { - this.setProperty("justify-self", value2); - } - get left() { - return this.getPropertyValue("left"); - } - set left(value2) { - this.setProperty("left", value2); - } - get letterSpacing() { - return this.getPropertyValue("letter-spacing"); - } - set letterSpacing(value2) { - this.setProperty("letter-spacing", value2); - } - get lightingColor() { - return this.getPropertyValue("lighting-color"); - } - set lightingColor(value2) { - this.setProperty("lighting-color", value2); - } - get lineBreak() { - return this.getPropertyValue("line-break"); - } - set lineBreak(value2) { - this.setProperty("line-break", value2); - } - get lineHeight() { - return this.getPropertyValue("line-height"); - } - set lineHeight(value2) { - this.setProperty("line-height", value2); - } - get listStyle() { - return this.getPropertyValue("list-style"); - } - set listStyle(value2) { - this.setProperty("list-style", value2); - } - get listStyleImage() { - return this.getPropertyValue("list-style-image"); - } - set listStyleImage(value2) { - this.setProperty("list-style-image", value2); - } - get listStylePosition() { - return this.getPropertyValue("list-style-position"); - } - set listStylePosition(value2) { - this.setProperty("list-style-position", value2); - } - get listStyleType() { - return this.getPropertyValue("list-style-type"); - } - set listStyleType(value2) { - this.setProperty("list-style-type", value2); - } - get margin() { - return this.getPropertyValue("margin"); - } - set margin(value2) { - this.setProperty("margin", value2); - } - get marginBlockEnd() { - return this.getPropertyValue("margin-block-end"); - } - set marginBlockEnd(value2) { - this.setProperty("margin-block-end", value2); - } - get marginBlockStart() { - return this.getPropertyValue("margin-block-start"); - } - set marginBlockStart(value2) { - this.setProperty("margin-block-start", value2); - } - get marginBottom() { - return this.getPropertyValue("margin-bottom"); - } - set marginBottom(value2) { - this.setProperty("margin-bottom", value2); - } - get marginInlineEnd() { - return this.getPropertyValue("margin-inline-end"); - } - set marginInlineEnd(value2) { - this.setProperty("margin-inline-end", value2); - } - get marginInlineStart() { - return this.getPropertyValue("margin-inline-start"); - } - set marginInlineStart(value2) { - this.setProperty("margin-inline-start", value2); - } - get marginLeft() { - return this.getPropertyValue("margin-left"); - } - set marginLeft(value2) { - this.setProperty("margin-left", value2); - } - get marginRight() { - return this.getPropertyValue("margin-right"); - } - set marginRight(value2) { - this.setProperty("margin-right", value2); - } - get marginTop() { - return this.getPropertyValue("margin-top"); - } - set marginTop(value2) { - this.setProperty("margin-top", value2); - } - get marker() { - return this.getPropertyValue("marker"); - } - set marker(value2) { - this.setProperty("marker", value2); - } - get markerEnd() { - return this.getPropertyValue("marker-end"); - } - set markerEnd(value2) { - this.setProperty("marker-end", value2); - } - get markerMid() { - return this.getPropertyValue("marker-mid"); - } - set markerMid(value2) { - this.setProperty("marker-mid", value2); - } - get markerStart() { - return this.getPropertyValue("marker-start"); - } - set markerStart(value2) { - this.setProperty("marker-start", value2); - } - get mask() { - return this.getPropertyValue("mask"); - } - set mask(value2) { - this.setProperty("mask", value2); - } - get maskType() { - return this.getPropertyValue("mask-type"); - } - set maskType(value2) { - this.setProperty("mask-type", value2); - } - get maxBlockSize() { - return this.getPropertyValue("max-block-size"); - } - set maxBlockSize(value2) { - this.setProperty("max-block-size", value2); - } - get maxHeight() { - return this.getPropertyValue("max-height"); - } - set maxHeight(value2) { - this.setProperty("max-height", value2); - } - get maxInlineSize() { - return this.getPropertyValue("max-inline-size"); - } - set maxInlineSize(value2) { - this.setProperty("max-inline-size", value2); - } - get maxWidth() { - return this.getPropertyValue("max-width"); - } - set maxWidth(value2) { - this.setProperty("max-width", value2); - } - get maxZoom() { - return this.getPropertyValue("max-zoom"); - } - set maxZoom(value2) { - this.setProperty("max-zoom", value2); - } - get minBlockSize() { - return this.getPropertyValue("min-block-size"); - } - set minBlockSize(value2) { - this.setProperty("min-block-size", value2); - } - get minHeight() { - return this.getPropertyValue("min-height"); - } - set minHeight(value2) { - this.setProperty("min-height", value2); - } - get minInlineSize() { - return this.getPropertyValue("min-inline-size"); - } - set minInlineSize(value2) { - this.setProperty("min-inline-size", value2); - } - get minWidth() { - return this.getPropertyValue("min-width"); - } - set minWidth(value2) { - this.setProperty("min-width", value2); - } - get minZoom() { - return this.getPropertyValue("min-zoom"); - } - set minZoom(value2) { - this.setProperty("min-zoom", value2); - } - get mixBlendMode() { - return this.getPropertyValue("mix-blend-mode"); - } - set mixBlendMode(value2) { - this.setProperty("mix-blend-mode", value2); - } - get objectFit() { - return this.getPropertyValue("object-fit"); - } - set objectFit(value2) { - this.setProperty("object-fit", value2); - } - get objectPosition() { - return this.getPropertyValue("object-position"); - } - set objectPosition(value2) { - this.setProperty("object-position", value2); - } - get offset() { - return this.getPropertyValue("offset"); - } - set offset(value2) { - this.setProperty("offset", value2); - } - get offsetDistance() { - return this.getPropertyValue("offset-distance"); - } - set offsetDistance(value2) { - this.setProperty("offset-distance", value2); - } - get offsetPath() { - return this.getPropertyValue("offset-path"); - } - set offsetPath(value2) { - this.setProperty("offset-path", value2); - } - get offsetRotate() { - return this.getPropertyValue("offset-rotate"); - } - set offsetRotate(value2) { - this.setProperty("offset-rotate", value2); - } - get opacity() { - return this.getPropertyValue("opacity"); - } - set opacity(value2) { - this.setProperty("opacity", value2); - } - get order() { - return this.getPropertyValue("order"); - } - set order(value2) { - this.setProperty("order", value2); - } - get orientation() { - return this.getPropertyValue("orientation"); - } - set orientation(value2) { - this.setProperty("orientation", value2); - } - get orphans() { - return this.getPropertyValue("orphans"); - } - set orphans(value2) { - this.setProperty("orphans", value2); - } - get outline() { - return this.getPropertyValue("outline"); - } - set outline(value2) { - this.setProperty("outline", value2); - } - get outlineColor() { - return this.getPropertyValue("outline-color"); - } - set outlineColor(value2) { - this.setProperty("outline-color", value2); - } - get outlineOffset() { - return this.getPropertyValue("outline-offset"); - } - set outlineOffset(value2) { - this.setProperty("outline-offset", value2); - } - get outlineStyle() { - return this.getPropertyValue("outline-style"); - } - set outlineStyle(value2) { - this.setProperty("outline-style", value2); - } - get outlineWidth() { - return this.getPropertyValue("outline-width"); - } - set outlineWidth(value2) { - this.setProperty("outline-width", value2); - } - get overflow() { - return this.getPropertyValue("overflow"); - } - set overflow(value2) { - this.setProperty("overflow", value2); - } - get overflowAnchor() { - return this.getPropertyValue("overflow-anchor"); - } - set overflowAnchor(value2) { - this.setProperty("overflow-anchor", value2); - } - get overflowWrap() { - return this.getPropertyValue("overflow-wrap"); - } - set overflowWrap(value2) { - this.setProperty("overflow-wrap", value2); - } - get overflowX() { - return this.getPropertyValue("overflow-x"); - } - set overflowX(value2) { - this.setProperty("overflow-x", value2); - } - get overflowY() { - return this.getPropertyValue("overflow-y"); - } - set overflowY(value2) { - this.setProperty("overflow-y", value2); - } - get overscrollBehavior() { - return this.getPropertyValue("overscroll-behavior"); - } - set overscrollBehavior(value2) { - this.setProperty("overscroll-behavior", value2); - } - get overscrollBehaviorBlock() { - return this.getPropertyValue("overscroll-behavior-block"); - } - set overscrollBehaviorBlock(value2) { - this.setProperty("overscroll-behavior-block", value2); - } - get overscrollBehaviorInline() { - return this.getPropertyValue("overscroll-behavior-inline"); - } - set overscrollBehaviorInline(value2) { - this.setProperty("overscroll-behavior-inline", value2); - } - get overscrollBehaviorX() { - return this.getPropertyValue("overscroll-behavior-x"); - } - set overscrollBehaviorX(value2) { - this.setProperty("overscroll-behavior-x", value2); - } - get overscrollBehaviorY() { - return this.getPropertyValue("overscroll-behavior-y"); - } - set overscrollBehaviorY(value2) { - this.setProperty("overscroll-behavior-y", value2); - } - get overflowClipMargin() { - return this.getPropertyValue("overflow-clip-margin"); - } - set overflowClipMargin(value2) { - this.setProperty("overflow-clip-margin", value2); - } - get padding() { - return this.getPropertyValue("padding"); - } - set padding(value2) { - this.setProperty("padding", value2); - } - get paddingBlockEnd() { - return this.getPropertyValue("padding-block-end"); - } - set paddingBlockEnd(value2) { - this.setProperty("padding-block-end", value2); - } - get paddingBlockStart() { - return this.getPropertyValue("padding-block-start"); - } - set paddingBlockStart(value2) { - this.setProperty("padding-block-start", value2); - } - get paddingBottom() { - return this.getPropertyValue("padding-bottom"); - } - set paddingBottom(value2) { - this.setProperty("padding-bottom", value2); - } - get paddingInlineEnd() { - return this.getPropertyValue("padding-inline-end"); - } - set paddingInlineEnd(value2) { - this.setProperty("padding-inline-end", value2); - } - get paddingInlineStart() { - return this.getPropertyValue("padding-inline-start"); - } - set paddingInlineStart(value2) { - this.setProperty("padding-inline-start", value2); - } - get paddingLeft() { - return this.getPropertyValue("padding-left"); - } - set paddingLeft(value2) { - this.setProperty("padding-left", value2); - } - get paddingRight() { - return this.getPropertyValue("padding-right"); - } - set paddingRight(value2) { - this.setProperty("padding-right", value2); - } - get paddingTop() { - return this.getPropertyValue("padding-top"); - } - set paddingTop(value2) { - this.setProperty("padding-top", value2); - } - get page() { - return this.getPropertyValue("page"); - } - set page(value2) { - this.setProperty("page", value2); - } - get pageBreakAfter() { - return this.getPropertyValue("page-break-after"); - } - set pageBreakAfter(value2) { - this.setProperty("page-break-after", value2); - } - get pageBreakBefore() { - return this.getPropertyValue("page-break-before"); - } - set pageBreakBefore(value2) { - this.setProperty("page-break-before", value2); - } - get pageBreakInside() { - return this.getPropertyValue("page-break-inside"); - } - set pageBreakInside(value2) { - this.setProperty("page-break-inside", value2); - } - get pageOrientation() { - return this.getPropertyValue("page-orientation"); - } - set pageOrientation(value2) { - this.setProperty("page-orientation", value2); - } - get paintOrder() { - return this.getPropertyValue("paint-order"); - } - set paintOrder(value2) { - this.setProperty("paint-order", value2); - } - get perspective() { - return this.getPropertyValue("perspective"); - } - set perspective(value2) { - this.setProperty("perspective", value2); - } - get perspectiveOrigin() { - return this.getPropertyValue("perspective-origin"); - } - set perspectiveOrigin(value2) { - this.setProperty("perspective-origin", value2); - } - get placeContent() { - return this.getPropertyValue("place-content"); - } - set placeContent(value2) { - this.setProperty("place-content", value2); - } - get placeItems() { - return this.getPropertyValue("place-items"); - } - set placeItems(value2) { - this.setProperty("place-items", value2); - } - get placeSelf() { - return this.getPropertyValue("place-self"); - } - set placeSelf(value2) { - this.setProperty("place-self", value2); - } - get pointerEvents() { - return this.getPropertyValue("pointer-events"); - } - set pointerEvents(value2) { - this.setProperty("pointer-events", value2); - } - get position() { - return this.getPropertyValue("position"); - } - set position(value2) { - this.setProperty("position", value2); - } - get quotes() { - return this.getPropertyValue("quotes"); - } - set quotes(value2) { - this.setProperty("quotes", value2); - } - get r() { - return this.getPropertyValue("r"); - } - set r(value2) { - this.setProperty("r", value2); - } - get resize() { - return this.getPropertyValue("resize"); - } - set resize(value2) { - this.setProperty("resize", value2); - } - get right() { - return this.getPropertyValue("right"); - } - set right(value2) { - this.setProperty("right", value2); - } - get rowGap() { - return this.getPropertyValue("row-gap"); - } - set rowGap(value2) { - this.setProperty("row-gap", value2); - } - get rubyPosition() { - return this.getPropertyValue("ruby-position"); - } - set rubyPosition(value2) { - this.setProperty("ruby-position", value2); - } - get rx() { - return this.getPropertyValue("rx"); - } - set rx(value2) { - this.setProperty("rx", value2); - } - get ry() { - return this.getPropertyValue("ry"); - } - set ry(value2) { - this.setProperty("ry", value2); - } - get scrollBehavior() { - return this.getPropertyValue("scroll-behavior"); - } - set scrollBehavior(value2) { - this.setProperty("scroll-behavior", value2); - } - get scrollMargin() { - return this.getPropertyValue("scroll-margin"); - } - set scrollMargin(value2) { - this.setProperty("scroll-margin", value2); - } - get scrollMarginBlock() { - return this.getPropertyValue("scroll-margin-block"); - } - set scrollMarginBlock(value2) { - this.setProperty("scroll-margin-block", value2); - } - get scrollMarginBlockEnd() { - return this.getPropertyValue("scroll-margin-block-end"); - } - set scrollMarginBlockEnd(value2) { - this.setProperty("scroll-margin-block-end", value2); - } - get scrollMarginBlockStart() { - return this.getPropertyValue("scroll-margin-block-start"); - } - set scrollMarginBlockStart(value2) { - this.setProperty("scroll-margin-block-start", value2); - } - get scrollMarginBottom() { - return this.getPropertyValue("scroll-margin-bottom"); - } - set scrollMarginBottom(value2) { - this.setProperty("scroll-margin-bottom", value2); - } - get scrollMarginInline() { - return this.getPropertyValue("scroll-margin-inline"); - } - set scrollMarginInline(value2) { - this.setProperty("scroll-margin-inline", value2); - } - get scrollMarginInlineEnd() { - return this.getPropertyValue("scroll-margin-inline-end"); - } - set scrollMarginInlineEnd(value2) { - this.setProperty("scroll-margin-inline-end", value2); - } - get scrollMarginInlineStart() { - return this.getPropertyValue("scroll-margin-inline-start"); - } - set scrollMarginInlineStart(value2) { - this.setProperty("scroll-margin-inline-start", value2); - } - get scrollMarginLeft() { - return this.getPropertyValue("scroll-margin-left"); - } - set scrollMarginLeft(value2) { - this.setProperty("scroll-margin-left", value2); - } - get scrollMarginRight() { - return this.getPropertyValue("scroll-margin-right"); - } - set scrollMarginRight(value2) { - this.setProperty("scroll-margin-right", value2); - } - get scrollMarginTop() { - return this.getPropertyValue("scroll-margin-top"); - } - set scrollMarginTop(value2) { - this.setProperty("scroll-margin-top", value2); - } - get scrollPadding() { - return this.getPropertyValue("scroll-padding"); - } - set scrollPadding(value2) { - this.setProperty("scroll-padding", value2); - } - get scrollPaddingBlock() { - return this.getPropertyValue("scroll-padding-block"); - } - set scrollPaddingBlock(value2) { - this.setProperty("scroll-padding-block", value2); - } - get scrollPaddingBlockEnd() { - return this.getPropertyValue("scroll-padding-block-end"); - } - set scrollPaddingBlockEnd(value2) { - this.setProperty("scroll-padding-block-end", value2); - } - get scrollPaddingBlockStart() { - return this.getPropertyValue("scroll-padding-block-start"); - } - set scrollPaddingBlockStart(value2) { - this.setProperty("scroll-padding-block-start", value2); - } - get scrollPaddingBottom() { - return this.getPropertyValue("scroll-padding-bottom"); - } - set scrollPaddingBottom(value2) { - this.setProperty("scroll-padding-bottom", value2); - } - get scrollPaddingInline() { - return this.getPropertyValue("scroll-padding-inline"); - } - set scrollPaddingInline(value2) { - this.setProperty("scroll-padding-inline", value2); - } - get scrollPaddingInlineEnd() { - return this.getPropertyValue("scroll-padding-inline-end"); - } - set scrollPaddingInlineEnd(value2) { - this.setProperty("scroll-padding-inline-end", value2); - } - get scrollPaddingInlineStart() { - return this.getPropertyValue("scroll-padding-inline-start"); - } - set scrollPaddingInlineStart(value2) { - this.setProperty("scroll-padding-inline-start", value2); - } - get scrollPaddingLeft() { - return this.getPropertyValue("scroll-padding-left"); - } - set scrollPaddingLeft(value2) { - this.setProperty("scroll-padding-left", value2); - } - get scrollPaddingRight() { - return this.getPropertyValue("scroll-padding-right"); - } - set scrollPaddingRight(value2) { - this.setProperty("scroll-padding-right", value2); - } - get scrollPaddingTop() { - return this.getPropertyValue("scroll-padding-top"); - } - set scrollPaddingTop(value2) { - this.setProperty("scroll-padding-top", value2); - } - get scrollSnapAlign() { - return this.getPropertyValue("scroll-snap-align"); - } - set scrollSnapAlign(value2) { - this.setProperty("scroll-snap-align", value2); - } - get scrollSnapStop() { - return this.getPropertyValue("scroll-snap-stop"); - } - set scrollSnapStop(value2) { - this.setProperty("scroll-snap-stop", value2); - } - get scrollSnapType() { - return this.getPropertyValue("scroll-snap-type"); - } - set scrollSnapType(value2) { - this.setProperty("scroll-snap-type", value2); - } - get shapeImageThreshold() { - return this.getPropertyValue("shape-image-threshold"); - } - set shapeImageThreshold(value2) { - this.setProperty("shape-image-threshold", value2); - } - get shapeMargin() { - return this.getPropertyValue("shape-margin"); - } - set shapeMargin(value2) { - this.setProperty("shape-margin", value2); - } - get shapeOutside() { - return this.getPropertyValue("shape-outside"); - } - set shapeOutside(value2) { - this.setProperty("shape-outside", value2); - } - get shapeRendering() { - return this.getPropertyValue("shape-rendering"); - } - set shapeRendering(value2) { - this.setProperty("shape-rendering", value2); - } - get size() { - return this.getPropertyValue("size"); - } - set size(value2) { - this.setProperty("size", value2); - } - get speak() { - return this.getPropertyValue("speak"); - } - set speak(value2) { - this.setProperty("speak", value2); - } - get src() { - return this.getPropertyValue("src"); - } - set src(value2) { - this.setProperty("src", value2); - } - get stopColor() { - return this.getPropertyValue("stop-color"); - } - set stopColor(value2) { - this.setProperty("stop-color", value2); - } - get stopOpacity() { - return this.getPropertyValue("stop-opacity"); - } - set stopOpacity(value2) { - this.setProperty("stop-opacity", value2); - } - get stroke() { - return this.getPropertyValue("stroke"); - } - set stroke(value2) { - this.setProperty("stroke", value2); - } - get strokeDasharray() { - return this.getPropertyValue("stroke-dasharray"); - } - set strokeDasharray(value2) { - this.setProperty("stroke-dasharray", value2); - } - get strokeDashoffset() { - return this.getPropertyValue("stroke-dashoffset"); - } - set strokeDashoffset(value2) { - this.setProperty("stroke-dashoffset", value2); - } - get strokeLinecap() { - return this.getPropertyValue("stroke-linecap"); - } - set strokeLinecap(value2) { - this.setProperty("stroke-linecap", value2); - } - get strokeLinejoin() { - return this.getPropertyValue("stroke-linejoin"); - } - set strokeLinejoin(value2) { - this.setProperty("stroke-linejoin", value2); - } - get strokeMiterlimit() { - return this.getPropertyValue("stroke-miterlimit"); - } - set strokeMiterlimit(value2) { - this.setProperty("stroke-miterlimit", value2); - } - get strokeOpacity() { - return this.getPropertyValue("stroke-opacity"); - } - set strokeOpacity(value2) { - this.setProperty("stroke-opacity", value2); - } - get strokeWidth() { - return this.getPropertyValue("stroke-width"); - } - set strokeWidth(value2) { - this.setProperty("stroke-width", value2); - } - get syntax() { - return this.getPropertyValue("syntax"); - } - set syntax(value2) { - this.setProperty("syntax", value2); - } - get scrollbarGutter() { - return this.getPropertyValue("scrollbar-gutter"); - } - set scrollbarGutter(value2) { - this.setProperty("scrollbar-gutter", value2); - } - get tabSize() { - return this.getPropertyValue("tab-size"); - } - set tabSize(value2) { - this.setProperty("tab-size", value2); - } - get tableLayout() { - return this.getPropertyValue("table-layout"); - } - set tableLayout(value2) { - this.setProperty("table-layout", value2); - } - get textAlign() { - return this.getPropertyValue("text-align"); - } - set textAlign(value2) { - this.setProperty("text-align", value2); - } - get textAlignLast() { - return this.getPropertyValue("text-align-last"); - } - set textAlignLast(value2) { - this.setProperty("text-align-last", value2); - } - get textAnchor() { - return this.getPropertyValue("text-anchor"); - } - set textAnchor(value2) { - this.setProperty("text-anchor", value2); - } - get textCombineUpright() { - return this.getPropertyValue("text-combine-upright"); - } - set textCombineUpright(value2) { - this.setProperty("text-combine-upright", value2); - } - get textDecoration() { - return this.getPropertyValue("text-decoration"); - } - set textDecoration(value2) { - this.setProperty("text-decoration", value2); - } - get textDecorationColor() { - return this.getPropertyValue("text-decoration-color"); - } - set textDecorationColor(value2) { - this.setProperty("text-decoration-color", value2); - } - get textDecorationLine() { - return this.getPropertyValue("text-decoration-line"); - } - set textDecorationLine(value2) { - this.setProperty("text-decoration-line", value2); - } - get textDecorationSkipInk() { - return this.getPropertyValue("text-decoration-skip-ink"); - } - set textDecorationSkipInk(value2) { - this.setProperty("text-decoration-skip-ink", value2); - } - get textDecorationStyle() { - return this.getPropertyValue("text-decoration-style"); - } - set textDecorationStyle(value2) { - this.setProperty("text-decoration-style", value2); - } - get textIndent() { - return this.getPropertyValue("text-indent"); - } - set textIndent(value2) { - this.setProperty("text-indent", value2); - } - get textOrientation() { - return this.getPropertyValue("text-orientation"); - } - set textOrientation(value2) { - this.setProperty("text-orientation", value2); - } - get textOverflow() { - return this.getPropertyValue("text-overflow"); - } - set textOverflow(value2) { - this.setProperty("text-overflow", value2); - } - get textRendering() { - return this.getPropertyValue("text-rendering"); - } - set textRendering(value2) { - this.setProperty("text-rendering", value2); - } - get textShadow() { - return this.getPropertyValue("text-shadow"); - } - set textShadow(value2) { - this.setProperty("text-shadow", value2); - } - get textSizeAdjust() { - return this.getPropertyValue("text-size-adjust"); - } - set textSizeAdjust(value2) { - this.setProperty("text-size-adjust", value2); - } - get textTransform() { - return this.getPropertyValue("text-transform"); - } - set textTransform(value2) { - this.setProperty("text-transform", value2); - } - get textUnderlinePosition() { - return this.getPropertyValue("text-underline-position"); - } - set textUnderlinePosition(value2) { - this.setProperty("text-underline-position", value2); - } - get top() { - return this.getPropertyValue("top"); - } - set top(value2) { - this.setProperty("top", value2); - } - get touchAction() { - return this.getPropertyValue("touch-action"); - } - set touchAction(value2) { - this.setProperty("touch-action", value2); - } - get transform() { - return this.getPropertyValue("transform"); - } - set transform(value2) { - this.setProperty("transform", value2); - } - get transformBox() { - return this.getPropertyValue("transform-box"); - } - set transformBox(value2) { - this.setProperty("transform-box", value2); - } - get transformOrigin() { - return this.getPropertyValue("transform-origin"); - } - set transformOrigin(value2) { - this.setProperty("transform-origin", value2); - } - get transformStyle() { - return this.getPropertyValue("transform-style"); - } - set transformStyle(value2) { - this.setProperty("transform-style", value2); - } - get transition() { - return this.getPropertyValue("transition"); - } - set transition(value2) { - this.setProperty("transition", value2); - } - get transitionDelay() { - return this.getPropertyValue("transition-delay"); - } - set transitionDelay(value2) { - this.setProperty("transition-delay", value2); - } - get transitionDuration() { - return this.getPropertyValue("transition-duration"); - } - set transitionDuration(value2) { - this.setProperty("transition-duration", value2); - } - get transitionProperty() { - return this.getPropertyValue("transition-property"); - } - set transitionProperty(value2) { - this.setProperty("transition-property", value2); - } - get transitionTimingFunction() { - return this.getPropertyValue("transition-timing-function"); - } - set transitionTimingFunction(value2) { - this.setProperty("transition-timing-function", value2); - } - get textEmphasisColor() { - return this.getPropertyValue("text-emphasis-color"); - } - set textEmphasisColor(value2) { - this.setProperty("text-emphasis-color", value2); - } - get textEmphasisPosition() { - return this.getPropertyValue("text-emphasis-position"); - } - set textEmphasisPosition(value2) { - this.setProperty("text-emphasis-position", value2); - } - get textEmphasisStyle() { - return this.getPropertyValue("text-emphasis-style"); - } - set textEmphasisStyle(value2) { - this.setProperty("text-emphasis-style", value2); - } - get unicodeBidi() { - return this.getPropertyValue("unicode-bidi"); - } - set unicodeBidi(value2) { - this.setProperty("unicode-bidi", value2); - } - get unicodeRange() { - return this.getPropertyValue("unicode-range"); - } - set unicodeRange(value2) { - this.setProperty("unicode-range", value2); - } - get userSelect() { - return this.getPropertyValue("user-select"); - } - set userSelect(value2) { - this.setProperty("user-select", value2); - } - get userZoom() { - return this.getPropertyValue("user-zoom"); - } - set userZoom(value2) { - this.setProperty("user-zoom", value2); - } - get vectorEffect() { - return this.getPropertyValue("vector-effect"); - } - set vectorEffect(value2) { - this.setProperty("vector-effect", value2); - } - get verticalAlign() { - return this.getPropertyValue("vertical-align"); - } - set verticalAlign(value2) { - this.setProperty("vertical-align", value2); - } - get visibility() { - return this.getPropertyValue("visibility"); - } - set visibility(value2) { - this.setProperty("visibility", value2); - } - get whiteSpace() { - return this.getPropertyValue("white-space"); - } - set whiteSpace(value2) { - this.setProperty("white-space", value2); - } - get widows() { - return this.getPropertyValue("widows"); - } - set widows(value2) { - this.setProperty("widows", value2); - } - get width() { - return this.getPropertyValue("width"); - } - set width(value2) { - this.setProperty("width", value2); - } - get willChange() { - return this.getPropertyValue("will-change"); - } - set willChange(value2) { - this.setProperty("will-change", value2); - } - get wordBreak() { - return this.getPropertyValue("word-break"); - } - set wordBreak(value2) { - this.setProperty("word-break", value2); - } - get wordSpacing() { - return this.getPropertyValue("word-spacing"); - } - set wordSpacing(value2) { - this.setProperty("word-spacing", value2); - } - get wordWrap() { - return this.getPropertyValue("word-wrap"); - } - set wordWrap(value2) { - this.setProperty("word-wrap", value2); - } - get writingMode() { - return this.getPropertyValue("writing-mode"); - } - set writingMode(value2) { - this.setProperty("writing-mode", value2); - } - get x() { - return this.getPropertyValue("x"); - } - set x(value2) { - this.setProperty("x", value2); - } - get y() { - return this.getPropertyValue("y"); - } - set y(value2) { - this.setProperty("y", value2); - } - get zIndex() { - return this.getPropertyValue("z-index"); - } - set zIndex(value2) { - this.setProperty("z-index", value2); - } - get zoom() { - return this.getPropertyValue("zoom"); - } - set zoom(value2) { - this.setProperty("zoom", value2); - } - get containerType() { - return this.getPropertyValue("container-type"); - } - set containerType(value2) { - this.setProperty("container-type", value2); - } - get containerName() { - return this.getPropertyValue("container-name"); - } - set containerName(value2) { - this.setProperty("container-name", value2); - } - get aspectRatio() { - return this.getPropertyValue("aspect-ratio"); - } - set aspectRatio(value2) { - this.setProperty("aspect-ratio", value2); - } - /* eslint-enable jsdoc/require-jsdoc */ - /** - * Returns length. - * - * @returns Length. - */ - get length() { - return this.#getPropertyManager().size(); - } - /** - * Returns the style decleration as a CSS text. - * - * @returns CSS text. - */ - get cssText() { - if (this.#element && this.#computed) { - return ""; - } - return this.#getPropertyManager().toString(); - } - /** - * Sets CSS text. - * - * @param cssText CSS text. - */ - set cssText(cssText2) { - if (this.#computed) { - throw new this[window].DOMException(`Failed to execute 'cssText' on 'CSSStyleDeclaration': These styles are computed, and the properties are therefore read-only.`, DOMExceptionNameEnum_default.domException); - } - if (this.#element) { - this.#cache.propertyManager = new CSSStyleDeclarationPropertyManager({ cssText: cssText2 }); - this.#cache.attributeValue = cssText2; - this.#element.setAttribute("style", this.#cache.propertyManager.toString()); - } else { - this.#cache.propertyManager = new CSSStyleDeclarationPropertyManager({ cssText: cssText2 }); - } - } - /** - * Returns item. - * - * @param index Index. - * @returns Item. - */ - item(index) { - return this.#getPropertyManager().item(index); - } - /** - * Set a property. - * - * @param name Property name. - * @param value Value. Must not contain "!important" as that should be set using the priority parameter. - * @param [priority] Can be "important", or an empty string. - */ - setProperty(name2, value2, priority) { - if (this.#computed) { - throw new this[window].DOMException(`Failed to execute 'setProperty' on 'CSSStyleDeclaration': These styles are computed, and therefore the '${name2}' property is read-only.`, DOMExceptionNameEnum_default.domException); - } - if (priority !== "" && priority !== void 0 && priority !== "important") { - return; - } - const stringValue = String(value2).trim(); - const propertyManager = this.#getPropertyManager(); - if (stringValue) { - propertyManager.set(name2, stringValue, !!priority); - } else { - propertyManager.remove(name2); - } - if (this.#element) { - this.#cache.attributeValue = propertyManager.toString(); - if (this.#cache.attributeValue) { - this.#element.setAttribute("style", this.#cache.attributeValue); - } else { - this.#element.removeAttribute("style"); - } - } - } - /** - * Removes a property. - * - * @param name Property name in kebab case. - * @param value Value. Must not contain "!important" as that should be set using the priority parameter. - * @param [priority] Can be "important", or an empty string. - */ - removeProperty(name2) { - if (this.#computed) { - throw new this[window].DOMException(`Failed to execute 'removeProperty' on 'CSSStyleDeclaration': These styles are computed, and therefore the '${name2}' property is read-only.`, DOMExceptionNameEnum_default.domException); - } - const propertyManager = this.#getPropertyManager(); - propertyManager.remove(name2); - if (this.#element) { - this.#cache.attributeValue = propertyManager.toString(); - if (this.#cache.attributeValue) { - this.#element.setAttribute("style", this.#cache.attributeValue); - } else { - this.#element.removeAttribute("style"); - } - } - } - /** - * Returns a property. - * - * @param name Property name in kebab case. - * @returns Property value. - */ - getPropertyValue(name2) { - return this.#getPropertyManager().get(name2)?.value || ""; - } - /** - * Returns a property. - * - * @param name Property name in kebab case. - * @returns "important" if set to be important. - */ - getPropertyPriority(name2) { - return this.#getPropertyManager().get(name2)?.important ? "important" : ""; - } - /** - * Returns property manager. - * - * @returns Property manager. - */ - #getPropertyManager() { - const element = this.#element; - const cache2 = this.#cache; - if (!element) { - if (!cache2.propertyManager) { - cache2.propertyManager = new CSSStyleDeclarationPropertyManager(); - } - return cache2.propertyManager; - } - if (this.#computed) { - return new CSSStyleDeclarationComputedStyle(element).getComputedStyle(); - } - const attributeValue2 = element.getAttribute("style") || ""; - if (cache2.attributeValue !== attributeValue2) { - cache2.propertyManager = new CSSStyleDeclarationPropertyManager({ cssText: attributeValue2 }); - } - return cache2.propertyManager; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/rules/CSSConditionRule.js -var CSSConditionRule; -var init_CSSConditionRule = __esm({ - "node_modules/happy-dom/lib/css/rules/CSSConditionRule.js"() { - init_PropertySymbol(); - init_CSSGroupingRule(); - CSSConditionRule = class extends CSSGroupingRule { - [conditionText] = ""; - /** - * Returns condition text. - * - * @returns Condition text. - */ - get conditionText() { - return this[conditionText]; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/rules/CSSContainerRule.js -var CSSContainerRule; -var init_CSSContainerRule = __esm({ - "node_modules/happy-dom/lib/css/rules/CSSContainerRule.js"() { - init_CSSRuleTypeEnum(); - init_CSSConditionRule(); - init_PropertySymbol(); - CSSContainerRule = class extends CSSConditionRule { - [type] = CSSRuleTypeEnum_default.containerRule; - [rulePrefix] = ""; - /** - * @override - */ - get type() { - return CSSRuleTypeEnum_default.containerRule; - } - /** - * @override - */ - get cssText() { - let cssText2 = ""; - for (const cssRule2 of this[cssRules]) { - cssText2 += "\n " + cssRule2.cssText; - } - cssText2 += "\n"; - return `@${this[rulePrefix]}container ${this[conditionText]} {${cssText2}}`; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/rules/CSSFontFaceRule.js -var CSSFontFaceRule; -var init_CSSFontFaceRule = __esm({ - "node_modules/happy-dom/lib/css/rules/CSSFontFaceRule.js"() { - init_CSSRule(); - init_PropertySymbol(); - init_CSSStyleDeclaration(); - init_CSSRuleTypeEnum(); - CSSFontFaceRule = class extends CSSRule { - [cssText] = ""; - #style = null; - /** - * @override - */ - get type() { - return CSSRuleTypeEnum_default.fontFaceRule; - } - /** - * @override - */ - get cssText() { - return `@font-face { ${this.style.cssText} }`; - } - /** - * Returns style. - * - * @returns Style. - */ - get style() { - if (!this.#style) { - this.#style = new CSSStyleDeclaration(illegalConstructor, this[window]); - this.#style.parentRule = this; - this.#style.cssText = this[cssText]; - } - return this.#style; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/rules/CSSKeyframeRule.js -var CSSKeyframeRule; -var init_CSSKeyframeRule = __esm({ - "node_modules/happy-dom/lib/css/rules/CSSKeyframeRule.js"() { - init_CSSRule(); - init_PropertySymbol(); - init_CSSStyleDeclaration(); - init_CSSRuleTypeEnum(); - CSSKeyframeRule = class extends CSSRule { - [keyText] = ""; - [cssText] = ""; - #style = null; - /** - * @override - */ - get type() { - return CSSRuleTypeEnum_default.keyframeRule; - } - /** - * @override - */ - get cssText() { - return `${this[keyText]} { ${this.style.cssText} }`; - } - /** - * Returns style. - * - * @returns Style. - */ - get style() { - if (!this.#style) { - this.#style = new CSSStyleDeclaration(illegalConstructor, this[window]); - this.#style.parentRule = this; - this.#style.cssText = this[cssText]; - } - return this.#style; - } - /** - * Returns key text. - * - * @returns Key text. - */ - get keyText() { - return this[keyText]; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/rules/CSSKeyframesRule.js -var CSS_RULE_REGEXP, CSSKeyframesRule; -var init_CSSKeyframesRule = __esm({ - "node_modules/happy-dom/lib/css/rules/CSSKeyframesRule.js"() { - init_CSSRule(); - init_CSSKeyframeRule(); - init_PropertySymbol(); - init_CSSRuleTypeEnum(); - init_DOMExceptionNameEnum(); - CSS_RULE_REGEXP = /^(from|to|[0-9]{1,3}%)\s*{([^}]*)}$/; - CSSKeyframesRule = class extends CSSRule { - [cssRules] = []; - [name] = ""; - [rulePrefix] = ""; - /** - * @override - */ - get type() { - return CSSRuleTypeEnum_default.keyframesRule; - } - /** - * @override - */ - get cssText() { - let cssText2 = ""; - for (const cssRule2 of this[cssRules]) { - cssText2 += "\n " + cssRule2.cssText; - } - cssText2 += "\n"; - return `@${this[rulePrefix]}keyframes ${this[name]} { ${cssText2}}`; - } - /** - * Returns CSS rules. - * - * @returns CSS rules. - */ - get cssRules() { - return this[cssRules]; - } - /** - * Returns name. - * - * @returns Name. - */ - get name() { - return this[name]; - } - /** - * Returns length. - * - * @returns Length. - */ - get length() { - return this[cssRules].length; - } - /** - * Appends a rule. - * - * @param rule Rule. E.g. "0% { transform: rotate(360deg); }". - */ - appendRule(rule) { - if (arguments.length === 0) { - throw new this[window].TypeError(`Failed to execute 'appendRule' on 'CSSKeyframesRule': 1 argument required, but only 0 present.`); - } - const match = String(rule).trim().match(CSS_RULE_REGEXP); - if (!match) { - throw new this[window].DOMException(`Invalid or unexpected token`, DOMExceptionNameEnum_default.syntaxError); - } - const cssRule2 = new CSSKeyframeRule(illegalConstructor, this[window], this[cssParser]); - let keyText2 = match[1].trim(); - if (keyText2 === "from") { - keyText2 = "0%"; - } else if (keyText2 === "to") { - keyText2 = "100%"; - } - cssRule2[parentRule] = this; - cssRule2[keyText] = keyText2; - cssRule2[cssText] = match[2].trim(); - this[cssRules].push(cssRule2); - } - /** - * Removes a rule. - * - * @param rule Rule. E.g. "0%". - */ - deleteRule(rule) { - if (arguments.length === 0) { - throw new this[window].TypeError(`Failed to execute 'deleteRule' on 'CSSKeyframesRule': 1 argument required, but only 0 present.`); - } - for (let i = 0, max = this[cssRules].length; i < max; i++) { - if (this[cssRules][i][keyText] === rule) { - this[cssRules].splice(i, 1); - return; - } - } - } - /** - * Finds a rule. - * - * @param rule Rule. E.g. "0%". - * @returns Rule. - */ - findRule(rule) { - if (arguments.length === 0) { - throw new this[window].TypeError(`Failed to execute 'findRule' on 'CSSKeyframesRule': 1 argument required, but only 0 present.`); - } - for (let i = 0, max = this[cssRules].length; i < max; i++) { - if (this[cssRules][i][keyText] === rule) { - return this[cssRules][i]; - } - } - return null; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/MediaList.js -var MEDIUM_REGEXP, MediaList; -var init_MediaList = __esm({ - "node_modules/happy-dom/lib/css/MediaList.js"() { - init_PropertySymbol(); - init_ClassMethodBinder(); - MEDIUM_REGEXP = /\s*,\s*/; - MediaList = class _MediaList { - [cssRule]; - /** - * - * @param illegalConstructorSymbol - * @param cssRule - */ - constructor(illegalConstructorSymbol, cssRule2) { - if (illegalConstructorSymbol !== illegalConstructor) { - throw new TypeError("Illegal constructor"); - } - this[cssRule] = cssRule2; - const methodBinder = new ClassMethodBinder(this, [_MediaList]); - return new Proxy(this, { - get: (target2, property) => { - if (property in target2 || typeof property === "symbol") { - methodBinder.bind(property); - return target2[property]; - } - const index = Number(property); - if (!isNaN(index)) { - return target2[getItemList]()[index]; - } - }, - set(target2, property, newValue) { - methodBinder.bind(property); - if (property in target2 || typeof property === "symbol") { - target2[property] = newValue; - return true; - } - return true; - }, - deleteProperty(target2, property) { - if (property in target2 || typeof property === "symbol") { - delete target2[property]; - return true; - } - return true; - }, - ownKeys(target2) { - return Object.keys(target2[getItemList]()); - }, - has(target2, property) { - if (typeof property === "symbol") { - return false; - } - if (property in target2) { - return true; - } - const index = Number(property); - return !isNaN(index) && index >= 0 && index < target2[getItemList]().length; - }, - defineProperty(target2, property, descriptor) { - methodBinder.preventBinding(property); - if (property in target2) { - Object.defineProperty(target2, property, descriptor); - return true; - } - return false; - }, - getOwnPropertyDescriptor(target2, property) { - if (property in target2 || typeof property === "symbol") { - return; - } - const index = Number(property); - const items2 = target2[getItemList](); - if (!isNaN(index) && items2[index]) { - return { - value: items2[index], - writable: false, - enumerable: true, - configurable: true - }; - } - } - }); - } - /** - * Returns length. - * - * @returns Length. - */ - get length() { - return this[getItemList]().length; - } - /** - * Returns media text. - * - * @returns Media text. - */ - get mediaText() { - return this[cssRule][conditionText]; - } - /** - * Sets media text. - * - * @param mediaText Media text. - */ - set mediaText(mediaText) { - this[cssRule][conditionText] = mediaText === null ? "" : String(mediaText).split(MEDIUM_REGEXP).join(", "); - } - /** - * Returns item. - * - * @param index Index. - * @returns Item. - */ - item(index) { - const items2 = this[getItemList](); - return items2[Number(index)] || null; - } - /** - * Appends a medium. - * - * @param medium Medium. - */ - appendMedium(medium) { - const items2 = this[getItemList](); - if (items2.indexOf(medium) === -1) { - items2.push(medium); - this[cssRule][conditionText] = items2.join(", "); - } - } - /** - * Deletes a medium. - * - * @param medium Medium. - */ - deleteMedium(medium) { - const items2 = this[getItemList](); - const index = items2.indexOf(medium); - if (index !== -1) { - items2.splice(index, 1); - this[cssRule][conditionText] = items2.join(", "); - } - } - /** - * Returns item list. - * - * @returns Item list. - */ - [getItemList]() { - const text = this[cssRule][conditionText].trim(); - const media2 = text ? this[cssRule][conditionText].split(MEDIUM_REGEXP) : []; - return media2; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/rules/CSSMediaRule.js -var CSSMediaRule; -var init_CSSMediaRule = __esm({ - "node_modules/happy-dom/lib/css/rules/CSSMediaRule.js"() { - init_CSSRuleTypeEnum(); - init_MediaList(); - init_CSSConditionRule(); - init_PropertySymbol(); - CSSMediaRule = class extends CSSConditionRule { - [media] = new MediaList(illegalConstructor, this); - /** - * @override - */ - get type() { - return CSSRuleTypeEnum_default.mediaRule; - } - /** - * @override - */ - get cssText() { - let cssText2 = ""; - for (const cssRule2 of this[cssRules]) { - cssText2 += "\n " + cssRule2.cssText; - } - cssText2 += cssText2 ? "\n" : " "; - return `@media ${this.conditionText} {${cssText2}}`; - } - /** - * Returns media. - * - * @returns Media. - */ - get media() { - return this[media]; - } - /** - * Returns conditional text. - * - * @returns Conditional text. - */ - get conditionText() { - return this.media.mediaText; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/style-property-map/CSSKeywordValue.js -var CSSKeywordValue; -var init_CSSKeywordValue = __esm({ - "node_modules/happy-dom/lib/css/style-property-map/CSSKeywordValue.js"() { - CSSKeywordValue = class { - #value; - /** - * Constructor. - * - * @param value Value.. - */ - constructor(value2) { - this.#value = value2; - } - /** - * Returns value. - * - * @returns Value. - */ - get value() { - return this.#value; - } - /** - * Sets value. - * - * @param value Value. - */ - set value(value2) { - this.#value = value2; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/style-property-map/CSSStyleValue.js -var CSSStyleValue; -var init_CSSStyleValue = __esm({ - "node_modules/happy-dom/lib/css/style-property-map/CSSStyleValue.js"() { - init_PropertySymbol(); - CSSStyleValue = class { - #style; - #property; - /** - * Constructor. - * - * @param illegalConstructorSymbol - * @param style Style. - * @param property Property. - */ - constructor(illegalConstructorSymbol, style2, property) { - if (illegalConstructorSymbol !== illegalConstructor) { - throw new TypeError("Illegal constructor"); - } - this.#style = style2; - this.#property = property; - } - /** - * Returns value as string. - * - * @returns Value. - */ - toString() { - return this.#style.getPropertyValue(this.#property); - } - }; - } -}); - -// node_modules/happy-dom/lib/css/style-property-map/StylePropertyMapReadOnly.js -var StylePropertyMapReadOnly; -var init_StylePropertyMapReadOnly = __esm({ - "node_modules/happy-dom/lib/css/style-property-map/StylePropertyMapReadOnly.js"() { - init_CSSKeywordValue(); - init_CSSStyleValue(); - init_PropertySymbol(); - StylePropertyMapReadOnly = class { - [style]; - /** - * Constructor. - * - * @param illegalConstructorSymbol Illegal constructor symbol. - * @param style Style. - */ - constructor(illegalConstructorSymbol, style2) { - if (illegalConstructorSymbol !== illegalConstructor) { - throw new TypeError("Illegal constructor"); - } - this[style] = style2; - } - /** - * Returns size. - * - * @returns Size. - */ - get size() { - return this[style].length; - } - /** - * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. - * - * @returns Iterator. - */ - [Symbol.iterator]() { - return this.entries(); - } - /** - * Returns an iterator, allowing you to go through all key/value pairs contained in this object. - * - * @returns Entries. - */ - entries() { - const length2 = this[style].length; - const array = new Array(length2); - for (let i = 0; i < length2; i++) { - const property = this[style][i]; - array[i] = [ - property, - [new CSSKeywordValue(this[style].getPropertyValue(property))] - ]; - } - return array.values(); - } - /** - * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. - * - * @returns Values. - */ - values() { - const length2 = this[style].length; - const array = new Array(length2); - for (let i = 0; i < length2; i++) { - const property = this[style][i]; - array[i] = [new CSSKeywordValue(this[style].getPropertyValue(property))]; - } - return array.values(); - } - /** - * Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object. - * - * @returns Keys. - */ - keys() { - const length2 = this[style].length; - const array = new Array(length2); - for (let i = 0; i < length2; i++) { - array[i] = this[style][i]; - } - return array.values(); - } - /** - * Returns a property value. - * - * @param property Property. - * @returns Value. - */ - get(property) { - return new CSSStyleValue(illegalConstructor, this[style], property); - } - /** - * Returns array of property values. - * - * @param property Property. - * @returns Values. - */ - getAll(property) { - return [ - new CSSStyleValue(illegalConstructor, this[style], property) - ]; - } - /** - * Checks if a property is present. - * - * @param property Property. - * @returns True if the property is present. - */ - has(property) { - return !!this[style].getPropertyValue(property); - } - }; - } -}); - -// node_modules/happy-dom/lib/css/style-property-map/StylePropertyMap.js -var StylePropertyMap; -var init_StylePropertyMap = __esm({ - "node_modules/happy-dom/lib/css/style-property-map/StylePropertyMap.js"() { - init_StylePropertyMapReadOnly(); - init_PropertySymbol(); - StylePropertyMap = class extends StylePropertyMapReadOnly { - /** - * Appends a property. - * - * @param property Property. - * @param value Value. - */ - append(property, value2) { - this[style].setProperty(property, value2); - } - /** - * Clears all properties. - */ - clear() { - this[style].cssText = ""; - } - /** - * Deletes a property. - * - * @param property Property. - */ - delete(property) { - this[style].removeProperty(property); - } - /** - * Sets a property. - * - * @param property Property. - * @param value Value. - */ - set(property, value2) { - this[style].setProperty(property, value2); - } - }; - } -}); - -// node_modules/happy-dom/lib/css/rules/CSSStyleRule.js -var CSSStyleRule; -var init_CSSStyleRule = __esm({ - "node_modules/happy-dom/lib/css/rules/CSSStyleRule.js"() { - init_PropertySymbol(); - init_CSSStyleDeclaration(); - init_CSSRuleTypeEnum(); - init_CSSGroupingRule(); - init_StylePropertyMap(); - CSSStyleRule = class extends CSSGroupingRule { - [styleMap] = null; - [selectorText] = ""; - [cssText] = ""; - #style = null; - /** - * @override - */ - get type() { - return CSSRuleTypeEnum_default.styleRule; - } - /** - * @override - */ - get cssText() { - return `${this[selectorText]} { ${this.style.cssText} }`; - } - /** - * Returns style map. - * - * @returns Style map. - */ - get styleMap() { - if (!this[styleMap]) { - this[styleMap] = new StylePropertyMap(illegalConstructor, this.style); - } - return this[styleMap]; - } - /** - * Returns selector text. - * - * @returns Selector text. - */ - get selectorText() { - return this[selectorText]; - } - /** - * Returns style. - * - * @returns Style. - */ - get style() { - if (!this.#style) { - this.#style = new CSSStyleDeclaration(illegalConstructor, this[window]); - this.#style.parentRule = this; - this.#style.cssText = this[cssText]; - } - return this.#style; - } - }; - } -}); - -// node_modules/happy-dom/lib/css/rules/CSSSupportsRule.js -var CSSSupportsRule; -var init_CSSSupportsRule = __esm({ - "node_modules/happy-dom/lib/css/rules/CSSSupportsRule.js"() { - init_CSSRuleTypeEnum(); - init_CSSConditionRule(); - init_PropertySymbol(); - CSSSupportsRule = class extends CSSConditionRule { - [type] = CSSRuleTypeEnum_default.supportsRule; - [rulePrefix] = ""; - /** - * @override - */ - get type() { - return CSSRuleTypeEnum_default.supportsRule; - } - /** - * @override - */ - get cssText() { - let cssText2 = ""; - for (const cssRule2 of this[cssRules]) { - cssText2 += "\n " + cssRule2.cssText; - } - cssText2 += "\n"; - return `@${this[rulePrefix]}supports ${this.conditionText} {${cssText2}}`; - } - }; - } -}); - -// node_modules/happy-dom/lib/config/NamespaceURI.js -var NamespaceURI_default; -var init_NamespaceURI = __esm({ - "node_modules/happy-dom/lib/config/NamespaceURI.js"() { - NamespaceURI_default = { - html: "http://www.w3.org/1999/xhtml", - svg: "http://www.w3.org/2000/svg", - mathML: "http://www.w3.org/1998/Math/MathML", - xml: "http://www.w3.org/XML/1998/namespace", - xlink: "http://www.w3.org/1999/xlink", - xmlns: "http://www.w3.org/2000/xmlns/" - }; - } -}); - -// node_modules/happy-dom/lib/utilities/StringUtility.js -var ASCII_LOWER_CASE_CACHE, ASCII_UPPER_CASE_CACHE, ASCII_UPPER_CASE_REGEXP, ASCII_LOWER_CASE_REGEXP, StringUtility; -var init_StringUtility = __esm({ - "node_modules/happy-dom/lib/utilities/StringUtility.js"() { - ASCII_LOWER_CASE_CACHE = /* @__PURE__ */ new Map(); - ASCII_UPPER_CASE_CACHE = /* @__PURE__ */ new Map(); - ASCII_UPPER_CASE_REGEXP = /[A-Z]/g; - ASCII_LOWER_CASE_REGEXP = /[a-z]/g; - StringUtility = class { - /** - * ASCII lowercase. - * - * @see https://infra.spec.whatwg.org/#ascii-lowercase - * @param text Text. - * @returns Lowercase text. - */ - static asciiLowerCase(text) { - const cached = ASCII_LOWER_CASE_CACHE.get(text); - if (cached) { - return cached; - } - const newText = text.replace(ASCII_UPPER_CASE_REGEXP, (char) => String.fromCharCode(char.charCodeAt(0) + 32)); - ASCII_LOWER_CASE_CACHE.set(text, newText); - return newText; - } - /** - * ASCII uppercase. - * - * @see https://infra.spec.whatwg.org/#ascii-uppercase - * @param text Text. - * @returns Uppercase text. - */ - static asciiUpperCase(text) { - const cached = ASCII_UPPER_CASE_CACHE.get(text); - if (cached) { - return cached; - } - const newText = text.replace(ASCII_LOWER_CASE_REGEXP, (char) => String.fromCharCode(char.charCodeAt(0) - 32)); - ASCII_UPPER_CASE_CACHE.set(text, newText); - return newText; - } - }; - } -}); - -// node_modules/happy-dom/lib/custom-element/CustomElementUtility.js -var PCEN_CHAR, PCEN_REGEXP, RESERVED_NAMES, CustomElementUtility; -var init_CustomElementUtility = __esm({ - "node_modules/happy-dom/lib/custom-element/CustomElementUtility.js"() { - PCEN_CHAR = "[-_.]|[0-9]|[a-z]|\xB7|[\xC0-\xD6]|[\xD8-\xF6]|[\xF8-\u037D]|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u203F-\u2040]|[\u2070-\u218F]|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]|[\uFDF0-\uFFFD]|[\u{10000}-\u{EFFFF}]"; - PCEN_REGEXP = new RegExp(`^[a-z](${PCEN_CHAR})*-(${PCEN_CHAR})*$`, "u"); - RESERVED_NAMES = [ - "annotation-xml", - "color-profile", - "font-face", - "font-face-src", - "font-face-uri", - "font-face-format", - "font-face-name", - "missing-glyph" - ]; - CustomElementUtility = class { - /** - * Returns true if the tag name is a valid custom element name. - * - * @see https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name - * @param name Tag name. - * @returns True if valid. - */ - static isValidCustomElementName(name2) { - return PCEN_REGEXP.test(name2) && !RESERVED_NAMES.includes(name2); - } - }; - } -}); - -// node_modules/happy-dom/lib/custom-element/CustomElementRegistry.js -var CustomElementRegistry; -var init_CustomElementRegistry = __esm({ - "node_modules/happy-dom/lib/custom-element/CustomElementRegistry.js"() { - init_PropertySymbol(); - init_NamespaceURI(); - init_StringUtility(); - init_CustomElementUtility(); - CustomElementRegistry = class { - [registry] = /* @__PURE__ */ new Map(); - [classRegistry] = /* @__PURE__ */ new Map(); - [callbacks] = /* @__PURE__ */ new Map(); - [destroyed] = false; - #window; - /** - * Constructor. - * - * @param window Window. - */ - constructor(window2) { - if (!window2) { - throw new TypeError("Illegal constructor"); - } - this.#window = window2; - } - /** - * Defines a custom element class. - * - * @param name Tag name of element. - * @param elementClass Element class. - * @param [options] Options. - * @param [options.extends] Extends tag name. - */ - define(name2, elementClass, options2) { - if (this[destroyed]) { - return; - } - if (!CustomElementUtility.isValidCustomElementName(name2)) { - throw new this.#window.DOMException(`Failed to execute 'define' on 'CustomElementRegistry': "${name2}" is not a valid custom element name`); - } - if (this[registry].has(name2)) { - throw new this.#window.DOMException(`Failed to execute 'define' on 'CustomElementRegistry': the name "${name2}" has already been used with this registry`); - } - if (this[classRegistry].has(elementClass)) { - throw new this.#window.DOMException("Failed to execute 'define' on 'CustomElementRegistry': this constructor has already been used with this registry"); - } - const tagName2 = StringUtility.asciiUpperCase(name2); - elementClass.prototype[window] = this.#window; - elementClass.prototype[ownerDocument] = this.#window.document; - elementClass.prototype[tagName] = tagName2; - elementClass.prototype[localName] = name2; - elementClass.prototype[namespaceURI] = NamespaceURI_default.html; - const observedAttributes = /* @__PURE__ */ new Set(); - const elementObservervedAttributes = elementClass.observedAttributes; - if (Array.isArray(elementObservervedAttributes)) { - for (const attribute of elementObservervedAttributes) { - observedAttributes.add(String(attribute).toLowerCase()); - } - } - this[registry].set(name2, { - elementClass, - extends: options2 && options2.extends ? options2.extends.toLowerCase() : null, - observedAttributes, - lifecycleCallbacks: { - connectedCallback: elementClass.prototype.connectedCallback, - disconnectedCallback: elementClass.prototype.disconnectedCallback, - attributeChangedCallback: elementClass.prototype.attributeChangedCallback - } - }); - this[classRegistry].set(elementClass, name2); - const callbacks2 = this[callbacks].get(name2); - if (callbacks2) { - this[callbacks].delete(name2); - for (const callback of callbacks2) { - callback(); - } - } - } - /** - * Returns a defined element class. - * - * @param name Tag name of element. - * @returns HTMLElement Class defined or undefined. - */ - get(name2) { - return this[registry].get(name2)?.elementClass; - } - /** - * Upgrades a custom element directly, even before it is connected to its shadow root. - * - * Not implemented yet. - * - * @param _root Root node. - */ - upgrade(_root) { - } - /** - * When defined. - * - * @param name Tag name of element. - */ - whenDefined(name2) { - if (this[destroyed]) { - return Promise.reject(new this.#window.DOMException(`Failed to execute 'whenDefined' on 'CustomElementRegistry': The custom element registry has been destroyed.`)); - } - if (!CustomElementUtility.isValidCustomElementName(name2)) { - return Promise.reject(new this.#window.DOMException(`Failed to execute 'whenDefined' on 'CustomElementRegistry': Invalid custom element name: "${name2}"`)); - } - if (this.get(name2)) { - return Promise.resolve(); - } - return new Promise((resolve) => { - const callbacks2 = this[callbacks].get(name2); - if (callbacks2) { - callbacks2.push(resolve); - } else { - this[callbacks].set(name2, [resolve]); - } - }); - } - /** - * Reverse lookup searching for name by given element class. - * - * @param elementClass Class constructor. - * @returns Found tag name or `null`. - */ - getName(elementClass) { - return this[classRegistry].get(elementClass) || null; - } - /** - * Destroys the registry. - */ - [destroy]() { - this[destroyed] = true; - for (const definition of this[registry].values()) { - definition.elementClass.prototype[window] = null; - definition.elementClass.prototype[ownerDocument] = null; - definition.elementClass.prototype[tagName] = null; - definition.elementClass.prototype[localName] = null; - definition.elementClass.prototype[namespaceURI] = null; - } - this[registry] = /* @__PURE__ */ new Map(); - this[classRegistry] = /* @__PURE__ */ new Map(); - this[callbacks] = /* @__PURE__ */ new Map(); - } - }; - } -}); - -// node_modules/happy-dom/lib/event/DataTransferItem.js -var DataTransferItem; -var init_DataTransferItem = __esm({ - "node_modules/happy-dom/lib/event/DataTransferItem.js"() { - DataTransferItem = class { - kind; - type; - #item = null; - /** - * Constructor. - * - * @param item Item. - * @param type Type. - */ - constructor(item, type2 = "") { - this.kind = typeof item === "string" ? "string" : "file"; - this.type = this.kind === "string" ? type2 : item.type; - this.#item = item; - } - /** - * Returns file. - */ - getAsFile() { - if (this.kind === "string") { - return null; - } - return this.#item; - } - /** - * Returns string. - * - * @param callback Callback. - */ - getAsString(callback) { - if (this.kind === "file") { - callback(""); - } - callback(this.#item); - } - }; - } -}); - -// node_modules/happy-dom/lib/file/File.js -var File2; -var init_File = __esm({ - "node_modules/happy-dom/lib/file/File.js"() { - init_Blob(); - File2 = class extends Blob2 { - lastModified; - name; - /** - * Constructor. - * - * @param bits File bits. - * @param name File name. - * @param [options] Options. - * @param [options.type] MIME type. - * @param [options.lastModifier] Last modified. Defaults to Date.now(). - * @param options.lastModified - */ - constructor(bits, name2, options2) { - if (arguments.length < 2) { - throw new TypeError("Failed to construct 'File': 2 arguments required, but only " + arguments.length + " present."); - } - super(bits, options2); - this.name = name2; - this.lastModified = options2 && options2.lastModified ? options2.lastModified : Date.now(); - } - }; - } -}); - -// node_modules/happy-dom/lib/event/DataTransferItemList.js -var DataTransferItemList; -var init_DataTransferItemList = __esm({ - "node_modules/happy-dom/lib/event/DataTransferItemList.js"() { - init_File(); - init_DataTransferItem(); - DataTransferItemList = class extends Array { - /** - * Adds an item. - * - * @param item Item. - * @param type Type. - */ - add(item, type2) { - if (item instanceof File2) { - this.push(new DataTransferItem(item)); - return; - } - if (!type2) { - throw new TypeError(`Failed to execute 'add' on 'DataTransferItemList': parameter 1 is not of type 'File'.`); - } - this.push(new DataTransferItem(item, type2)); - } - /** - * Removes an item. - * - * @param index Index. - */ - remove(index) { - this.splice(index, 1); - } - /** - * Clears list. - */ - clear() { - while (this.length) { - this.pop(); - } - } - }; - } -}); - -// node_modules/happy-dom/lib/event/DataTransfer.js -var DataTransfer; -var init_DataTransfer = __esm({ - "node_modules/happy-dom/lib/event/DataTransfer.js"() { - init_DataTransferItem(); - init_DataTransferItemList(); - DataTransfer = class { - dropEffect = "none"; - effectAllowed = "none"; - items = new DataTransferItemList(); - /** - * Returns files. - * - * @returns Files. - */ - get files() { - const files2 = []; - for (const item of this.items) { - if (item.kind === "file") { - const file = item.getAsFile(); - if (file) { - files2.push(file); - } - } - } - return files2; - } - /** - * Returns types. - * - * @returns Types. - */ - get types() { - return this.items.map((item) => item.type); - } - /** - * Clears the data. - */ - clearData() { - this.items.clear(); - } - /** - * Sets the data. - * - * @param format Format. - * @param data Data. - */ - setData(format, data2) { - for (let i = 0, max = this.items.length; i < max; i++) { - if (this.items[i].type === format) { - this.items[i] = new DataTransferItem(data2, format); - return; - } - } - this.items.add(data2, format); - } - /** - * Gets the data. - * - * @param format Format. - * @returns Data. - */ - getData(format) { - const normalizedFormat = this.#normalizeFormat(format); - for (let i = 0, max = this.items.length; i < max; i++) { - const itemFormat = this.#normalizeFormat(this.items[i].type); - if (itemFormat === normalizedFormat) { - let data2 = ""; - this.items[i].getAsString((s) => data2 = s); - return data2; - } - } - return ""; - } - /** - * Normalizes the format according to the HTML spec. - * - * @param format Format to normalize. - * @returns Normalized format. - */ - #normalizeFormat(format) { - const lowercaseFormat = format.toLowerCase(); - if (lowercaseFormat === "text") { - return "text/plain"; - } - if (lowercaseFormat === "url") { - return "text/uri-list"; - } - return lowercaseFormat; - } - /** - * Sets drag image. - * - * TODO: Implement. - */ - setDragImage() { - throw new Error("Not implemented."); - } - }; - } -}); - -// node_modules/happy-dom/lib/event/Touch.js -var Touch; -var init_Touch = __esm({ - "node_modules/happy-dom/lib/event/Touch.js"() { - Touch = class { - identifier; - target; - clientX; - clientY; - screenX; - screenY; - pageX; - pageY; - radiusX; - radiusY; - rotationAngle; - force; - /** - * Constructor. - * - * @param [touchInit] Touch init. - */ - constructor(touchInit) { - this.identifier = touchInit.identifier; - this.target = touchInit.target; - this.clientX = touchInit.clientX ?? 0; - this.clientY = touchInit.clientY ?? 0; - this.screenX = touchInit.screenX ?? 0; - this.screenY = touchInit.screenY ?? 0; - this.pageX = touchInit.pageX ?? 0; - this.pageY = touchInit.pageY ?? 0; - this.radiusX = touchInit.radiusX ?? 0; - this.radiusY = touchInit.radiusY ?? 0; - this.rotationAngle = touchInit.rotationAngle ?? 0; - this.force = touchInit.force ?? 0; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/UIEvent.js -var UIEvent; -var init_UIEvent = __esm({ - "node_modules/happy-dom/lib/event/UIEvent.js"() { - init_Event(); - UIEvent = class extends Event2 { - static NONE = 0; - static CAPTURING_PHASE = 1; - static AT_TARGET = 2; - static BUBBLING_PHASE = 3; - detail; - layerX = 0; - layerY = 0; - pageX = 0; - pageY = 0; - view; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.detail = eventInit?.detail ?? 0; - this.view = eventInit?.view ?? null; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/AnimationEvent.js -var AnimationEvent; -var init_AnimationEvent = __esm({ - "node_modules/happy-dom/lib/event/events/AnimationEvent.js"() { - init_Event(); - AnimationEvent = class extends Event2 { - animationName; - elapsedTime; - pseudoElement; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.animationName = eventInit?.animationName ?? ""; - this.elapsedTime = eventInit?.elapsedTime ?? 0; - this.pseudoElement = eventInit?.pseudoElement ?? ""; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/ClipboardEvent.js -var ClipboardEvent; -var init_ClipboardEvent = __esm({ - "node_modules/happy-dom/lib/event/events/ClipboardEvent.js"() { - init_Event(); - ClipboardEvent = class extends Event2 { - clipboardData; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.clipboardData = eventInit?.clipboardData ?? null; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/CustomEvent.js -var CustomEvent; -var init_CustomEvent = __esm({ - "node_modules/happy-dom/lib/event/events/CustomEvent.js"() { - init_Event(); - init_PropertySymbol(); - CustomEvent = class extends Event2 { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [detail]; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this[detail] = eventInit?.detail ?? null; - } - /** - * Returns detail. - * - * @returns Detail. - */ - get detail() { - return this[detail]; - } - /** - * Init event. - * - * @deprecated - * @param type Type. - * @param [bubbles=false] "true" if it bubbles. - * @param [cancelable=false] "true" if it cancelable. - * @param [detail=null] Custom event detail. - */ - initCustomEvent(type2, bubbles2 = false, cancelable2 = false, detail2 = null) { - this[type] = type2; - this[bubbles] = bubbles2; - this[cancelable] = cancelable2; - this[detail] = detail2; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/ErrorEvent.js -var ErrorEvent; -var init_ErrorEvent = __esm({ - "node_modules/happy-dom/lib/event/events/ErrorEvent.js"() { - init_UIEvent(); - ErrorEvent = class extends UIEvent { - message; - filename; - lineno; - colno; - error; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.message = eventInit?.message ?? ""; - this.filename = eventInit?.filename ?? ""; - this.lineno = eventInit?.lineno ?? 0; - this.colno = eventInit?.colno ?? 0; - this.error = eventInit?.error ?? null; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/FocusEvent.js -var FocusEvent; -var init_FocusEvent = __esm({ - "node_modules/happy-dom/lib/event/events/FocusEvent.js"() { - init_UIEvent(); - FocusEvent = class extends UIEvent { - relatedTarget; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.relatedTarget = eventInit?.relatedTarget ?? null; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/HashChangeEvent.js -var HashChangeEvent; -var init_HashChangeEvent = __esm({ - "node_modules/happy-dom/lib/event/events/HashChangeEvent.js"() { - init_Event(); - HashChangeEvent = class extends Event2 { - newURL; - oldURL; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.newURL = eventInit?.newURL ?? ""; - this.oldURL = eventInit?.oldURL ?? ""; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/InputEvent.js -var InputEvent; -var init_InputEvent = __esm({ - "node_modules/happy-dom/lib/event/events/InputEvent.js"() { - init_UIEvent(); - InputEvent = class extends UIEvent { - data; - dataTransfer; - inputType; - isComposing; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.data = eventInit?.data ?? ""; - this.dataTransfer = eventInit?.dataTransfer ?? null; - this.inputType = eventInit?.inputType ?? ""; - this.isComposing = eventInit?.isComposing ?? false; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/KeyboardEvent.js -var KeyboardEvent; -var init_KeyboardEvent = __esm({ - "node_modules/happy-dom/lib/event/events/KeyboardEvent.js"() { - init_UIEvent(); - KeyboardEvent = class extends UIEvent { - static DOM_KEY_LOCATION_STANDARD = 0; - static DOM_KEY_LOCATION_LEFT = 1; - static DOM_KEY_LOCATION_RIGHT = 2; - static DOM_KEY_LOCATION_NUMPAD = 3; - altKey; - code; - ctrlKey; - isComposing; - key; - location; - metaKey; - repeat; - shiftKey; - /** - * @deprecated - */ - keyCode; - /** - * @deprecated - */ - which; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.altKey = eventInit?.altKey ?? false; - this.code = eventInit?.code ?? ""; - this.ctrlKey = eventInit?.ctrlKey ?? false; - this.isComposing = eventInit?.isComposing ?? false; - this.key = eventInit?.key ?? ""; - this.location = eventInit?.location ?? 0; - this.metaKey = eventInit?.metaKey ?? false; - this.repeat = eventInit?.repeat ?? false; - this.shiftKey = eventInit?.shiftKey ?? false; - this.keyCode = eventInit?.keyCode ?? 0; - this.which = eventInit?.which ?? eventInit?.keyCode ?? 0; - } - /** - * Returns the state of a modifier key. - * - * @param key A modifier key value. - * @returns True if it's pressed, false otherwise. - */ - getModifierState(key) { - if (arguments.length < 1) { - throw new TypeError("Failed to execute 'getModifierState' on 'KeyboardEvent': 1 argument required, but only 0 present."); - } - switch (String(key).toLowerCase()) { - case "alt": - case "altgraph": - return this.altKey; - case "control": - return this.ctrlKey; - case "meta": - return this.metaKey; - case "shift": - return this.shiftKey; - default: - return false; - } - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/MessageEvent.js -var MessageEvent; -var init_MessageEvent = __esm({ - "node_modules/happy-dom/lib/event/events/MessageEvent.js"() { - init_Event(); - MessageEvent = class extends Event2 { - data; - origin; - lastEventId; - source; - ports; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.data = eventInit?.data ?? null; - this.origin = eventInit?.origin ?? ""; - this.lastEventId = eventInit?.lastEventId ?? ""; - this.source = eventInit?.source ?? null; - this.ports = eventInit?.ports ?? []; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/MouseEvent.js -var MouseEvent; -var init_MouseEvent = __esm({ - "node_modules/happy-dom/lib/event/events/MouseEvent.js"() { - init_UIEvent(); - MouseEvent = class extends UIEvent { - altKey; - button; - buttons; - clientX; - clientY; - ctrlKey; - metaKey; - movementX; - movementY; - offsetX; - offsetY; - region; - relatedTarget; - screenX; - screenY; - shiftKey; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.altKey = eventInit?.altKey ?? false; - this.button = eventInit?.button ?? 0; - this.buttons = eventInit?.buttons ?? 0; - this.clientX = eventInit?.clientX ?? 0; - this.clientY = eventInit?.clientY ?? 0; - this.ctrlKey = eventInit?.ctrlKey ?? false; - this.metaKey = eventInit?.metaKey ?? false; - this.movementX = eventInit?.movementX ?? 0; - this.movementY = eventInit?.movementY ?? 0; - this.offsetX = eventInit?.offsetX ?? 0; - this.offsetY = eventInit?.offsetY ?? 0; - this.region = eventInit?.region ?? ""; - this.relatedTarget = eventInit?.relatedTarget ?? null; - this.screenX = eventInit?.screenX ?? 0; - this.screenY = eventInit?.screenY ?? 0; - this.shiftKey = eventInit?.shiftKey ?? false; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/PointerEvent.js -var PointerEvent; -var init_PointerEvent = __esm({ - "node_modules/happy-dom/lib/event/events/PointerEvent.js"() { - init_MouseEvent(); - PointerEvent = class extends MouseEvent { - pointerId; - width; - height; - pressure; - tangentialPressure; - tiltX; - tiltY; - twist; - altitudeAngle; - azimuthAngle; - pointerType; - isPrimary; - coalescedEvents; - predictedEvents; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.pointerId = eventInit?.pointerId ?? 0; - this.width = eventInit?.width ?? 1; - this.height = eventInit?.height ?? 1; - this.pressure = eventInit?.pressure ?? 0; - this.tangentialPressure = eventInit?.tangentialPressure ?? 0; - this.tiltX = eventInit?.tiltX ?? 0; - this.tiltY = eventInit?.tiltY ?? 0; - this.twist = eventInit?.twist ?? 0; - this.altitudeAngle = eventInit?.altitudeAngle ?? 0; - this.azimuthAngle = eventInit?.azimuthAngle ?? 0; - this.pointerType = eventInit?.pointerType ?? ""; - this.isPrimary = eventInit?.isPrimary ?? false; - this.coalescedEvents = eventInit?.coalescedEvents ?? []; - this.predictedEvents = eventInit?.predictedEvents ?? []; - } - getCoalescedEvents = () => this.coalescedEvents; - getPredictedEvents = () => this.predictedEvents; - }; - } -}); - -// node_modules/happy-dom/lib/event/events/ProgressEvent.js -var ProgressEvent; -var init_ProgressEvent = __esm({ - "node_modules/happy-dom/lib/event/events/ProgressEvent.js"() { - init_Event(); - ProgressEvent = class extends Event2 { - lengthComputable; - loaded; - total; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2); - this.lengthComputable = eventInit?.lengthComputable ?? false; - this.loaded = eventInit?.loaded ?? 0; - this.total = eventInit?.total ?? 0; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/StorageEvent.js -var StorageEvent; -var init_StorageEvent = __esm({ - "node_modules/happy-dom/lib/event/events/StorageEvent.js"() { - init_Event(); - StorageEvent = class extends Event2 { - key; - oldValue; - newValue; - url; - storageArea; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2); - this.key = eventInit?.key ?? null; - this.oldValue = eventInit?.oldValue ?? null; - this.newValue = eventInit?.newValue ?? null; - this.url = eventInit?.url ?? ""; - this.storageArea = eventInit?.storageArea ?? null; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/SubmitEvent.js -var SubmitEvent; -var init_SubmitEvent = __esm({ - "node_modules/happy-dom/lib/event/events/SubmitEvent.js"() { - init_Event(); - SubmitEvent = class extends Event2 { - submitter; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.submitter = eventInit?.submitter ?? null; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/TouchEvent.js -var TouchEvent; -var init_TouchEvent = __esm({ - "node_modules/happy-dom/lib/event/events/TouchEvent.js"() { - init_UIEvent(); - TouchEvent = class extends UIEvent { - altKey; - changedTouches; - ctrlKey; - metaKey; - shiftKey; - targetTouches; - touches; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.altKey = eventInit?.altKey ?? false; - this.changedTouches = eventInit?.changedTouches ?? []; - this.ctrlKey = eventInit?.ctrlKey ?? false; - this.metaKey = eventInit?.metaKey ?? false; - this.shiftKey = eventInit?.shiftKey ?? false; - this.targetTouches = eventInit?.targetTouches ?? []; - this.touches = eventInit?.touches ?? []; - } - }; - } -}); - -// node_modules/happy-dom/lib/event/events/WheelEvent.js -var WheelEvent; -var init_WheelEvent = __esm({ - "node_modules/happy-dom/lib/event/events/WheelEvent.js"() { - init_UIEvent(); - WheelEvent = class extends UIEvent { - static DOM_DELTA_PIXEL = 0; - static DOM_DELTA_LINE = 1; - static DOM_DELTA_PAGE = 2; - deltaX; - deltaY; - deltaZ; - deltaMode; - /** - * Constructor. - * - * @param type Event type. - * @param [eventInit] Event init. - */ - constructor(type2, eventInit = null) { - super(type2, eventInit); - this.deltaX = eventInit?.deltaX ?? 0; - this.deltaY = eventInit?.deltaY ?? 0; - this.deltaZ = eventInit?.deltaZ ?? 0; - this.deltaMode = eventInit?.deltaMode ?? 0; - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/utilities/FetchRequestReferrerUtility.js -var import_net, REQUEST_REFERRER_UNSUPPORTED_PROTOCOL_REGEXP, REFERRER_POLICIES, FetchRequestReferrerUtility; -var init_FetchRequestReferrerUtility = __esm({ - "node_modules/happy-dom/lib/fetch/utilities/FetchRequestReferrerUtility.js"() { - init_URL(); - init_PropertySymbol(); - import_net = require("net"); - REQUEST_REFERRER_UNSUPPORTED_PROTOCOL_REGEXP = /^(about|blob|data):$/; - REFERRER_POLICIES = [ - "", - "no-referrer", - "no-referrer-when-downgrade", - "same-origin", - "origin", - "strict-origin", - "origin-when-cross-origin", - "strict-origin-when-cross-origin", - "unsafe-url" - ]; - FetchRequestReferrerUtility = class { - /** - * Prepares the request before being sent. - * - * @param originURL Origin URL. - * @param request Request. - */ - static prepareRequest(originURL, request) { - if (!request.referrerPolicy) { - request[referrerPolicy] = "strict-origin-when-cross-origin"; - } - if (request.referrer && request.referrer !== "no-referrer") { - request[referrer] = this.getSentReferrer(originURL, request); - } else { - request[referrer] = "no-referrer"; - } - } - /** - * Returns initial referrer. - * - * @param window Window. - * @param referrer Referrer. - * @returns Initial referrer. - */ - static getInitialReferrer(window2, referrer2) { - if (referrer2 === "" || referrer2 === "no-referrer" || referrer2 === "client") { - return referrer2; - } else if (referrer2) { - const referrerURL = referrer2 instanceof URL2 ? referrer2 : new URL2(referrer2, window2.location.href); - return referrerURL.origin === window2.location.origin ? referrerURL : "client"; - } - return "client"; - } - /** - * Returns referrer policy from header. - * - * @see https://w3c.github.io/webappsec-referrer-policy/#parse-referrer-policy-from-header - * @param headers Response headers - * @returns Policy. - */ - static getReferrerPolicyFromHeader(headers2) { - const referrerPolicyHeader = headers2.get("Referrer-Policy"); - if (!referrerPolicyHeader) { - return ""; - } - const policyTokens = referrerPolicyHeader.split(/[,\s]+/); - let policy = ""; - for (const token of policyTokens) { - if (token && REFERRER_POLICIES.includes(token)) { - policy = token; - } - } - return policy; - } - /** - * Returns the request referrer to be used as the value for the "Referer" header. - * - * Based on: - * https://github.com/node-fetch/node-fetch/blob/main/src/utils/referrer.js (MIT) - * - * @see https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer - * @param originURL Origin URL. - * @param request Request. - * @returns Request referrer. - */ - static getSentReferrer(originURL, request) { - if (request.referrer === "about:client" && originURL.origin === "null") { - return "no-referrer"; - } - const requestURL = new URL2(request.url); - const referrerURL = request.referrer === "about:client" ? new URL2(originURL.href) : new URL2(request.referrer); - if (REQUEST_REFERRER_UNSUPPORTED_PROTOCOL_REGEXP.test(referrerURL.protocol)) { - return "no-referrer"; - } - referrerURL.username = ""; - referrerURL.password = ""; - referrerURL.hash = ""; - switch (request.referrerPolicy) { - case "no-referrer": - return "no-referrer"; - case "origin": - return new URL2(referrerURL.origin); - case "unsafe-url": - return referrerURL; - case "strict-origin": - if (this.isURLPotentiallyTrustWorthy(referrerURL) && !this.isURLPotentiallyTrustWorthy(requestURL)) { - return "no-referrer"; - } - return new URL2(referrerURL.origin); - case "strict-origin-when-cross-origin": - if (referrerURL.origin === requestURL.origin) { - return referrerURL; - } - if (this.isURLPotentiallyTrustWorthy(referrerURL) && !this.isURLPotentiallyTrustWorthy(requestURL)) { - return "no-referrer"; - } - return new URL2(referrerURL.origin); - case "same-origin": - if (referrerURL.origin === requestURL.origin) { - return referrerURL; - } - return "no-referrer"; - case "origin-when-cross-origin": - if (referrerURL.origin === requestURL.origin) { - return referrerURL; - } - return new URL2(referrerURL.origin); - case "no-referrer-when-downgrade": - if (this.isURLPotentiallyTrustWorthy(referrerURL) && !this.isURLPotentiallyTrustWorthy(requestURL)) { - return "no-referrer"; - } - return referrerURL; - } - return "no-referrer"; - } - /** - * Returns "true" if the request's referrer is potentially trustworthy. - * - * @see https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy - * @param url URL. - * @returns "true" if the request's referrer is potentially trustworthy. - */ - static isURLPotentiallyTrustWorthy(url2) { - if (/^about:(blank|srcdoc)$/.test(url2.href)) { - return true; - } - if (url2.protocol === "data:") { - return true; - } - if (/^(blob|filesystem):$/.test(url2.protocol)) { - return true; - } - return this.isOriginPotentiallyTrustWorthy(url2); - } - /** - * Returns "true" if the request's referrer origin is potentially trustworthy. - * - * @see https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy - * @param url URL. - * @returns "true" if the request's referrer origin is potentially trustworthy. - */ - static isOriginPotentiallyTrustWorthy(url2) { - if (/^(http|ws)s:$/.test(url2.protocol)) { - return true; - } - const hostIp = url2.host.replace(/(^\[)|(]$)/g, ""); - const hostIPVersion = (0, import_net.isIP)(hostIp); - if (hostIPVersion === 4 && /^127\./.test(hostIp)) { - return true; - } - if (hostIPVersion === 6 && /^(((0+:){7})|(::(0+:){0,6}))0*1$/.test(hostIp)) { - return true; - } - if (url2.host === "localhost" || url2.host.endsWith(".localhost")) { - return false; - } - if (url2.protocol === "file:") { - return true; - } - return false; - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/data-uri/DataURIParser.js -var DataURIParser; -var init_DataURIParser = __esm({ - "node_modules/happy-dom/lib/fetch/data-uri/DataURIParser.js"() { - DataURIParser = class { - /** - * Returns a Buffer instance from the given data URI `uri`. - * - * @param uri Data URI. - * @returns Buffer. - */ - static parse(uri) { - if (!/^data:/i.test(uri)) { - throw new TypeError('`uri` does not appear to be a Data URI (must begin with "data:")'); - } - uri = uri.replace(/\r?\n/g, ""); - const firstComma = uri.indexOf(","); - if (firstComma === -1 || firstComma <= 4) { - throw new TypeError("malformed data: URI"); - } - const meta = uri.substring(5, firstComma).split(";"); - let charset = ""; - let base64 = false; - let type2 = meta[0] || "text/plain"; - for (let i = 1; i < meta.length; i++) { - if (meta[i] === "base64") { - base64 = true; - } else if (meta[i]) { - type2 += `;${meta[i]}`; - if (meta[i].indexOf("charset=") === 0) { - charset = meta[i].substring(8); - } - } - } - if (!meta[0] && !charset.length) { - type2 += ";charset=US-ASCII"; - charset = "US-ASCII"; - } - const encoding = base64 ? "base64" : "ascii"; - const data2 = unescape(uri.substring(firstComma + 1)); - const buffer2 = Buffer.from(data2, encoding); - return { - type: type2, - charset, - buffer: buffer2 - }; - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/utilities/FetchCORSUtility.js -var import_url2, FetchCORSUtility; -var init_FetchCORSUtility = __esm({ - "node_modules/happy-dom/lib/fetch/utilities/FetchCORSUtility.js"() { - import_url2 = require("url"); - FetchCORSUtility = class { - /** - * Validates request headers. - * - * @param originURL Origin URL. - * @param targetURL Target URL. - */ - static isCORS(originURL, targetURL) { - originURL = typeof originURL === "string" ? new import_url2.URL(originURL) : originURL; - targetURL = typeof targetURL === "string" ? new import_url2.URL(targetURL) : targetURL; - if (targetURL.protocol === "about:" || targetURL.protocol === "javascript:") { - return false; - } - return originURL.origin !== targetURL.origin; - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/multipart/MultipartReader.js -var MultipartParserStateEnum, CHARACTER_CODE, MultipartReader; -var init_MultipartReader = __esm({ - "node_modules/happy-dom/lib/fetch/multipart/MultipartReader.js"() { - init_File(); - (function(MultipartParserStateEnum2) { - MultipartParserStateEnum2[MultipartParserStateEnum2["boundary"] = 0] = "boundary"; - MultipartParserStateEnum2[MultipartParserStateEnum2["headerStart"] = 2] = "headerStart"; - MultipartParserStateEnum2[MultipartParserStateEnum2["header"] = 3] = "header"; - MultipartParserStateEnum2[MultipartParserStateEnum2["data"] = 5] = "data"; - })(MultipartParserStateEnum || (MultipartParserStateEnum = {})); - CHARACTER_CODE = { - lf: 10, - cr: 13 - }; - MultipartReader = class { - formData; - boundary; - boundaryIndex = 0; - state = MultipartParserStateEnum.boundary; - data = { - contentDisposition: null, - value: [], - contentType: null, - header: "" - }; - /** - * Constructor. - * - * @param window Window. - * @param formData Form data. - * @param boundary Boundary. - */ - constructor(window2, boundary) { - const boundaryHeader = `--${boundary}`; - this.boundary = new Uint8Array(boundaryHeader.length); - this.formData = new window2.FormData(); - for (let i = 0, max = boundaryHeader.length; i < max; i++) { - this.boundary[i] = boundaryHeader.charCodeAt(i); - } - } - /** - * Appends data. - * - * @param data Data. - */ - write(data2) { - let char; - let nextChar; - for (let i = 0, max = data2.length; i < max; i++) { - char = data2[i]; - nextChar = data2[i + 1]; - switch (this.state) { - case MultipartParserStateEnum.boundary: - if (char === this.boundary[this.boundaryIndex]) { - this.boundaryIndex++; - } else { - this.boundaryIndex = 0; - } - if (this.boundaryIndex === this.boundary.length) { - this.state = MultipartParserStateEnum.headerStart; - this.boundaryIndex = 0; - } - break; - case MultipartParserStateEnum.headerStart: - if (nextChar !== CHARACTER_CODE.cr && nextChar !== CHARACTER_CODE.lf) { - this.data.header = ""; - this.state = data2[i - 2] === CHARACTER_CODE.lf ? MultipartParserStateEnum.data : MultipartParserStateEnum.header; - } - break; - case MultipartParserStateEnum.header: - if (char === CHARACTER_CODE.cr) { - if (this.data.header) { - const headerParts = this.data.header.split(":"); - if (headerParts.length > 1) { - const headerName = headerParts[0].toLowerCase(); - const headerValue = headerParts[1].trim(); - switch (headerName) { - case "content-disposition": - this.data.contentDisposition = this.getContentDisposition(headerValue); - break; - case "content-type": - this.data.contentType = headerValue; - break; - } - } - } - this.state = MultipartParserStateEnum.headerStart; - } else { - this.data.header += String.fromCharCode(char); - } - break; - case MultipartParserStateEnum.data: - if (char === this.boundary[this.boundaryIndex]) { - this.boundaryIndex++; - } else { - this.boundaryIndex = 0; - } - if (this.boundaryIndex === this.boundary.length) { - this.state = MultipartParserStateEnum.headerStart; - if (this.data.value.length) { - this.appendFormData(this.data.contentDisposition.name, Buffer.from(this.data.value.slice(0, -(this.boundary.length + 1))), this.data.contentDisposition.filename, this.data.contentType); - this.data.value = []; - this.data.contentDisposition = null; - this.data.contentType = null; - } - this.boundaryIndex = 0; - } else { - this.data.value.push(char); - } - break; - } - } - } - /** - * Ends the stream. - * - * @returns Form data. - */ - end() { - if (this.data.contentDisposition && this.data.value.length) { - this.appendFormData(this.data.contentDisposition.name, Buffer.from(this.data.value.slice(0, -2)), this.data.contentDisposition.filename, this.data.contentType); - } - return this.formData; - } - /** - * Appends data. - * - * @param key Key. - * @param value value. - * @param filename Filename. - * @param type Type. - */ - appendFormData(key, value2, filename, type2) { - if (!value2.length) { - return; - } - if (filename) { - this.formData.append(key, new File2([value2], filename, { - type: type2 - })); - } else { - this.formData.append(key, value2.toString()); - } - } - /** - * Returns content disposition. - * - * @param headerValue Header value. - * @returns Content disposition. - */ - getContentDisposition(headerValue) { - const regex = /([a-z]+) *= *"([^"]+)"/g; - const contentDisposition = {}; - let match; - while (match = regex.exec(headerValue)) { - contentDisposition[match[1]] = match[2]; - } - return contentDisposition; - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/ReadableStreamWrapper.js -var ReadableStreamWrapper; -var init_ReadableStreamWrapper = __esm({ - "node_modules/happy-dom/lib/fetch/ReadableStreamWrapper.js"() { - ReadableStreamWrapper = class { - #read; - #readableStream = null; - /** - * Constructor. - * - * @param read Function that returns a ReadableStream when called. - */ - constructor(read) { - this.#read = read; - } - /** - * Returns the ReadableStream. If the stream has already been created, it returns the existing instance. - * - * @returns ReadableStream instance - */ - get readableStream() { - if (!this.#readableStream) { - this.#readableStream = this.#read(); - } - return this.#readableStream; - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/multipart/MultipartFormDataParser.js -var import_web2, import_buffer3, MultipartFormDataParser; -var init_MultipartFormDataParser = __esm({ - "node_modules/happy-dom/lib/fetch/multipart/MultipartFormDataParser.js"() { - import_web2 = require("stream/web"); - init_PropertySymbol(); - init_MultipartReader(); - init_DOMExceptionNameEnum(); - import_buffer3 = require("buffer"); - init_ReadableStreamWrapper(); - MultipartFormDataParser = class { - /** - * Returns form data. - * - * @param window Window. - * @param response Response object containing a body stream. - * @param response.body Body stream. - * @param requestOrResponse - * @param requestOrResponse.body - * @param contentType Content type header value. - * @returns Form data. - */ - static async streamToFormData(window2, requestOrResponse, contentType2) { - if (!/multipart/i.test(contentType2)) { - throw new window2.DOMException(`Failed to build FormData object: The "content-type" header isn't of type "multipart/form-data".`, DOMExceptionNameEnum_default.invalidStateError); - } - const body2 = requestOrResponse.body; - if (!body2) { - throw new window2.DOMException("Failed to build FormData object: The response body is null.", DOMExceptionNameEnum_default.invalidStateError); - } - const match = contentType2.match(/boundary=(?:"([^"]+)"|([^;]+))/i); - if (!match) { - throw new window2.DOMException(`Failed to build FormData object: The "content-type" header doesn't contain any multipart boundary.`, DOMExceptionNameEnum_default.invalidStateError); - } - const bodyReader = body2.getReader(); - const reader = new MultipartReader(window2, match[1] || match[2]); - const chunks = []; - let buffer2; - const bytes = 0; - let readResult = await bodyReader.read(); - while (!readResult.done) { - if (requestOrResponse[error]) { - throw requestOrResponse[error]; - } - if (requestOrResponse[aborted]) { - throw new window2.DOMException("Failed to read response body: The stream was aborted.", DOMExceptionNameEnum_default.abortError); - } - reader.write(readResult.value); - readResult = await bodyReader.read(); - } - try { - buffer2 = typeof chunks[0] === "string" ? import_buffer3.Buffer.from(chunks.join("")) : import_buffer3.Buffer.concat(chunks, bytes); - } catch (error2) { - throw new window2.DOMException(`Could not create Buffer from response body. Error: ${error2.message}.`, DOMExceptionNameEnum_default.invalidStateError); - } - return { - formData: reader.end(), - buffer: buffer2 - }; - } - /** - * Converts a FormData object to a ReadableStream. - * - * @param formData FormData. - * @returns Stream and type. - */ - static formDataToStream(formData) { - const boundary = "----HappyDOMFormDataBoundary" + Math.random().toString(36); - const chunks = []; - const prefix2 = `--${boundary}\r -Content-Disposition: form-data; name="`; - for (const [name2, value2] of formData) { - if (typeof value2 === "string") { - chunks.push(import_buffer3.Buffer.from(`${prefix2}${this.escapeName(name2)}"\r -\r -${value2.replace(/\r(?!\n)|(? new import_web2.ReadableStream({ - start(controller) { - controller.enqueue(buffer2); - controller.close(); - } - })) - }; - } - /** - * Escapes a form data entry name. - * - * @param name Name. - * @param filename Whether it is a filename. - * @returns Escaped name. - */ - static escapeName(name2, filename = false) { - return (filename ? name2 : name2.replace(/\r?\n|\r/g, "\r\n")).replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22"); - } - }; - } -}); - -// node_modules/happy-dom/lib/form-data/FormData.js -var FormData; -var init_FormData = __esm({ - "node_modules/happy-dom/lib/form-data/FormData.js"() { - init_Blob(); - init_PropertySymbol(); - init_File(); - init_DOMExceptionNameEnum(); - FormData = class { - #entries = []; - /** - * Constructor. - * - * @param [form] Form. - * @param [submitter] The element that triggered the submission if this came from a form submit. - */ - constructor(form, submitter) { - if (!form) { - return; - } - if (submitter) { - const formProxy = form[proxy] ? form[proxy] : form; - if (submitter.form !== formProxy) { - throw new this[window].DOMException("The specified element is not owned by this form element", DOMExceptionNameEnum_default.notFoundError); - } - const isSubmitButton = submitter[tagName] === "INPUT" && (submitter.type === "submit" || submitter.type === "image") || submitter[tagName] === "BUTTON" && submitter.type === "submit"; - if (!isSubmitButton) { - throw new this[window].TypeError("The specified element is not a submit button"); - } - } - const items2 = form[getFormControlItems](); - for (const item of items2) { - const name2 = item.name; - if (name2) { - switch (item[tagName]) { - case "INPUT": - if (item.disabled) { - break; - } - switch (item.type) { - case "file": - if (item[files].length === 0) { - this.append(name2, new File2([], "", { type: "application/octet-stream" })); - } else { - for (const file of item[files]) { - this.append(name2, file); - } - } - break; - case "checkbox": - case "radio": - if (item.checked) { - this.append(name2, item.value); - } - break; - case "submit": - case "reset": - case "button": - if (item === submitter && item.value) { - this.append(name2, item.value); - } - break; - default: - this.append(name2, item.value); - break; - } - break; - case "BUTTON": - if (item === submitter && item.value) { - this.append(name2, item.value); - } - break; - case "TEXTAREA": - case "SELECT": - this.append(name2, item.value); - break; - } - } - } - } - /** - * For each. - * - * @param callback Callback. - * @param thisArg thisArg. - */ - forEach(callback, thisArg) { - for (const entry of this.#entries) { - callback.call(thisArg, entry.value, entry.name, this); - } - } - /** - * Appends a new value onto an existing key. - * - * @param name Name. - * @param value Value. - * @param [filename] Filename. - */ - append(name2, value2, filename) { - if (filename && !(value2 instanceof Blob2)) { - throw new this[window].TypeError('Failed to execute "append" on "FormData": parameter 2 is not of type "Blob".'); - } - this.#entries.push({ - name: name2, - value: this.#parseValue(value2, filename) - }); - } - /** - * Removes a value. - * - * @param name Name. - */ - delete(name2) { - const newEntries = []; - for (const entry of this.#entries) { - if (entry.name !== name2) { - newEntries.push(entry); - } - } - this.#entries = newEntries; - } - /** - * Returns value. - * - * @param name Name. - * @returns Value. - */ - get(name2) { - for (const entry of this.#entries) { - if (entry.name === name2) { - return entry.value; - } - } - return null; - } - /** - * Returns all values associated with the given name. - * - * @param name Name. - * @returns Values. - */ - getAll(name2) { - const values2 = []; - for (const entry of this.#entries) { - if (entry.name === name2) { - values2.push(entry.value); - } - } - return values2; - } - /** - * Returns whether a FormData object contains a certain key. - * - * @param name Name. - * @returns "true" if the FormData object contains the key. - */ - has(name2) { - for (const entry of this.#entries) { - if (entry.name === name2) { - return true; - } - } - return false; - } - /** - * Sets a new value for an existing key inside a FormData object, or adds the key/value if it does not already exist. - * - * @param name Name. - * @param value Value. - * @param [filename] Filename. - */ - set(name2, value2, filename) { - for (const entry of this.#entries) { - if (entry.name === name2) { - entry.value = this.#parseValue(value2, filename); - return; - } - } - this.append(name2, value2); - } - /** - * Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object. - * - * @returns Iterator. - */ - *keys() { - for (const entry of this.#entries) { - yield entry.name; - } - } - /** - * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. - * - * @returns Iterator. - */ - *values() { - for (const entry of this.#entries) { - yield entry.value; - } - } - /** - * Returns an iterator, allowing you to go through all key/value pairs contained in this object. - * - * @returns Iterator. - */ - *entries() { - for (const entry of this.#entries) { - yield [entry.name, entry.value]; - } - } - /** - * Iterator. - * - * @returns Iterator. - */ - *[Symbol.iterator]() { - for (const entry of this.#entries) { - yield [entry.name, entry.value]; - } - } - /** - * Parses a value. - * - * @param value Value. - * @param [filename] Filename. - * @returns Parsed value. - */ - #parseValue(value2, filename) { - if (value2 instanceof File2) { - if (filename) { - const file = new File2([], filename, { type: value2.type, lastModified: value2.lastModified }); - file[buffer] = value2[buffer]; - return file; - } - return value2; - } - if (value2 instanceof Blob2) { - const file = new File2([], "blob", { type: value2.type }); - file[buffer] = value2[buffer]; - return file; - } - return String(value2); - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/utilities/FetchBodyUtility.js -var import_web3, import_url3, import_buffer4, import_stream, FetchBodyUtility; -var init_FetchBodyUtility = __esm({ - "node_modules/happy-dom/lib/fetch/utilities/FetchBodyUtility.js"() { - init_MultipartFormDataParser(); - import_web3 = require("stream/web"); - init_PropertySymbol(); - import_url3 = require("url"); - init_FormData(); - init_Blob(); - init_DOMException(); - init_DOMExceptionNameEnum(); - import_buffer4 = require("buffer"); - import_stream = __toESM(require("stream"), 1); - init_ReadableStreamWrapper(); - FetchBodyUtility = class { - /** - * Parses body and returns stream and type. - * - * Based on: - * https://github.com/node-fetch/node-fetch/blob/main/src/body.js (MIT) - * - * @param body Body. - * @returns Stream and type. - */ - static getBodyStream(body2) { - if (body2 === null || body2 === void 0) { - return { stream: null, buffer: null, contentType: null, contentLength: null }; - } else if (body2 instanceof import_url3.URLSearchParams) { - const buffer3 = import_buffer4.Buffer.from(body2.toString()); - return { - buffer: buffer3, - stream: this.getReadableStream(buffer3), - contentType: "application/x-www-form-urlencoded;charset=UTF-8", - contentLength: buffer3.length - }; - } else if (body2 instanceof Blob2) { - const buffer3 = body2[buffer]; - return { - buffer: buffer3, - stream: this.getReadableStream(buffer3), - contentType: body2.type, - contentLength: body2.size - }; - } else if (import_buffer4.Buffer.isBuffer(body2)) { - return { - buffer: body2, - stream: this.getReadableStream(body2), - contentType: null, - contentLength: body2.length - }; - } else if (body2 instanceof ArrayBuffer) { - const buffer3 = import_buffer4.Buffer.from(body2); - return { - buffer: buffer3, - stream: this.getReadableStream(buffer3), - contentType: null, - contentLength: body2.byteLength - }; - } else if (ArrayBuffer.isView(body2)) { - const buffer3 = import_buffer4.Buffer.from(body2.buffer, body2.byteOffset, body2.byteLength); - return { - buffer: buffer3, - stream: this.getReadableStream(buffer3), - contentType: null, - contentLength: body2.byteLength - }; - } else if (body2 instanceof import_web3.ReadableStream) { - return { - buffer: null, - stream: new ReadableStreamWrapper(() => body2), - contentType: null, - contentLength: null - }; - } else if (body2 instanceof FormData) { - return MultipartFormDataParser.formDataToStream(body2); - } - const buffer2 = import_buffer4.Buffer.from(String(body2)); - return { - buffer: buffer2, - stream: this.getReadableStream(buffer2), - contentType: "text/plain;charset=UTF-8", - contentLength: buffer2.length - }; - } - /** - * Clones a request or body body stream. - * - * It is actually not cloning the stream. - * It creates a pass through stream and pipes the original stream to it. - * - * @param window Window. - * @param requestOrResponse Request or Response. - * @param requestOrResponse.body Body. - * @param requestOrResponse.bodyUsed Body used. - * @returns New stream. - */ - static cloneBodyStream(window2, requestOrResponse) { - if (requestOrResponse.bodyUsed) { - throw new window2.DOMException(`Failed to clone body stream of request: Request body is already used.`, DOMExceptionNameEnum_default.invalidStateError); - } - if (requestOrResponse.body === null || requestOrResponse.body === void 0) { - return null; - } - if (requestOrResponse[buffer]) { - return this.getReadableStream(requestOrResponse[buffer]).readableStream; - } - if (requestOrResponse.body[nodeStream]) { - const stream12 = new import_stream.default.PassThrough(); - const stream22 = new import_stream.default.PassThrough(); - requestOrResponse.body[nodeStream].pipe(stream12); - requestOrResponse.body[nodeStream].pipe(stream22); - requestOrResponse[body] = new ReadableStreamWrapper(() => this.nodeToWebStream(stream12)); - return this.nodeToWebStream(stream22); - } - const [stream1, stream2] = requestOrResponse.body.tee(); - requestOrResponse[body] = new ReadableStreamWrapper(() => stream1); - return stream2; - } - /** - * Consume and convert an entire Body to a Buffer. - * - * Based on: - * https://github.com/node-fetch/node-fetch/blob/main/src/body.js (MIT) - * - * @see https://fetch.spec.whatwg.org/#concept-body-consume-body - * @param window Window. - * @param requestOrResponse - * @param requestOrResponse.body - * @param body Body stream. - * @returns Promise. - */ - static async consumeBodyStream(window2, requestOrResponse) { - const body2 = requestOrResponse.body; - if (body2 === null || !(body2 instanceof import_web3.ReadableStream)) { - return import_buffer4.Buffer.alloc(0); - } - if (requestOrResponse[error]) { - throw requestOrResponse[error]; - } - const reader = body2.getReader(); - const chunks = []; - let bytes = 0; - try { - let readResult = await reader.read(); - while (!readResult.done) { - if (requestOrResponse[error]) { - throw requestOrResponse[error]; - } - if (requestOrResponse[aborted]) { - throw new window2.DOMException("Failed to read response body: The stream was aborted.", DOMExceptionNameEnum_default.abortError); - } - const chunk = readResult.value; - bytes += chunk.length; - chunks.push(chunk); - readResult = await reader.read(); - } - } catch (error2) { - if (error2 instanceof DOMException2) { - throw error2; - } - throw new window2.DOMException(`Failed to read response body. Error: ${error2.message}.`, DOMExceptionNameEnum_default.encodingError); - } - try { - if (typeof chunks[0] === "string") { - return import_buffer4.Buffer.from(chunks.join("")); - } - return import_buffer4.Buffer.concat(chunks, bytes); - } catch (error2) { - throw new window2.DOMException(`Could not create Buffer from response body. Error: ${error2.message}.`, DOMExceptionNameEnum_default.invalidStateError); - } - } - /** - * Wraps a Node.js stream into a browser-compatible ReadableStream. - * - * Enables the use of Node.js streams where browser ReadableStreams are required. - * Handles 'data', 'end', and 'error' events from the Node.js stream. - * - * @param nodeStream The Node.js stream to be converted. - * @returns ReadableStream - */ - static nodeToWebStream(nodeStream2) { - const readableStream = new import_web3.ReadableStream({ - start(controller) { - nodeStream2.on("data", (chunk) => { - controller.enqueue(chunk); - }); - nodeStream2.on("end", () => { - controller.close(); - }); - nodeStream2.on("error", (err) => { - controller.error(err); - }); - } - }); - readableStream[nodeStream] = nodeStream2; - return readableStream; - } - /** - * Wraps a given value in a browser ReadableStream. - * - * This method creates a ReadableStream and immediately enqueues and closes it - * with the provided value, useful for stream API compatibility. - * - * @param value The value to be wrapped in a ReadableStream. - * @returns ReadableStream - */ - static getReadableStream(value2) { - return new ReadableStreamWrapper(() => new import_web3.ReadableStream({ - start(controller) { - controller.enqueue(value2); - controller.close(); - } - })); - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/utilities/FetchRequestValidationUtility.js -var VALID_REFERRER_POLICIES, VALID_REDIRECTS, SUPPORTED_SCHEMAS, FORBIDDEN_REQUEST_METHODS, REQUEST_METHOD_REGEXP, FetchRequestValidationUtility; -var init_FetchRequestValidationUtility = __esm({ - "node_modules/happy-dom/lib/fetch/utilities/FetchRequestValidationUtility.js"() { - init_DOMException(); - init_PropertySymbol(); - init_DOMExceptionNameEnum(); - VALID_REFERRER_POLICIES = [ - "", - "no-referrer", - "no-referrer-when-downgrade", - "same-origin", - "origin", - "strict-origin", - "origin-when-cross-origin", - "strict-origin-when-cross-origin", - "unsafe-url" - ]; - VALID_REDIRECTS = ["error", "manual", "follow"]; - SUPPORTED_SCHEMAS = ["data:", "http:", "https:"]; - FORBIDDEN_REQUEST_METHODS = ["TRACE", "TRACK", "CONNECT"]; - REQUEST_METHOD_REGEXP = /^[A-Z]+$/; - FetchRequestValidationUtility = class { - /** - * Validates request method. - * - * @throws DOMException - * @param request Request. - */ - static validateMethod(request) { - if (!request.method || FORBIDDEN_REQUEST_METHODS.includes(request.method)) { - throw new DOMException2(`'${request.method || ""}' is not a valid HTTP method.`, DOMExceptionNameEnum_default.invalidStateError); - } - if (!REQUEST_METHOD_REGEXP.test(request.method)) { - throw new DOMException2(`'${request.method}' HTTP method is unsupported.`, DOMExceptionNameEnum_default.invalidStateError); - } - } - /** - * Validates request body. - * - * @throws DOMException - * @param request Request. - */ - static validateBody(request) { - if (request.body && (request.method === "GET" || request.method === "HEAD")) { - throw new DOMException2(`Request with GET/HEAD method cannot have body.`, DOMExceptionNameEnum_default.invalidStateError); - } - } - /** - * Validates request URL. - * - * @throws DOMException - * @param url URL. - */ - static validateURL(url2) { - if (url2.username !== "" || url2.password !== "") { - throw new DOMException2(`${url2} is an url with embedded credentials.`, DOMExceptionNameEnum_default.notSupportedError); - } - } - /** - * Validates request referrer policy. - * - * @throws DOMException - * @param referrerPolicy Referrer policy. - */ - static validateReferrerPolicy(referrerPolicy2) { - if (!VALID_REFERRER_POLICIES.includes(referrerPolicy2)) { - throw new DOMException2(`Invalid referrer policy "${referrerPolicy2}".`, DOMExceptionNameEnum_default.syntaxError); - } - } - /** - * Validates request redirect. - * - * @throws DOMException - * @param redirect Redirect. - */ - static validateRedirect(redirect2) { - if (!VALID_REDIRECTS.includes(redirect2)) { - throw new DOMException2(`Invalid redirect "${redirect2}".`, DOMExceptionNameEnum_default.syntaxError); - } - } - /** - * Validates request redirect. - * - * @throws DOMException - * @param request - * @param redirect Redirect. - */ - static validateSchema(request) { - if (!SUPPORTED_SCHEMAS.includes(request[url].protocol)) { - throw new DOMException2(`Failed to fetch from "${request.url}": URL scheme "${request[url].protocol.replace(/:$/, "")}" is not supported.`, DOMExceptionNameEnum_default.notSupportedError); - } - } - }; - } -}); - -// node_modules/happy-dom/lib/cookie/urilities/CookieStringUtility.js -var CookieStringUtility; -var init_CookieStringUtility = __esm({ - "node_modules/happy-dom/lib/cookie/urilities/CookieStringUtility.js"() { - init_CookieSameSiteEnum(); - init_DefaultCookie(); - CookieStringUtility = class { - /** - * Returns cookie. - * - * @param originURL Origin URL. - * @param cookieString Cookie string. - * @returns Cookie. - */ - static stringToCookie(originURL, cookieString) { - const parts = cookieString.split(";"); - const part = parts.shift(); - if (!part) { - return null; - } - const index = part.indexOf("="); - const key = index !== -1 ? part.slice(0, index).trim() : part.trim(); - const value2 = index !== -1 ? part.slice(index + 1).trim() : null; - const cookie = Object.assign({}, DefaultCookie_default, { - // Required - key, - value: value2, - originURL - }); - if (!cookie.key) { - return null; - } - for (const part2 of parts) { - const index2 = part2.indexOf("="); - const key2 = index2 !== -1 ? part2.slice(0, index2).trim().toLowerCase() : part2.trim().toLowerCase(); - const value3 = index2 !== -1 ? part2.slice(index2 + 1).trim() : ""; - switch (key2) { - case "expires": - cookie.expires = new Date(value3); - break; - case "max-age": - cookie.expires = new Date(parseInt(value3, 10) * 1e3 + Date.now()); - break; - case "domain": - cookie.domain = value3; - break; - case "path": - cookie.path = value3[0] === "/" ? value3 : `/${value3}`; - break; - case "httponly": - cookie.httpOnly = true; - break; - case "secure": - cookie.secure = true; - break; - case "samesite": - switch (value3.toLowerCase()) { - case "strict": - cookie.sameSite = CookieSameSiteEnum_default.strict; - break; - case "lax": - cookie.sameSite = CookieSameSiteEnum_default.lax; - break; - case "none": - cookie.sameSite = CookieSameSiteEnum_default.none; - } - break; - } - } - const lowerKey = cookie.key.toLowerCase(); - if (lowerKey.startsWith("__secure-") && !cookie.secure) { - return null; - } - if (lowerKey.startsWith("__host-") && (!cookie.secure || cookie.path !== "/" || cookie.domain)) { - return null; - } - return cookie; - } - /** - * Returns cookie string with key and value. - * - * @param cookies Cookies. - * @returns Cookie string. - */ - static cookiesToString(cookies) { - const cookieString = []; - for (const cookie of cookies) { - if (cookie.value !== null) { - cookieString.push(`${cookie.key}=${cookie.value}`); - } else { - cookieString.push(cookie.key); - } - } - return cookieString.join("; "); - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/utilities/FetchRequestHeaderUtility.js -var import_url4, FORBIDDEN_HEADER_NAMES, FetchRequestHeaderUtility; -var init_FetchRequestHeaderUtility = __esm({ - "node_modules/happy-dom/lib/fetch/utilities/FetchRequestHeaderUtility.js"() { - init_PropertySymbol(); - init_CookieStringUtility(); - init_FetchCORSUtility(); - import_url4 = require("url"); - FORBIDDEN_HEADER_NAMES = [ - "accept-charset", - "accept-encoding", - "access-control-request-headers", - "access-control-request-method", - "connection", - "content-length", - "content-transfer-encoding", - "cookie", - "cookie2", - "date", - "dnt", - "expect", - "host", - "keep-alive", - "origin", - "referer", - "te", - "trailer", - "transfer-encoding", - "upgrade", - "via" - ]; - FetchRequestHeaderUtility = class { - /** - * Validates request headers. - * - * @param headers Headers. - */ - static removeForbiddenHeaders(headers2) { - for (const key of Object.keys(headers2[entries])) { - if (FORBIDDEN_HEADER_NAMES.includes(key) || key.startsWith("proxy-") || key.startsWith("sec-")) { - delete headers2[entries][key]; - } - } - } - /** - * Returns "true" if the header is forbidden. - * - * @param name Header name. - * @returns "true" if the header is forbidden. - */ - static isHeaderForbidden(name2) { - return FORBIDDEN_HEADER_NAMES.includes(name2.toLowerCase()); - } - /** - * Returns request headers. - * - * @param options Options. - * @param options.browserFrame Browser frame. - * @param options.window Window. - * @param options.request Request. - * @param [options.baseHeaders] Any base headers (may be overwritten by browser/window headers). - * @returns Headers. - */ - static getRequestHeaders(options2) { - const headers2 = new options2.window.Headers(options2.baseHeaders); - options2.request.headers.forEach((value2, key) => { - headers2.set(key, value2); - }); - const originURL = new import_url4.URL(options2.window.location.href); - const isCORS = FetchCORSUtility.isCORS(originURL, options2.request[url]); - headers2.set("Accept-Encoding", "gzip, deflate, br"); - headers2.set("Connection", "close"); - if (!headers2.has("User-Agent")) { - headers2.set("User-Agent", options2.window.navigator.userAgent); - } - if (options2.request[referrer] instanceof import_url4.URL) { - headers2.set("Referer", options2.request[referrer].href); - } - if (options2.request.credentials === "include" || options2.request.credentials === "same-origin" && !isCORS) { - const cookies = options2.browserFrame.page.context.cookieContainer.getCookies(options2.request[url], false); - if (cookies.length > 0) { - headers2.set("Cookie", CookieStringUtility.cookiesToString(cookies)); - } - } else { - headers2.delete("Cookie"); - headers2.delete("Cookie2"); - } - if (!headers2.has("Accept")) { - headers2.set("Accept", "*/*"); - } - if (!headers2.has("Content-Length") && options2.request[contentLength] !== null) { - headers2.set("Content-Length", String(options2.request[contentLength])); - } - if (!headers2.has("Content-Type") && options2.request[contentType]) { - headers2.set("Content-Type", options2.request[contentType]); - } - if (isCORS) { - headers2.set("Origin", originURL.origin); - } - const httpRequestHeaders = {}; - for (const header of Object.values(headers2[entries])) { - httpRequestHeaders[header.name] = header.value.join(", "); - } - return httpRequestHeaders; - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/Request.js -var import_url5, Request2; -var init_Request = __esm({ - "node_modules/happy-dom/lib/fetch/Request.js"() { - init_PropertySymbol(); - import_url5 = require("url"); - init_DOMExceptionNameEnum(); - init_FetchBodyUtility(); - init_Blob(); - init_FetchRequestValidationUtility(); - init_FetchRequestReferrerUtility(); - init_FetchRequestHeaderUtility(); - init_MultipartFormDataParser(); - init_WindowBrowserContext(); - Request2 = class _Request { - // Public properties - [method]; - [body]; - [mode] = "cors"; - [headers]; - [redirect]; - [referrerPolicy]; - [signal]; - [bodyUsed] = false; - [credentials]; - // Internal properties - [aborted] = false; - [error] = null; - [contentLength] = null; - [contentType] = null; - [referrer] = "client"; - [url]; - [bodyBuffer]; - /** - * Constructor. - * - * @param input Input. - * @param [init] Init. - */ - constructor(input, init) { - const window2 = this[window]; - if (!window2) { - throw new TypeError(`Failed to construct 'Request': 'Request' was constructed outside a Window context.`); - } - if (typeof input !== `string` && !input) { - throw new window2.TypeError(`Failed to construct 'Request': 1 argument required, only 0 present.`); - } - this[method] = (init?.method || input.method || "GET").toUpperCase(); - if (init?.mode) { - switch (init.mode) { - case "navigate": - case "websocket": - throw new window2.DOMException(`Failed to construct 'Request': Cannot construct a Request with a RequestInit whose mode member is set as '${init.mode}'.`, DOMExceptionNameEnum_default.securityError); - case "same-origin": - case "no-cors": - case "cors": - this[mode] = init.mode; - break; - default: - throw new window2.DOMException(`Failed to construct 'Request': The provided value '${init.mode}' is not a valid enum value of type RequestMode.`, DOMExceptionNameEnum_default.syntaxError); - } - } else if (input instanceof _Request) { - this[mode] = input.mode; - } - const { stream, buffer: buffer2, contentType: contentType2, contentLength: contentLength2 } = FetchBodyUtility.getBodyStream(input instanceof _Request && (input[bodyBuffer] || input.body) ? input[bodyBuffer] || FetchBodyUtility.cloneBodyStream(window2, input) : init?.body ?? null); - this[bodyBuffer] = buffer2; - this[body] = stream; - this[credentials] = init?.credentials || input.credentials || "same-origin"; - this[headers] = new this[window].Headers(init?.headers || input.headers || {}); - FetchRequestHeaderUtility.removeForbiddenHeaders(this.headers); - if (contentLength2) { - this[contentLength] = contentLength2; - } else if (!this.body && (this.method === "POST" || this.method === "PUT")) { - this[contentLength] = 0; - } - if (contentType2) { - if (!this.headers.has("Content-Type")) { - this.headers.set("Content-Type", contentType2); - } - this[contentType] = contentType2; - } else if (input instanceof _Request && input[contentType]) { - this[contentType] = input[contentType]; - } - this[redirect] = init?.redirect || input.redirect || "follow"; - this[referrerPolicy] = (init?.referrerPolicy || input.referrerPolicy || "").toLowerCase(); - this[signal] = init?.signal || input.signal || new window2.AbortSignal(); - this[referrer] = FetchRequestReferrerUtility.getInitialReferrer(window2, init?.referrer !== null && init?.referrer !== void 0 ? init?.referrer : input.referrer); - if (input instanceof import_url5.URL) { - this[url] = input; - } else { - try { - if (input instanceof _Request && input.url) { - this[url] = new import_url5.URL(input.url, window2.location.href); - } else { - this[url] = new import_url5.URL(input, window2.location.href); - } - } catch (error2) { - throw new window2.DOMException(`Failed to construct 'Request': Invalid URL "${input}" on document location '${window2.location}'.${window2.location.origin === "null" ? " Relative URLs are not permitted on current document location." : ""}`, DOMExceptionNameEnum_default.notSupportedError); - } - } - FetchRequestValidationUtility.validateMethod(this); - FetchRequestValidationUtility.validateBody(this); - FetchRequestValidationUtility.validateURL(this[url]); - FetchRequestValidationUtility.validateReferrerPolicy(this.referrerPolicy); - FetchRequestValidationUtility.validateRedirect(this.redirect); - } - /** - * Returns method. - * - * @returns Method. - */ - get method() { - return this[method]; - } - /** - * Returns body. - * - * @returns Body. - */ - get body() { - return this[body]?.readableStream || null; - } - /** - * Returns mode. - * - * @returns Mode. - */ - get mode() { - return this[mode]; - } - /** - * Returns headers. - * - * @returns Headers. - */ - get headers() { - return this[headers]; - } - /** - * Returns redirect. - * - * @returns Redirect. - */ - get redirect() { - return this[redirect]; - } - /** - * Returns referrer policy. - * - * @returns Referrer policy. - */ - get referrerPolicy() { - return this[referrerPolicy]; - } - /** - * Returns signal. - * - * @returns Signal. - */ - get signal() { - return this[signal]; - } - /** - * Returns body used. - * - * @returns Body used. - */ - get bodyUsed() { - return this[bodyUsed]; - } - /** - * Returns credentials. - * - * @returns Credentials. - */ - get credentials() { - return this[credentials]; - } - /** - * Returns referrer. - * - * @returns Referrer. - */ - get referrer() { - if (!this[referrer] || this[referrer] === "no-referrer") { - return ""; - } - if (this[referrer] === "client") { - return "about:client"; - } - return this[referrer].toString(); - } - /** - * Returns URL. - * - * @returns URL. - */ - get url() { - return this[url].href; - } - /** - * Returns string tag. - * - * @returns String tag. - */ - get [Symbol.toStringTag]() { - return "Request"; - } - /** - * Returns array buffer. - * - * @returns Array buffer. - */ - async arrayBuffer() { - const window2 = this[window]; - if (this[bodyUsed]) { - throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); - } - const asyncTaskManager2 = new WindowBrowserContext(window2).getAsyncTaskManager(); - this[bodyUsed] = true; - const taskID = asyncTaskManager2.startTask(() => { - this[aborted] = true; - this.signal[abort](); - }); - let buffer2; - try { - buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); - } catch (error2) { - asyncTaskManager2.endTask(taskID); - throw error2; - } - asyncTaskManager2.endTask(taskID); - return buffer2.buffer.slice(buffer2.byteOffset, buffer2.byteOffset + buffer2.byteLength); - } - /** - * Returns blob. - * - * @returns Blob. - */ - async blob() { - const type2 = this.headers.get("Content-Type") || ""; - const buffer2 = await this.arrayBuffer(); - return new Blob2([buffer2], { type: type2 }); - } - /** - * Returns buffer. - * - * @returns Buffer. - */ - async buffer() { - const window2 = this[window]; - if (this[bodyUsed]) { - throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); - } - const asyncTaskManager2 = new WindowBrowserContext(window2).getAsyncTaskManager(); - this[bodyUsed] = true; - const taskID = asyncTaskManager2.startTask(() => { - this[aborted] = true; - this.signal[abort](); - }); - let buffer2; - try { - buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); - } catch (error2) { - asyncTaskManager2.endTask(taskID); - throw error2; - } - asyncTaskManager2.endTask(taskID); - return buffer2; - } - /** - * Returns text. - * - * @returns Text. - */ - async text() { - const window2 = this[window]; - if (this[bodyUsed]) { - throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); - } - const asyncTaskManager2 = new WindowBrowserContext(window2).getAsyncTaskManager(); - this[bodyUsed] = true; - const taskID = asyncTaskManager2.startTask(() => { - this[aborted] = true; - this.signal[abort](); - }); - let buffer2; - try { - buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); - } catch (error2) { - asyncTaskManager2.endTask(taskID); - throw error2; - } - asyncTaskManager2.endTask(taskID); - return new TextDecoder().decode(buffer2); - } - /** - * Returns json. - * - * @returns JSON. - */ - async json() { - const text = await this.text(); - return JSON.parse(text); - } - /** - * Returns FormData. - * - * @returns FormData. - */ - async formData() { - const window2 = this[window]; - const asyncTaskManager2 = new WindowBrowserContext(window2).getAsyncTaskManager(); - const contentType2 = this.headers.get("Content-Type") ?? this[contentType]; - if (this.body && contentType2 && /multipart/i.test(contentType2)) { - if (this[bodyUsed]) { - throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); - } - this[bodyUsed] = true; - const taskID = asyncTaskManager2.startTask(() => { - this[aborted] = true; - this.signal[abort](); - }); - let formData; - try { - const result3 = await MultipartFormDataParser.streamToFormData(window2, this, contentType2); - formData = result3.formData; - } catch (error2) { - asyncTaskManager2.endTask(taskID); - throw error2; - } - asyncTaskManager2.endTask(taskID); - return formData; - } - if (contentType2?.startsWith("application/x-www-form-urlencoded")) { - const parameters = new URLSearchParams(await this.text()); - const formData = new window2.FormData(); - for (const [key, value2] of parameters) { - formData.append(key, value2); - } - return formData; - } - throw new window2.DOMException(`Failed to construct FormData object: The "content-type" header is neither "application/x-www-form-urlencoded" nor "multipart/form-data".`, DOMExceptionNameEnum_default.invalidStateError); - } - /** - * Clones request. - * - * @returns Clone. - */ - clone() { - return new this[window].Request(this); - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/Response.js -var import_url6, import_buffer5, REDIRECT_STATUS_CODES, Response2; -var init_Response = __esm({ - "node_modules/happy-dom/lib/fetch/Response.js"() { - init_PropertySymbol(); - init_Blob(); - import_url6 = require("url"); - init_URL(); - init_FetchBodyUtility(); - init_DOMExceptionNameEnum(); - init_MultipartFormDataParser(); - import_buffer5 = require("buffer"); - init_WindowBrowserContext(); - REDIRECT_STATUS_CODES = [301, 302, 303, 307, 308]; - Response2 = class { - // Public properties - bodyUsed = false; - redirected = false; - type = "basic"; - url = ""; - status; - statusText; - ok; - headers; - [cachedResponse] = null; - [buffer] = null; - [virtualServerFile] = null; - [aborted] = false; - [error] = null; - [body] = null; - /** - * Constructor. - * - * @param body Body. - * @param [init] Init. - */ - constructor(body2, init) { - if (!this[window]) { - throw new TypeError(`Failed to construct '${this.constructor.name}': '${this.constructor.name}' was constructed outside a Window context.`); - } - this.status = init?.status !== void 0 ? init.status : 200; - this.statusText = init?.statusText || ""; - this.ok = this.status >= 200 && this.status < 300; - this.headers = new this[window].Headers(init?.headers); - this.headers.delete("Set-Cookie"); - this.headers.delete("Set-Cookie2"); - if (body2) { - const { stream, buffer: buffer2, contentType: contentType2 } = FetchBodyUtility.getBodyStream(body2); - this[body] = stream; - if (buffer2) { - this[buffer] = buffer2; - } - if (contentType2 && !this.headers.has("Content-Type")) { - this.headers.set("Content-Type", contentType2); - } - } - } - /** - * Returns string tag. - * - * @returns String tag. - */ - get [Symbol.toStringTag]() { - return "Response"; - } - /** - * Returns body stream. - * - * @returns Body stream. - */ - get body() { - return this[body]?.readableStream || null; - } - /** - * Returns array buffer. - * - * @returns Array buffer. - */ - async arrayBuffer() { - const window2 = this[window]; - if (this.bodyUsed) { - throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); - } - const browserFrame = new WindowBrowserContext(window2).getBrowserFrame(); - if (!browserFrame) { - return new ArrayBuffer(0); - } - const asyncTaskManager2 = browserFrame[asyncTaskManager]; - this.bodyUsed = true; - let buffer2 = this[buffer]; - if (!buffer2) { - const taskID = asyncTaskManager2.startTask(() => { - this[aborted] = true; - }); - try { - buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); - } catch (error2) { - asyncTaskManager2.endTask(taskID); - throw error2; - } - asyncTaskManager2.endTask(taskID); - } - this.#storeBodyInCache(buffer2); - return buffer2.buffer.slice(buffer2.byteOffset, buffer2.byteOffset + buffer2.byteLength); - } - /** - * Returns blob. - * - * @returns Blob. - */ - async blob() { - const type2 = this.headers.get("Content-Type") || ""; - const buffer2 = await this.arrayBuffer(); - return new Blob2([buffer2], { type: type2 }); - } - /** - * Returns buffer. - * - * @returns Buffer. - */ - async buffer() { - const window2 = this[window]; - if (this.bodyUsed) { - throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); - } - const browserFrame = new WindowBrowserContext(window2).getBrowserFrame(); - if (!browserFrame) { - return import_buffer5.Buffer.alloc(0); - } - const asyncTaskManager2 = browserFrame[asyncTaskManager]; - this.bodyUsed = true; - let buffer2 = this[buffer]; - if (!buffer2) { - const taskID = asyncTaskManager2.startTask(() => { - this[aborted] = true; - }); - try { - buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); - } catch (error2) { - asyncTaskManager2.endTask(taskID); - throw error2; - } - asyncTaskManager2.endTask(taskID); - } - this.#storeBodyInCache(buffer2); - return buffer2; - } - /** - * Returns text. - * - * @returns Text. - */ - async text() { - const window2 = this[window]; - if (this.bodyUsed) { - throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); - } - const browserFrame = new WindowBrowserContext(window2).getBrowserFrame(); - if (!browserFrame) { - return ""; - } - const asyncTaskManager2 = browserFrame[asyncTaskManager]; - this.bodyUsed = true; - let buffer2 = this[buffer]; - if (!buffer2) { - const taskID = asyncTaskManager2.startTask(() => { - this[aborted] = true; - }); - try { - buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); - } catch (error2) { - asyncTaskManager2.endTask(taskID); - throw error2; - } - asyncTaskManager2.endTask(taskID); - } - this.#storeBodyInCache(buffer2); - return new TextDecoder().decode(buffer2); - } - /** - * Returns json. - * - * @returns JSON. - */ - async json() { - const text = await this.text(); - return JSON.parse(text); - } - /** - * Returns form data. - * - * @returns Form data. - */ - async formData() { - const window2 = this[window]; - const browserFrame = new WindowBrowserContext(window2).getBrowserFrame(); - if (!browserFrame) { - return new window2.FormData(); - } - const asyncTaskManager2 = browserFrame[asyncTaskManager]; - const contentType2 = this.headers.get("Content-Type"); - if (contentType2 && this.body && /multipart/i.test(contentType2)) { - if (this.bodyUsed) { - throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); - } - this.bodyUsed = true; - const taskID = browserFrame[asyncTaskManager].startTask(() => { - this[aborted] = true; - }); - let formData; - let buffer2; - try { - const result3 = await MultipartFormDataParser.streamToFormData(window2, this, contentType2); - formData = result3.formData; - buffer2 = result3.buffer; - } catch (error2) { - asyncTaskManager2.endTask(taskID); - throw error2; - } - this.#storeBodyInCache(buffer2); - asyncTaskManager2.endTask(taskID); - return formData; - } - if (contentType2?.startsWith("application/x-www-form-urlencoded")) { - const parameters = new import_url6.URLSearchParams(await this.text()); - const formData = new window2.FormData(); - for (const [key, value2] of parameters) { - formData.append(key, value2); - } - return formData; - } - throw new window2.DOMException(`Failed to build FormData object: The "content-type" header is neither "application/x-www-form-urlencoded" nor "multipart/form-data".`, DOMExceptionNameEnum_default.invalidStateError); - } - /** - * Clones request. - * - * @returns Clone. - */ - clone() { - const window2 = this[window]; - const body2 = FetchBodyUtility.cloneBodyStream(window2, this); - const response = new window2.Response(body2, { - status: this.status, - statusText: this.statusText, - headers: this.headers - }); - response[cachedResponse] = this[cachedResponse]; - response[buffer] = this[buffer]; - response.ok = this.ok; - response.redirected = this.redirected; - response.type = this.type; - response.url = this.url; - return response; - } - /** - * Stores body in cache. - * - * @param buffer Buffer. - */ - #storeBodyInCache(buffer2) { - this[buffer] = buffer2; - if (this[cachedResponse]?.response?.waitingForBody) { - this[cachedResponse].response.body = buffer2; - this[cachedResponse].response.waitingForBody = false; - } - } - /** - * Returns a redirect response. - * - * @param url URL. - * @param status Status code. - * @returns Response. - */ - static redirect(url2, status = 302) { - const window2 = this[window]; - if (!REDIRECT_STATUS_CODES.includes(status)) { - throw new window2.DOMException("Failed to create redirect response: Invalid redirect status code.", DOMExceptionNameEnum_default.invalidStateError); - } - return new window2.Response(null, { - headers: { - location: new URL2(url2).toString() - }, - status - }); - } - /** - * Returns an error response. - * - * @param url URL. - * @param status Status code. - * @returns Response. - */ - static error() { - const response = new this[window].Response(null, { status: 0, statusText: "" }); - response.type = "error"; - return response; - } - /** - * Returns an JSON response. - * - * @param injected Injected properties. - * @param data Data. - * @param [init] Init. - * @returns Response. - */ - static json(data2, init) { - const window2 = this[window]; - const body2 = JSON.stringify(data2); - if (body2 === void 0) { - throw new window2.TypeError("data is not JSON serializable"); - } - const headers2 = new window2.Headers(init && init.headers); - if (!headers2.has("Content-Type")) { - headers2.set("Content-Type", "application/json"); - } - return new window2.Response(body2, { - status: 200, - ...init, - headers: headers2 - }); - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/utilities/FetchResponseRedirectUtility.js -var REDIRECT_STATUS_CODES2, MAX_REDIRECT_COUNT, FetchResponseRedirectUtility; -var init_FetchResponseRedirectUtility = __esm({ - "node_modules/happy-dom/lib/fetch/utilities/FetchResponseRedirectUtility.js"() { - REDIRECT_STATUS_CODES2 = [301, 302, 303, 307, 308]; - MAX_REDIRECT_COUNT = 20; - FetchResponseRedirectUtility = class { - /** - * Returns "true" if redirect. - * - * @param statusCode Status code. - * @returns "true" if redirect. - */ - static isRedirect(statusCode) { - return REDIRECT_STATUS_CODES2.includes(statusCode); - } - /** - * Returns "true" if max redirects is reached. - * - * @param redirectCount Redirect count. - * @returns "true" if max redirects is reached. - */ - static isMaxRedirectsReached(redirectCount) { - return redirectCount >= MAX_REDIRECT_COUNT; - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/utilities/FetchResponseHeaderUtility.js -var FetchResponseHeaderUtility; -var init_FetchResponseHeaderUtility = __esm({ - "node_modules/happy-dom/lib/fetch/utilities/FetchResponseHeaderUtility.js"() { - init_CookieStringUtility(); - FetchResponseHeaderUtility = class { - /** - * Appends headers to response. - * - * @param nodeResponse HTTP request. - * @param options - * @param options.browserFrame - * @param options.requestURL - * @param options.rawHeaders - * @returns Headers. - */ - static parseResponseHeaders(options2) { - const headers2 = new options2.browserFrame.window.Headers(); - let key = null; - for (const header of options2.rawHeaders) { - if (!key) { - key = header; - } else { - const lowerName = key.toLowerCase(); - if (lowerName === "set-cookie" || lowerName === "set-cookie2") { - const cookie = CookieStringUtility.stringToCookie(options2.requestURL, header); - if (cookie) { - options2.browserFrame.page.context.cookieContainer.addCookies([cookie]); - } - } else { - headers2.append(key, header); - } - key = null; - } - } - return headers2; - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/certificate/FetchHTTPSCertificate.js -var FetchHTTPSCertificate_default; -var init_FetchHTTPSCertificate = __esm({ - "node_modules/happy-dom/lib/fetch/certificate/FetchHTTPSCertificate.js"() { - FetchHTTPSCertificate_default = { - cert: `-----BEGIN CERTIFICATE----- -MIIDYzCCAkugAwIBAgIUJRKB/H66hpet1VfUlm0CiXqePA4wDQYJKoZIhvcNAQEL -BQAwQTELMAkGA1UEBhMCU0UxDjAMBgNVBAgMBVNrYW5lMQ4wDAYDVQQHDAVNYWxt -bzESMBAGA1UECgwJSGFwcHkgRE9NMB4XDTIyMTAxMTIyMDM0OVoXDTMyMTAwODIy -MDM0OVowQTELMAkGA1UEBhMCU0UxDjAMBgNVBAgMBVNrYW5lMQ4wDAYDVQQHDAVN -YWxtbzESMBAGA1UECgwJSGFwcHkgRE9NMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAqerQSQEg/SxVxRiwlItithr5e5EMZo1nsqt/xOxagbmpW3IEmt0j -bpbH7iEF4DDEo7KAOwUCOwVWeFxRoag8lG2ax48wrgjlCna45XDn0Xeg1ARajL04 -gs46HZ0VrzIloVGfln0zgt/Vum5BNqs9Oc5fQoBmoP3cAn3dn4ZVcP0AKthtcyPl -q2DuNRN0PV0D2RtMSiAy9l1Ko6N5x+sAeClDyOL+sTDLngZBVeZyOKt9Id15S8Zt -XtA6VMgHnnF3jChn7pag77rsd/y5iANAVNZYqRl+Eg7xaDcsvbgH46UBOrBcB39Q -tTh5Mtjoxep5e3ZDFG+kQ1HUE+iz5O5n0wIDAQABo1MwUTAdBgNVHQ4EFgQU69s9 -YSobG/m2SN4L/7zTaF7iDbwwHwYDVR0jBBgwFoAU69s9YSobG/m2SN4L/7zTaF7i -DbwwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAi/WUXx2oal8L -YnPlIuKfh49n/K18wXSYG//oFYwxfVxqpYH8hUiXVm/GUcXCxS++hUkaKLqXmH9q -MKJiCrZr3vS+2nsBKopkICu/TLdROl0sAI9lByfnEbfSAzjxe1IWJdK8NdY0y5m5 -9pEr/URVIAp/CxrneyASb4q0Jg5To3FR7vYc+2X6wZn0MundKMg6Dp9/A37jiF3l -Tt/EJp299YZcsUzh+LnRuggRjnoOVu1aLcLFlaUiwZfy9m8mLG6B/mdW/qNzNMh9 -Oqvg1zfGdpz/4D/2UUUBn6pq1vbsoAaF3OesoA3mfDcegDf/H9woJlpT0Wql+e68 -Y3FblSokcA== ------END CERTIFICATE-----`, - key: `-----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCp6tBJASD9LFXF -GLCUi2K2Gvl7kQxmjWeyq3/E7FqBualbcgSa3SNulsfuIQXgMMSjsoA7BQI7BVZ4 -XFGhqDyUbZrHjzCuCOUKdrjlcOfRd6DUBFqMvTiCzjodnRWvMiWhUZ+WfTOC39W6 -bkE2qz05zl9CgGag/dwCfd2fhlVw/QAq2G1zI+WrYO41E3Q9XQPZG0xKIDL2XUqj -o3nH6wB4KUPI4v6xMMueBkFV5nI4q30h3XlLxm1e0DpUyAeecXeMKGfulqDvuux3 -/LmIA0BU1lipGX4SDvFoNyy9uAfjpQE6sFwHf1C1OHky2OjF6nl7dkMUb6RDUdQT -6LPk7mfTAgMBAAECggEAKkwTkTjAt4UjzK56tl+EMQTB+ep/hb/JgoaChci4Nva6 -m9LkJpDJ0yuhlTuPNOGu8XjrxsVWas7HWarRf0Zb3i7yip6wZYI9Ub+AA015x4DZ -/i0fRU2NFbK0cM67qSL4jxG8gj+kZP3HPGNZxHwX/53JxMolwgmvjMc8NgvAlSFd -NnV9h4xtbhUh1NGS5zmP3iU2rwnE8JrIEzwy6axLom7nekAgkdcbAr0UoBs8gcgH -aYNhU4Gz3tGcZZ0IXAfT/bJIH1Ko8AGv4pssWc3BXcmmNdm/+kzvHIxEIV7Qegmo -XG1ZyZCyD/0b4/3e8ySDBEDqwR+HeyTW2isWG2agAQKBgQDp44aTwr3dkIXY30xv -FPfUOipg/B49dWnffYJ9MWc1FT9ijNPAngWSk0EIiEQIazICcUBI4Yji6/KeyqLJ -GdLpDi1CkKqtyh73mjELinYp3EUQgEa77aQogGa2+nMOVfu+O5CtloUrv/A18jX3 -+VEyaEASK0fWmnSI0OdlxQHIAQKBgQC5+xOls2F3MlKASvWRLlnW1wHqlDTtVoYg -5Nh8syZH4Ci2UH8tON3A5/7SWNM0t1cgV6Cw4zW8Z2spgIT/W0iYYrQ4hHL1xdCu -+CxL1km4Gy8Uwpsd+KdFahFqF/XTmLzW0HXLxWSK0fTwmdV0SFrKF3MXfTCU2AeZ -jJoMFb6P0wKBgQC3Odw6s0vkYAzLGhuZxfZkVvDOK5RRF0NKpttr0iEFL9EJFkPo -2KKK8jr3QTDy229BBJGUxsJi6u6VwS8HlehpVQbV59kd7oKV/EBBx0XMg1fDlopT -PNbmN7i/zbIG4AsoOyebJZjL7kBzMn1e9vzKHWtcEHXlw/hZGja8vjooAQKBgAeg -xK2HLfg1mCyq5meN/yFQsENu0LzrT5UJzddPgcJw7zqLEqxIKNBAs7Ls8by3yFsL -PQwERa/0jfCl1M6kb9XQNpQa2pw6ANUsWKTDpUJn2wZ+9N3F1RaDwzMWyH5lRVmK -M0qoTfdjpSg5Jwgd75taWt4bxGJWeflSSv8z5R0BAoGAWL8c527AbeBvx2tOYKkD -2TFranvANNcoMrbeviZSkkGvMNDP3p8b6juJwXOIeWNr8q4vFgCzLmq6d1/9gYm2 -3XJwwyD0LKlqzkBrrKU47qrnmMosUrIRlrAzd3HbShOptxc6Iz2apSaUDKGKXkaw -gl5OpEjeliU7Mus0BVS858g= ------END PRIVATE KEY-----` - }; - } -}); - -// node_modules/happy-dom/lib/fetch/utilities/VirtualServerUtility.js -var import_path2, NOT_FOUND_HTML, VirtualServerUtility; -var init_VirtualServerUtility = __esm({ - "node_modules/happy-dom/lib/fetch/utilities/VirtualServerUtility.js"() { - init_WindowBrowserContext(); - import_path2 = __toESM(require("path"), 1); - init_PropertySymbol(); - NOT_FOUND_HTML = "Happy DOM Virtual Server - 404 Not Found

Happy DOM Virtual Server - 404 Not Found

"; - VirtualServerUtility = class { - /** - * Returns the filesystem path for a request URL if it matches a virtual server. - * - * @param window Window. - * @param requestURL Request URL. - */ - static getFilepath(window2, requestURL) { - const browserSettings = new WindowBrowserContext(window2).getSettings(); - if (!browserSettings || !browserSettings.fetch.virtualServers && !browserSettings.module.resolveNodeModules) { - return null; - } - if (browserSettings.fetch.virtualServers) { - for (const virtualServer of browserSettings.fetch.virtualServers) { - let baseURL = null; - if (typeof virtualServer.url === "string") { - const url2 = new URL(virtualServer.url[virtualServer.url.length - 1] === "/" ? virtualServer.url.slice(0, -1) : virtualServer.url, window2.location.origin !== "null" ? window2.location.origin : void 0); - if (requestURL.startsWith(url2.href)) { - baseURL = url2; - } - } else if (virtualServer.url instanceof RegExp) { - const match = requestURL.match(virtualServer.url); - if (match) { - baseURL = new URL(match[0][match[0].length - 1] === "/" ? match[0].slice(0, -1) : match[0], window2.location.origin); - } - } - if (baseURL) { - const path2 = requestURL.slice(baseURL.href.length).split("?")[0].split("#")[0]; - return import_path2.default.join(import_path2.default.resolve(virtualServer.directory), path2.replaceAll("/", import_path2.default.sep)); - } - } - } - if (browserSettings.module.resolveNodeModules) { - const moduleUrl = browserSettings.module.resolveNodeModules.url; - const url2 = new URL(moduleUrl[moduleUrl.length - 1] === "/" ? moduleUrl.slice(0, -1) : moduleUrl, window2.location.origin); - if (requestURL.startsWith(url2.href)) { - const path2 = requestURL.slice(url2.href.length).split("?")[0].split("#")[0]; - return import_path2.default.join(import_path2.default.resolve(browserSettings.module.resolveNodeModules.directory), path2.replaceAll("/", import_path2.default.sep)); - } - } - return null; - } - /** - * Returns a 404 response. - * - * @param window Window. - * @returns 404 response. - */ - static getNotFoundResponse(window2) { - return new window2.Response(NOT_FOUND_HTML, { - status: 404, - statusText: "Not Found", - headers: { - "Content-Type": "text/html" - } - }); - } - /** - * Returns a 404 response. - * - * @param window Window. - * @param requestURL Request URL. - * @returns 404 response. - */ - static getNotFoundSyncResponse(window2, requestURL) { - return { - status: 404, - statusText: "Not Found", - ok: false, - url: requestURL, - redirected: false, - headers: new window2.Headers({ - "Content-Type": "text/html" - }), - body: Buffer.from(NOT_FOUND_HTML), - [virtualServerFile]: null - }; - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/preload/PreloadUtility.js -var PreloadUtility; -var init_PreloadUtility = __esm({ - "node_modules/happy-dom/lib/fetch/preload/PreloadUtility.js"() { - PreloadUtility = class { - /** - * Returns a key for a preload entry. - * - * @param options Options. - * @param options.url URL. - * @param options.destination Destination. - * @param options.mode Mode. - * @param options.credentialsMode Credentials mode. - * @returns Key. - */ - static getKey(options2) { - return JSON.stringify({ - url: options2.url, - destination: options2.destination, - mode: options2.mode, - credentialsMode: options2.credentialsMode - }); - } - }; - } -}); - -// node_modules/happy-dom/lib/fetch/Fetch.js -var import_http, import_https, import_zlib, import_url7, import_fs2, import_path3, import_stream2, import_buffer6, LAST_CHUNK, Fetch; -var init_Fetch = __esm({ - "node_modules/happy-dom/lib/fetch/Fetch.js"() { - init_PropertySymbol(); - init_FetchRequestReferrerUtility(); - init_DOMExceptionNameEnum(); - import_http = __toESM(require("http"), 1); - import_https = __toESM(require("https"), 1); - import_zlib = __toESM(require("zlib"), 1); - import_url7 = require("url"); - import_fs2 = __toESM(require("fs"), 1); - import_path3 = __toESM(require("path"), 1); - import_stream2 = __toESM(require("stream"), 1); - init_DataURIParser(); - init_FetchCORSUtility(); - init_Request(); - init_Response(); - init_CachedResponseStateEnum(); - init_FetchRequestHeaderUtility(); - init_FetchRequestValidationUtility(); - init_FetchResponseRedirectUtility(); - init_FetchResponseHeaderUtility(); - init_FetchHTTPSCertificate(); - import_buffer6 = require("buffer"); - init_FetchBodyUtility(); - init_VirtualServerUtility(); - init_PreloadUtility(); - LAST_CHUNK = import_buffer6.Buffer.from("0\r\n\r\n"); - Fetch = class _Fetch { - reject = null; - resolve = null; - listeners = { - onSignalAbort: this.onSignalAbort.bind(this) - }; - isChunkedTransfer = false; - isProperLastChunkReceived = false; - previousChunk = null; - nodeRequest = null; - nodeResponse = null; - response = null; - responseHeaders = null; - interceptor; - requestHeaders; - request; - redirectCount = 0; - disableCache; - disableSameOriginPolicy; - disablePreload; - #browserFrame; - #window; - #unfilteredHeaders = null; - /** - * Constructor. - * - * @param options Options. - * @param options.browserFrame Browser frame. - * @param options.window Window. - * @param options.url URL. - * @param [options.init] Init. - * @param [options.redirectCount] Redirect count. - * @param [options.contentType] Content Type. - * @param [options.disableCache] Disables the use of cached responses. It will still store the response in the cache. - * @param [options.disableSameOriginPolicy] Disables the Same-Origin policy. - * @param [options.unfilteredHeaders] Unfiltered headers - necessary for preflight requests. - * @param [options.disablePreload] Disables the use of preloaded responses. - */ - constructor(options2) { - this.#browserFrame = options2.browserFrame; - this.#window = options2.window; - this.#unfilteredHeaders = options2.unfilteredHeaders ?? null; - this.request = typeof options2.url === "string" || options2.url instanceof import_url7.URL ? new options2.window.Request(options2.url, options2.init) : options2.url; - if (options2.contentType) { - this.request[contentType] = options2.contentType; - } - this.redirectCount = options2.redirectCount ?? 0; - this.disableCache = options2.disableCache ?? false; - this.disableSameOriginPolicy = options2.disableSameOriginPolicy ?? this.#browserFrame.page.context.browser.settings.fetch.disableSameOriginPolicy ?? false; - this.interceptor = this.#browserFrame.page.context.browser.settings.fetch.interceptor; - this.requestHeaders = this.#browserFrame.page.context.browser.settings.fetch.requestHeaders; - this.disablePreload = options2.disablePreload ?? false; - } - /** - * Sends request. - * - * @returns Response. - */ - async send() { - if (!(this.request instanceof Request2) || !(this.request[url] instanceof import_url7.URL)) { - throw new this.#window.DOMException("Unknown request object. Request object must be an instance of Request.", DOMExceptionNameEnum_default.invalidStateError); - } - FetchRequestReferrerUtility.prepareRequest(new import_url7.URL(this.#window.location.href), this.request); - if (this.requestHeaders) { - for (const header of this.requestHeaders) { - if (!header.url || (typeof header.url === "string" ? header.url.startsWith(this.request.url) : this.request.url.match(header.url))) { - for (const [key, value2] of Object.entries(header.headers)) { - this.request.headers.set(key, value2); - } - } - } - } - if (this.interceptor?.beforeAsyncRequest) { - const taskID = this.#browserFrame[asyncTaskManager].startTask(); - const response = await this.interceptor.beforeAsyncRequest({ - request: this.request, - window: this.#window - }); - this.#browserFrame[asyncTaskManager].endTask(taskID); - if (response instanceof Response2) { - return response; - } - } - FetchRequestValidationUtility.validateSchema(this.request); - if (this.request.signal[aborted]) { - if (this.request.signal[reason] !== void 0) { - throw this.request.signal[reason]; - } - throw new this.#window.DOMException("signal is aborted without reason", DOMExceptionNameEnum_default.abortError); - } - if (this.request[url].protocol === "data:") { - const result3 = DataURIParser.parse(this.request.url); - this.response = new this.#window.Response(result3.buffer, { - headers: { "Content-Type": result3.type } - }); - const interceptedResponse = this.interceptor?.afterAsyncResponse ? await this.interceptor.afterAsyncResponse({ - window: this.#window, - response: this.response, - request: this.request - }) : void 0; - return interceptedResponse instanceof Response2 ? interceptedResponse : this.response; - } - if (this.request[url].protocol === "http:" && this.#window.location.protocol === "https:") { - throw new this.#window.DOMException(`Mixed Content: The page at '${this.#window.location.href}' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint '${this.request.url}'. This request has been blocked; the content must be served over HTTPS.`, DOMExceptionNameEnum_default.securityError); - } - if (!this.disableCache) { - const cachedResponse2 = await this.getCachedResponse(); - if (cachedResponse2) { - return cachedResponse2; - } - } - if (!this.disablePreload) { - const preloadKey = PreloadUtility.getKey({ - url: this.request.url, - destination: "fetch", - mode: this.request.mode, - credentialsMode: this.request.credentials - }); - const preloadEntry = this.#window.document[preloads].get(preloadKey); - if (preloadEntry) { - this.#window.document[preloads].delete(preloadKey); - if (preloadEntry.response) { - return preloadEntry.response; - } - const taskID = this.#browserFrame[asyncTaskManager].startTask(); - const response = await preloadEntry.onResponseAvailable(); - this.#browserFrame[asyncTaskManager].endTask(taskID); - return response; - } - } - const virtualServerResponse = await this.getVirtualServerResponse(); - if (virtualServerResponse) { - return virtualServerResponse; - } - if (!this.disableSameOriginPolicy) { - const compliesWithCrossOriginPolicy = await this.compliesWithCrossOriginPolicy(); - if (!compliesWithCrossOriginPolicy) { - this.#browserFrame.page.console.warn(`Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at "${this.request.url}".`); - throw new this.#window.DOMException(`Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at "${this.request.url}".`, DOMExceptionNameEnum_default.networkError); - } - } - return await this.sendRequest(); - } - /** - * Returns cached response. - * - * @returns Response. - */ - async getCachedResponse() { - if (this.disableCache) { - return null; - } - let cachedResponse2 = this.#browserFrame.page.context.responseCache.get(this.request); - if (!cachedResponse2 || cachedResponse2.response.waitingForBody) { - return null; - } - if (cachedResponse2.state === CachedResponseStateEnum_default.stale) { - const headers2 = new this.#window.Headers(cachedResponse2.request.headers); - if (cachedResponse2.etag) { - headers2.set("If-None-Match", cachedResponse2.etag); - } else { - if (!cachedResponse2.lastModified) { - return null; - } - headers2.set("If-Modified-Since", new Date(cachedResponse2.lastModified).toUTCString()); - } - const fetch2 = new _Fetch({ - browserFrame: this.#browserFrame, - window: this.#window, - url: this.request.url, - init: { headers: headers2, method: cachedResponse2.request.method }, - disableCache: true, - disableSameOriginPolicy: true - }); - if (cachedResponse2.etag || !cachedResponse2.staleWhileRevalidate) { - const validateResponse = await fetch2.send(); - const body2 = validateResponse.status !== 304 ? await validateResponse.buffer() : null; - cachedResponse2 = this.#browserFrame.page.context.responseCache.add(this.request, { - ...validateResponse, - body: body2, - waitingForBody: false - }); - if (validateResponse.status !== 304) { - const response2 = new this.#window.Response(body2, { - status: validateResponse.status, - statusText: validateResponse.statusText, - headers: validateResponse.headers - }); - response2.url = validateResponse.url; - response2[cachedResponse] = cachedResponse2; - return response2; - } - } else { - fetch2.send().then((response2) => { - response2.buffer().then((body2) => { - this.#browserFrame.page.context.responseCache.add(this.request, { - ...response2, - body: body2, - waitingForBody: false - }); - }); - }); - } - } - if (!cachedResponse2 || cachedResponse2.response.waitingForBody) { - return null; - } - const response = new this.#window.Response(cachedResponse2.response.body, { - status: cachedResponse2.response.status, - statusText: cachedResponse2.response.statusText, - headers: cachedResponse2.response.headers - }); - response.url = cachedResponse2.response.url; - response[cachedResponse] = cachedResponse2; - return response; - } - /** - * Returns virtual server response. - * - * @returns Response. - */ - async getVirtualServerResponse() { - let filePath = VirtualServerUtility.getFilepath(this.#window, this.request.url); - if (!filePath) { - return null; - } - const taskID = this.#browserFrame[asyncTaskManager].startTask(); - if (this.request.method !== "GET") { - this.#browserFrame.page.console.error(`${this.request.method} ${this.request.url} 404 (Not Found)`); - const response2 = VirtualServerUtility.getNotFoundResponse(this.#window); - const interceptedResponse2 = this.interceptor?.afterAsyncResponse ? await this.interceptor.afterAsyncResponse({ - window: this.#window, - response: await response2, - request: this.request - }) : void 0; - this.#browserFrame[asyncTaskManager].endTask(taskID); - return interceptedResponse2 instanceof Response2 ? interceptedResponse2 : response2; - } - let buffer2; - try { - const stat = await import_fs2.default.promises.stat(filePath); - filePath = stat.isDirectory() ? import_path3.default.join(filePath, "index.html") : filePath; - buffer2 = await import_fs2.default.promises.readFile(filePath); - } catch (error2) { - this.#browserFrame.page.console.error(`${this.request.method} ${this.request.url} 404 (Not Found)`); - const response2 = VirtualServerUtility.getNotFoundResponse(this.#window); - const interceptedResponse2 = this.interceptor?.afterAsyncResponse ? await this.interceptor.afterAsyncResponse({ - window: this.#window, - response: await response2, - request: this.request - }) : void 0; - this.#browserFrame[asyncTaskManager].endTask(taskID); - return interceptedResponse2 instanceof Response2 ? interceptedResponse2 : response2; - } - const body2 = new this.#window.ReadableStream({ - start: (controller) => { - this.#window.queueMicrotask(() => { - controller.enqueue(buffer2); - controller.close(); - }); - } - }); - const response = new this.#window.Response(body2); - response[buffer] = buffer2; - response[virtualServerFile] = filePath; - response.url = this.request.url; - const interceptedResponse = this.interceptor?.afterAsyncResponse ? await this.interceptor.afterAsyncResponse({ - window: this.#window, - response: await response, - request: this.request - }) : void 0; - this.#browserFrame[asyncTaskManager].endTask(taskID); - const returnResponse = interceptedResponse instanceof Response2 ? interceptedResponse : response; - const cacheableResponse = { - ...returnResponse, - body: buffer2, - waitingForBody: false, - virtual: true - }; - response[cachedResponse] = this.#browserFrame.page.context.responseCache.add(this.request, cacheableResponse); - return returnResponse; - } - /** - * Checks if the request complies with the Cross-Origin policy. - * - * @returns True if it complies with the policy. - */ - async compliesWithCrossOriginPolicy() { - if (this.disableSameOriginPolicy || !FetchCORSUtility.isCORS(this.#window.location.href, this.request[url])) { - return true; - } - const cachedPreflightResponse = this.#browserFrame.page.context.preflightResponseCache.get(this.request); - if (cachedPreflightResponse) { - if (cachedPreflightResponse.allowOrigin !== "*" && cachedPreflightResponse.allowOrigin !== this.#window.location.origin) { - return false; - } - if (cachedPreflightResponse.allowMethods.length !== 0 && !cachedPreflightResponse.allowMethods.includes(this.request.method)) { - return false; - } - return true; - } - const requestHeaders = []; - for (const [header] of this.request.headers) { - requestHeaders.push(header.toLowerCase()); - } - const corsHeaders2 = new this.#window.Headers({ - "Access-Control-Request-Method": this.request.method, - Origin: this.#window.location.origin - }); - if (requestHeaders.length > 0) { - corsHeaders2.set("Access-Control-Request-Headers", requestHeaders.slice().sort().join(",")); - } - const fetch2 = new _Fetch({ - browserFrame: this.#browserFrame, - window: this.#window, - url: this.request.url, - init: { method: "OPTIONS" }, - disableCache: true, - disableSameOriginPolicy: true, - unfilteredHeaders: corsHeaders2 - }); - const response = await fetch2.send(); - if (!response.ok) { - return false; - } - const allowOrigin = response.headers.get("Access-Control-Allow-Origin"); - if (!allowOrigin) { - return false; - } - if (allowOrigin !== "*" && allowOrigin !== this.#window.location.origin) { - return false; - } - const allowMethods = []; - if (response.headers.has("Access-Control-Allow-Methods")) { - const allowMethodsHeader = response.headers.get("Access-Control-Allow-Methods"); - if (allowMethodsHeader !== "*") { - for (const method2 of allowMethodsHeader.split(",")) { - allowMethods.push(method2.trim().toUpperCase()); - } - } - } - if (allowMethods.length !== 0 && !allowMethods.includes(this.request.method)) { - return false; - } - return true; - } - /** - * Sends request. - * - * @returns Response. - */ - sendRequest() { - return new Promise((resolve, reject) => { - const taskID = this.#browserFrame[asyncTaskManager].startTask(() => this.onAsyncTaskManagerAbort()); - if (this.resolve) { - throw new this.#window.Error("Fetch already sent."); - } - this.resolve = async (response) => { - if (!this.disableCache && response instanceof Response2 && this.#browserFrame.page && this.#browserFrame.page.context) { - response[cachedResponse] = this.#browserFrame.page.context.responseCache.add(this.request, { - ...response, - headers: this.responseHeaders, - body: response[buffer], - waitingForBody: !response[buffer] && !!response.body - }); - } - const interceptedResponse = this.interceptor?.afterAsyncResponse ? await this.interceptor.afterAsyncResponse({ - window: this.#window, - response: await response, - request: this.request - }) : void 0; - this.#browserFrame[asyncTaskManager].endTask(taskID); - const returnResponse = interceptedResponse instanceof Response2 ? interceptedResponse : response; - if (returnResponse instanceof Response2 && !returnResponse.ok) { - this.#browserFrame.page.console.error(`${this.request.method} ${this.request.url} ${returnResponse.status} (${returnResponse.statusText})`); - } - resolve(returnResponse); - }; - this.reject = (error2) => { - this.#browserFrame[asyncTaskManager].endTask(taskID); - reject(error2); - }; - this.request.signal.addEventListener("abort", this.listeners.onSignalAbort); - const send = (this.request[url].protocol === "https:" ? import_https.default : import_http.default).request; - this.nodeRequest = send(this.request[url].href, { - method: this.request.method, - headers: FetchRequestHeaderUtility.getRequestHeaders({ - browserFrame: this.#browserFrame, - window: this.#window, - request: this.request, - baseHeaders: this.#unfilteredHeaders - }), - agent: false, - rejectUnauthorized: !this.#browserFrame.page.context.browser.settings.fetch.disableStrictSSL, - key: this.request[url].protocol === "https:" ? FetchHTTPSCertificate_default.key : void 0, - cert: this.request[url].protocol === "https:" ? FetchHTTPSCertificate_default.cert : void 0 - }); - this.nodeRequest.on("error", this.onError.bind(this)); - this.nodeRequest.on("socket", this.onSocket.bind(this)); - this.nodeRequest.on("response", this.onResponse.bind(this)); - if (this.request.body === null) { - this.nodeRequest.end(); - } else { - import_stream2.default.pipeline(this.request.body, this.nodeRequest, (error2) => { - if (error2) { - this.onError(error2); - } - }); - } - }); - } - /** - * Event listener for "socket" event. - * - * @param socket Socket. - */ - onSocket(socket) { - const onSocketClose = () => { - if (this.isChunkedTransfer && !this.isProperLastChunkReceived) { - const error2 = new this.#window.DOMException("Premature close.", DOMExceptionNameEnum_default.networkError); - this.request[error] = error2; - if (this.response) { - this.response[error] = error2; - if (this.response.body && !this.response.body.locked) { - this.response.body.cancel(error2); - } - } - } - }; - const onData = (buffer2) => { - this.isProperLastChunkReceived = import_buffer6.Buffer.compare(buffer2.slice(-5), LAST_CHUNK) === 0; - if (!this.isProperLastChunkReceived && this.previousChunk) { - this.isProperLastChunkReceived = import_buffer6.Buffer.compare(this.previousChunk.slice(-3), LAST_CHUNK.slice(0, 3)) === 0 && import_buffer6.Buffer.compare(buffer2.slice(-2), LAST_CHUNK.slice(3)) === 0; - } - this.previousChunk = buffer2; - }; - socket.prependListener("close", onSocketClose); - socket.on("data", onData); - this.nodeRequest.on("close", () => { - socket.removeListener("close", onSocketClose); - socket.removeListener("data", onData); - }); - } - /** - * Event listener for signal "abort" event. - * - * @param event Event. - */ - onSignalAbort(event) { - this.finalizeRequest(); - this.abort(event.target?.reason); - } - /** - * Event listener for request "error" event. - * - * @param error Error. - */ - onError(error2) { - this.finalizeRequest(); - this.#browserFrame.page.console.error(error2); - this.reject(new this.#window.DOMException(`Failed to execute "fetch()" on "Window" with URL "${this.request.url}": ${error2.message}`, DOMExceptionNameEnum_default.networkError)); - } - /** - * Triggered when the async task manager aborts. - */ - onAsyncTaskManagerAbort() { - const error2 = new this.#window.DOMException("The operation was aborted.", DOMExceptionNameEnum_default.abortError); - this.request[aborted] = true; - this.request[error] = error2; - if (this.response) { - this.response[aborted] = true; - this.response[error] = error2; - } - if (this.listeners.onSignalAbort) { - this.request.signal.removeEventListener("abort", this.listeners.onSignalAbort); - } - if (this.nodeRequest && !this.nodeRequest.destroyed) { - this.nodeRequest.destroy(error2); - } - if (this.nodeResponse && !this.nodeResponse.destroyed) { - this.nodeResponse.destroy(error2); - } - if (this.response && this.response.body) { - if (!this.response.body.locked) { - this.response.body.cancel(error2); - } - } - } - /** - * Event listener for request "response" event. - * - * @param nodeResponse Node response. - */ - onResponse(nodeResponse) { - this.isChunkedTransfer = nodeResponse.headers["transfer-encoding"] === "chunked" && !nodeResponse.headers["content-length"]; - this.nodeRequest.setTimeout(0); - this.responseHeaders = FetchResponseHeaderUtility.parseResponseHeaders({ - browserFrame: this.#browserFrame, - requestURL: this.request[url], - rawHeaders: nodeResponse.rawHeaders - }); - if (this.handleRedirectResponse(nodeResponse, this.responseHeaders)) { - return; - } - nodeResponse.once("end", () => this.request.signal.removeEventListener("abort", this.listeners.onSignalAbort)); - let body2 = import_stream2.default.pipeline(nodeResponse, new import_stream2.default.PassThrough(), (error2) => { - if (error2) { - } - }); - const responseOptions = { - status: nodeResponse.statusCode, - statusText: nodeResponse.statusMessage, - headers: this.responseHeaders - }; - const contentEncodingHeader = this.responseHeaders.get("Content-Encoding"); - if (this.request.method === "HEAD" || contentEncodingHeader === null || nodeResponse.statusCode === 204 || nodeResponse.statusCode === 304) { - this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); - this.response.redirected = this.redirectCount > 0; - this.response.url = this.request.url; - this.resolve(this.response); - return; - } - if (contentEncodingHeader === "gzip" || contentEncodingHeader === "x-gzip") { - const zlibOptions = { - flush: import_zlib.default.constants.Z_SYNC_FLUSH, - finishFlush: import_zlib.default.constants.Z_SYNC_FLUSH - }; - body2 = import_stream2.default.pipeline(body2, import_zlib.default.createGunzip(zlibOptions), (error2) => { - if (error2) { - } - }); - this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); - this.response.redirected = this.redirectCount > 0; - this.response.url = this.request.url; - this.resolve(this.response); - return; - } - if (contentEncodingHeader === "deflate" || contentEncodingHeader === "x-deflate") { - const raw = import_stream2.default.pipeline(nodeResponse, new import_stream2.default.PassThrough(), (error2) => { - if (error2) { - } - }); - raw.on("data", (chunk) => { - if ((chunk[0] & 15) === 8) { - body2 = import_stream2.default.pipeline(body2, import_zlib.default.createInflate(), (error2) => { - if (error2) { - } - }); - } else { - body2 = import_stream2.default.pipeline(body2, import_zlib.default.createInflateRaw(), (error2) => { - if (error2) { - } - }); - } - this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); - this.response.redirected = this.redirectCount > 0; - this.response.url = this.request.url; - this.resolve(this.response); - }); - raw.on("end", () => { - if (!this.response) { - this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); - this.response.redirected = this.redirectCount > 0; - this.response.url = this.request.url; - this.resolve(this.response); - } - }); - return; - } - if (contentEncodingHeader === "br") { - body2 = import_stream2.default.pipeline(body2, import_zlib.default.createBrotliDecompress(), (error2) => { - if (error2) { - } - }); - this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); - this.response.redirected = this.redirectCount > 0; - this.response.url = this.request.url; - this.resolve(this.response); - return; - } - this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); - this.response.redirected = this.redirectCount > 0; - this.response.url = this.request.url; - this.resolve(this.response); - } - /** - * Handles redirect response. - * - * @param nodeResponse Node response. - * @param responseHeaders Headers. - * @returns True if redirect response was handled, false otherwise. - */ - handleRedirectResponse(nodeResponse, responseHeaders) { - if (!FetchResponseRedirectUtility.isRedirect(nodeResponse.statusCode)) { - return false; - } - switch (this.request.redirect) { - case "error": - this.finalizeRequest(); - this.reject(new this.#window.DOMException(`URI requested responds with a redirect, redirect mode is set to "error": ${this.request.url}`, DOMExceptionNameEnum_default.abortError)); - return true; - case "manual": - return false; - case "follow": - const locationHeader = responseHeaders.get("Location"); - const shouldBecomeGetRequest = nodeResponse.statusCode === 303 || (nodeResponse.statusCode === 301 || nodeResponse.statusCode === 302) && this.request.method === "POST"; - let locationURL = null; - if (locationHeader !== null) { - try { - locationURL = new import_url7.URL(locationHeader, this.request.url); - } catch { - this.finalizeRequest(); - this.reject(new this.#window.DOMException(`URI requested responds with an invalid redirect URL: ${locationHeader}`, DOMExceptionNameEnum_default.uriMismatchError)); - return true; - } - } - if (locationURL === null) { - return false; - } - if (FetchResponseRedirectUtility.isMaxRedirectsReached(this.redirectCount)) { - this.finalizeRequest(); - this.reject(new this.#window.DOMException(`Maximum redirects reached at: ${this.request.url}`, DOMExceptionNameEnum_default.networkError)); - return true; - } - const headers2 = new this.#window.Headers(this.request.headers); - const requestInit = { - method: this.request.method, - signal: this.request.signal, - referrer: this.request.referrer, - referrerPolicy: this.request.referrerPolicy, - credentials: this.request.credentials, - headers: headers2, - body: this.request[bodyBuffer] - }; - if (this.request.credentials === "omit" || this.request.credentials === "same-origin" && FetchCORSUtility.isCORS(this.#window.location.href, locationURL)) { - headers2.delete("cookie"); - headers2.delete("cookie2"); - } - if (this.request.signal[aborted]) { - this.abort(this.request.signal[reason]); - return true; - } - if (shouldBecomeGetRequest) { - requestInit.method = "GET"; - requestInit.body = void 0; - headers2.delete("Content-Length"); - headers2.delete("Content-Type"); - } - const responseReferrerPolicy = FetchRequestReferrerUtility.getReferrerPolicyFromHeader(headers2); - if (responseReferrerPolicy) { - requestInit.referrerPolicy = responseReferrerPolicy; - } - const fetch2 = new _Fetch({ - browserFrame: this.#browserFrame, - window: this.#window, - url: locationURL, - init: requestInit, - redirectCount: this.redirectCount + 1, - disableSameOriginPolicy: this.disableSameOriginPolicy, - contentType: !shouldBecomeGetRequest ? this.request[contentType] : null - }); - this.finalizeRequest(); - fetch2.send().then((response) => this.resolve(response)).catch((error2) => this.reject(error2)); - return true; - default: - this.finalizeRequest(); - this.reject(new this.#window.DOMException(`Redirect option '${this.request.redirect}' is not a valid value of TRequestRedirect`)); - return true; - } - } - /** - * Finalizes the request. - */ - finalizeRequest() { - this.request.signal.removeEventListener("abort", this.listeners.onSignalAbort); - this.nodeRequest?.destroy(); - } - /** - * Aborts the request. - * - * @param reason Reason. - */ - abort(reason2) { - const error2 = new this.#window.DOMException("The operation was aborted." + (reason2 ? " " + reason2.toString() : ""), DOMExceptionNameEnum_default.abortError); - this.request[aborted] = true; - this.request[error] = error2; - if (this.response) { - this.response[aborted] = true; - this.response[error] = error2; - } - if (this.nodeRequest && !this.nodeRequest.destroyed) { - this.nodeRequest.destroy(error2); - } - if (this.nodeResponse && !this.nodeResponse.destroyed) { - this.nodeResponse.destroy(error2); - } - if (this.response && this.response.body) { - if (!this.response.body.locked) { - this.response.body.cancel(error2); - } - } - if (this.reject) { - this.reject(reason2 !== void 0 ? reason2 : error2); - } - } - }; - } -}); - -// node_modules/happy-dom/lib/history/HistoryScrollRestorationEnum.js -var HistoryScrollRestorationEnum, HistoryScrollRestorationEnum_default; -var init_HistoryScrollRestorationEnum = __esm({ - "node_modules/happy-dom/lib/history/HistoryScrollRestorationEnum.js"() { - (function(HistoryScrollRestorationEnum2) { - HistoryScrollRestorationEnum2["auto"] = "auto"; - HistoryScrollRestorationEnum2["manual"] = "manual"; - })(HistoryScrollRestorationEnum || (HistoryScrollRestorationEnum = {})); - HistoryScrollRestorationEnum_default = HistoryScrollRestorationEnum; - } -}); - -// node_modules/happy-dom/lib/browser/utilities/BrowserFrameURL.js -var import_url8, BrowserFrameURL; -var init_BrowserFrameURL = __esm({ - "node_modules/happy-dom/lib/browser/utilities/BrowserFrameURL.js"() { - import_url8 = require("url"); - init_PropertySymbol(); - BrowserFrameURL = class { - /** - * Returns relative URL. - * - * @param frame Frame. - * @param url URL. - * @returns Relative URL. - */ - static getRelativeURL(frame, url2) { - url2 = url2 ? String(url2) : "about:blank"; - if (url2.startsWith("about:") || url2.startsWith("javascript:")) { - return new import_url8.URL(url2); - } - try { - return new import_url8.URL(url2, frame.window[location].href); - } catch (e) { - return new import_url8.URL("about:blank"); - } - } - }; - } -}); - -// node_modules/happy-dom/lib/history/History.js -var History; -var init_History = __esm({ - "node_modules/happy-dom/lib/history/History.js"() { - init_HistoryScrollRestorationEnum(); - init_PropertySymbol(); - init_BrowserFrameURL(); - init_DOMExceptionNameEnum(); - History = class { - #browserFrame; - #window; - /** - * Constructor. - * - * @param browserFrame Browser frame. - * @param window Owner window. - */ - constructor(browserFrame, window2) { - if (!browserFrame) { - throw new TypeError("Illegal constructor"); - } - this.#browserFrame = browserFrame; - this.#window = window2; - } - /** - * Returns the history length. - * - * @returns History length. - */ - get length() { - return this.#browserFrame?.[history].items.length || 0; - } - /** - * Returns an any value representing the state at the top of the history stack. This is a way to look at the state without having to wait for a popstate event. - * - * @returns State. - */ - get state() { - return this.#browserFrame?.[history].currentItem.state || null; - } - /** - * Returns scroll restoration. - * - * @returns Sroll restoration. - */ - get scrollRestoration() { - return this.#browserFrame?.[history].currentItem.scrollRestoration || HistoryScrollRestorationEnum_default.auto; - } - /** - * Sets scroll restoration. - * - * @param scrollRestoration Sroll restoration. - */ - set scrollRestoration(scrollRestoration) { - switch (scrollRestoration) { - case HistoryScrollRestorationEnum_default.auto: - case HistoryScrollRestorationEnum_default.manual: - const currentItem = this.#browserFrame?.[history].currentItem; - if (currentItem) { - currentItem.scrollRestoration = scrollRestoration; - } - break; - } - } - /** - * Goes to the previous page in session history. - */ - back() { - if (!this.#window.closed) { - this.#browserFrame?.goBack(); - } - } - /** - * Goes to the next page in session history. - */ - forward() { - if (!this.#window.closed) { - this.#browserFrame?.goForward(); - } - } - /** - * Load a specific page from the session history. - * - * @param delta Delta. - * @param _delta - */ - go(delta) { - if (!this.#window.closed) { - this.#browserFrame?.goSteps(delta); - } - } - /** - * Pushes the given data onto the session history stack. - * - * @param state State. - * @param _unused Unused. - * @param [url] URL. - */ - pushState(state2, _unused, url2) { - if (!this.#browserFrame || this.#window.closed) { - return; - } - const history2 = this.#browserFrame?.[history]; - if (!history2) { - return; - } - if (arguments.length < 2) { - throw new this.#window.TypeError(`Failed to execute 'pushState' on 'History': 2 arguments required, but only ${arguments.length} present.`); - } - const location2 = this.#window[location]; - const newURL = url2 ? BrowserFrameURL.getRelativeURL(this.#browserFrame, url2) : location2; - if (url2 && newURL.origin !== location2.origin) { - throw new this.#window.DOMException(`Failed to execute 'pushState' on 'History': A history state object with URL '${url2.toString()}' cannot be created in a document with origin '${location2.origin}' and URL '${location2.href}'.`, DOMExceptionNameEnum_default.securityError); - } - history2.currentItem.popState = true; - history2.push({ - title: this.#window.document.title, - href: newURL.href, - state: state2, - popState: true, - scrollRestoration: history2.currentItem.scrollRestoration, - method: history2.currentItem.method || "GET", - formData: history2.currentItem.formData || null - }); - location2[setURL](this.#browserFrame, history2.currentItem.href); - } - /** - * This method modifies the current history entry, replacing it with a new state. - * - * @param state State. - * @param _unused Unused. - * @param [url] URL. - */ - replaceState(state2, _unused, url2) { - if (!this.#browserFrame || this.#window.closed) { - return; - } - const history2 = this.#browserFrame?.[history]; - if (!history2) { - return; - } - if (arguments.length < 2) { - throw new this.#window.TypeError(`Failed to execute 'pushState' on 'History': 2 arguments required, but only ${arguments.length} present.`); - } - const location2 = this.#window[location]; - const newURL = url2 ? BrowserFrameURL.getRelativeURL(this.#browserFrame, url2) : location2; - if (url2 && newURL.origin !== location2.origin) { - throw new this.#window.DOMException(`Failed to execute 'pushState' on 'History': A history state object with URL '${url2.toString()}' cannot be created in a document with origin '${location2.origin}' and URL '${location2.href}'.`, DOMExceptionNameEnum_default.securityError); - } - history2.replace({ - title: this.#window.document.title, - href: newURL.href, - state: state2, - popState: history2.currentItem.popState, - scrollRestoration: history2.currentItem.scrollRestoration, - method: history2.currentItem.method, - formData: history2.currentItem.formData - }); - if (url2) { - location2[setURL](this.#browserFrame, history2.currentItem.href); - } - } - /** - * Destroys the history. - * - * This will make sure that the History API can't access page data from the next history item. - */ - [destroy]() { - this.#browserFrame = null; - } - }; - } -}); - -// node_modules/happy-dom/lib/intersection-observer/IntersectionObserver.js -var IntersectionObserver; -var init_IntersectionObserver = __esm({ - "node_modules/happy-dom/lib/intersection-observer/IntersectionObserver.js"() { - IntersectionObserver = class { - // @ts-ignore - #callback; - // @ts-ignore - #options; - /** - * Constructor. - * - * @param callback Callback. - * @param options Options. - */ - constructor(callback, options2) { - this.#callback = callback; - this.#options = options2 || {}; - } - /** - * Starts observing. - * - * @param _target Target. - */ - observe(_target) { - } - /** - * Disconnects. - */ - disconnect() { - } - /** - * Unobserves an element. - * - * @param _target Target. - */ - unobserve(_target) { - } - /** - * Returns an array of IntersectionObserverEntry objects for all observed targets. - * - * @returns Records. - */ - takeRecords() { - return []; - } - }; - } -}); - -// node_modules/happy-dom/lib/intersection-observer/IntersectionObserverEntry.js -var IntersectionObserverEntry; -var init_IntersectionObserverEntry = __esm({ - "node_modules/happy-dom/lib/intersection-observer/IntersectionObserverEntry.js"() { - IntersectionObserverEntry = class { - boundingClientRect = null; - intersectionRatio = 0; - intersectionRect = null; - isIntersecting = false; - rootBounds = null; - target = null; - time = 0; - /** - * Constructor. - * - * @param init Options to initialize the intersection observer entry. - */ - constructor(init) { - Object.assign(this, init); - } - }; - } -}); - -// node_modules/happy-dom/lib/location/Location.js -var Location; -var init_Location = __esm({ - "node_modules/happy-dom/lib/location/Location.js"() { - init_HashChangeEvent(); - init_HistoryScrollRestorationEnum(); - init_PropertySymbol(); - Location = class { - // Public properties - [Symbol.toStringTag] = "Location"; - // Private properties - #browserFrame; - #url; - #hashChangeTimeout = null; - #hashChangeEvents = []; - /** - * Constructor. - * - * @param browserFrame Browser frame. - * @param url URL. - */ - constructor(browserFrame, url2) { - if (!browserFrame) { - throw new TypeError("Illegal constructor"); - } - this.#browserFrame = browserFrame; - this.#url = new URL(url2); - } - /** - * Returns hash. - * - * @returns Hash. - */ - get hash() { - return this.#url.hash; - } - /** - * Sets hash. - * - * @param hash Value. - */ - set hash(hash) { - const history2 = this.#browserFrame?.[history]; - if (!history2 || !this.#browserFrame) { - return; - } - const url2 = new URL(this.#url.href); - const oldHash = this.#url.hash; - url2.hash = hash; - if (url2.hash !== oldHash) { - history2.currentItem.popState = true; - history2.push({ - title: "", - href: url2.href, - state: history2.currentItem.state, - popState: true, - scrollRestoration: HistoryScrollRestorationEnum_default.manual, - method: history2.currentItem.method, - formData: history2.currentItem.formData || null - }); - this[setURL](this.#browserFrame, url2.href); - } - } - /** - * Returns host. - * - * @returns Host. - */ - get host() { - return this.#url.host; - } - /** - * Sets host. - * - * @param host Value. - */ - set host(host2) { - const url2 = new URL(this.#url.href); - url2.host = host2; - this.href = url2.href; - } - /** - * Returns hostname. - * - * @returns Hostname. - */ - get hostname() { - return this.#url.hostname; - } - /** - * Sets hostname. - * - * @param hostname Value. - */ - set hostname(hostname) { - const url2 = new URL(this.#url.href); - url2.hostname = hostname; - this.href = url2.href; - } - /** - * Override set href. - */ - get href() { - return this.#url.href; - } - /** - * Override set href. - */ - set href(url2) { - if (!this.#browserFrame) { - return; - } - this.#browserFrame.goto(url2).catch((error2) => { - if (this.#browserFrame?.page?.console) { - this.#browserFrame.page.console.error(error2); - } else { - throw error2; - } - }); - } - /** - * Returns origin. - * - * @returns Origin. - */ - get origin() { - return this.#url.origin; - } - /** - * Returns pathname - * - * @returns Pathname. - */ - get pathname() { - return this.#url.pathname; - } - /** - * Sets pathname. - * - * @param pathname Value. - */ - set pathname(pathname) { - const url2 = new URL(this.#url.href); - url2.pathname = pathname; - this.href = url2.href; - } - /** - * Returns port. - * - * @returns Port. - */ - get port() { - return this.#url.port; - } - /** - * Sets port. - * - * @param port Value. - */ - set port(port) { - const url2 = new URL(this.#url.href); - url2.port = port; - this.href = url2.href; - } - /** - * Returns protocol. - * - * @returns Protocol. - */ - get protocol() { - return this.#url.protocol; - } - /** - * Sets protocol. - * - * @param protocol Value. - */ - set protocol(protocol) { - const url2 = new URL(this.#url.href); - url2.protocol = protocol; - this.href = url2.href; - } - /** - * Returns search. - * - * @returns Search. - */ - get search() { - return this.#url.search; - } - /** - * Sets search. - * - * @param search Value. - */ - set search(search) { - const url2 = new URL(this.#url.href); - url2.search = search; - this.href = url2.href; - } - /** - * Replaces the current resource with the one at the provided URL. The difference from the assign() method is that after using replace() the current page will not be saved in session History, meaning the user won't be able to use the back button to navigate to it. - * - * @param url URL. - */ - replace(url2) { - this.href = String(url2); - } - /** - * Loads the resource at the URL provided in parameter. - * - * @param url URL. - */ - assign(url2) { - this.href = String(url2); - } - /** - * Reloads the resource from the current URL. - */ - reload() { - if (!this.#browserFrame) { - return; - } - this.#browserFrame.goto(this.href).catch((error2) => { - if (this.#browserFrame?.page.console) { - this.#browserFrame.page.console.error(error2); - } else { - throw error2; - } - }); - } - /** - * Replaces the current URL state with the provided one without navigating to the new URL. - * - * @param browserFrame Browser frame that must match the current one as validation. - * @param url URL. - */ - [setURL](browserFrame, url2) { - if (!this.#browserFrame) { - return; - } - if (this.#browserFrame !== browserFrame) { - throw new Error("Failed to set URL. Browser frame mismatch."); - } - const oldURL = this.#url.href; - const oldHash = this.#url.hash; - this.#url.href = url2; - if (this.#url.hash !== oldHash) { - const newURL = this.#url.href; - this.#hashChangeEvents.push(new HashChangeEvent("hashchange", { oldURL, newURL })); - this.#browserFrame?.window?.document?.[clearCache](); - if (this.#hashChangeTimeout) { - this.#browserFrame.window?.clearTimeout(this.#hashChangeTimeout); - } - this.#hashChangeTimeout = this.#browserFrame.window?.setTimeout(() => { - const hashChangeEvents = this.#hashChangeEvents; - this.#hashChangeEvents = []; - for (const event of hashChangeEvents) { - this.#browserFrame?.window?.dispatchEvent(event); - } - }); - } - } - /** - * Destroys the location. - */ - [destroy]() { - if (this.#hashChangeTimeout) { - this.#browserFrame?.window?.clearTimeout(this.#hashChangeTimeout); - } - this.#browserFrame = null; - } - /** - * Returns the URL as a string. - * - * @returns URL as a string. - */ - toString() { - return this.#url.toString(); - } - }; - } -}); - -// node_modules/happy-dom/lib/mutation-observer/MutationRecord.js -var MutationRecord; -var init_MutationRecord = __esm({ - "node_modules/happy-dom/lib/mutation-observer/MutationRecord.js"() { - MutationRecord = class { - type; - target; - addedNodes; - removedNodes; - previousSibling; - nextSibling; - attributeName; - attributeNamespace; - oldValue; - /** - * Constructor. - * - * @param init Options to initialize the mutation record. - * @param init.type Type. - * @param init.target Target node. - * @param init.addedNodes Nodes added. - * @param init.removedNodes Nodes removed. - * @param init.previousSibling Previous sibling node. - * @param init.nextSibling Next sibling node. - * @param init.attributeName Name of the attribute. - * @param init.attributeNamespace Namespace of the attribute. - * @param init.oldValue Previous value of the attribute. - */ - constructor(init) { - this.type = init.type; - this.target = init.target; - this.addedNodes = init.addedNodes || []; - this.removedNodes = init.removedNodes || []; - this.previousSibling = init.previousSibling || null; - this.nextSibling = init.nextSibling || null; - this.attributeName = init.attributeName || null; - this.attributeNamespace = init.attributeNamespace || null; - this.oldValue = init.oldValue || null; - } - }; - } -}); - -// node_modules/happy-dom/lib/navigator/MimeType.js -var MimeType; -var init_MimeType = __esm({ - "node_modules/happy-dom/lib/navigator/MimeType.js"() { - MimeType = class { - description; - enabledPlugin; - suffixes; - type; - /** - * Constructor. - * - * @param description - * @param enabledPlugin - * @param suffixes - * @param type - */ - constructor(description, enabledPlugin, suffixes, type2) { - this.description = description; - this.enabledPlugin = enabledPlugin; - this.suffixes = suffixes; - this.type = type2; - } - /** - * Returns the object as a string. - * - * @returns String. - */ - toString() { - return "[object MimeType]"; - } - }; - } -}); - -// node_modules/happy-dom/lib/navigator/MimeTypeArray.js -var MimeTypeArray; -var init_MimeTypeArray = __esm({ - "node_modules/happy-dom/lib/navigator/MimeTypeArray.js"() { - MimeTypeArray = class { - length; - /** - * Constructor. - * - * @param mimeTypes - */ - constructor(mimeTypes) { - for (let i = 0, max = mimeTypes.length; i < max; i++) { - this[i] = mimeTypes[i]; - this[mimeTypes[i].type] = mimeTypes[i]; - } - this.length = mimeTypes.length; - } - /** - * @param index - */ - item(index) { - return this[index] || null; - } - /** - * @param name - */ - namedItem(name2) { - return this[name2] || null; - } - /** - * Returns the object as a string. - * - * @returns String. - */ - toString() { - return "[object MimeTypeArray]"; - } - }; - } -}); - -// node_modules/happy-dom/lib/navigator/PluginArray.js -var PluginArray; -var init_PluginArray = __esm({ - "node_modules/happy-dom/lib/navigator/PluginArray.js"() { - PluginArray = class { - length; - /** - * Constructor. - * - * @param plugins Plugins. - */ - constructor(plugins) { - for (let i = 0, max = plugins.length; i < max; i++) { - this[i] = plugins[i]; - this[plugins[i].name] = plugins[i]; - } - this.length = plugins.length; - } - /** - * Returns an item. - * - * @param index Index. - * @returns Plugin. - */ - item(index) { - return this[index] || null; - } - /** - * Returns an item. - * - * @param name Name. - * @returns Plugin. - */ - namedItem(name2) { - return this[name2] || null; - } - /** - * Refreshes the list. - */ - refresh() { - } - /** - * Returns the object as a string. - * - * @returns String. - */ - toString() { - return "[object PluginArray]"; - } - }; - } -}); - -// node_modules/happy-dom/lib/permissions/PermissionNameEnum.js -var PermissionNameEnum, PermissionNameEnum_default; -var init_PermissionNameEnum = __esm({ - "node_modules/happy-dom/lib/permissions/PermissionNameEnum.js"() { - (function(PermissionNameEnum2) { - PermissionNameEnum2["geolocation"] = "geolocation"; - PermissionNameEnum2["notifications"] = "notifications"; - PermissionNameEnum2["push"] = "push"; - PermissionNameEnum2["midi"] = "midi"; - PermissionNameEnum2["camera"] = "camera"; - PermissionNameEnum2["microphone"] = "microphone"; - PermissionNameEnum2["backgroundFetch"] = "background-fetch"; - PermissionNameEnum2["backgroundSync"] = "background-sync"; - PermissionNameEnum2["persistentStorage"] = "persistent-storage"; - PermissionNameEnum2["ambientLightSensor"] = "ambient-light-sensor"; - PermissionNameEnum2["accelerometer"] = "accelerometer"; - PermissionNameEnum2["gyroscope"] = "gyroscope"; - PermissionNameEnum2["magnetometer"] = "magnetometer"; - PermissionNameEnum2["screenWakeLock"] = "screen-wake-lock"; - PermissionNameEnum2["nfc"] = "nfc"; - PermissionNameEnum2["displayCapture"] = "display-capture"; - PermissionNameEnum2["accessibilityEvents"] = "accessibility-events"; - PermissionNameEnum2["clipboardRead"] = "clipboard-read"; - PermissionNameEnum2["clipboardWrite"] = "clipboard-write"; - PermissionNameEnum2["paymentHandler"] = "payment-handler"; - PermissionNameEnum2["idleDetection"] = "idle-detection"; - PermissionNameEnum2["periodicBackgroundSync"] = "periodic-background-sync"; - PermissionNameEnum2["systemWakeLock"] = "system-wake-lock"; - PermissionNameEnum2["storageAccess"] = "storage-access"; - PermissionNameEnum2["windowManagement"] = "window-management"; - PermissionNameEnum2["windowPlacement"] = "window-placement"; - PermissionNameEnum2["localFonts"] = "local-fonts"; - PermissionNameEnum2["topLevelStorageAccess"] = "top-level-storage-access"; - })(PermissionNameEnum || (PermissionNameEnum = {})); - PermissionNameEnum_default = PermissionNameEnum; - } -}); - -// node_modules/happy-dom/lib/permissions/Permissions.js -var Permissions; -var init_Permissions = __esm({ - "node_modules/happy-dom/lib/permissions/Permissions.js"() { - init_PermissionNameEnum(); - Permissions = class { - #permissionStatus = {}; - #window; - /** - * Constructor. - * - * @param window Window. - */ - constructor(window2) { - if (!window2?.document) { - new TypeError("Invalid constructor"); - } - this.#window = window2; - } - /** - * Returns scroll restoration. - * - * @param permissionDescriptor Permission descriptor. - * @param permissionDescriptor.name Permission name. - * @param [permissionDescriptor.userVisibleOnly] User visible only. - * @param [permissionDescriptor.sysex] Sysex. - * @returns Permission status. - */ - async query(permissionDescriptor) { - const name2 = permissionDescriptor?.name; - if (name2 && this.#permissionStatus[name2]) { - return this.#permissionStatus[name2]; - } - if (!Object.values(PermissionNameEnum_default).includes(name2)) { - throw new Error(`Failed to execute 'query' on 'Permissions': Failed to read the 'name' property from 'PermissionDescriptor': The provided value '${name2}' is not a valid enum value of type PermissionName.`); - } - this.#permissionStatus[name2] = new this.#window.PermissionStatus("granted"); - return this.#permissionStatus[name2]; - } - }; - } -}); - -// node_modules/happy-dom/lib/navigator/Navigator.js -var Navigator; -var init_Navigator = __esm({ - "node_modules/happy-dom/lib/navigator/Navigator.js"() { - init_MimeTypeArray(); - init_PluginArray(); - init_Permissions(); - init_Clipboard(); - init_WindowBrowserContext(); - Navigator = class { - #window; - #clipboard; - #permissions; - /** - * Constructor. - * - * @param window Owner window. - */ - constructor(window2) { - if (!window2) { - throw new TypeError("Invalid constructor"); - } - this.#window = window2; - this.#clipboard = new Clipboard(window2); - this.#permissions = new Permissions(window2); - } - /** - * False if setting a cookie will be ignored and true otherwise. - */ - get cookieEnabled() { - return true; - } - /** - * TODO: Not implemented. - */ - get credentials() { - return null; - } - /** - * TODO: Not implemented. - */ - get geolocation() { - return null; - } - /** - * String representing the preferred language of the user, usually the language of the browser UI. - */ - get language() { - return "en-US"; - } - /** - * Array of string representing the user's preferred languages. - */ - get languages() { - return ["en-US", "en"]; - } - /** - * TODO: Not implemented. - */ - get locks() { - return null; - } - /** - * Maximum number of simultaneous touch contact points are supported by the current device. - */ - get maxTouchPoints() { - return new WindowBrowserContext(this.#window).getSettings()?.navigator.maxTouchPoints || 0; - } - /** - * Number of logical processors available to run threads on the user's computer. - */ - get hardwareConcurrency() { - return 8; - } - /** - * Browser app code name. - */ - get appCodeName() { - return "Mozilla"; - } - /** - * Browser app name. - */ - get appName() { - return "Netscape"; - } - /** - * Browser app version. - */ - get appVersion() { - const userAgent = this.userAgent; - const index = userAgent.indexOf("/"); - return index > -1 ? userAgent.substring(index + 1) : ""; - } - /** - * Browser platform. - */ - get platform() { - const userAgent = this.userAgent; - const indexStart = userAgent.indexOf("("); - const indexEnd = userAgent.indexOf(")"); - return indexStart > -1 && indexEnd > -1 ? userAgent.substring(indexStart + 1, indexEnd) : ""; - } - /** - * Browser product. - */ - get product() { - return "Gecko"; - } - /** - * Browser product sub. - */ - get productSub() { - return "20100101"; - } - /** - * Browser vendor. - */ - get vendor() { - return ""; - } - /** - * Browser vendor sub. - */ - get vendorSub() { - return ""; - } - /** - * Browser user agent. - * - * "appCodeName/appVersion number (Platform; Security; OS-or-CPU; Localization; rv: revision-version-number) product/productSub Application-Name Application-Name-version". - */ - get userAgent() { - return new WindowBrowserContext(this.#window).getSettings()?.navigator.userAgent || ""; - } - /** - * Boolean value indicating whether the browser is working online. - */ - get onLine() { - return true; - } - /** - * Returns a Permissions object that can be used to query and update permission status of APIs covered by the Permissions API. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/permissions - * @returns Permissions. - */ - get permissions() { - return this.#permissions; - } - /** - * Returns a Clipboard object providing access to the contents of the system clipboard. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/clipboard - * @returns Clipboard. - */ - get clipboard() { - return this.#clipboard; - } - /** - * Boolean Indicates whether the user agent is controlled by automation. - */ - get webdriver() { - return true; - } - /** - * The user's Do Not Track setting, which indicates whether the user is requesting web sites and advertisers to not track them. - * - * The value of the property reflects that of the DNT HTTP header, i.e. Values of "1", "0", or "unspecified". - */ - get doNotTrack() { - return "unspecified"; - } - /** - * Browser mime-types. - */ - get mimeTypes() { - return new MimeTypeArray([]); - } - /** - * Browser plugins. - */ - get plugins() { - return new PluginArray([]); - } - /** - * Sends an HTTP POST request containing a small amount of data to a web server. - * - * @param url URL. - * @param data Data. - * @returns "true" if the user agent successfully queued the data for transfer. Otherwise, it returns "false". - */ - sendBeacon(url2, data2) { - this.#window.fetch(url2, { - method: "POST", - body: data2 - }); - return true; - } - /** - * Returns the object as a string. - * - * @returns String. - */ - toString() { - return "[object Navigator]"; - } - }; - } -}); - -// node_modules/happy-dom/lib/navigator/Plugin.js -var Plugin; -var init_Plugin = __esm({ - "node_modules/happy-dom/lib/navigator/Plugin.js"() { - Plugin = class { - length = 0; - description; - filename; - name; - /** - * Constructor. - * - * @param mimeTypes Mime types. - * @param description Description. - * @param filename Filename. - * @param name Name. - */ - constructor(mimeTypes, description, filename, name2) { - this.description = description; - this.filename = filename; - this.name = name2; - for (let i = 0, max = mimeTypes.length; i < max; i++) { - this[i] = mimeTypes[i]; - this[mimeTypes[i].type] = mimeTypes[i]; - } - this.length = mimeTypes.length; - } - /** - * Item. - * - * @param index Number. - * @returns IMimeType. - */ - item(index) { - return this[index] || null; - } - /** - * NamedItem. - * - * @param name String. - * @returns IMimeType. - */ - namedItem(name2) { - return this[name2] || null; - } - /** - * Returns the object as a string. - * - * @returns String. - */ - toString() { - return "[object Plugin]"; - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/node/NodeDocumentPositionEnum.js -var NodeDocumentPositionEnum, NodeDocumentPositionEnum_default; -var init_NodeDocumentPositionEnum = __esm({ - "node_modules/happy-dom/lib/nodes/node/NodeDocumentPositionEnum.js"() { - (function(NodeDocumentPositionEnum2) { - NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["disconnect"] = 1] = "disconnect"; - NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["preceding"] = 2] = "preceding"; - NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["following"] = 4] = "following"; - NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["contains"] = 8] = "contains"; - NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["containedBy"] = 16] = "containedBy"; - NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["implementationSpecific"] = 32] = "implementationSpecific"; - })(NodeDocumentPositionEnum || (NodeDocumentPositionEnum = {})); - NodeDocumentPositionEnum_default = NodeDocumentPositionEnum; - } -}); - -// node_modules/happy-dom/lib/nodes/node/NodeUtility.js -var NodeUtility; -var init_NodeUtility = __esm({ - "node_modules/happy-dom/lib/nodes/node/NodeUtility.js"() { - init_PropertySymbol(); - init_NodeTypeEnum(); - NodeUtility = class _NodeUtility { - /** - * Returns whether the passed node is a text node, and narrows its type. - * - * @param node The node to be tested. - * @returns "true" if the node is a text node. - */ - static isTextNode(node) { - return node?.[nodeType] === NodeTypeEnum_default.textNode; - } - /** - * Returns boolean indicating if "ancestorNode" is an inclusive ancestor of "referenceNode". - * - * Based on: - * https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/helpers/node.js - * - * @see https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor - * @param ancestorNode Ancestor node. - * @param referenceNode Reference node. - * @param [includeShadowRoots = false] Include shadow roots. - * @returns "true" if inclusive ancestor. - */ - static isInclusiveAncestor(ancestorNode, referenceNode, includeShadowRoots = false) { - if (ancestorNode === null || referenceNode === null) { - return false; - } - if (ancestorNode === referenceNode) { - return true; - } - if (!ancestorNode[nodeArray].length) { - return false; - } - if (includeShadowRoots && referenceNode[isConnected] !== ancestorNode[isConnected]) { - return false; - } - if (includeShadowRoots && ancestorNode === referenceNode[ownerDocument] && referenceNode[isConnected]) { - return true; - } - let parent2 = referenceNode[parentNode]; - while (parent2) { - if (ancestorNode === parent2) { - return true; - } - if (ancestorNode[parentNode] === parent2[parentNode]) { - return false; - } - parent2 = parent2[parentNode] ? parent2[parentNode] : includeShadowRoots && parent2.host ? parent2.host : null; - } - return false; - } - /** - * Returns boolean indicating if nodeB is following nodeA in the document tree. - * - * Based on: - * https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/helpers/node.js - * - * @see https://dom.spec.whatwg.org/#concept-tree-following - * @param nodeA Node A. - * @param nodeB Node B. - * @returns "true" if following. - */ - static isFollowing(nodeA, nodeB) { - if (nodeA === nodeB) { - return false; - } - let current = nodeB; - while (current) { - current = this.following(current); - if (current === nodeA) { - return true; - } - } - return false; - } - /** - * Node length. - * - * Based on: - * https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/helpers/node.js - * - * @see https://dom.spec.whatwg.org/#concept-node-length - * @param node Node. - * @returns Node length. - */ - static getNodeLength(node) { - switch (node[nodeType]) { - case NodeTypeEnum_default.documentTypeNode: - return 0; - case NodeTypeEnum_default.textNode: - case NodeTypeEnum_default.processingInstructionNode: - case NodeTypeEnum_default.commentNode: - return node.data.length; - default: - return node[nodeArray].length; - } - } - /** - * Returns boolean indicating if nodeB is following nodeA in the document tree. - * - * Based on: - * https://github.com/jsdom/js-symbol-tree/blob/master/lib/SymbolTree.js#L220 - * - * @param node Node. - * @param [root] Root. - * @returns Following node. - */ - static following(node, root2) { - const firstChild = node.firstChild; - if (firstChild) { - return firstChild; - } - let current = node; - while (current) { - if (current === root2) { - return null; - } - const nextSibling = current.nextSibling; - if (nextSibling) { - return nextSibling; - } - current = current[parentNode]; - } - return null; - } - /** - * Returns the next sibling or parents sibling. - * - * @param node Node. - * @returns Next descendant node. - */ - static nextDescendantNode(node) { - while (node && !node.nextSibling) { - node = node[parentNode]; - } - if (!node) { - return null; - } - return node.nextSibling; - } - /** - * Needed by https://dom.spec.whatwg.org/#concept-node-equals - * - * @param elementA - * @param elementB - */ - static attributeListsEqual(elementA, elementB) { - const attributesA = Array.from(elementA[attributes][items].values()); - const attributesB = Array.from(elementB[attributes][items].values()); - for (const attributeA of attributesA) { - let found = false; - for (const attributeB of attributesB) { - if (attributeA[namespaceURI] === attributeB[namespaceURI] && attributeA.localName === attributeB.localName && attributeA[value] === attributeB[value]) { - found = true; - break; - } - } - if (!found) { - return false; - } - } - return true; - } - /** - * Check if node nodeA equals node nodeB. - * Reference: https://dom.spec.whatwg.org/#concept-node-equals - * - * @param nodeA Node A. - * @param nodeB Node B. - */ - static isEqualNode(nodeA, nodeB) { - if (nodeA[nodeType] !== nodeB[nodeType]) { - return false; - } - switch (nodeA[nodeType]) { - case NodeTypeEnum_default.documentTypeNode: - const documentTypeA = nodeA; - const documentTypeB = nodeB; - if (documentTypeA.name !== documentTypeB.name || documentTypeA.publicId !== documentTypeB.publicId || documentTypeA.systemId !== documentTypeB.systemId) { - return false; - } - break; - case NodeTypeEnum_default.elementNode: - const elementA = nodeA; - const elementB = nodeB; - if (elementA[namespaceURI] !== elementB[namespaceURI] || elementA[prefix] !== elementB[prefix] || elementA[localName] !== elementB[localName] || elementA[attributes][items].size !== elementB[attributes][items].size) { - return false; - } - break; - case NodeTypeEnum_default.attributeNode: - const attributeA = nodeA; - const attributeB = nodeB; - if (attributeA[namespaceURI] !== attributeB[namespaceURI] || attributeA.localName !== attributeB.localName || attributeA[value] !== attributeB[value]) { - return false; - } - break; - case NodeTypeEnum_default.processingInstructionNode: - const processingInstructionA = nodeA; - const processingInstructionB = nodeB; - if (processingInstructionA.target !== processingInstructionB.target || processingInstructionA.data !== processingInstructionB.data) { - return false; - } - break; - case NodeTypeEnum_default.textNode: - case NodeTypeEnum_default.commentNode: - const textOrCommentA = nodeA; - const textOrCommentB = nodeB; - if (textOrCommentA.data !== textOrCommentB.data) { - return false; - } - break; - } - if (nodeA[nodeType] === NodeTypeEnum_default.elementNode && !_NodeUtility.attributeListsEqual(nodeA, nodeB)) { - return false; - } - if (nodeA[nodeArray].length !== nodeB[nodeArray].length) { - return false; - } - for (let i = 0; i < nodeA[nodeArray].length; i++) { - const childNodeA = nodeA[nodeArray][i]; - const childNodeB = nodeB[nodeArray][i]; - if (!_NodeUtility.isEqualNode(childNodeA, childNodeB)) { - return false; - } - } - return true; - } - }; - } -}); - -// node_modules/happy-dom/lib/mutation-observer/MutationTypeEnum.js -var MutationTypeEnum, MutationTypeEnum_default; -var init_MutationTypeEnum = __esm({ - "node_modules/happy-dom/lib/mutation-observer/MutationTypeEnum.js"() { - (function(MutationTypeEnum2) { - MutationTypeEnum2["attributes"] = "attributes"; - MutationTypeEnum2["characterData"] = "characterData"; - MutationTypeEnum2["childList"] = "childList"; - })(MutationTypeEnum || (MutationTypeEnum = {})); - MutationTypeEnum_default = MutationTypeEnum; - } -}); - -// node_modules/happy-dom/lib/nodes/NodeFactory.js -var NodeFactory; -var init_NodeFactory = __esm({ - "node_modules/happy-dom/lib/nodes/NodeFactory.js"() { - init_PropertySymbol(); - NodeFactory = class { - static ownerDocuments = []; - /** - * Creates a node instance with the given owner document. - * - * @param ownerDocument Owner document. - * @param nodeClass Node class. - * @param [args] Node arguments. - * @returns Node instance. - */ - static createNode(ownerDocument2, nodeClass, ...args) { - if (!nodeClass.prototype[window]) { - this.ownerDocuments.push(ownerDocument2); - } - return new nodeClass(...args); - } - /** - * Pulls an owner document from the queue. - * - * @returns Document. - */ - static pullOwnerDocument() { - return this.ownerDocuments.pop() || null; - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/node/Node.js -var Node; -var init_Node = __esm({ - "node_modules/happy-dom/lib/nodes/node/Node.js"() { - init_EventTarget(); - init_PropertySymbol(); - init_NodeTypeEnum(); - init_NodeDocumentPositionEnum(); - init_NodeUtility(); - init_NodeList(); - init_MutationRecord(); - init_MutationTypeEnum(); - init_DOMExceptionNameEnum(); - init_NodeFactory(); - Node = class _Node extends EventTarget2 { - // Public properties - static ELEMENT_NODE = NodeTypeEnum_default.elementNode; - static ATTRIBUTE_NODE = NodeTypeEnum_default.attributeNode; - static TEXT_NODE = NodeTypeEnum_default.textNode; - static CDATA_SECTION_NODE = NodeTypeEnum_default.cdataSectionNode; - static COMMENT_NODE = NodeTypeEnum_default.commentNode; - static DOCUMENT_NODE = NodeTypeEnum_default.documentNode; - static DOCUMENT_TYPE_NODE = NodeTypeEnum_default.documentTypeNode; - static DOCUMENT_FRAGMENT_NODE = NodeTypeEnum_default.documentFragmentNode; - static PROCESSING_INSTRUCTION_NODE = NodeTypeEnum_default.processingInstructionNode; - static DOCUMENT_POSITION_CONTAINED_BY = NodeDocumentPositionEnum_default.containedBy; - static DOCUMENT_POSITION_CONTAINS = NodeDocumentPositionEnum_default.contains; - static DOCUMENT_POSITION_DISCONNECTED = NodeDocumentPositionEnum_default.disconnect; - static DOCUMENT_POSITION_FOLLOWING = NodeDocumentPositionEnum_default.following; - static DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = NodeDocumentPositionEnum_default.implementationSpecific; - static DOCUMENT_POSITION_PRECEDING = NodeDocumentPositionEnum_default.preceding; - // Internal properties - [isConnected] = false; - [parentNode] = null; - [rootNode] = null; - [styleNode] = null; - [textAreaNode] = null; - [formNode] = null; - [selectNode] = null; - [mutationListeners] = []; - [nodeArray] = []; - [elementArray] = []; - [childNodes] = null; - [assignedToSlot] = null; - [cache] = { - querySelector: /* @__PURE__ */ new Map(), - querySelectorAll: /* @__PURE__ */ new Map(), - matches: /* @__PURE__ */ new Map(), - elementsByTagName: /* @__PURE__ */ new Map(), - elementsByTagNameNS: /* @__PURE__ */ new Map(), - elementByTagName: /* @__PURE__ */ new Map(), - elementById: /* @__PURE__ */ new Map(), - computedStyle: null - }; - [affectsCache] = []; - /** - * Constructor. - */ - constructor() { - super(); - if (this[window]) { - this[ownerDocument] = this[window].document; - } else { - const ownerDocument2 = NodeFactory.pullOwnerDocument(); - if (!ownerDocument2) { - throw new TypeError("Illegal constructor"); - } - this[ownerDocument] = ownerDocument2; - this[window] = ownerDocument2[window]; - } - } - /** - * Returns `Symbol.toStringTag`. - * - * @returns `Symbol.toStringTag`. - */ - get [Symbol.toStringTag]() { - return this.constructor.name; - } - /** - * Returns connected state. - * - * @returns Connected state. - */ - get isConnected() { - return this[isConnected]; - } - /** - * Returns owner document. - * - * @returns Owner document. - */ - get ownerDocument() { - return this[ownerDocument]; - } - /** - * Returns parent node. - * - * @returns Parent node. - */ - get parentNode() { - return this[parentNode]; - } - /** - * Returns node type. - * - * @returns Node type. - */ - get nodeType() { - return this[nodeType]; - } - /** - * Get child nodes. - * - * @returns Child nodes list. - */ - get childNodes() { - if (!this[childNodes]) { - this[childNodes] = new NodeList_default(illegalConstructor, this[nodeArray]); - } - return this[childNodes]; - } - /** - * Get text value of children. - * - * @returns Text content. - */ - get textContent() { - return ""; - } - /** - * Sets text content. - * - * @param _textContent Text content. - */ - set textContent(_textContent) { - } - /** - * Node value. - * - * @returns Node value. - */ - get nodeValue() { - return null; - } - /** - * Sets node value. - */ - set nodeValue(_nodeValue) { - } - /** - * Node name. - * - * @returns Node name. - */ - get nodeName() { - return ""; - } - /** - * Previous sibling. - * - * @returns Node. - */ - get previousSibling() { - if (this[parentNode]) { - const nodeArray2 = this[parentNode][nodeArray]; - const index = nodeArray2.indexOf(this[proxy] || this); - if (index > 0) { - return nodeArray2[index - 1]; - } - } - return null; - } - /** - * Next sibling. - * - * @returns Node. - */ - get nextSibling() { - if (this[parentNode]) { - const nodeArray2 = this[parentNode][nodeArray]; - const index = nodeArray2.indexOf(this[proxy] || this); - if (index > -1 && index + 1 < nodeArray2.length) { - return nodeArray2[index + 1]; - } - } - return null; - } - /** - * First child. - * - * @returns Node. - */ - get firstChild() { - const nodeArray2 = this[nodeArray]; - if (nodeArray2.length > 0) { - return nodeArray2[0]; - } - return null; - } - /** - * Last child. - * - * @returns Node. - */ - get lastChild() { - const nodeArray2 = this[nodeArray]; - if (nodeArray2.length > 0) { - return nodeArray2[nodeArray2.length - 1]; - } - return null; - } - /** - * Returns parent element. - * - * @returns Element. - */ - get parentElement() { - let parent2 = this[parentNode]; - while (parent2 && parent2[nodeType] !== NodeTypeEnum_default.elementNode) { - parent2 = parent2[parentNode]; - } - return parent2; - } - /** - * Returns base URI. - * - * @returns Base URI. - */ - get baseURI() { - const base = this[ownerDocument].querySelector("base"); - if (base) { - return base.href; - } - return this[window].location.href; - } - /** - * Returns "true" if the node has child nodes. - * - * @returns "true" if the node has child nodes. - */ - hasChildNodes() { - return this[nodeArray].length > 0; - } - /** - * Returns "true" if this node contains the other node. - * - * @param otherNode Node to test with. - * @returns "true" if this node contains the other node. - */ - contains(otherNode) { - if (otherNode === void 0) { - return false; - } - const self2 = this[proxy] || this; - return NodeUtility.isInclusiveAncestor(self2, otherNode); - } - /** - * Returns closest root node (Document or ShadowRoot). - * - * @param options Options. - * @param options.composed A Boolean that indicates whether the shadow root should be returned (false, the default), or a root node beyond shadow root (true). - * @returns Node. - */ - getRootNode(options2) { - if (this[isConnected]) { - if (this[rootNode] && !options2?.composed) { - return this[rootNode]; - } - return this[ownerDocument]; - } - let root2 = this; - while (root2[parentNode]) { - root2 = root2[parentNode]; - } - return root2; - } - /** - * Clones a node. - * - * @param [deep=false] "true" to clone deep. - * @returns Cloned node. - */ - cloneNode(deep = false) { - return this[cloneNode](deep); - } - /** - * Append a child node to childNodes. - * - * @param node Node to append. - * @returns Appended node. - */ - appendChild(node) { - if (arguments.length < 1) { - throw new this[window].TypeError(`Failed to execute 'appendChild' on 'Node': 1 argument required, but only 0 present`); - } - return this[appendChild](node); - } - /** - * Remove Child element from childNodes array. - * - * @param node Node to remove. - * @returns Removed node. - */ - removeChild(node) { - if (arguments.length < 1) { - throw new this[window].TypeError(`Failed to execute 'removeChild' on 'Node': 1 argument required, but only 0 present`); - } - return this[removeChild](node); - } - /** - * Inserts a node before another. - * - * @param newNode Node to insert. - * @param referenceNode Node to insert before. - * @returns Inserted node. - */ - insertBefore(newNode, referenceNode) { - if (arguments.length < 2) { - throw new this[window].TypeError(`Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only ${arguments.length} present.`); - } - return this[insertBefore](newNode, referenceNode); - } - /** - * Replaces a node with another. - * - * @param newChild New child. - * @param oldChild Old child. - * @returns Replaced node. - */ - replaceChild(newChild, oldChild) { - if (arguments.length < 2) { - throw new this[window].TypeError(`Failed to execute 'replaceChild' on 'Node': 2 arguments required, but only ${arguments.length} present.`); - } - return this[replaceChild](newChild, oldChild); - } - /** - * Clones a node. - * - * @param [deep=false] "true" to clone deep. - * @returns Cloned node. - */ - [cloneNode](deep = false) { - const clone2 = NodeFactory.createNode(this[ownerDocument], this.constructor); - if (clone2[nodeArray].length) { - const childNodes2 = clone2[nodeArray]; - while (childNodes2.length) { - clone2.removeChild(childNodes2[0]); - } - } - if (deep) { - for (const childNode of this[nodeArray]) { - const childClone = childNode.cloneNode(true); - childClone[parentNode] = clone2; - clone2[nodeArray].push(childClone); - if (childClone[nodeType] === NodeTypeEnum_default.elementNode) { - clone2[elementArray].push(childClone); - } - } - } - return clone2; - } - /** - * Append a child node to childNodes. - * - * @param node Node to append. - * @param [disableValidations=false] "true" to disable validations. - * @returns Appended node. - */ - [appendChild](node, disableValidations = false) { - if (node[proxy]) { - node = node[proxy]; - } - const self2 = this[proxy] || this; - if (!disableValidations) { - if (node === self2) { - throw new this[window].DOMException("Failed to execute 'appendChild' on 'Node': Not possible to append a node as a child of itself."); - } - if (NodeUtility.isInclusiveAncestor(node, self2, true)) { - throw new this[window].DOMException("Failed to execute 'appendChild' on 'Node': The new node is a parent of the node to insert to.", DOMExceptionNameEnum_default.domException); - } - } - if (node[nodeType] === NodeTypeEnum_default.documentFragmentNode) { - const childNodes2 = node[nodeArray]; - while (childNodes2.length) { - this.appendChild(childNodes2[0]); - } - return node; - } - if (node[parentNode]) { - node[parentNode][removeChild](node); - } - node[parentNode] = self2; - node[clearCache](); - this[nodeArray].push(node); - if (node[nodeType] === NodeTypeEnum_default.elementNode) { - this[elementArray].push(node); - } - node[connectedToNode](); - for (const mutationListener of this[mutationListeners]) { - if (mutationListener.options?.subtree && mutationListener.callback.deref()) { - node[observeMutations](mutationListener); - } - } - this[reportMutation](new MutationRecord({ - target: self2, - type: MutationTypeEnum_default.childList, - addedNodes: [node] - })); - return node; - } - /** - * Remove Child element from childNodes array. - * - * @param node Node to remove. - * @returns Removed node. - */ - [removeChild](node) { - if (node[proxy]) { - node = node[proxy]; - } - const index = this[nodeArray].indexOf(node); - if (index === -1) { - throw new this[window].DOMException(`Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.`); - } - const previousSibling = node.previousSibling; - const nextSibling = node.nextSibling; - node[parentNode] = null; - node[clearCache](); - this[nodeArray].splice(index, 1); - if (node[nodeType] === NodeTypeEnum_default.elementNode) { - const index2 = this[elementArray].indexOf(node); - if (index2 !== -1) { - this[elementArray].splice(index2, 1); - } - } - if (node[assignedToSlot]) { - const index2 = node[assignedToSlot][assignedNodes].indexOf(node); - if (index2 !== -1) { - node[assignedToSlot][assignedNodes].splice(index2, 1); - } - node[assignedToSlot] = null; - } - node[disconnectedFromNode](); - for (const mutationListener of this[mutationListeners]) { - if (mutationListener.options?.subtree && mutationListener.callback.deref()) { - node[unobserveMutations](mutationListener); - } - } - this[reportMutation](new MutationRecord({ - target: this[proxy] || this, - type: MutationTypeEnum_default.childList, - removedNodes: [node], - previousSibling, - nextSibling - })); - return node; - } - /** - * Inserts a node before another. - * - * @param newNode Node to insert. - * @param referenceNode Node to insert before. - * @param [disableValidations=false] "true" to disable validations. - * @returns Inserted node. - */ - [insertBefore](newNode, referenceNode, disableValidations = false) { - if (newNode[proxy]) { - newNode = newNode[proxy]; - } - if (referenceNode && referenceNode[proxy]) { - referenceNode = referenceNode[proxy]; - } - if (newNode === referenceNode) { - return newNode; - } - const self2 = this[proxy] || this; - if (!disableValidations) { - if (newNode === self2) { - throw new this[window].DOMException("Failed to execute 'insertBefore' on 'Node': Not possible to insert a node as a child of itself."); - } - if (NodeUtility.isInclusiveAncestor(newNode, self2, true)) { - throw new this[window].DOMException("Failed to execute 'insertBefore' on 'Node': The new node is a parent of the node to insert to.", DOMExceptionNameEnum_default.domException); - } - } - if (newNode[nodeType] === NodeTypeEnum_default.documentFragmentNode) { - const childNodes2 = newNode[nodeArray]; - while (childNodes2.length > 0) { - this[insertBefore](childNodes2[0], referenceNode, true); - } - return newNode; - } - if (!referenceNode) { - this[appendChild](newNode, true); - return newNode; - } - const nodeArray2 = this[nodeArray]; - if (!nodeArray2.includes(referenceNode)) { - throw new this[window].DOMException("Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node."); - } - if (newNode[parentNode]) { - newNode[parentNode][removeChild](newNode); - } - newNode[parentNode] = self2; - newNode[clearCache](); - const index = nodeArray2.indexOf(referenceNode); - if (newNode[nodeType] === NodeTypeEnum_default.elementNode) { - const elementArray2 = this[elementArray]; - if (referenceNode[nodeType] === NodeTypeEnum_default.elementNode) { - elementArray2.splice(elementArray2.indexOf(referenceNode), 0, newNode); - } else { - let isInserted = false; - for (let i = index, max = nodeArray2.length; i < max; i++) { - if (nodeArray2[i][nodeType] === NodeTypeEnum_default.elementNode) { - elementArray2.splice(elementArray2.indexOf(nodeArray2[i]), 0, newNode); - isInserted = true; - break; - } - } - if (!isInserted) { - elementArray2.push(newNode); - } - } - } - nodeArray2.splice(index, 0, newNode); - newNode[connectedToNode](); - for (const mutationListener of this[mutationListeners]) { - if (mutationListener.options?.subtree && mutationListener.callback.deref()) { - newNode[observeMutations](mutationListener); - } - } - this[reportMutation](new MutationRecord({ - target: self2, - type: MutationTypeEnum_default.childList, - addedNodes: [newNode] - })); - return newNode; - } - /** - * Replaces a node with another. - * - * @param newChild New child. - * @param oldChild Old child. - * @returns Replaced node. - */ - [replaceChild](newChild, oldChild) { - this.insertBefore(newChild, oldChild); - this.removeChild(oldChild); - return oldChild; - } - /** - * Compares two nodes. - * Two nodes are equal if they have the same type, defining the same attributes, and so on. - * - * @param node Node to compare. - * @returns boolean - `true` if two nodes are equal. - */ - isEqualNode(node) { - return NodeUtility.isEqualNode(this, node); - } - /** - * Converts the node to a string. - * - * @param listener Listener. - */ - toString() { - return `[object ${this.constructor.name}]`; - } - /** - * Observeres mutations on the node. - * - * Used by MutationObserver and internal logic. - * - * @param listener Listener. - */ - [observeMutations](listener) { - this[mutationListeners].push(listener); - if (listener.options.subtree) { - for (const node of this[nodeArray]) { - node[observeMutations](listener); - } - } - } - /** - * Stops observing mutations on the node. - * - * Used by MutationObserver and internal logic. - * - * @param listener Listener. - */ - [unobserveMutations](listener) { - const index = this[mutationListeners].indexOf(listener); - if (index !== -1) { - this[mutationListeners].splice(index, 1); - } - if (listener.options.subtree) { - for (const node of this[nodeArray]) { - node[unobserveMutations](listener); - } - } - } - /** - * Reports a mutation on the node. - * - * Used by MutationObserver and internal logic. - * - * @param record Mutation record. - */ - [reportMutation](record) { - this[clearCache](); - const mutationListeners2 = this[mutationListeners]; - if (!mutationListeners2.length) { - return; - } - for (let i = 0, max = mutationListeners2.length; i < max; i++) { - const mutationListener = mutationListeners2[i]; - const callback = mutationListener.callback.deref(); - if (callback) { - switch (record.type) { - case MutationTypeEnum_default.childList: - if (mutationListener.options.childList) { - callback(record); - } - break; - case MutationTypeEnum_default.attributes: - if (mutationListener.options.attributes && (!mutationListener.options.attributeFilter || mutationListener.options.attributeFilter.includes(record.attributeName))) { - callback(record); - } - break; - case MutationTypeEnum_default.characterData: - if (mutationListener.options?.characterData) { - callback(record); - } - break; - } - } else { - mutationListeners2.splice(i, 1); - i--; - max--; - } - } - } - /** - * Clears query selector cache. - */ - [clearCache]() { - const cache2 = this[cache]; - if (cache2.querySelector.size) { - for (const item of cache2.querySelector.values()) { - if (item.result) { - item.result = null; - } - } - cache2.querySelector = /* @__PURE__ */ new Map(); - } - if (cache2.querySelectorAll.size) { - for (const item of cache2.querySelectorAll.values()) { - if (item.result) { - item.result = null; - } - } - cache2.querySelectorAll = /* @__PURE__ */ new Map(); - } - if (cache2.matches.size) { - for (const item of cache2.matches.values()) { - if (item.result) { - item.result = null; - } - } - cache2.matches = /* @__PURE__ */ new Map(); - } - if (cache2.elementsByTagName.size) { - for (const item of cache2.elementsByTagName.values()) { - if (item.result) { - item.result = null; - } - } - cache2.elementsByTagName = /* @__PURE__ */ new Map(); - } - if (cache2.elementsByTagNameNS.size) { - for (const item of cache2.elementsByTagNameNS.values()) { - if (item.result) { - item.result = null; - } - } - cache2.elementsByTagNameNS = /* @__PURE__ */ new Map(); - } - if (cache2.elementByTagName.size) { - for (const item of cache2.elementByTagName.values()) { - if (item.result) { - item.result = null; - } - } - cache2.elementByTagName = /* @__PURE__ */ new Map(); - } - if (cache2.elementById.size) { - for (const item of cache2.elementById.values()) { - if (item.result) { - item.result = null; - } - } - cache2.elementById = /* @__PURE__ */ new Map(); - } - const affectsCache2 = this[affectsCache]; - if (affectsCache2.length) { - for (const item of affectsCache2) { - item.result = null; - } - this[affectsCache] = []; - } - const document = this[ownerDocument]; - if (document && document[affectsComputedStyleCache].length) { - for (const item of document[affectsComputedStyleCache]) { - item.result = null; - } - document[affectsComputedStyleCache] = []; - } - } - /** - * Called when connected to a node. - */ - [connectedToNode]() { - const parentNode2 = this[parentNode]; - const parent2 = parentNode2 || this[host]; - let isConnected2 = false; - let isDisconnected = false; - if (!this[isConnected] && parent2[isConnected]) { - this[isConnected] = true; - isConnected2 = true; - } else if (this[isConnected] && !parent2[isConnected]) { - this[isConnected] = false; - isDisconnected = true; - } - this[ownerDocument] = parent2[ownerDocument] || parent2; - this[window] = parent2[window] || parent2[defaultView]; - if (parentNode2) { - if (this[nodeType] !== NodeTypeEnum_default.documentFragmentNode) { - this[rootNode] = parentNode2[rootNode]; - } - const tagName2 = this[tagName]; - if (parentNode2[styleNode] && tagName2 !== "STYLE") { - this[styleNode] = parentNode2[styleNode]; - } - if (parentNode2[textAreaNode] && tagName2 !== "TEXTAREA") { - this[textAreaNode] = parentNode2[textAreaNode]; - } - if (parentNode2[formNode] && tagName2 !== "FORM") { - this[formNode] = parentNode2[formNode]; - } - if (parentNode2[selectNode] && tagName2 !== "SELECT") { - this[selectNode] = parentNode2[selectNode]; - } - } - const childNodes2 = this[nodeArray].slice(); - for (let i = 0, max = childNodes2.length; i < max; i++) { - childNodes2[i][parentNode] = this; - childNodes2[i][connectedToNode](); - } - if (this[shadowRoot]) { - this[shadowRoot][connectedToNode](); - } - if (isConnected2) { - this[connectedToDocument](); - } else if (isDisconnected) { - this[disconnectedFromDocument](); - } - } - /** - * Called when disconnected from a node. - */ - [disconnectedFromNode]() { - if (this[nodeType] !== NodeTypeEnum_default.documentFragmentNode) { - this[rootNode] = null; - } - const tagName2 = this[tagName]; - if (tagName2 !== "STYLE") { - this[styleNode] = null; - } - if (tagName2 !== "TEXTAREA") { - this[textAreaNode] = null; - } - if (tagName2 !== "FORM") { - this[formNode] = null; - } - if (tagName2 !== "SELECT") { - this[selectNode] = null; - } - if (this[isConnected]) { - this[isConnected] = false; - this[disconnectedFromDocument](); - } - const childNodes2 = this[nodeArray].slice(); - for (let i = 0, max = childNodes2.length; i < max; i++) { - childNodes2[i][connectedToNode](); - } - if (this[shadowRoot]) { - this[shadowRoot][disconnectedFromNode](); - } - } - /** - * Called when connected to document. - */ - [connectedToDocument]() { - if (this[shadowRoot]) { - this[shadowRoot][connectedToDocument](); - } - } - /** - * Called when disconnected from document. - */ - [disconnectedFromDocument]() { - if (this[ownerDocument][activeElement] === this) { - this[ownerDocument][clearCache](); - this[ownerDocument][activeElement] = null; - } - if (this[shadowRoot]) { - this[shadowRoot][disconnectedFromDocument](); - } - } - /** - * @override - */ - [destroy]() { - super[destroy](); - this[isConnected] = false; - for (let i = 0, max = this[nodeArray].length; i < max; i++) { - this[nodeArray][i][destroy](); - } - this[mutationListeners] = []; - this[parentNode] = null; - this[rootNode] = null; - this[styleNode] = null; - this[textAreaNode] = null; - this[formNode] = null; - this[selectNode] = null; - this[mutationListeners] = []; - this[nodeArray] = []; - this[elementArray] = []; - this[childNodes] = null; - this[assignedToSlot] = null; - this[clearCache](); - } - /** - * Reports the position of its argument node relative to the node on which it is called. - * - * @see https://dom.spec.whatwg.org/#dom-node-comparedocumentposition - * @param otherNode Other node. - */ - compareDocumentPosition(otherNode) { - if (this === otherNode) { - return 0; - } - let node1 = otherNode; - let node2 = this[proxy] || this; - let attr1 = null; - let attr2 = null; - if (node1[nodeType] === NodeTypeEnum_default.attributeNode) { - attr1 = node1; - node1 = attr1[ownerElement]; - } - if (node2[nodeType] === NodeTypeEnum_default.attributeNode) { - attr2 = node2; - node2 = attr2[ownerElement]; - if (attr1 !== null && node1 !== null && node2 === node1) { - for (const attribute of node2[attributes][items].values()) { - if (NodeUtility.isEqualNode(attribute, attr1)) { - return _Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | _Node.DOCUMENT_POSITION_PRECEDING; - } - if (NodeUtility.isEqualNode(attribute, attr2)) { - return _Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | _Node.DOCUMENT_POSITION_FOLLOWING; - } - } - } - } - const node2Ancestors = []; - let node2Ancestor = node2; - while (node2Ancestor) { - if (node2Ancestor === node1) { - return _Node.DOCUMENT_POSITION_CONTAINS | _Node.DOCUMENT_POSITION_PRECEDING; - } - node2Ancestors.push(node2Ancestor); - node2Ancestor = node2Ancestor[parentNode]; - } - const node1Ancestors = []; - let node1Ancestor = node1; - while (node1Ancestor) { - if (node1Ancestor === node2) { - return _Node.DOCUMENT_POSITION_CONTAINED_BY | _Node.DOCUMENT_POSITION_FOLLOWING; - } - node1Ancestors.push(node1Ancestor); - node1Ancestor = node1Ancestor[parentNode]; - } - const reverseArrayIndex = (array, reverseIndex) => { - return array[array.length - 1 - reverseIndex]; - }; - const root2 = reverseArrayIndex(node2Ancestors, 0); - if (!root2 || root2 !== reverseArrayIndex(node1Ancestors, 0)) { - return _Node.DOCUMENT_POSITION_DISCONNECTED | _Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | _Node.DOCUMENT_POSITION_FOLLOWING; - } - let commonAncestorIndex = 0; - const ancestorsMinLength = Math.min(node2Ancestors.length, node1Ancestors.length); - for (let i = 0; i < ancestorsMinLength; ++i) { - const node2Ancestor2 = reverseArrayIndex(node2Ancestors, i); - const node1Ancestor2 = reverseArrayIndex(node1Ancestors, i); - if (node2Ancestor2 !== node1Ancestor2) { - break; - } - commonAncestorIndex = i; - } - const commonAncestor = reverseArrayIndex(node2Ancestors, commonAncestorIndex); - let indexes = 0; - let node2Index = -1; - let node1Index = -1; - const node2Node = reverseArrayIndex(node2Ancestors, commonAncestorIndex + 1); - const node1Node = reverseArrayIndex(node1Ancestors, commonAncestorIndex + 1); - const computeNodeIndexes = (nodes) => { - for (const childNode of nodes) { - computeNodeIndexes(childNode[nodeArray]); - if (childNode === node2Node) { - node2Index = indexes; - } else if (childNode === node1Node) { - node1Index = indexes; - } - if (node2Index !== -1 && node1Index !== -1) { - break; - } - indexes++; - } - }; - computeNodeIndexes(commonAncestor[nodeArray]); - return node1Index < node2Index ? _Node.DOCUMENT_POSITION_PRECEDING : _Node.DOCUMENT_POSITION_FOLLOWING; - } - /** - * Normalizes the sub-tree of the node, i.e. joins adjacent text nodes, and - * removes all empty text nodes. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/Node/normalize - */ - normalize() { - let child = this.firstChild; - while (child) { - if (NodeUtility.isTextNode(child)) { - while (NodeUtility.isTextNode(child.nextSibling)) { - child.data += child.nextSibling.data; - child.nextSibling.remove(); - } - if (!child.data.length) { - const node = child; - child = child.nextSibling; - node.remove(); - continue; - } - } else { - child.normalize(); - } - child = child.nextSibling; - } - } - /** - * Determines whether the given node is equal to the current node. - * - * @see https://developer.mozilla.org/en-US/docs/Web/API/Node/isSameNode - * @param node Node to check. - * @returns True if the given node is equal to the current node, otherwise false. - */ - isSameNode(node) { - return this === node; - } - }; - Node.prototype.ELEMENT_NODE = NodeTypeEnum_default.elementNode; - Node.prototype.ATTRIBUTE_NODE = NodeTypeEnum_default.attributeNode; - Node.prototype.TEXT_NODE = NodeTypeEnum_default.textNode; - Node.prototype.CDATA_SECTION_NODE = NodeTypeEnum_default.cdataSectionNode; - Node.prototype.COMMENT_NODE = NodeTypeEnum_default.commentNode; - Node.prototype.DOCUMENT_NODE = NodeTypeEnum_default.documentNode; - Node.prototype.DOCUMENT_TYPE_NODE = NodeTypeEnum_default.documentTypeNode; - Node.prototype.DOCUMENT_FRAGMENT_NODE = NodeTypeEnum_default.documentFragmentNode; - Node.prototype.PROCESSING_INSTRUCTION_NODE = NodeTypeEnum_default.processingInstructionNode; - Node.prototype.DOCUMENT_POSITION_CONTAINED_BY = NodeDocumentPositionEnum_default.containedBy; - Node.prototype.DOCUMENT_POSITION_CONTAINS = NodeDocumentPositionEnum_default.contains; - Node.prototype.DOCUMENT_POSITION_DISCONNECTED = NodeDocumentPositionEnum_default.disconnect; - Node.prototype.DOCUMENT_POSITION_FOLLOWING = NodeDocumentPositionEnum_default.following; - Node.prototype.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = NodeDocumentPositionEnum_default.implementationSpecific; - Node.prototype.DOCUMENT_POSITION_PRECEDING = NodeDocumentPositionEnum_default.preceding; - } -}); - -// node_modules/happy-dom/lib/nodes/attr/Attr.js -var Attr; -var init_Attr = __esm({ - "node_modules/happy-dom/lib/nodes/attr/Attr.js"() { - init_Node(); - init_PropertySymbol(); - init_NodeTypeEnum(); - Attr = class extends Node { - [nodeType] = NodeTypeEnum_default.attributeNode; - [namespaceURI] = null; - [name] = null; - [localName] = null; - [prefix] = null; - [value] = null; - [specified] = true; - [ownerElement] = null; - /** - * Returns specified. - * - * @deprecated - * @returns Specified. - */ - get specified() { - return this[specified]; - } - /** - * Returns owner element. - * - * @returns Owner element. - */ - get ownerElement() { - return this[ownerElement]; - } - /** - * Returns value. - * - * @returns Value. - */ - get value() { - return this[value]; - } - /** - * Sets value. - * - * @param value Value. - */ - set value(value2) { - this[value] = value2; - } - /** - * Returns name. - * - * @returns Name. - */ - get name() { - return this[name] || ""; - } - /** - * Returns local name. - * - * @returns Local name. - */ - get localName() { - return this[localName] || ""; - } - /** - * Returns prefix. - * - * @returns Prefix. - */ - get prefix() { - return this[prefix]; - } - /** - * @override - */ - get textContent() { - return this[value] || ""; - } - /** - * Returns namespace URI. - * - * @returns Namespace URI. - */ - get namespaceURI() { - return this[namespaceURI]; - } - /** - * @override - */ - [cloneNode](deep = false) { - const clone2 = super[cloneNode](deep); - clone2[namespaceURI] = this[namespaceURI]; - clone2[name] = this[name]; - clone2[localName] = this[localName]; - clone2[prefix] = this[prefix]; - clone2[value] = this[value]; - clone2[specified] = this[specified]; - return clone2; - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/character-data/CharacterDataUtility.js -var CharacterDataUtility; -var init_CharacterDataUtility = __esm({ - "node_modules/happy-dom/lib/nodes/character-data/CharacterDataUtility.js"() { - CharacterDataUtility = class { - /** - * Appends the given DOMString to the CharacterData.data string; when this method returns, data contains the concatenated DOMString. - * - * @param characterData Character data. - * @param data Data. - */ - static appendData(characterData, data2) { - characterData.data += data2; - } - /** - * Removes the specified amount of characters, starting at the specified offset, from the CharacterData.data string; when this method returns, data contains the shortened DOMString. - * - * @param characterData Character data. - * @param offset Offset. - * @param count Count. - */ - static deleteData(characterData, offset2, count) { - characterData.data = characterData.data.substring(0, offset2) + characterData.data.substring(offset2 + count); - } - /** - * Inserts the specified characters, at the specified offset, in the CharacterData.data string; when this method returns, data contains the modified DOMString. - * - * @param characterData Character data. - * @param offset Offset. - * @param data Data. - */ - static insertData(characterData, offset2, data2) { - characterData.data = characterData.data.substring(0, offset2) + data2 + characterData.data.substring(offset2); - } - /** - * Replaces the specified amount of characters, starting at the specified offset, with the specified DOMString; when this method returns, data contains the modified DOMString. - * - * @param characterData Character data. - * @param offset Offset. - * @param count Count. - * @param data Data. - */ - static replaceData(characterData, offset2, count, data2) { - characterData.data = characterData.data.substring(0, offset2) + data2 + characterData.data.substring(offset2 + count); - } - /** - * Returns a DOMString containing the part of CharacterData.data of the specified length and starting at the specified offset. - * - * @param characterData Character data. - * @param offset Offset. - * @param count Count. - */ - static substringData(characterData, offset2, count) { - return characterData.data.substring(offset2, offset2 + count); - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/child-node/NonDocumentChildNodeUtility.js -var NonDocumentChildNodeUtility; -var init_NonDocumentChildNodeUtility = __esm({ - "node_modules/happy-dom/lib/nodes/child-node/NonDocumentChildNodeUtility.js"() { - init_NodeTypeEnum(); - init_PropertySymbol(); - NonDocumentChildNodeUtility = class { - /** - * Previous element sibling. - * - * @param childNode Child node. - * @returns Element. - */ - static previousElementSibling(childNode) { - let sibling = childNode.previousSibling; - while (sibling && sibling[nodeType] !== NodeTypeEnum_default.elementNode) { - sibling = sibling.previousSibling; - } - return sibling; - } - /** - * Next element sibling. - * - * @param childNode Child node. - * @returns Element. - */ - static nextElementSibling(childNode) { - let sibling = childNode.nextSibling; - while (sibling && sibling[nodeType] !== NodeTypeEnum_default.elementNode) { - sibling = sibling.nextSibling; - } - return sibling; - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/child-node/ChildNodeUtility.js -var ChildNodeUtility; -var init_ChildNodeUtility = __esm({ - "node_modules/happy-dom/lib/nodes/child-node/ChildNodeUtility.js"() { - init_PropertySymbol(); - init_Node(); - ChildNodeUtility = class { - /** - * Removes the node from its parent. - * - * @param childNode Child node. - */ - static remove(childNode) { - if (childNode[parentNode]) { - childNode[parentNode].removeChild(childNode); - } - } - /** - * The Node.replaceWith() method replaces this Node in the children list of its parent with a set of Node or DOMString objects. - * - * @param childNode Child node. - * @param nodes List of Node or DOMString. - */ - static replaceWith(childNode, ...nodes) { - const parent2 = childNode[parentNode]; - if (!parent2) { - return; - } - for (const node of nodes) { - if (node instanceof Node) { - parent2.insertBefore(node, childNode); - } else { - parent2.insertBefore(parent2[ownerDocument].createTextNode(String(node)), childNode); - } - } - parent2.removeChild(childNode); - } - /** - * Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just before this ChildNode. DOMString objects are inserted as equivalent Text nodes. - * - * @param childNode Child node. - * @param nodes List of Node or DOMString. - */ - static before(childNode, ...nodes) { - const parent2 = childNode[parentNode]; - if (!parent2) { - return; - } - for (const node of nodes) { - if (node instanceof Node) { - parent2.insertBefore(node, childNode); - } else { - parent2.insertBefore(parent2[ownerDocument].createTextNode(String(node)), childNode); - } - } - } - /** - * Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just after this ChildNode. DOMString objects are inserted as equivalent Text nodes. - * - * @param childNode Child node. - * @param nodes List of Node or DOMString. - */ - static after(childNode, ...nodes) { - const parent2 = childNode[parentNode]; - if (!parent2) { - return; - } - const nextSibling = childNode.nextSibling; - for (const node of nodes) { - const insertedNode = node instanceof Node ? node : parent2[ownerDocument].createTextNode(String(node)); - if (!nextSibling) { - parent2.appendChild(insertedNode); - } else { - parent2.insertBefore(insertedNode, nextSibling); - } - } - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/character-data/CharacterData.js -var CharacterData; -var init_CharacterData = __esm({ - "node_modules/happy-dom/lib/nodes/character-data/CharacterData.js"() { - init_Node(); - init_PropertySymbol(); - init_CharacterDataUtility(); - init_NonDocumentChildNodeUtility(); - init_ChildNodeUtility(); - init_MutationRecord(); - init_MutationTypeEnum(); - CharacterData = class extends Node { - [data] = ""; - /** - * Constructor. - * - * @param [data] Data. - */ - constructor(data2) { - super(); - this[data] = data2 !== void 0 ? String(data2) : ""; - } - /** - * Returns text content. - * - * @returns Text content. - */ - get length() { - return this[data].length; - } - /** - * Returns text content. - * - * @returns Text content. - */ - get data() { - return this[data]; - } - /** - * Sets text content. - * - * @param textContent Text content. - */ - set data(data2) { - const oldValue = this[data]; - this[data] = String(data2); - this[reportMutation](new MutationRecord({ - target: this, - type: MutationTypeEnum_default.characterData, - oldValue - })); - } - /** - * Returns text content. - * - * @returns Text content. - */ - get textContent() { - return this[data]; - } - /** - * Sets text content. - * - * @param textContent Text content. - */ - set textContent(textContent) { - this.data = textContent; - } - /** - * Returns node value. - * - * @returns Node value. - */ - get nodeValue() { - return this[data]; - } - /** - * Sets node value. - * - * @param nodeValue Node value. - */ - set nodeValue(nodeValue) { - this.textContent = nodeValue; - } - /** - * Previous element sibling. - * - * @returns Element. - */ - get previousElementSibling() { - return NonDocumentChildNodeUtility.previousElementSibling(this); - } - /** - * Next element sibling. - * - * @returns Element. - */ - get nextElementSibling() { - return NonDocumentChildNodeUtility.nextElementSibling(this); - } - /** - * Appends the given DOMString to the CharacterData.data string; when this method returns, data contains the concatenated DOMString. - * - * @param data Data. - */ - appendData(data2) { - CharacterDataUtility.appendData(this, data2); - } - /** - * Removes the specified amount of characters, starting at the specified offset, from the CharacterData.data string; when this method returns, data contains the shortened DOMString. - * - * @param offset Offset. - * @param count Count. - */ - deleteData(offset2, count) { - CharacterDataUtility.deleteData(this, offset2, count); - } - /** - * Inserts the specified characters, at the specified offset, in the CharacterData.data string; when this method returns, data contains the modified DOMString. - * - * @param offset Offset. - * @param data Data. - */ - insertData(offset2, data2) { - CharacterDataUtility.insertData(this, offset2, data2); - } - /** - * Replaces the specified amount of characters, starting at the specified offset, with the specified DOMString; when this method returns, data contains the modified DOMString. - * - * @param offset Offset. - * @param count Count. - * @param data Data. - */ - replaceData(offset2, count, data2) { - CharacterDataUtility.replaceData(this, offset2, count, data2); - } - /** - * Returns a DOMString containing the part of CharacterData.data of the specified length and starting at the specified offset. - * - * @param offset Offset. - * @param count Count. - */ - substringData(offset2, count) { - return CharacterDataUtility.substringData(this, offset2, count); - } - /** - * Removes the object from its parent children list. - */ - remove() { - ChildNodeUtility.remove(this); - } - /** - * The Node.replaceWith() method replaces this Node in the children list of its parent with a set of Node or DOMString objects. - * - * @param nodes List of Node or DOMString. - */ - replaceWith(...nodes) { - ChildNodeUtility.replaceWith(this, ...nodes); - } - /** - * Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just before this ChildNode. DOMString objects are inserted as equivalent Text nodes. - * - * @param nodes List of Node or DOMString. - */ - before(...nodes) { - ChildNodeUtility.before(this, ...nodes); - } - /** - * Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just after this ChildNode. DOMString objects are inserted as equivalent Text nodes. - * - * @param nodes List of Node or DOMString. - */ - after(...nodes) { - ChildNodeUtility.after(this, ...nodes); - } - /** - * @override - */ - [cloneNode](deep = false) { - const clone2 = super[cloneNode](deep); - clone2[data] = this[data]; - return clone2; - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/document-type/DocumentType.js -var DocumentType; -var init_DocumentType = __esm({ - "node_modules/happy-dom/lib/nodes/document-type/DocumentType.js"() { - init_Node(); - init_PropertySymbol(); - init_NodeTypeEnum(); - DocumentType = class extends Node { - [nodeType] = NodeTypeEnum_default.documentTypeNode; - [name] = ""; - [publicId] = ""; - [systemId] = ""; - /** - * Returns name. - * - * @returns Name. - */ - get name() { - return this[name]; - } - /** - * Returns public ID. - * - * @returns Public ID. - */ - get publicId() { - return this[publicId]; - } - /** - * Returns system ID. - * - * @returns System ID. - */ - get systemId() { - return this[systemId]; - } - /** - * Node name. - * - * @returns Node name. - */ - get nodeName() { - return this.name; - } - /** - * Converts to string. - * - * @returns String. - */ - toString() { - return "[object DocumentType]"; - } - /** - * @override - */ - [cloneNode](deep = false) { - const clone2 = super[cloneNode](deep); - clone2[name] = this[name]; - clone2[publicId] = this[publicId]; - clone2[systemId] = this[systemId]; - return clone2; - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/document/DocumentReadyStateEnum.js -var DocumentReadyStateEnum, DocumentReadyStateEnum_default; -var init_DocumentReadyStateEnum = __esm({ - "node_modules/happy-dom/lib/nodes/document/DocumentReadyStateEnum.js"() { - (function(DocumentReadyStateEnum2) { - DocumentReadyStateEnum2["loading"] = "loading"; - DocumentReadyStateEnum2["interactive"] = "interactive"; - DocumentReadyStateEnum2["complete"] = "complete"; - })(DocumentReadyStateEnum || (DocumentReadyStateEnum = {})); - DocumentReadyStateEnum_default = DocumentReadyStateEnum; - } -}); - -// node_modules/happy-dom/lib/nodes/document/DocumentReadyStateManager.js -var DocumentReadyStateManager; -var init_DocumentReadyStateManager = __esm({ - "node_modules/happy-dom/lib/nodes/document/DocumentReadyStateManager.js"() { - init_AsyncTaskManager(); - DocumentReadyStateManager = class { - #asyncTaskManager; - /** - * Constructor. - * - * @param browserFrame Browser frame. - */ - constructor(browserFrame) { - this.#asyncTaskManager = new AsyncTaskManager(browserFrame); - } - /** - * Returns a promise that is fulfilled when ready state is complete. - * - * @returns Promise. - */ - waitUntilComplete() { - return this.#asyncTaskManager.waitUntilComplete(); - } - /** - * Starts a task. - * - * @returns Task ID. - */ - startTask() { - return this.#asyncTaskManager.startTask(); - } - /** - * Ends a task. - * - * @param taskID Task ID. - */ - endTask(taskID) { - this.#asyncTaskManager.endTask(taskID); - } - /** - * Destroys the manager. - */ - destroy() { - return this.#asyncTaskManager.destroy(); - } - }; - } -}); - -// node_modules/happy-dom/lib/dom/DOMRectReadOnly.js -var DOMRectReadOnly; -var init_DOMRectReadOnly = __esm({ - "node_modules/happy-dom/lib/dom/DOMRectReadOnly.js"() { - init_PropertySymbol(); - DOMRectReadOnly = class _DOMRectReadOnly { - [x] = 0; - [y] = 0; - [width] = 0; - [height] = 0; - /** - * Constructor. - * - * @param [x] X position. - * @param [y] Y position. - * @param [width] Width. - * @param [height] Height. - */ - constructor(x3, y3, width2, height2) { - this[x] = x3 !== void 0 && x3 !== null ? Number(x3) : 0; - this[y] = y3 !== void 0 && y3 !== null ? Number(y3) : 0; - this[width] = width2 !== void 0 && width2 !== null ? Number(width2) : 0; - this[height] = height2 !== void 0 && height2 !== null ? Number(height2) : 0; - } - /** - * Returns x. - * - * @returns X. - */ - get x() { - return this[x]; - } - /** - * Returns y. - * - * @returns Y. - */ - get y() { - return this[y]; - } - /** - * Returns width. - * - * @returns Width. - */ - get width() { - return this[width]; - } - /** - * Returns height. - * - * @returns Height. - */ - get height() { - return this[height]; - } - /** - * Returns top. - * - * @returns Top. - */ - get top() { - return Math.min(this[y], this[y] + this[height]); - } - /** - * Returns right. - * - * @returns Right. - */ - get right() { - return Math.max(this[x], this[x] + this[width]); - } - /** - * Returns bottom. - * - * @returns Bottom. - */ - get bottom() { - return Math.max(this[y], this[y] + this[height]); - } - /** - * Returns left. - * - * @returns Left. - */ - get left() { - return Math.min(this[x], this[x] + this[width]); - } - /** - * Returns the JSON representation of the object. - * - * @returns JSON representation. - */ - toJSON() { - return { - x: this.x, - y: this.y, - width: this.width, - height: this.height, - top: this.top, - right: this.right, - bottom: this.bottom, - left: this.left - }; - } - /** - * Returns a new DOMRectReadOnly object. - * - * @param other - * @returns Cloned object. - */ - static fromRect(other) { - return new _DOMRectReadOnly(other.x, other.y, other.width, other.height); - } - }; - } -}); - -// node_modules/happy-dom/lib/dom/DOMRect.js -var DOMRect; -var init_DOMRect = __esm({ - "node_modules/happy-dom/lib/dom/DOMRect.js"() { - init_DOMRectReadOnly(); - init_PropertySymbol(); - DOMRect = class _DOMRect extends DOMRectReadOnly { - /** - * Sets x. - * - * @param value X. - */ - set x(value2) { - this[x] = value2; - } - /** - * Returns x. - * - * @returns X. - */ - get x() { - return this[x]; - } - /** - * Sets y. - * - * @param value Y. - */ - set y(value2) { - this[y] = value2; - } - /** - * Returns y. - * - * @returns Y. - */ - get y() { - return this[y]; - } - /** - * Sets width. - * - * @param value Width. - */ - set width(value2) { - this[width] = value2; - } - /** - * Returns width. - * - * @returns Width. - */ - get width() { - return this[width]; - } - /** - * Sets height. - * - * @param value Height. - */ - set height(value2) { - this[height] = value2; - } - /** - * Returns height. - * - * @returns Height. - */ - get height() { - return this[height]; - } - /** - * Returns a new DOMRect object. - * - * @param other - * @returns Cloned object. - */ - static fromRect(other) { - return new _DOMRect(other.x, other.y, other.width, other.height); - } - }; - } -}); - -// node_modules/happy-dom/lib/dom/DOMTokenList.js -var ATTRIBUTE_SPLIT_REGEXP, DOMTokenList; -var init_DOMTokenList = __esm({ - "node_modules/happy-dom/lib/dom/DOMTokenList.js"() { - init_ClassMethodBinder(); - init_PropertySymbol(); - ATTRIBUTE_SPLIT_REGEXP = /[\t\f\n\r ]+/; - DOMTokenList = class _DOMTokenList { - [ownerElement]; - [attributeName]; - [cache] = { - items: [], - attributeValue: "" - }; - [supports]; - [proxy]; - /** - * Constructor. - * - * @param illegalConstructorSymbol Illegal constructor symbol. - * @param ownerElement Owner element. - * @param attributeName Attribute name. - * @param [supports] Supports. - */ - constructor(illegalConstructorSymbol, ownerElement2, attributeName2, supports2) { - if (illegalConstructorSymbol !== illegalConstructor) { - throw new TypeError("Illegal constructor"); - } - this[ownerElement] = ownerElement2; - this[attributeName] = attributeName2; - this[supports] = supports2 || []; - const methodBinder = new ClassMethodBinder(this, [_DOMTokenList]); - const proxy2 = new Proxy(this, { - get: (target2, property) => { - if (property === "length") { - return target2[getTokenList]().length; - } - if (property in target2 || typeof property === "symbol") { - methodBinder.bind(property); - return target2[property]; - } - const index = Number(property); - if (!isNaN(index)) { - return target2[getTokenList]()[index]; - } - }, - set(target2, property, newValue) { - methodBinder.bind(property); - if (typeof property === "symbol") { - target2[property] = newValue; - return true; - } - const index = Number(property); - if (isNaN(index)) { - target2[property] = newValue; - } - return true; - }, - deleteProperty(target2, property) { - if (typeof property === "symbol") { - delete target2[property]; - return true; - } - const index = Number(property); - if (isNaN(index)) { - delete target2[property]; - } - return true; - }, - ownKeys(target2) { - return Object.keys(target2[getTokenList]()); - }, - has(target2, property) { - if (property in target2) { - return true; - } - if (typeof property === "symbol") { - return false; - } - const index = Number(property); - return !isNaN(index) && index >= 0 && index < target2[getTokenList]().length; - }, - defineProperty(target2, property, descriptor) { - methodBinder.preventBinding(property); - if (property in target2) { - Object.defineProperty(target2, property, descriptor); - return true; - } - return false; - }, - getOwnPropertyDescriptor(target2, property) { - if (property in target2 || typeof property === "symbol") { - return; - } - const index = Number(property); - const items2 = target2[getTokenList](); - if (!isNaN(index) && items2[index]) { - return { - value: items2[index], - writable: false, - enumerable: true, - configurable: true - }; - } - } - }); - this[proxy] = proxy2; - return proxy2; - } - /** - * Returns length. - * - * @returns Length. - */ - get length() { - return this[getTokenList]().length; - } - /** - * Set value. - * - * @param value Value. - */ - set value(value2) { - this[ownerElement].setAttribute(this[attributeName], value2); - } - /** - * Get value. - */ - get value() { - return this[ownerElement].getAttribute(this[attributeName]) || ""; - } - /** - * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. - */ - [Symbol.iterator]() { - return this[getTokenList]().values(); - } - /** - * Get ClassName. - * - * @param index Index. - * */ - item(index) { - const items2 = this[getTokenList](); - if (typeof index === "number") { - return items2[index] ? items2[index] : null; - } - index = Number(index); - index = isNaN(index) ? 0 : index; - return items2[index] ? items2[index] : null; - } - /** - * Replace Token. - * - * @param token Token. - * @param newToken NewToken. - */ - replace(token, newToken) { - const list = this[getTokenList]().slice(); - const index = list.indexOf(token); - if (index === -1) { - return false; - } - list[index] = newToken; - this[ownerElement].setAttribute(this[attributeName], list.join(" ")); - return true; - } - /** - * Supports. - * - * @param token Token. - */ - supports(token) { - return this[supports].includes(token); - } - /** - * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. - */ - values() { - return this[getTokenList]().values(); - } - /** - * Returns an iterator, allowing you to go through all key/value pairs contained in this object. - */ - entries() { - return this[getTokenList]().entries(); - } - /** - * Executes a provided callback function once for each DOMTokenList element. - * - * @param callback - * @param thisArg - */ - forEach(callback, thisArg) { - const thisArgValue = thisArg ?? this[ownerElement][window]; - const items2 = this[getTokenList](); - const proxy2 = this[proxy] ?? this; - for (let i = 0, max = items2.length; i < max; i++) { - callback.call(thisArgValue, items2[i], i, proxy2); - } - } - /** - * Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object. - * - */ - keys() { - return this[getTokenList]().keys(); - } - /** - * Adds tokens. - * - * @param tokens Tokens. - */ - add(...tokens) { - const list = this[getTokenList]().slice(); - const existingTokens = new Set(list); - for (const token of tokens) { - if (!existingTokens.has(token)) { - existingTokens.add(token); - list.push(token); - } - } - this[ownerElement].setAttribute(this[attributeName], list.join(" ")); - } - /** - * Removes tokens. - * - * @param tokens Tokens. - */ - remove(...tokens) { - const list = this[getTokenList](); - const tokensToRemove = new Set(tokens); - const newList = list.filter((item) => !tokensToRemove.has(item)); - this[ownerElement].setAttribute(this[attributeName], newList.join(" ")); - } - /** - * Check if the list contains a class. - * - * @param className Class name. - * @returns TRUE if it contains. - */ - contains(className) { - return this[getTokenList]().includes(className); - } - /** - * Toggle a class name. - * - * @param token A string representing the class name you want to toggle. - * @param [force] If included, turns the toggle into a one way-only operation. If set to `false`, then class name will only be removed, but not added. If set to `true`, then class name will only be added, but not removed. - * @returns A boolean value, `true` or `false`, indicating whether class name is in the list after the call or not. - */ - toggle(token, force) { - let shouldAdd; - if (force !== void 0) { - shouldAdd = force; - } else { - shouldAdd = !this.contains(token); - } - if (shouldAdd) { - this.add(token); - return true; - } - this.remove(token); - return false; - } - /** - * Returns token list from attribute value. - * - * @see https://infra.spec.whatwg.org/#split-on-ascii-whitespace - */ - [getTokenList]() { - const attributeValue2 = this[ownerElement].getAttribute(this[attributeName]) ?? ""; - const cache2 = this[cache]; - if (cache2.attributeValue === attributeValue2) { - return cache2.items; - } - const items2 = []; - const trimmed = attributeValue2.trim(); - if (trimmed) { - for (const item of trimmed.split(ATTRIBUTE_SPLIT_REGEXP)) { - if (!items2.includes(item)) { - items2.push(item); - } - } - } - cache2.attributeValue = attributeValue2; - cache2.items = items2; - return items2; - } - /** - * Returns DOMTokenList value. - */ - toString() { - return this.value || ""; - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/element/HTMLCollection.js -var HTMLCollection; -var init_HTMLCollection = __esm({ - "node_modules/happy-dom/lib/nodes/element/HTMLCollection.js"() { - init_ClassMethodBinder(); - init_PropertySymbol(); - HTMLCollection = class _HTMLCollection { - [query]; - /** - * Constructor. - * - * @param illegalConstructorSymbol Illegal constructor symbol. - * @param query Query function. - */ - constructor(illegalConstructorSymbol, query2) { - if (illegalConstructorSymbol !== illegalConstructor) { - throw new TypeError("Illegal constructor"); - } - this[query] = query2; - const methodBinder = new ClassMethodBinder(this, this.constructor !== _HTMLCollection ? [this.constructor, _HTMLCollection] : [_HTMLCollection]); - return new Proxy(this, { - get: (target2, property) => { - if (property === "length") { - return query2().length; - } - if (property in target2 || typeof property === "symbol") { - methodBinder.bind(property); - return target2[property]; - } - const index = Number(property); - if (!isNaN(index)) { - return query2()[index]; - } - return target2.namedItem(property) || void 0; - }, - set(target2, property, newValue) { - methodBinder.bind(property); - if (typeof property === "symbol") { - target2[property] = newValue; - return true; - } - const index = Number(property); - if (isNaN(index)) { - target2[property] = newValue; - } - return true; - }, - deleteProperty(target2, property) { - if (typeof property === "symbol") { - delete target2[property]; - return true; - } - const index = Number(property); - if (isNaN(index)) { - delete target2[property]; - } - return true; - }, - ownKeys() { - const keys = []; - const items2 = query2(); - for (let i = 0; i < items2.length; i++) { - const item = items2[i]; - const name2 = item.getAttribute("id") || item.getAttribute("name"); - keys.push(String(i)); - if (name2) { - keys.push(name2); - } - } - return keys; - }, - has(target2, property) { - if (property in target2) { - return true; - } - const items2 = query2(); - const index = Number(property); - if (!isNaN(index) && index >= 0 && index < items2.length) { - return true; - } - property = String(property); - for (let i = 0; i < items2.length; i++) { - const item = items2[i]; - const name2 = item.getAttribute("id") || item.getAttribute("name"); - if (name2 && name2 === property) { - return true; - } - } - return false; - }, - defineProperty(target2, property, descriptor) { - methodBinder.preventBinding(property); - if (property in target2) { - Object.defineProperty(target2, property, descriptor); - return true; - } - return false; - }, - getOwnPropertyDescriptor(target2, property) { - if (property in target2 || typeof property === "symbol") { - return; - } - const items2 = query2(); - const index = Number(property); - if (!isNaN(index) && index >= 0 && index < items2.length) { - return { - value: items2[index], - writable: false, - enumerable: true, - configurable: true - }; - } - for (let i = 0; i < items2.length; i++) { - const item = items2[i]; - const name2 = item.getAttribute("id") || item.getAttribute("name"); - if (name2 && name2 === property) { - return { - value: item, - writable: false, - enumerable: true, - configurable: true - }; - } - } - } - }); - } - /** - * Returns length. - * - * @returns Length. - */ - get length() { - return this[query]().length; - } - /** - * Returns `Symbol.toStringTag`. - * - * @returns `Symbol.toStringTag`. - */ - get [Symbol.toStringTag]() { - return this.constructor.name; - } - /** - * Returns `[object HTMLCollection]`. - * - * @returns `[object HTMLCollection]`. - */ - toLocaleString() { - return `[object ${this.constructor.name}]`; - } - /** - * Returns `[object HTMLCollection]`. - * - * @returns `[object HTMLCollection]`. - */ - toString() { - return `[object ${this.constructor.name}]`; - } - /** - * Returns item by index. - * - * @param index Index. - */ - item(index) { - const items2 = this[query](); - return index >= 0 && items2[index] ? items2[index] : null; - } - /** - * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. - * - * @returns Iterator. - */ - [Symbol.iterator]() { - const items2 = this[query](); - return items2[Symbol.iterator](); - } - /** - * Returns named item. - * - * @param name Name. - * @returns Node. - */ - namedItem(name2) { - const items2 = this[query](); - name2 = String(name2); - for (const item of items2) { - if (item.getAttribute("id") === name2 || item.getAttribute("name") === name2) { - return item; - } - } - return null; - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/parent-node/ParentNodeUtility.js -var ParentNodeUtility; -var init_ParentNodeUtility = __esm({ - "node_modules/happy-dom/lib/nodes/parent-node/ParentNodeUtility.js"() { - init_PropertySymbol(); - init_Node(); - init_NamespaceURI(); - init_HTMLCollection(); - init_QuerySelector(); - ParentNodeUtility = class { - /** - * Inserts a set of Node objects or DOMString objects after the last child of the ParentNode. DOMString objects are inserted as equivalent Text nodes. - * - * @param parentNode Parent node. - * @param nodes List of Node or DOMString. - */ - static append(parentNode2, ...nodes) { - for (const node of nodes) { - if (node instanceof Node) { - parentNode2.appendChild(node); - } else { - parentNode2.appendChild(parentNode2[ownerDocument].createTextNode(String(node))); - } - } - } - /** - * Inserts a set of Node objects or DOMString objects before the first child of the ParentNode. DOMString objects are inserted as equivalent Text nodes. - * - * @param parentNode Parent node. - * @param nodes List of Node or DOMString. - */ - static prepend(parentNode2, ...nodes) { - const firstChild = parentNode2.firstChild; - for (const node of nodes) { - if (node instanceof Node) { - parentNode2.insertBefore(node, firstChild); - } else { - parentNode2.insertBefore(parentNode2[ownerDocument].createTextNode(String(node)), firstChild); - } - } - } - /** - * Replaces the existing children of a ParentNode with a specified new set of children. - * - * @param parentNode Parent node. - * @param nodes List of Node or DOMString. - */ - static replaceChildren(parentNode2, ...nodes) { - const childNodes2 = parentNode2[nodeArray]; - while (childNodes2.length) { - parentNode2.removeChild(childNodes2[0]); - } - this.append(parentNode2, ...nodes); - } - /** - * Returns an elements by class name. - * - * @param parentNode Parent node. - * @param className Tag name. - * @returns Matching element. - */ - static getElementsByClassName(parentNode2, className) { - return new HTMLCollection(illegalConstructor, () => QuerySelector.querySelectorAll(parentNode2, `.${className.replace(/\s+/gm, ".")}`)[items]); - } - /** - * Returns an elements by tag name. - * - * @param parentNode Parent node. - * @param tagName Tag name. - * @returns Matching element. - */ - static getElementsByTagName(parentNode2, tagName2) { - const upperTagName = tagName2.toUpperCase(); - const includeAll = tagName2 === "*"; - const find = (parent2, cachedResult) => { - const elements2 = []; - for (const element of parent2[elementArray]) { - if (includeAll || element[tagName].toUpperCase() === upperTagName) { - elements2.push(element); - } - element[affectsCache].push(cachedResult); - for (const foundElement of find(element, cachedResult)) { - elements2.push(foundElement); - } - } - return elements2; - }; - const query2 = () => { - const cache2 = parentNode2[cache].elementsByTagName; - const cachedItems = cache2.get(tagName2); - if (cachedItems?.result) { - const items3 = cachedItems.result.deref(); - if (items3) { - return items3; - } - } - const cachedResult = { result: null }; - const items2 = find(parentNode2, cachedResult); - cachedResult.result = new WeakRef(items2); - cache2.set(tagName2, cachedResult); - return items2; - }; - return new HTMLCollection(illegalConstructor, query2); - } - /** - * Returns an elements by tag name and namespace. - * - * @param parentNode Parent node. - * @param namespaceURI Namespace URI. - * @param tagName Tag name. - * @returns Matching element. - */ - static getElementsByTagNameNS(parentNode2, namespaceURI2, tagName2) { - const formattedTagName = namespaceURI2 === NamespaceURI_default.html && parentNode2[ownerDocument][contentType] === "text/html" ? tagName2.toUpperCase() : tagName2; - const includeAll = tagName2 === "*"; - const find = (parent2, cachedResult) => { - const elements2 = []; - for (const element of parent2[elementArray]) { - if ((includeAll || element[tagName] === formattedTagName) && element[namespaceURI] === namespaceURI2) { - elements2.push(element); - } - element[affectsCache].push(cachedResult); - for (const foundElement of find(element, cachedResult)) { - elements2.push(foundElement); - } - } - return elements2; - }; - const query2 = () => { - const cache2 = parentNode2[cache].elementsByTagNameNS; - const cachedItems = cache2.get(tagName2); - if (cachedItems?.result) { - const items3 = cachedItems.result.deref(); - if (items3) { - return items3; - } - } - const cachedResult = { result: null }; - const items2 = find(parentNode2, cachedResult); - cachedResult.result = new WeakRef(items2); - cache2.set(tagName2, cachedResult); - return items2; - }; - return new HTMLCollection(illegalConstructor, query2); - } - /** - * Returns the first element matching a tag name. - * This is not part of the browser standard and is only used internally (used in Document). - * - * @param parentNode Parent node. - * @param tagName Tag name. - * @returns Matching element. - */ - static getElementByTagName(parentNode2, tagName2) { - const upperTagName = tagName2.toUpperCase(); - const find = (parent2, cachedResult2) => { - for (const element of parent2[elementArray]) { - element[affectsCache].push(cachedResult2); - if (element[tagName] === upperTagName) { - return element; - } - const foundElement = find(element, cachedResult2); - if (foundElement) { - return foundElement; - } - } - return null; - }; - const cache2 = parentNode2[cache].elementByTagName; - const cachedItem = cache2.get(tagName2); - if (cachedItem?.result) { - const item2 = cachedItem.result.deref(); - if (item2) { - return item2; - } - } - const cachedResult = { result: null }; - const item = find(parentNode2, cachedResult); - cachedResult.result = item ? new WeakRef(item) : { deref: () => null }; - cache2.set(tagName2, cachedResult); - return item; - } - /** - * Returns an element by ID. - * - * @param parentNode Parent node. - * @param id ID. - * @returns Matching element. - */ - static getElementById(parentNode2, id2) { - id2 = String(id2); - if (parentNode2[nodeType] === Node.DOCUMENT_NODE) { - const entry = parentNode2[elementIdMap].get(id2); - if (entry && entry.elements.length > 0) { - return entry.elements[0]; - } - return null; - } - const find = (parent2, cachedResult2) => { - for (const element of parent2[elementArray]) { - element[affectsCache].push(cachedResult2); - if (element.getAttribute("id") === id2) { - return element; - } - const foundElement = find(element, cachedResult2); - if (foundElement) { - return foundElement; - } - } - return null; - }; - const cache2 = parentNode2[cache].elementById; - const cachedItem = cache2.get(id2); - if (cachedItem?.result) { - const item2 = cachedItem.result.deref(); - if (item2) { - return item2; - } - } - const cachedResult = { result: null }; - const item = find(parentNode2, cachedResult); - cachedResult.result = item ? new WeakRef(item) : { deref: () => null }; - cache2.set(id2, cachedResult); - return item; - } - }; - } -}); - -// node_modules/happy-dom/lib/dom/DOMRectList.js -var DOMRectList; -var init_DOMRectList = __esm({ - "node_modules/happy-dom/lib/dom/DOMRectList.js"() { - init_PropertySymbol(); - DOMRectList = class extends Array { - /** - * Constructor. - * - * @param illegalConstructorSymbol Illegal constructor symbol. - */ - constructor(illegalConstructorSymbol) { - super(); - if (illegalConstructorSymbol !== 1 && illegalConstructorSymbol !== illegalConstructor) { - throw new TypeError("Illegal constructor"); - } - } - /** - * Returns item by index. - * - * @param index Index. - */ - item(index) { - return this[index] ?? null; - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/element/NamedNodeMap.js -var NamedNodeMap; -var init_NamedNodeMap = __esm({ - "node_modules/happy-dom/lib/nodes/element/NamedNodeMap.js"() { - init_PropertySymbol(); - init_DOMExceptionNameEnum(); - init_NamespaceURI(); - init_StringUtility(); - NamedNodeMap = class { - // Items by attribute namespaceURI - [itemsByNamespaceURI] = /* @__PURE__ */ new Map(); - // Items by attribute name - [itemsByName] = /* @__PURE__ */ new Map(); - // All items - [items] = /* @__PURE__ */ new Map(); - /** - * Constructor. - * - * @param ownerElement Owner element. - */ - constructor(ownerElement2) { - this[ownerElement] = ownerElement2; - } - /** - * Returns length. - * - * @returns Length. - */ - get length() { - return this[items].size; - } - /** - * Returns string. - * - * @returns string. - */ - get [Symbol.toStringTag]() { - return "NamedNodeMap"; - } - /** - * Returns string. - * - * @returns string. - */ - toString() { - return "[object NamedNodeMap]"; - } - /** - * Iterator. - * - * @returns Iterator. - */ - [Symbol.iterator]() { - return this[items].values(); - } - /** - * Returns item by index. - * - * @param index Index. - */ - item(index) { - const items2 = Array.from(this[items].values()); - return index >= 0 && items2[index] ? items2[index] : null; - } - /** - * Returns named item. - * - * @param name Name. - * @returns Item. - */ - getNamedItem(name2) { - name2 = String(name2); - if (this[ownerElement][namespaceURI] === NamespaceURI_default.html && this[ownerElement][ownerDocument][contentType] === "text/html") { - return this[itemsByName].get(StringUtility.asciiLowerCase(name2))?.[0] || null; - } - return this[itemsByName].get(name2)?.[0] || null; - } - /** - * Returns item by name and namespace. - * - * @param namespace Namespace. - * @param localName Local name of the attribute. - * @returns Item. - */ - getNamedItemNS(namespace, localName2) { - const item = this[itemsByNamespaceURI].get(`${namespace || ""}:${localName2}`); - if (item && (!item[prefix] || item[namespaceURI])) { - return item; - } - return null; - } - /** - * Sets named item. - * - * @param item Item. - * @returns Replaced item. - */ - setNamedItem(item) { - return this[setNamedItem](item); - } - /** - * Adds a new namespaced item. - * - * @alias setNamedItem() - * @param item Item. - * @returns Replaced item. - */ - setNamedItemNS(item) { - return this[setNamedItem](item); - } - /** - * Removes an item. - * - * @throws DOMException - * @param name Name of item. - * @returns Removed item. - */ - removeNamedItem(name2) { - const item = this.getNamedItem(name2); - if (!item) { - throw new this[ownerElement][window].DOMException(`Failed to execute 'removeNamedItem' on 'NamedNodeMap': No item with name '${name2}' was found.`, DOMExceptionNameEnum_default.notFoundError); - } - this[removeNamedItem](item); - return item; - } - /** - * Removes a namespaced item. - * - * @param namespace Namespace. - * @param localName Local name of the item. - * @returns Removed item. - */ - removeNamedItemNS(namespace, localName2) { - const item = this.getNamedItemNS(namespace, localName2); - if (!item) { - throw new this[ownerElement][window].DOMException(`Failed to execute 'removeNamedItemNS' on 'NamedNodeMap': No item with name '${localName2}' in namespace '${namespace}' was found.`, DOMExceptionNameEnum_default.notFoundError); - } - this[removeNamedItem](item); - return item; - } - /** - * Sets named item. - * - * @param item Item. - * @param [ignoreListeners] Ignore listeners. - * @returns Replaced item. - */ - [setNamedItem](item, ignoreListeners = false) { - if (item[ownerElement] !== null && item[ownerElement] !== this[ownerElement]) { - throw new this[ownerElement][window].DOMException("The attribute is in use.", DOMExceptionNameEnum_default.inUseAttributeError); - } - item[ownerElement] = this[ownerElement]; - const replacedItem = this.getNamedItemNS(item[namespaceURI], item[localName]) || null; - const itemsByName2 = this[itemsByName].get(item[name]); - if (replacedItem === item) { - return item; - } - this[itemsByNamespaceURI].set(`${item[namespaceURI] || ""}:${item[localName]}`, item); - this[items].set(`${item[namespaceURI] || ""}:${item[name]}`, item); - if (!itemsByName2?.length) { - this[itemsByName].set(item[name], [item]); - } else { - const index = itemsByName2.indexOf(replacedItem); - if (index !== -1) { - itemsByName2.splice(index, 1); - } - itemsByName2.push(item); - } - if (!ignoreListeners) { - this[ownerElement][onSetAttribute](item, replacedItem); - } - return replacedItem; - } - /** - * Removes named item. - * - * @param item Item. - * @param ignoreListeners - */ - [removeNamedItem](item, ignoreListeners = false) { - item[ownerElement] = null; - this[itemsByNamespaceURI].delete(`${item[namespaceURI] || ""}:${item[localName]}`); - this[items].delete(`${item[namespaceURI] || ""}:${item[name]}`); - const itemsByName2 = this[itemsByName].get(item[name]); - if (itemsByName2?.length) { - const index = itemsByName2.indexOf(item); - if (index !== -1) { - itemsByName2.splice(index, 1); - } - if (!itemsByName2.length) { - this[itemsByName].delete(item[name]); - } - } - if (!ignoreListeners) { - this[ownerElement][onRemoveAttribute](item); - } - } - }; - } -}); - -// node_modules/happy-dom/lib/nodes/element/NamedNodeMapProxyFactory.js -var NamedNodeMapProxyFactory; -var init_NamedNodeMapProxyFactory = __esm({ - "node_modules/happy-dom/lib/nodes/element/NamedNodeMapProxyFactory.js"() { - init_ClassMethodBinder(); - init_PropertySymbol(); - init_NamedNodeMap(); - NamedNodeMapProxyFactory = class { - /** - * Constructor. - * - * @param namedNodeMap - */ - static createProxy(namedNodeMap) { - const methodBinder = new ClassMethodBinder(this, [NamedNodeMap]); - return new Proxy(namedNodeMap, { - get: (target2, property) => { - if (property === "length") { - return namedNodeMap[items].size; - } - if (property in target2 || typeof property === "symbol") { - methodBinder.bind(property); - return target2[property]; - } - const index = Number(property); - if (!isNaN(index)) { - return target2.item(index); - } - return target2.getNamedItem(property) || void 0; - }, - set(target2, property, newValue) { - methodBinder.bind(property); - if (typeof property === "symbol") { - target2[property] = newValue; - return true; - } - const index = Number(property); - if (isNaN(index)) { - target2[property] = newValue; - } - return true; - }, - deleteProperty(target2, property) { - if (typeof property === "symbol") { - delete target2[property]; - return true; - } - const index = Number(property); - if (isNaN(index)) { - delete target2[property]; - } - return true; - }, - ownKeys() { - const keys = Array.from(namedNodeMap[items].keys()); - for (let i = 0, max = namedNodeMap[items].size; i < max; i++) { - keys.push(String(i)); - } - return keys; - }, - has(target2, property) { - if (typeof property === "symbol") { - return false; - } - if (property in target2 || namedNodeMap[items].has(property)) { - return true; - } - const index = Number(property); - if (!isNaN(index) && index >= 0 && index < namedNodeMap[items].size) { - return true; - } - return false; - }, - defineProperty(target2, property, descriptor) { - methodBinder.preventBinding(property); - if (property in target2) { - Object.defineProperty(target2, property, descriptor); - return true; - } - return false; - }, - getOwnPropertyDescriptor(target2, property) { - if (property in target2 || typeof property === "symbol") { - return; - } - const index = Number(property); - if (!isNaN(index)) { - if (index >= 0) { - const itemByIndex = target2.item(index); - if (itemByIndex) { - return { - value: itemByIndex, - writable: false, - enumerable: true, - configurable: true - }; - } - } - return; - } - const items2 = namedNodeMap[items].get(property); - if (items2) { - return { - value: items2, - writable: false, - enumerable: true, - configurable: true - }; - } - } - }); - } - }; - } -}); - -// node_modules/happy-dom/lib/config/HTMLElementConfigContentModelEnum.js -var HTMLElementConfigContentModelEnum, HTMLElementConfigContentModelEnum_default; -var init_HTMLElementConfigContentModelEnum = __esm({ - "node_modules/happy-dom/lib/config/HTMLElementConfigContentModelEnum.js"() { - (function(HTMLElementConfigContentModelEnum2) { - HTMLElementConfigContentModelEnum2["rawText"] = "rawText"; - HTMLElementConfigContentModelEnum2["noSelfDescendants"] = "noSelfDescendants"; - HTMLElementConfigContentModelEnum2["noFirstLevelSelfDescendants"] = "noFirstLevelSelfDescendants"; - HTMLElementConfigContentModelEnum2["noForbiddenFirstLevelDescendants"] = "noForbiddenFirstLevelDescendants"; - HTMLElementConfigContentModelEnum2["noDescendants"] = "noDescendants"; - HTMLElementConfigContentModelEnum2["permittedDescendants"] = "permittedDescendants"; - HTMLElementConfigContentModelEnum2["textOrComments"] = "textOrComments"; - HTMLElementConfigContentModelEnum2["anyDescendants"] = "anyDescendants"; - })(HTMLElementConfigContentModelEnum || (HTMLElementConfigContentModelEnum = {})); - HTMLElementConfigContentModelEnum_default = HTMLElementConfigContentModelEnum; - } -}); - -// node_modules/happy-dom/lib/config/HTMLElementConfig.js -var HTMLElementConfig_default; -var init_HTMLElementConfig = __esm({ - "node_modules/happy-dom/lib/config/HTMLElementConfig.js"() { - init_HTMLElementConfigContentModelEnum(); - HTMLElementConfig_default = { - a: { - className: "HTMLAnchorElement", - contentModel: HTMLElementConfigContentModelEnum_default.noSelfDescendants - }, - abbr: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - address: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - area: { - className: "HTMLAreaElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - article: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - aside: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - audio: { - className: "HTMLAudioElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - b: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - base: { - className: "HTMLBaseElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - bdi: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - bdo: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - body: { - className: "HTMLBodyElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - template: { - className: "HTMLTemplateElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - form: { - className: "HTMLFormElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - input: { - className: "HTMLInputElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - textarea: { - className: "HTMLTextAreaElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - script: { - className: "HTMLScriptElement", - contentModel: HTMLElementConfigContentModelEnum_default.rawText - }, - img: { - className: "HTMLImageElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - link: { - className: "HTMLLinkElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - style: { - className: "HTMLStyleElement", - contentModel: HTMLElementConfigContentModelEnum_default.rawText - }, - label: { - className: "HTMLLabelElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - slot: { - className: "HTMLSlotElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - meta: { - className: "HTMLMetaElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - blockquote: { - className: "HTMLQuoteElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - br: { - className: "HTMLBRElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - button: { - className: "HTMLButtonElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - canvas: { - className: "HTMLCanvasElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - caption: { - className: "HTMLTableCaptionElement", - contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, - forbiddenDescendants: ["table", "tbody", "thead", "tfoot", "tr", "td", "th", "col", "colgroup"], - permittedParents: ["table"] - }, - cite: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - code: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - col: { - className: "HTMLTableColElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants, - permittedParents: ["colgroup"] - }, - colgroup: { - className: "HTMLTableColElement", - contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, - permittedDescendants: ["col"] - }, - data: { - className: "HTMLDataElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - datalist: { - className: "HTMLDataListElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - dd: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, - forbiddenDescendants: ["dt", "dd"] - }, - del: { - className: "HTMLModElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - details: { - className: "HTMLDetailsElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - dfn: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - dialog: { - className: "HTMLDialogElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - div: { - className: "HTMLDivElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - dl: { - className: "HTMLDListElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - dt: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, - forbiddenDescendants: ["dt", "dd"] - }, - em: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - embed: { - className: "HTMLEmbedElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - fieldset: { - className: "HTMLFieldSetElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - figcaption: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - figure: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - footer: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - h1: { - className: "HTMLHeadingElement", - contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants - }, - h2: { - className: "HTMLHeadingElement", - contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants - }, - h3: { - className: "HTMLHeadingElement", - contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants - }, - h4: { - className: "HTMLHeadingElement", - contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants - }, - h5: { - className: "HTMLHeadingElement", - contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants - }, - h6: { - className: "HTMLHeadingElement", - contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants - }, - head: { - className: "HTMLHeadElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - header: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - hgroup: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - hr: { - className: "HTMLHRElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - html: { - className: "HTMLHtmlElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - i: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - iframe: { - className: "HTMLIFrameElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - ins: { - className: "HTMLModElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - kbd: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - legend: { - className: "HTMLLegendElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - li: { - className: "HTMLLIElement", - contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants - }, - main: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - map: { - className: "HTMLMapElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - mark: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - menu: { - className: "HTMLMenuElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - meter: { - className: "HTMLMeterElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - nav: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - noscript: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - object: { - className: "HTMLObjectElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - ol: { - className: "HTMLOListElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - optgroup: { - className: "HTMLOptGroupElement", - contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants - }, - option: { - className: "HTMLOptionElement", - contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, - forbiddenDescendants: ["option", "optgroup"] - }, - output: { - className: "HTMLOutputElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - p: { - className: "HTMLParagraphElement", - contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, - forbiddenDescendants: [ - "address", - "article", - "aside", - "blockquote", - "details", - "dialog", - "div", - "dl", - "fieldset", - "figcaption", - "figure", - "footer", - "form", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "header", - "hgroup", - "hr", - "main", - "menu", - "nav", - "ol", - "p", - "pre", - "section", - "table", - "ul" - ] - }, - param: { - className: "HTMLParamElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - picture: { - className: "HTMLPictureElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - pre: { - className: "HTMLPreElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - progress: { - className: "HTMLProgressElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - q: { - className: "HTMLQuoteElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - rb: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - rp: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, - forbiddenDescendants: ["rp", "rt"] - }, - rt: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, - forbiddenDescendants: ["rp", "rt"] - }, - rtc: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - ruby: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - s: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - samp: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - section: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - select: { - className: "HTMLSelectElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - small: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - source: { - className: "HTMLSourceElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - span: { - className: "HTMLSpanElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - strong: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - sub: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - summary: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - sup: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - table: { - className: "HTMLTableElement", - contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, - permittedDescendants: ["caption", "colgroup", "thead", "tfoot", "tbody"], - moveForbiddenDescendant: { exclude: [] } - }, - tbody: { - className: "HTMLTableSectionElement", - contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, - permittedDescendants: ["tr"], - permittedParents: ["table"], - moveForbiddenDescendant: { exclude: ["caption", "colgroup", "thead", "tfoot", "tbody"] } - }, - td: { - className: "HTMLTableCellElement", - contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, - forbiddenDescendants: ["td", "th", "tr", "tbody", "tfoot", "thead"], - permittedParents: ["tr"] - }, - tfoot: { - className: "HTMLTableSectionElement", - contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, - permittedDescendants: ["tr"], - permittedParents: ["table"], - moveForbiddenDescendant: { exclude: ["caption", "colgroup", "thead", "tfoot", "tbody"] } - }, - th: { - className: "HTMLTableCellElement", - contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, - forbiddenDescendants: ["td", "th", "tr", "tbody", "tfoot", "thead"], - permittedParents: ["tr"] - }, - thead: { - className: "HTMLTableSectionElement", - contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, - permittedDescendants: ["tr"], - permittedParents: ["table"], - moveForbiddenDescendant: { exclude: ["caption", "colgroup", "thead", "tfoot", "tbody"] } - }, - time: { - className: "HTMLTimeElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - title: { - className: "HTMLTitleElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - tr: { - className: "HTMLTableRowElement", - contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, - permittedDescendants: ["td", "th"], - permittedParents: ["tbody", "tfoot", "thead"], - addPermittedParent: "tbody", - moveForbiddenDescendant: { exclude: ["caption", "colgroup", "thead", "tfoot", "tbody", "tr"] } - }, - track: { - className: "HTMLTrackElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - }, - u: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - ul: { - className: "HTMLUListElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - var: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - video: { - className: "HTMLVideoElement", - contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants - }, - wbr: { - className: "HTMLElement", - contentModel: HTMLElementConfigContentModelEnum_default.noDescendants - } - }; - } -}); - -// node_modules/entities/dist/esm/decode-codepoint.js -function replaceCodePoint(codePoint) { - var _a3; - if (codePoint >= 55296 && codePoint <= 57343 || codePoint > 1114111) { - return 65533; - } - return (_a3 = decodeMap.get(codePoint)) !== null && _a3 !== void 0 ? _a3 : codePoint; -} -var _a, decodeMap, fromCodePoint; -var init_decode_codepoint = __esm({ - "node_modules/entities/dist/esm/decode-codepoint.js"() { - decodeMap = /* @__PURE__ */ new Map([ - [0, 65533], - // C1 Unicode control character reference replacements - [128, 8364], - [130, 8218], - [131, 402], - [132, 8222], - [133, 8230], - [134, 8224], - [135, 8225], - [136, 710], - [137, 8240], - [138, 352], - [139, 8249], - [140, 338], - [142, 381], - [145, 8216], - [146, 8217], - [147, 8220], - [148, 8221], - [149, 8226], - [150, 8211], - [151, 8212], - [152, 732], - [153, 8482], - [154, 353], - [155, 8250], - [156, 339], - [158, 382], - [159, 376] - ]); - fromCodePoint = // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, n/no-unsupported-features/es-builtins - (_a = String.fromCodePoint) !== null && _a !== void 0 ? _a : ((codePoint) => { - let output = ""; - if (codePoint > 65535) { - codePoint -= 65536; - output += String.fromCharCode(codePoint >>> 10 & 1023 | 55296); - codePoint = 56320 | codePoint & 1023; - } - output += String.fromCharCode(codePoint); - return output; - }); - } -}); - -// node_modules/entities/dist/esm/internal/decode-shared.js -function decodeBase64(input) { - const binary = ( - // eslint-disable-next-line n/no-unsupported-features/node-builtins - typeof atob === "function" ? ( - // Browser (and Node >=16) - // eslint-disable-next-line n/no-unsupported-features/node-builtins - atob(input) - ) : ( - // Older Node versions (<16) - // eslint-disable-next-line n/no-unsupported-features/node-builtins - typeof Buffer.from === "function" ? ( - // eslint-disable-next-line n/no-unsupported-features/node-builtins - Buffer.from(input, "base64").toString("binary") - ) : ( - // eslint-disable-next-line unicorn/no-new-buffer, n/no-deprecated-api - new Buffer(input, "base64").toString("binary") - ) - ) - ); - const evenLength = binary.length & ~1; - const out = new Uint16Array(evenLength / 2); - for (let index = 0, outIndex = 0; index < evenLength; index += 2) { - const lo = binary.charCodeAt(index); - const hi = binary.charCodeAt(index + 1); - out[outIndex++] = lo | hi << 8; - } - return out; -} -var init_decode_shared = __esm({ - "node_modules/entities/dist/esm/internal/decode-shared.js"() { - } -}); - -// node_modules/entities/dist/esm/generated/decode-data-html.js -var htmlDecodeTree; -var init_decode_data_html = __esm({ - "node_modules/entities/dist/esm/generated/decode-data-html.js"() { - init_decode_shared(); - htmlDecodeTree = /* @__PURE__ */ decodeBase64("QR08ALkAAgH6AYsDNQR2BO0EPgXZBQEGLAbdBxMISQrvCmQLfQurDKQNLw4fD4YPpA+6D/IPAAAAAAAAAAAAAAAAKhBMEY8TmxUWF2EYLBkxGuAa3RsJHDscWR8YIC8jSCSIJcMl6ie3Ku8rEC0CLjoupS7kLgAIRU1hYmNmZ2xtbm9wcnN0dVQAWgBeAGUAaQBzAHcAfgCBAIQAhwCSAJoAoACsALMAbABpAGcAO4DGAMZAUAA7gCYAJkBjAHUAdABlADuAwQDBQHIiZXZlAAJhAAFpeW0AcgByAGMAO4DCAMJAEGRyAADgNdgE3XIAYQB2AGUAO4DAAMBA8CFoYZFj4SFjcgBhZAAAoFMqAAFncIsAjgBvAG4ABGFmAADgNdg43fAlbHlGdW5jdGlvbgCgYSBpAG4AZwA7gMUAxUAAAWNzpACoAHIAAOA12Jzc6SFnbgCgVCJpAGwAZABlADuAwwDDQG0AbAA7gMQAxEAABGFjZWZvcnN1xQDYANoA7QDxAPYA+QD8AAABY3LJAM8AayNzbGFzaAAAoBYidgHTANUAAKDnKmUAZAAAoAYjeQARZIABY3J0AOAA5QDrAGEidXNlAACgNSLuI291bGxpcwCgLCFhAJJjcgAA4DXYBd1wAGYAAOA12Dnd5SF2ZdhiYwDyAOoAbSJwZXEAAKBOIgAHSE9hY2RlZmhpbG9yc3UXARoBHwE6AVIBVQFiAWQBZgGCAakB6QHtAfIBYwB5ACdkUABZADuAqQCpQIABY3B5ACUBKAE1AfUhdGUGYWmg0iJ0KGFsRGlmZmVyZW50aWFsRAAAoEUhbCJleXMAAKAtIQACYWVpb0EBRAFKAU0B8iFvbgxhZABpAGwAO4DHAMdAcgBjAAhhbiJpbnQAAKAwIm8AdAAKYQABZG5ZAV0BaSJsbGEAuGB0I2VyRG90ALdg8gA5AWkAp2NyImNsZQAAAkRNUFRwAXQBeQF9AW8AdAAAoJkiaSJudXMAAKCWIuwhdXMAoJUiaSJtZXMAAKCXIm8AAAFjc4cBlAFrKndpc2VDb250b3VySW50ZWdyYWwAAKAyImUjQ3VybHkAAAFEUZwBpAFvJXVibGVRdW90ZQAAoB0gdSJvdGUAAKAZIAACbG5wdbABtgHNAdgBbwBuAGWgNyIAoHQqgAFnaXQAvAHBAcUB8iJ1ZW50AKBhIm4AdAAAoC8i7yV1ckludGVncmFsAKAuIgABZnLRAdMBAKACIe8iZHVjdACgECJuLnRlckNsb2Nrd2lzZUNvbnRvdXJJbnRlZ3JhbAAAoDMi7yFzcwCgLypjAHIAAOA12J7ccABDoNMiYQBwAACgTSKABURKU1phY2VmaW9zAAsCEgIVAhgCGwIsAjQCOQI9AnMCfwNvoEUh9CJyYWhkAKARKWMAeQACZGMAeQAFZGMAeQAPZIABZ3JzACECJQIoAuchZXIAoCEgcgAAoKEhaAB2AACg5CoAAWF5MAIzAvIhb24OYRRkbAB0oAciYQCUY3IAAOA12AfdAAFhZkECawIAAWNtRQJnAvIjaXRpY2FsAAJBREdUUAJUAl8CYwJjInV0ZQC0YG8AdAFZAloC2WJiJGxlQWN1dGUA3WJyImF2ZQBgYGkibGRlANxi7yFuZACgxCJmJWVyZW50aWFsRAAAoEYhcAR9AgAAAAAAAIECjgIAABoDZgAA4DXYO91EoagAhQKJAm8AdAAAoNwgcSJ1YWwAAKBQIuIhbGUAA0NETFJVVpkCqAK1Au8C/wIRA28AbgB0AG8AdQByAEkAbgB0AGUAZwByAGEA7ADEAW8AdAKvAgAAAACwAqhgbiNBcnJvdwAAoNMhAAFlb7kC0AJmAHQAgAFBUlQAwQLGAs0CciJyb3cAAKDQIekkZ2h0QXJyb3cAoNQhZQDlACsCbgBnAAABTFLWAugC5SFmdAABQVLcAuECciJyb3cAAKD4J+kkZ2h0QXJyb3cAoPon6SRnaHRBcnJvdwCg+SdpImdodAAAAUFU9gL7AnIicm93AACg0iFlAGUAAKCoInAAQQIGAwAAAAALA3Iicm93AACg0SFvJHduQXJyb3cAAKDVIWUlcnRpY2FsQmFyAACgJSJuAAADQUJMUlRhJAM2AzoDWgNxA3oDciJyb3cAAKGTIUJVLAMwA2EAcgAAoBMpcCNBcnJvdwAAoPUhciJldmUAEWPlIWZ00gJDAwAASwMAAFIDaSVnaHRWZWN0b3IAAKBQKWUkZVZlY3RvcgAAoF4p5SJjdG9yQqC9IWEAcgAAoFYpaSJnaHQA1AFiAwAAaQNlJGVWZWN0b3IAAKBfKeUiY3RvckKgwSFhAHIAAKBXKWUAZQBBoKQiciJyb3cAAKCnIXIAcgBvAPcAtAIAAWN0gwOHA3IAAOA12J/c8iFvaxBhAAhOVGFjZGZnbG1vcHFzdHV4owOlA6kDsAO/A8IDxgPNA9ID8gP9AwEEFAQeBCAEJQRHAEphSAA7gNAA0EBjAHUAdABlADuAyQDJQIABYWl5ALYDuQO+A/Ihb24aYXIAYwA7gMoAykAtZG8AdAAWYXIAAOA12AjdcgBhAHYAZQA7gMgAyEDlIm1lbnQAoAgiAAFhcNYD2QNjAHIAEmF0AHkAUwLhAwAAAADpA20lYWxsU3F1YXJlAACg+yVlJ3J5U21hbGxTcXVhcmUAAKCrJQABZ3D2A/kDbwBuABhhZgAA4DXYPN3zImlsb26VY3UAAAFhaQYEDgRsAFSgdSppImxkZQAAoEIi7CNpYnJpdW0AoMwhAAFjaRgEGwRyAACgMCFtAACgcyphAJdjbQBsADuAywDLQAABaXApBC0E8yF0cwCgAyLvJG5lbnRpYWxFAKBHIYACY2Zpb3MAPQQ/BEMEXQRyBHkAJGRyAADgNdgJ3WwibGVkAFMCTAQAAAAAVARtJWFsbFNxdWFyZQAAoPwlZSdyeVNtYWxsU3F1YXJlAACgqiVwA2UEAABpBAAAAABtBGYAAOA12D3dwSFsbACgACLyI2llcnRyZgCgMSFjAPIAcQQABkpUYWJjZGZnb3JzdIgEiwSOBJMElwSkBKcEqwStBLIE5QTqBGMAeQADZDuAPgA+QO0hbWFkoJMD3GNyImV2ZQAeYYABZWl5AJ0EoASjBOQhaWwiYXIAYwAcYRNkbwB0ACBhcgAA4DXYCt0AoNkicABmAADgNdg+3eUiYXRlcgADRUZHTFNUvwTIBM8E1QTZBOAEcSJ1YWwATKBlIuUhc3MAoNsidSRsbEVxdWFsAACgZyJyI2VhdGVyAACgoirlIXNzAKB3IuwkYW50RXF1YWwAoH4qaSJsZGUAAKBzImMAcgAA4DXYotwAoGsiAARBYWNmaW9zdfkE/QQFBQgFCwUTBSIFKwVSIkRjeQAqZAABY3QBBQQFZQBrAMdiXmDpIXJjJGFyAACgDCFsJWJlcnRTcGFjZQAAoAsh8AEYBQAAGwVmAACgDSHpJXpvbnRhbExpbmUAoAAlAAFjdCYFKAXyABIF8iFvayZhbQBwAEQBMQU5BW8AdwBuAEgAdQBtAPAAAAFxInVhbAAAoE8iAAdFSk9hY2RmZ21ub3N0dVMFVgVZBVwFYwVtBXAFcwV6BZAFtgXFBckFzQVjAHkAFWTsIWlnMmFjAHkAAWRjAHUAdABlADuAzQDNQAABaXlnBWwFcgBjADuAzgDOQBhkbwB0ADBhcgAAoBEhcgBhAHYAZQA7gMwAzEAAoREhYXB/BYsFAAFjZ4MFhQVyACphaSNuYXJ5SQAAoEghbABpAGUA8wD6AvQBlQUAAKUFZaAsIgABZ3KaBZ4F8iFhbACgKyLzI2VjdGlvbgCgwiJpI3NpYmxlAAABQ1SsBbEFbyJtbWEAAKBjIGkibWVzAACgYiCAAWdwdAC8Bb8FwwVvAG4ALmFmAADgNdhA3WEAmWNjAHIAAKAQIWkibGRlAChh6wHSBQAA1QVjAHkABmRsADuAzwDPQIACY2Zvc3UA4QXpBe0F8gX9BQABaXnlBegFcgBjADRhGWRyAADgNdgN3XAAZgAA4DXYQd3jAfcFAAD7BXIAAOA12KXc8iFjeQhk6yFjeQRkgANISmFjZm9zAAwGDwYSBhUGHQYhBiYGYwB5ACVkYwB5AAxk8CFwYZpjAAFleRkGHAbkIWlsNmEaZHIAAOA12A7dcABmAADgNdhC3WMAcgAA4DXYptyABUpUYWNlZmxtb3N0AD0GQAZDBl4GawZkB2gHcAd0B80H2gdjAHkACWQ7gDwAPECAAmNtbnByAEwGTwZSBlUGWwb1IXRlOWHiIWRhm2NnAACg6ifsI2FjZXRyZgCgEiFyAACgniGAAWFleQBkBmcGagbyIW9uPWHkIWlsO2EbZAABZnNvBjQHdAAABUFDREZSVFVWYXKABp4GpAbGBssG3AYDByEHwQIqBwABbnKEBowGZyVsZUJyYWNrZXQAAKDoJ/Ihb3cAoZAhQlKTBpcGYQByAACg5CHpJGdodEFycm93AKDGIWUjaWxpbmcAAKAII28A9QGqBgAAsgZiJWxlQnJhY2tldAAAoOYnbgDUAbcGAAC+BmUkZVZlY3RvcgAAoGEp5SJjdG9yQqDDIWEAcgAAoFkpbCJvb3IAAKAKI2kiZ2h0AAABQVbSBtcGciJyb3cAAKCUIeUiY3RvcgCgTikAAWVy4AbwBmUAAKGjIkFW5gbrBnIicm93AACgpCHlImN0b3IAoFopaSNhbmdsZQBCorIi+wYAAAAA/wZhAHIAAKDPKXEidWFsAACgtCJwAIABRFRWAAoHEQcYB+8kd25WZWN0b3IAoFEpZSRlVmVjdG9yAACgYCnlImN0b3JCoL8hYQByAACgWCnlImN0b3JCoLwhYQByAACgUilpAGcAaAB0AGEAcgByAG8A9wDMAnMAAANFRkdMU1Q/B0cHTgdUB1gHXwfxJXVhbEdyZWF0ZXIAoNoidSRsbEVxdWFsAACgZiJyI2VhdGVyAACgdiLlIXNzAKChKuwkYW50RXF1YWwAoH0qaSJsZGUAAKByInIAAOA12A/dZaDYIuYjdGFycm93AKDaIWkiZG90AD9hgAFucHcAege1B7kHZwAAAkxSbHKCB5QHmwerB+UhZnQAAUFSiAeNB3Iicm93AACg9SfpJGdodEFycm93AKD3J+kkZ2h0QXJyb3cAoPYn5SFmdAABYXLcAqEHaQBnAGgAdABhAHIAcgBvAPcA5wJpAGcAaAB0AGEAcgByAG8A9wDuAmYAAOA12EPdZQByAAABTFK/B8YHZSRmdEFycm93AACgmSHpJGdodEFycm93AKCYIYABY2h0ANMH1QfXB/IAWgYAoLAh8iFva0FhAKBqIgAEYWNlZmlvc3XpB+wH7gf/BwMICQgOCBEIcAAAoAUpeQAcZAABZGzyB/kHaSR1bVNwYWNlAACgXyBsI2ludHJmAACgMyFyAADgNdgQ3e4jdXNQbHVzAKATInAAZgAA4DXYRN1jAPIA/gecY4AESmFjZWZvc3R1ACEIJAgoCDUIgQiFCDsKQApHCmMAeQAKZGMidXRlAENhgAFhZXkALggxCDQI8iFvbkdh5CFpbEVhHWSAAWdzdwA7CGEIfQjhInRpdmWAAU1UVgBECEwIWQhlJWRpdW1TcGFjZQAAoAsgaABpAAABY25SCFMIawBTAHAAYQBjAOUASwhlAHIAeQBUAGgAaQDuAFQI9CFlZAABR0xnCHUIcgBlAGEAdABlAHIARwByAGUAYQB0AGUA8gDrBGUAcwBzAEwAZQBzAPMA2wdMImluZQAKYHIAAOA12BHdAAJCbnB0jAiRCJkInAhyImVhawAAoGAgwiZyZWFraW5nU3BhY2WgYGYAAKAVIUOq7CqzCMIIzQgAAOcIGwkAAAAAAAAtCQAAbwkAAIcJAACdCcAJGQoAADQKAAFvdbYIvAjuI2dydWVudACgYiJwIkNhcAAAoG0ibyh1YmxlVmVydGljYWxCYXIAAKAmIoABbHF4ANII1wjhCOUibWVudACgCSL1IWFsVKBgImkibGRlAADgQiI4A2kic3RzAACgBCJyI2VhdGVyAACjbyJFRkdMU1T1CPoIAgkJCQ0JFQlxInVhbAAAoHEidSRsbEVxdWFsAADgZyI4A3IjZWF0ZXIAAOBrIjgD5SFzcwCgeSLsJGFudEVxdWFsAOB+KjgDaSJsZGUAAKB1IvUhbXBEASAJJwnvI3duSHVtcADgTiI4A3EidWFsAADgTyI4A2UAAAFmczEJRgn0JFRyaWFuZ2xlQqLqIj0JAAAAAEIJYQByAADgzyk4A3EidWFsAACg7CJzAICibiJFR0xTVABRCVYJXAlhCWkJcSJ1YWwAAKBwInIjZWF0ZXIAAKB4IuUhc3MA4GoiOAPsJGFudEVxdWFsAOB9KjgDaSJsZGUAAKB0IuUic3RlZAABR0x1CX8J8iZlYXRlckdyZWF0ZXIA4KIqOAPlI3NzTGVzcwDgoSo4A/IjZWNlZGVzAKGAIkVTjwmVCXEidWFsAADgryo4A+wkYW50RXF1YWwAoOAiAAFlaaAJqQl2JmVyc2VFbGVtZW50AACgDCLnJWh0VHJpYW5nbGVCousitgkAAAAAuwlhAHIAAODQKTgDcSJ1YWwAAKDtIgABcXXDCeAJdSNhcmVTdQAAAWJwywnVCfMhZXRF4I8iOANxInVhbAAAoOIi5SJyc2V0ReCQIjgDcSJ1YWwAAKDjIoABYmNwAOYJ8AkNCvMhZXRF4IIi0iBxInVhbAAAoIgi4yJlZWRzgKGBIkVTVAD6CQAKBwpxInVhbAAA4LAqOAPsJGFudEVxdWFsAKDhImkibGRlAADgfyI4A+UicnNldEXggyLSIHEidWFsAACgiSJpImxkZQCAoUEiRUZUACIKJwouCnEidWFsAACgRCJ1JGxsRXF1YWwAAKBHImkibGRlAACgSSJlJXJ0aWNhbEJhcgAAoCQiYwByAADgNdip3GkAbABkAGUAO4DRANFAnWMAB0VhY2RmZ21vcHJzdHV2XgphCmgKcgp2CnoKgQqRCpYKqwqtCrsKyArNCuwhaWdSYWMAdQB0AGUAO4DTANNAAAFpeWwKcQpyAGMAO4DUANRAHmRiImxhYwBQYXIAAOA12BLdcgBhAHYAZQA7gNIA0kCAAWFlaQCHCooKjQpjAHIATGFnAGEAqWNjInJvbgCfY3AAZgAA4DXYRt3lI25DdXJseQABRFGeCqYKbyV1YmxlUXVvdGUAAKAcIHUib3RlAACgGCAAoFQqAAFjbLEKtQpyAADgNdiq3GEAcwBoADuA2ADYQGkAbAHACsUKZABlADuA1QDVQGUAcwAAoDcqbQBsADuA1gDWQGUAcgAAAUJQ0wrmCgABYXLXCtoKcgAAoD4gYQBjAAABZWvgCuIKAKDeI2UAdAAAoLQjYSVyZW50aGVzaXMAAKDcI4AEYWNmaGlsb3JzAP0KAwsFCwkLCwsMCxELIwtaC3IjdGlhbEQAAKACInkAH2RyAADgNdgT3WkApmOgY/Ujc01pbnVzsWAAAWlwFQsgC24AYwBhAHIAZQBwAGwAYQBuAOUACgVmAACgGSGAobsqZWlvACoLRQtJC+MiZWRlc4CheiJFU1QANAs5C0ALcSJ1YWwAAKCvKuwkYW50RXF1YWwAoHwiaSJsZGUAAKB+Im0AZQAAoDMgAAFkcE0LUQv1IWN0AKAPIm8jcnRpb24AYaA3ImwAAKAdIgABY2leC2ILcgAA4DXYq9yoYwACVWZvc2oLbwtzC3cLTwBUADuAIgAiQHIAAOA12BTdcABmAACgGiFjAHIAAOA12KzcAAZCRWFjZWZoaW9yc3WPC5MLlwupC7YL2AvbC90LhQyTDJoMowzhIXJyAKAQKUcAO4CuAK5AgAFjbnIAnQugC6ML9SF0ZVRhZwAAoOsncgB0oKAhbAAAoBYpgAFhZXkArwuyC7UL8iFvblhh5CFpbFZhIGR2oBwhZSJyc2UAAAFFVb8LzwsAAWxxwwvIC+UibWVudACgCyL1JGlsaWJyaXVtAKDLIXAmRXF1aWxpYnJpdW0AAKBvKXIAAKAcIW8AoWPnIWh0AARBQ0RGVFVWYewLCgwQDDIMNwxeDHwM9gIAAW5y8Av4C2clbGVCcmFja2V0AACg6SfyIW93AKGSIUJM/wsDDGEAcgAAoOUhZSRmdEFycm93AACgxCFlI2lsaW5nAACgCSNvAPUBFgwAAB4MYiVsZUJyYWNrZXQAAKDnJ24A1AEjDAAAKgxlJGVWZWN0b3IAAKBdKeUiY3RvckKgwiFhAHIAAKBVKWwib29yAACgCyMAAWVyOwxLDGUAAKGiIkFWQQxGDHIicm93AACgpiHlImN0b3IAoFspaSNhbmdsZQBCorMiVgwAAAAAWgxhAHIAAKDQKXEidWFsAACgtSJwAIABRFRWAGUMbAxzDO8kd25WZWN0b3IAoE8pZSRlVmVjdG9yAACgXCnlImN0b3JCoL4hYQByAACgVCnlImN0b3JCoMAhYQByAACgUykAAXB1iQyMDGYAAKAdIe4kZEltcGxpZXMAoHAp6SRnaHRhcnJvdwCg2yEAAWNongyhDHIAAKAbIQCgsSHsJGVEZWxheWVkAKD0KYAGSE9hY2ZoaW1vcXN0dQC/DMgMzAzQDOIM5gwKDQ0NFA0ZDU8NVA1YDQABQ2PDDMYMyCFjeSlkeQAoZEYiVGN5ACxkYyJ1dGUAWmEAorwqYWVpedgM2wzeDOEM8iFvbmBh5CFpbF5hcgBjAFxhIWRyAADgNdgW3e8hcnQAAkRMUlXvDPYM/QwEDW8kd25BcnJvdwAAoJMhZSRmdEFycm93AACgkCHpJGdodEFycm93AKCSIXAjQXJyb3cAAKCRIechbWGjY+EkbGxDaXJjbGUAoBgicABmAADgNdhK3XICHw0AAAAAIg10AACgGiLhIXJlgKGhJUlTVQAqDTINSg3uJXRlcnNlY3Rpb24AoJMidQAAAWJwNw1ADfMhZXRFoI8icSJ1YWwAAKCRIuUicnNldEWgkCJxInVhbAAAoJIibiJpb24AAKCUImMAcgAA4DXYrtxhAHIAAKDGIgACYmNtcF8Nag2ODZANc6DQImUAdABFoNAicSJ1YWwAAKCGIgABY2huDYkNZSJlZHMAgKF7IkVTVAB4DX0NhA1xInVhbAAAoLAq7CRhbnRFcXVhbACgfSJpImxkZQAAoH8iVABoAGEA9ADHCwCgESIAodEiZXOVDZ8NciJzZXQARaCDInEidWFsAACghyJlAHQAAKDRIoAFSFJTYWNmaGlvcnMAtQ27Db8NyA3ODdsN3w3+DRgOHQ4jDk8AUgBOADuA3gDeQMEhREUAoCIhAAFIY8MNxg1jAHkAC2R5ACZkAAFidcwNzQ0JYKRjgAFhZXkA1A3XDdoN8iFvbmRh5CFpbGJhImRyAADgNdgX3QABZWnjDe4N8gHoDQAA7Q3lImZvcmUAoDQiYQCYYwABY27yDfkNayNTcGFjZQAA4F8gCiDTInBhY2UAoAkg7CFkZYChPCJFRlQABw4MDhMOcSJ1YWwAAKBDInUkbGxFcXVhbAAAoEUiaSJsZGUAAKBIInAAZgAA4DXYS93pI3BsZURvdACg2yAAAWN0Jw4rDnIAAOA12K/c8iFva2Zh4QpFDlYOYA5qDgAAbg5yDgAAAAAAAAAAAAB5DnwOqA6zDgAADg8RDxYPGg8AAWNySA5ODnUAdABlADuA2gDaQHIAb6CfIeMhaXIAoEkpcgDjAVsOAABdDnkADmR2AGUAbGEAAWl5Yw5oDnIAYwA7gNsA20AjZGIibGFjAHBhcgAA4DXYGN1yAGEAdgBlADuA2QDZQOEhY3JqYQABZGl/Dp8OZQByAAABQlCFDpcOAAFhcokOiw5yAF9gYQBjAAABZWuRDpMOAKDfI2UAdAAAoLUjYSVyZW50aGVzaXMAAKDdI28AbgBQoMMi7CF1cwCgjiIAAWdwqw6uDm8AbgByYWYAAOA12EzdAARBREVUYWRwc78O0g7ZDuEOBQPqDvMOBw9yInJvdwDCoZEhyA4AAMwOYQByAACgEilvJHduQXJyb3cAAKDFIW8kd25BcnJvdwAAoJUhcSV1aWxpYnJpdW0AAKBuKWUAZQBBoKUiciJyb3cAAKClIW8AdwBuAGEAcgByAG8A9wAQA2UAcgAAAUxS+Q4AD2UkZnRBcnJvdwAAoJYh6SRnaHRBcnJvdwCglyFpAGyg0gNvAG4ApWPpIW5nbmFjAHIAAOA12LDcaSJsZGUAaGFtAGwAO4DcANxAgAREYmNkZWZvc3YALQ8xDzUPNw89D3IPdg97D4AP4SFzaACgqyJhAHIAAKDrKnkAEmThIXNobKCpIgCg5ioAAWVyQQ9DDwCgwSKAAWJ0eQBJD00Paw9hAHIAAKAWIGmgFiDjIWFsAAJCTFNUWA9cD18PZg9hAHIAAKAjIukhbmV8YGUkcGFyYXRvcgAAoFgnaSJsZGUAAKBAItQkaGluU3BhY2UAoAogcgAA4DXYGd1wAGYAAOA12E3dYwByAADgNdix3GQiYXNoAACgqiKAAmNlZm9zAI4PkQ+VD5kPng/pIXJjdGHkIWdlAKDAInIAAOA12BrdcABmAADgNdhO3WMAcgAA4DXYstwAAmZpb3OqD64Prw+0D3IAAOA12BvdnmNwAGYAAOA12E/dYwByAADgNdiz3IAEQUlVYWNmb3N1AMgPyw/OD9EP2A/gD+QP6Q/uD2MAeQAvZGMAeQAHZGMAeQAuZGMAdQB0AGUAO4DdAN1AAAFpedwP3w9yAGMAdmErZHIAAOA12BzdcABmAADgNdhQ3WMAcgAA4DXYtNxtAGwAeGEABEhhY2RlZm9z/g8BEAUQDRAQEB0QIBAkEGMAeQAWZGMidXRlAHlhAAFheQkQDBDyIW9ufWEXZG8AdAB7YfIBFRAAABwQbwBXAGkAZAB0AOgAVAhhAJZjcgAAoCghcABmAACgJCFjAHIAAOA12LXc4QtCEEkQTRAAAGcQbRByEAAAAAAAAAAAeRCKEJcQ8hD9EAAAGxEhETIROREAAD4RYwB1AHQAZQA7gOEA4UByImV2ZQADYYCiPiJFZGl1eQBWEFkQWxBgEGUQAOA+IjMDAKA/InIAYwA7gOIA4kB0AGUAO4C0ALRAMGRsAGkAZwA7gOYA5kByoGEgAOA12B7dcgBhAHYAZQA7gOAA4EAAAWVwfBCGEAABZnCAEIQQ8yF5bQCgNSHoAIMQaABhALFjAAFhcI0QWwAAAWNskRCTEHIAAWFnAACgPypkApwQAAAAALEQAKInImFkc3ajEKcQqRCuEG4AZAAAoFUqAKBcKmwib3BlAACgWCoAoFoqAKMgImVsbXJzersQvRDAEN0Q5RDtEACgpCllAACgICJzAGQAYaAhImEEzhDQENIQ1BDWENgQ2hDcEACgqCkAoKkpAKCqKQCgqykAoKwpAKCtKQCgrikAoK8pdAB2oB8iYgBkoL4iAKCdKQABcHTpEOwQaAAAoCIixWDhIXJyAKB8IwABZ3D1EPgQbwBuAAVhZgAA4DXYUt0Ao0giRWFlaW9wBxEJEQ0RDxESERQRAKBwKuMhaXIAoG8qAKBKImQAAKBLInMAJ2DyIW94ZaBIIvEADhFpAG4AZwA7gOUA5UCAAWN0eQAmESoRKxFyAADgNdi23CpgbQBwAGWgSCLxAPgBaQBsAGQAZQA7gOMA40BtAGwAO4DkAORAAAFjaUERRxFvAG4AaQBuAPQA6AFuAHQAAKARKgAITmFiY2RlZmlrbG5vcHJzdWQRaBGXEZ8RpxGrEdIR1hErEjASexKKEn0RThNbE3oTbwB0AACg7SoAAWNybBGJEWsAAAJjZXBzdBF4EX0RghHvIW5nAKBMInAjc2lsb24A9mNyImltZQAAoDUgaQBtAGWgPSJxAACgzSJ2AY0RkRFlAGUAAKC9ImUAZABnoAUjZQAAoAUjcgBrAHSgtSPiIXJrAKC2IwABb3mjEaYRbgDnAHcRMWTxIXVvAKAeIIACY21wcnQAtBG5Eb4RwRHFEeEhdXPloDUi5ABwInR5dgAAoLApcwDpAH0RbgBvAPUA6gCAAWFodwDLEcwRzhGyYwCgNiHlIWVuAKBsInIAAOA12B/dZwCAA2Nvc3R1dncA4xHyEQUSEhIhEiYSKRKAAWFpdQDpEesR7xHwAKMFcgBjAACg7yVwAACgwyKAAWRwdAD4EfwRABJvAHQAAKAAKuwhdXMAoAEqaSJtZXMAAKACKnECCxIAAAAADxLjIXVwAKAGKmEAcgAAoAUm8iNpYW5nbGUAAWR1GhIeEu8hd24AoL0lcAAAoLMlcCJsdXMAAKAEKmUA5QBCD+UAkg9hInJvdwAAoA0pgAFha28ANhJoEncSAAFjbjoSZRJrAIABbHN0AEESRxJNEm8jemVuZ2UAAKDrKXEAdQBhAHIA5QBcBPIjaWFuZ2xlgKG0JWRscgBYElwSYBLvIXduAKC+JeUhZnQAoMIlaSJnaHQAAKC4JWsAAKAjJLEBbRIAAHUSsgFxEgAAcxIAoJIlAKCRJTQAAKCTJWMAawAAoIglAAFlb38ShxJx4D0A5SD1IWl2AOBhIuUgdAAAoBAjAAJwdHd4kRKVEpsSnxJmAADgNdhT3XSgpSJvAG0AAKClIvQhaWUAoMgiAAZESFVWYmRobXB0dXayEsES0RLgEvcS+xIKExoTHxMjEygTNxMAAkxSbHK5ErsSvRK/EgCgVyUAoFQlAKBWJQCgUyUAolAlRFVkdckSyxLNEs8SAKBmJQCgaSUAoGQlAKBnJQACTFJsctgS2hLcEt4SAKBdJQCgWiUAoFwlAKBZJQCjUSVITFJobHLrEu0S7xLxEvMS9RIAoGwlAKBjJQCgYCUAoGslAKBiJQCgXyVvAHgAAKDJKQACTFJscgITBBMGEwgTAKBVJQCgUiUAoBAlAKAMJQCiACVEVWR1EhMUExYTGBMAoGUlAKBoJQCgLCUAoDQlaSJudXMAAKCfIuwhdXMAoJ4iaSJtZXMAAKCgIgACTFJsci8TMRMzEzUTAKBbJQCgWCUAoBglAKAUJQCjAiVITFJobHJCE0QTRhNIE0oTTBMAoGolAKBhJQCgXiUAoDwlAKAkJQCgHCUAAWV2UhNVE3YA5QD5AGIAYQByADuApgCmQAACY2Vpb2ITZhNqE24TcgAA4DXYt9xtAGkAAKBPIG0A5aA9IogRbAAAoVwAYmh0E3YTAKDFKfMhdWIAoMgnbAF+E4QTbABloCIgdAAAoCIgcAAAoU4iRWWJE4sTAKCuKvGgTyI8BeEMqRMAAN8TABQDFB8UAAAjFDQUAAAAAIUUAAAAAI0UAAAAANcU4xT3FPsUAACIFQAAlhWAAWNwcgCuE7ET1RP1IXRlB2GAoikiYWJjZHMAuxO/E8QTzhPSE24AZAAAoEQqciJjdXAAAKBJKgABYXXIE8sTcAAAoEsqcAAAoEcqbwB0AACgQCoA4CkiAP4AAWVv2RPcE3QAAKBBIO4ABAUAAmFlaXXlE+8T9RP4E/AB6hMAAO0TcwAAoE0qbwBuAA1hZABpAGwAO4DnAOdAcgBjAAlhcABzAHOgTCptAACgUCpvAHQAC2GAAWRtbgAIFA0UEhRpAGwAO4C4ALhAcCJ0eXYAAKCyKXQAAIGiADtlGBQZFKJAcgBkAG8A9ABiAXIAAOA12CDdgAFjZWkAKBQqFDIUeQBHZGMAawBtoBMn4SFyawCgEyfHY3IAAKPLJUVjZWZtcz8UQRRHFHcUfBSAFACgwykAocYCZWxGFEkUcQAAoFciZQBhAlAUAAAAAGAUciJyb3cAAAFsclYUWhTlIWZ0AKC6IWkiZ2h0AACguyGAAlJTYWNkAGgUaRRrFG8UcxSuYACgyCRzAHQAAKCbIukhcmMAoJoi4SFzaACgnSJuImludAAAoBAqaQBkAACg7yrjIWlyAKDCKfUhYnN1oGMmaQB0AACgYybsApMUmhS2FAAAwxRvAG4AZaA6APGgVCKrAG0CnxQAAAAAoxRhAHSgLABAYAChASJmbKcUqRTuABMNZQAAAW14rhSyFOUhbnQAoAEiZQDzANIB5wG6FAAAwBRkoEUibwB0AACgbSpuAPQAzAGAAWZyeQDIFMsUzhQA4DXYVN1vAOQA1wEAgakAO3MeAdMUcgAAoBchAAFhb9oU3hRyAHIAAKC1IXMAcwAAoBcnAAFjdeYU6hRyAADgNdi43AABYnDuFPIUZaDPKgCg0SploNAqAKDSKuQhb3QAoO8igANkZWxwcnZ3AAYVEBUbFSEVRBVlFYQV4SFycgABbHIMFQ4VAKA4KQCgNSlwAhYVAAAAABkVcgAAoN4iYwAAoN8i4SFycnCgtiEAoD0pgKIqImJjZG9zACsVMBU6FT4VQRVyImNhcAAAoEgqAAFhdTQVNxVwAACgRipwAACgSipvAHQAAKCNInIAAKBFKgDgKiIA/gACYWxydksVURVuFXMVcgByAG2gtyEAoDwpeQCAAWV2dwBYFWUVaRVxAHACXxUAAAAAYxVyAGUA4wAXFXUA4wAZFWUAZQAAoM4iZSJkZ2UAAKDPImUAbgA7gKQApEBlI2Fycm93AAABbHJ7FX8V5SFmdACgtiFpImdodAAAoLchZQDkAG0VAAFjaYsVkRVvAG4AaQBuAPQAkwFuAHQAAKAxImwiY3R5AACgLSOACUFIYWJjZGVmaGlqbG9yc3R1d3oAuBW7Fb8V1RXgFegV+RUKFhUWHxZUFlcWZRbFFtsW7xb7FgUXChdyAPIAtAJhAHIAAKBlKQACZ2xyc8YVyhXOFdAV5yFlcgCgICDlIXRoAKA4IfIA9QxoAHagECAAoKMiawHZFd4VYSJyb3cAAKAPKWEA4wBfAgABYXnkFecV8iFvbg9hNGQAoUYhYW/tFfQVAAFnciEC8RVyAACgyiF0InNlcQAAoHcqgAFnbG0A/xUCFgUWO4CwALBAdABhALRjcCJ0eXYAAKCxKQABaXIOFhIW8yFodACgfykA4DXYId1hAHIAAAFschsWHRYAoMMhAKDCIYACYWVnc3YAKBauAjYWOhY+Fm0AAKHEIm9zLhY0Fm4AZABzoMQi9SFpdACgZiZhIm1tYQDdY2kAbgAAoPIiAKH3AGlvQxZRFmQAZQAAgfcAO29KFksW90BuI3RpbWVzAACgxyJuAPgAUBZjAHkAUmRjAG8CXhYAAAAAYhZyAG4AAKAeI28AcAAAoA0jgAJscHR1dwBuFnEWdRaSFp4W7CFhciRgZgAA4DXYVd0AotkCZW1wc30WhBaJFo0WcQBkoFAibwB0AACgUSJpIm51cwAAoDgi7CF1cwCgFCLxInVhcmUAoKEiYgBsAGUAYgBhAHIAdwBlAGQAZwDlANcAbgCAAWFkaAClFqoWtBZyAHIAbwD3APUMbwB3AG4AYQByAHIAbwB3APMA8xVhI3Jwb29uAAABbHK8FsAWZQBmAPQAHBZpAGcAaAD0AB4WYgHJFs8WawBhAHIAbwD3AJILbwLUFgAAAADYFnIAbgAAoB8jbwBwAACgDCOAAWNvdADhFukW7BYAAXJ55RboFgDgNdi53FVkbAAAoPYp8iFvaxFhAAFkcvMW9xZvAHQAAKDxImkA5qC/JVsSAAFhaP8WAhdyAPIANQNhAPIA1wvhIm5nbGUAoKYpAAFjaQ4XEBd5AF9k5yJyYXJyAKD/JwAJRGFjZGVmZ2xtbm9wcXJzdHV4MRc4F0YXWxcyBF4XaRd5F40XrBe0F78X2RcVGCEYLRg1GEAYAAFEbzUXgRZvAPQA+BUAAWNzPBdCF3UAdABlADuA6QDpQPQhZXIAoG4qAAJhaW95TRdQF1YXWhfyIW9uG2FyAGOgViI7gOoA6kDsIW9uAKBVIk1kbwB0ABdhAAFEcmIXZhdvAHQAAKBSIgDgNdgi3XKhmipuF3QXYQB2AGUAO4DoAOhAZKCWKm8AdAAAoJgqgKGZKmlscwCAF4UXhxfuInRlcnMAoOcjAKATIWSglSpvAHQAAKCXKoABYXBzAJMXlheiF2MAcgATYXQAeQBzogUinxcAAAAAoRdlAHQAAKAFInAAMaADIDMBqRerFwCgBCAAoAUgAAFnc7AXsRdLYXAAAKACIAABZ3C4F7sXbwBuABlhZgAA4DXYVt2AAWFscwDFF8sXzxdyAHOg1SJsAACg4yl1AHMAAKBxKmkAAKG1A2x21RfYF28AbgC1Y/VjAAJjc3V24BfoF/0XEBgAAWlv5BdWF3IAYwAAoFYiaQLuFwAAAADwF+0ADQThIW50AAFnbPUX+Rd0AHIAAKCWKuUhc3MAoJUqgAFhZWkAAxgGGAoYbABzAD1gcwB0AACgXyJ2AESgYSJEAACgeCrwImFyc2wAoOUpAAFEYRkYHRhvAHQAAKBTInIAcgAAoHEpgAFjZGkAJxgqGO0XcgAAoC8hbwD0AIwCAAFhaDEYMhi3YzuA8ADwQAABbXI5GD0YbAA7gOsA60BvAACgrCCAAWNpcABGGEgYSxhsACFgcwD0ACwEAAFlb08YVxhjAHQAYQB0AGkAbwDuABoEbgBlAG4AdABpAGEAbADlADME4Ql1GAAAgRgAAIMYiBgAAAAAoRilGAAAqhgAALsYvhjRGAAA1xgnGWwAbABpAG4AZwBkAG8AdABzAGUA8QBlF3kARGRtImFsZQAAoEAmgAFpbHIAjRiRGJ0Y7CFpZwCgA/tpApcYAAAAAJoYZwAAoAD7aQBnAACgBPsA4DXYI93sIWlnAKAB++whaWcA4GYAagCAAWFsdACvGLIYthh0AACgbSZpAGcAAKAC+24AcwAAoLElbwBmAJJh8AHCGAAAxhhmAADgNdhX3QABYWvJGMwYbADsAGsEdqDUIgCg2SphI3J0aW50AACgDSoAAWFv2hgiGQABY3PeGB8ZsQPnGP0YBRkSGRUZAAAdGbID7xjyGPQY9xj5GAAA+xg7gL0AvUAAoFMhO4C8ALxAAKBVIQCgWSEAoFshswEBGQAAAxkAoFQhAKBWIbQCCxkOGQAAAAAQGTuAvgC+QACgVyEAoFwhNQAAoFghtgEZGQAAGxkAoFohAKBdITgAAKBeIWwAAKBEIHcAbgAAoCIjYwByAADgNdi73IAIRWFiY2RlZmdpamxub3JzdHYARhlKGVoZXhlmGWkZkhmWGZkZnRmgGa0ZxhnLGc8Z4BkjGmygZyIAoIwqgAFjbXAAUBlTGVgZ9SF0ZfVhbQBhAOSgswM6FgCghipyImV2ZQAfYQABaXliGWUZcgBjAB1hM2RvAHQAIWGAoWUibHFzAMYEcBl6GfGhZSLOBAAAdhlsAGEAbgD0AN8EgKF+KmNkbACBGYQZjBljAACgqSpvAHQAb6CAKmyggioAoIQqZeDbIgD+cwAAoJQqcgAA4DXYJN3noGsirATtIWVsAKA3IWMAeQBTZIChdyJFYWoApxmpGasZAKCSKgCgpSoAoKQqAAJFYWVztBm2Gb0ZwhkAoGkicABwoIoq8iFveACgiipxoIgq8aCIKrUZaQBtAACg5yJwAGYAAOA12FjdYQB2AOUAYwIAAWNp0xnWGXIAAKAKIW0AAKFzImVs3BneGQCgjioAoJAqAIM+ADtjZGxxco0E6xn0GfgZ/BkBGgABY2nvGfEZAKCnKnIAAKB6Km8AdAAAoNci0CFhcgCglSl1ImVzdAAAoHwqgAJhZGVscwAKGvQZFhrVBCAa8AEPGgAAFBpwAHIAbwD4AFkZcgAAoHgpcQAAAWxxxAQbGmwAZQBzAPMASRlpAO0A5AQAAWVuJxouGnIjdG5lcXEAAOBpIgD+xQAsGgAFQWFiY2Vma29zeUAaQxpmGmoabRqDGocalhrCGtMacgDyAMwCAAJpbG1yShpOGlAaVBpyAHMA8ABxD2YAvWBpAGwA9AASBQABZHJYGlsaYwB5AEpkAKGUIWN3YBpkGmkAcgAAoEgpAKCtIWEAcgAAoA8h6SFyYyVhgAFhbHIAcxp7Gn8a8iF0c3WgZSZpAHQAAKBlJuwhaXAAoCYg4yFvbgCguSJyAADgNdgl3XMAAAFld4wakRphInJvdwAAoCUpYSJyb3cAAKAmKYACYW1vcHIAnxqjGqcauhq+GnIAcgAAoP8h9CFodACgOyJrAAABbHKsGrMaZSRmdGFycm93AACgqSHpJGdodGFycm93AKCqIWYAAOA12Fnd4iFhcgCgFSCAAWNsdADIGswa0BpyAADgNdi93GEAcwDoAGka8iFvaydhAAFicNca2xr1IWxsAKBDIOghZW4AoBAg4Qr2GgAA/RoAAAgbExsaGwAAIRs7GwAAAAA+G2IbmRuVG6sbAACyG80b0htjAHUAdABlADuA7QDtQAChYyBpeQEbBhtyAGMAO4DuAO5AOGQAAWN4CxsNG3kANWRjAGwAO4ChAKFAAAFmcssCFhsA4DXYJt1yAGEAdgBlADuA7ADsQIChSCFpbm8AJxsyGzYbAAFpbisbLxtuAHQAAKAMKnQAAKAtIuYhaW4AoNwpdABhAACgKSHsIWlnM2GAAWFvcABDG1sbXhuAAWNndABJG0sbWRtyACthgAFlbHAAcQVRG1UbaQBuAOUAyAVhAHIA9AByBWgAMWFmAACgtyJlAGQAtWEAoggiY2ZvdGkbbRt1G3kb4SFyZQCgBSFpAG4AdKAeImkAZQAAoN0pZABvAPQAWxsAoisiY2VscIEbhRuPG5QbYQBsAACguiIAAWdyiRuNG2UAcgDzACMQ4wCCG2EicmhrAACgFyryIW9kAKA8KgACY2dwdJ8boRukG6gbeQBRZG8AbgAvYWYAAOA12FrdYQC5Y3UAZQBzAHQAO4C/AL9AAAFjabUbuRtyAADgNdi+3G4AAKIIIkVkc3bCG8QbyBvQAwCg+SJvAHQAAKD1Inag9CIAoPMiaaBiIOwhZGUpYesB1hsAANkbYwB5AFZkbAA7gO8A70AAA2NmbW9zdeYb7hvyG/Ub+hsFHAABaXnqG+0bcgBjADVhOWRyAADgNdgn3eEhdGg3YnAAZgAA4DXYW93jAf8bAAADHHIAAOA12L/c8iFjeVhk6yFjeVRkAARhY2ZnaGpvcxUcGhwiHCYcKhwtHDAcNRzwIXBhdqC6A/BjAAFleR4cIRzkIWlsN2E6ZHIAAOA12CjdciJlZW4AOGFjAHkARWRjAHkAXGRwAGYAAOA12FzdYwByAADgNdjA3IALQUJFSGFiY2RlZmdoamxtbm9wcnN0dXYAXhxtHHEcdRx5HN8cBx0dHTwd3B3tHfEdAR4EHh0eLB5FHrwewx7hHgkfPR9LH4ABYXJ0AGQcZxxpHHIA8gBvB/IAxQLhIWlsAKAbKeEhcnIAoA4pZ6BmIgCgiyphAHIAAKBiKWMJjRwAAJAcAACVHAAAAAAAAAAAAACZHJwcAACmHKgcrRwAANIc9SF0ZTph7SJwdHl2AKC0KXIAYQDuAFoG4iFkYbtjZwAAoegnZGyhHKMcAKCRKeUAiwYAoIUqdQBvADuAqwCrQHIAgKOQIWJmaGxwc3QAuhy/HMIcxBzHHMoczhxmoOQhcwAAoB8pcwAAoB0p6wCyGnAAAKCrIWwAAKA5KWkAbQAAoHMpbAAAoKIhAKGrKmFl1hzaHGkAbAAAoBkpc6CtKgDgrSoA/oABYWJyAOUc6RztHHIAcgAAoAwpcgBrAACgcicAAWFr8Rz4HGMAAAFla/Yc9xx7YFtgAAFlc/wc/hwAoIspbAAAAWR1Ax0FHQCgjykAoI0pAAJhZXV5Dh0RHRodHB3yIW9uPmEAAWRpFR0YHWkAbAA8YewAowbiAPccO2QAAmNxcnMkHScdLB05HWEAAKA2KXUAbwDyoBwgqhEAAWR1MB00HeghYXIAoGcpcyJoYXIAAKBLKWgAAKCyIQCiZCJmZ3FzRB1FB5Qdnh10AIACYWhscnQATh1WHWUdbB2NHXIicm93AHSgkCFhAOkAzxxhI3Jwb29uAAABZHVeHWId7yF3bgCgvSFwAACgvCHlJGZ0YXJyb3dzAKDHIWkiZ2h0AIABYWhzAHUdex2DHXIicm93APOglCGdBmEAcgBwAG8AbwBuAPMAzgtxAHUAaQBnAGEAcgByAG8A9wBlGugkcmVldGltZXMAoMsi8aFkIk0HAACaHWwAYQBuAPQAXgcAon0qY2Rnc6YdqR2xHbcdYwAAoKgqbwB0AG+gfypyoIEqAKCDKmXg2iIA/nMAAKCTKoACYWRlZ3MAwB3GHcod1h3ZHXAAcAByAG8A+ACmHG8AdAAAoNYicQAAAWdxzx3SHXQA8gBGB2cAdADyAHQcdADyAFMHaQDtAGMHgAFpbHIA4h3mHeod8yFodACgfClvAG8A8gDKBgDgNdgp3UWgdiIAoJEqYQH1Hf4dcgAAAWR1YB35HWygvCEAoGopbABrAACghCVjAHkAWWQAomoiYWNodAweDx4VHhkecgDyAGsdbwByAG4AZQDyAGAW4SFyZACgaylyAGkAAKD6JQABaW8hHiQe5CFvdEBh9SFzdGGgsCPjIWhlAKCwIwACRWFlczMeNR48HkEeAKBoInAAcKCJKvIhb3gAoIkqcaCHKvGghyo0HmkAbQAAoOYiAARhYm5vcHR3elIeXB5fHoUelh6mHqsetB4AAW5yVh5ZHmcAAKDsJ3IAAKD9IXIA6wCwBmcAgAFsbXIAZh52Hnse5SFmdAABYXKIB2weaQBnAGgAdABhAHIAcgBvAPcAkwfhInBzdG8AoPwnaQBnAGgAdABhAHIAcgBvAPcAmgdwI2Fycm93AAABbHKNHpEeZQBmAPQAxhxpImdodAAAoKwhgAFhZmwAnB6fHqIecgAAoIUpAOA12F3ddQBzAACgLSppIm1lcwAAoDQqYQGvHrMecwB0AACgFyLhAIoOZaHKJbkeRhLuIWdlAKDKJWEAcgBsoCgAdAAAoJMpgAJhY2htdADMHs8e1R7bHt0ecgDyAJ0GbwByAG4AZQDyANYWYQByAGSgyyEAoG0pAKAOIHIAaQAAoL8iAANhY2hpcXTrHu8e1QfzHv0eBh/xIXVvAKA5IHIAAOA12MHcbQDloXIi+h4AAPweAKCNKgCgjyoAAWJ19xwBH28AcqAYIACgGiDyIW9rQmEAhDwAO2NkaGlscXJCBhcfxh0gHyQfKB8sHzEfAAFjaRsfHR8AoKYqcgAAoHkqcgBlAOUAkx3tIWVzAKDJIuEhcnIAoHYpdSJlc3QAAKB7KgABUGk1HzkfYQByAACglillocMlAgdfEnIAAAFkdUIfRx9zImhhcgAAoEop6CFhcgCgZikAAWVuTx9WH3IjdG5lcXEAAOBoIgD+xQBUHwAHRGFjZGVmaGlsbm9wc3VuH3Ifoh+rH68ftx+7H74f5h/uH/MfBwj/HwsgxCFvdACgOiIAAmNscHJ5H30fiR+eH3IAO4CvAK9AAAFldIEfgx8AoEImZaAgJ3MAZQAAoCAnc6CmIXQAbwCAoaYhZGx1AJQfmB+cH28AdwDuAHkDZQBmAPQA6gbwAOkO6yFlcgCgriUAAW95ph+qH+0hbWEAoCkqPGThIXNoAKAUIOElc3VyZWRhbmdsZQCgISJyAADgNdgq3W8AAKAnIYABY2RuAMQfyR/bH3IAbwA7gLUAtUBhoiMi0B8AANMf1x9zAPQAKxFpAHIAAKDwKm8AdAA7gLcAt0B1AHMA4qESIh4TAADjH3WgOCIAoCoqYwHqH+0fcAAAoNsq8gB+GnAAbAB1APMACAgAAWRw9x/7H+UhbHMAoKciZgAA4DXYXt0AAWN0AyAHIHIAAOA12MLc8CFvcwCgPiJsobwDECAVIPQiaW1hcACguCJhAPAAEyAADEdMUlZhYmNkZWZnaGlqbG1vcHJzdHV2dzwgRyBmIG0geSCqILgg2iDeIBEhFSEyIUMhTSFQIZwhnyHSIQAiIyKLIrEivyIUIwABZ3RAIEMgAODZIjgD9uBrItIgBwmAAWVsdABNIF8gYiBmAHQAAAFhclMgWCByInJvdwAAoM0h6SRnaHRhcnJvdwCgziEA4NgiOAP24Goi0iBfCekkZ2h0YXJyb3cAoM8hAAFEZHEgdSDhIXNoAKCvIuEhc2gAoK4igAJiY25wdACCIIYgiSCNIKIgbABhAACgByL1IXRlRGFnAADgICLSIACiSSJFaW9wlSCYIJwgniAA4HAqOANkAADgSyI4A3MASWFyAG8A+AAyCnUAcgBhoG4mbADzoG4mmwjzAa8gAACzIHAAO4CgAKBAbQBwAOXgTiI4AyoJgAJhZW91eQDBIMogzSDWINkg8AHGIAAAyCAAoEMqbwBuAEhh5CFpbEZhbgBnAGSgRyJvAHQAAOBtKjgDcAAAoEIqPWThIXNoAKATIACjYCJBYWRxc3jpIO0g+SD+IAIhDCFyAHIAAKDXIXIAAAFocvIg9SBrAACgJClvoJch9wAGD28AdAAA4FAiOAN1AGkA9gC7CAABZWkGIQohYQByAACgKCntAN8I6SFzdPOgBCLlCHIAAOA12CvdAAJFZXN0/wgcISshLiHxoXEiIiEAABMJ8aFxIgAJAAAnIWwAYQBuAPQAEwlpAO0AGQlyoG8iAKBvIoABQWFwADghOyE/IXIA8gBeIHIAcgAAoK4hYQByAACg8ipzogsiSiEAAAAAxwtkoPwiAKD6ImMAeQBaZIADQUVhZGVzdABcIV8hYiFmIWkhkyGWIXIA8gBXIADgZiI4A3IAcgAAoJohcgAAoCUggKFwImZxcwBwIYQhjiF0AAABYXJ1IXohcgByAG8A9wBlIWkAZwBoAHQAYQByAHIAbwD3AD4h8aFwImAhAACKIWwAYQBuAPQAZwlz4H0qOAMAoG4iaQDtAG0JcqBuImkA5aDqIkUJaQDkADoKAAFwdKMhpyFmAADgNdhf3YCBrAA7aW4AriGvIcchrEBuAIChCSJFZHYAtyG6Ib8hAOD5IjgDbwB0AADg9SI4A+EB1gjEIcYhAKD3IgCg9iJpAHagDCLhAagJzyHRIQCg/iIAoP0igAFhb3IA2CHsIfEhcgCAoSYiYXN0AOAh5SHpIWwAbABlAOwAywhsAADg/SrlIADgAiI4A2wiaW50AACgFCrjoYAi9yEAAPohdQDlAJsJY+CvKjgDZaCAIvEAkwkAAkFhaXQHIgoiFyIeInIA8gBsIHIAcgAAoZshY3cRIhQiAOAzKTgDAOCdITgDZyRodGFycm93AACgmyFyAGkA5aDrIr4JgANjaGltcHF1AC8iPCJHIpwhTSJQIloigKGBImNlcgA2Iv0JOSJ1AOUABgoA4DXYw9zvIXJ0bQKdIQAAAABEImEAcgDhAOEhbQBloEEi8aBEIiYKYQDyAMsIcwB1AAABYnBWIlgi5QDUCeUA3wmAAWJjcABgInMieCKAoYQiRWVzAGci7glqIgDgxSo4A2UAdABl4IIi0iBxAPGgiCJoImMAZaCBIvEA/gmAoYUiRWVzAH8iFgqCIgDgxio4A2UAdABl4IMi0iBxAPGgiSKAIgACZ2lscpIilCKaIpwi7AAMCWwAZABlADuA8QDxQOcAWwlpI2FuZ2xlAAABbHKkIqoi5SFmdGWg6iLxAEUJaSJnaHQAZaDrIvEAvgltoL0DAKEjAGVzuCK8InIAbwAAoBYhcAAAoAcggARESGFkZ2lscnMAziLSItYi2iLeIugi7SICIw8j4SFzaACgrSLhIXJyAKAEKXAAAOBNItIg4SFzaACgrCIAAWV04iLlIgDgZSLSIADgPgDSIG4iZmluAACg3imAAUFldADzIvci+iJyAHIAAKACKQDgZCLSIHLgPADSIGkAZQAA4LQi0iAAAUF0BiMKI3IAcgAAoAMp8iFpZQDgtSLSIGkAbQAA4Dwi0iCAAUFhbgAaIx4jKiNyAHIAAKDWIXIAAAFociMjJiNrAACgIylvoJYh9wD/DuUhYXIAoCcpUxJqFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVCMAAF4jaSN/I4IjjSOeI8AUAAAAAKYjwCMAANoj3yMAAO8jHiQvJD8kRCQAAWNzVyNsFHUAdABlADuA8wDzQAABaXlhI2cjcgBjoJoiO4D0APRAPmSAAmFiaW9zAHEjdCN3I3EBeiNzAOgAdhTsIWFjUWF2AACgOCrvIWxkAKC8KewhaWdTYQABY3KFI4kjaQByAACgvykA4DXYLN1vA5QjAAAAAJYjAACcI24A22JhAHYAZQA7gPIA8kAAoMEpAAFibaEjjAphAHIAAKC1KQACYWNpdKwjryO6I70jcgDyAFkUAAFpcrMjtiNyAACgvinvIXNzAKC7KW4A5QDZCgCgwCmAAWFlaQDFI8gjyyNjAHIATWFnAGEAyWOAAWNkbgDRI9Qj1iPyIW9uv2MAoLYpdQDzAHgBcABmAADgNdhg3YABYWVsAOQj5yPrI3IAAKC3KXIAcAAAoLkpdQDzAHwBAKMoImFkaW9zdvkj/CMPJBMkFiQbJHIA8gBeFIChXSplZm0AAyQJJAwkcgBvoDQhZgAAoDQhO4CqAKpAO4C6ALpA5yFvZgCgtiJyAACgVipsIm9wZQAAoFcqAKBbKoABY2xvACMkJSQrJPIACCRhAHMAaAA7gPgA+EBsAACgmCJpAGwBMyQ4JGQAZQA7gPUA9UBlAHMAYaCXInMAAKA2Km0AbAA7gPYA9kDiIWFyAKA9I+EKXiQAAHokAAB8JJQkAACYJKkkAAAAALUkEQsAAPAkAAAAAAQleiUAAIMlcgCAoSUiYXN0AGUkbyQBCwCBtgA7bGokayS2QGwAZQDsABgDaQJ1JAAAAAB4JG0AAKDzKgCg/Sp5AD9kcgCAAmNpbXB0AIUkiCSLJJkSjyRuAHQAJWBvAGQALmBpAGwAAKAwIOUhbmsAoDEgcgAA4DXYLd2AAWltbwCdJKAkpCR2oMYD1WNtAGEA9AD+B24AZQAAoA4m9KHAA64kAAC0JGMjaGZvcmsAAKDUItZjAAFhdbgkxCRuAAABY2u9JMIkawBooA8hAKAOIfYAaRpzAACkKwBhYmNkZW1zdNMkIRPXJNsk4STjJOck6yTjIWlyAKAjKmkAcgAAoCIqAAFvdYsW3yQAoCUqAKByKm4AO4CxALFAaQBtAACgJip3AG8AAKAnKoABaXB1APUk+iT+JO4idGludACgFSpmAADgNdhh3W4AZAA7gKMAo0CApHoiRWFjZWlub3N1ABMlFSUYJRslTCVRJVklSSV1JQCgsypwAACgtyp1AOUAPwtjoK8qgKJ6ImFjZW5zACclLSU0JTYlSSVwAHAAcgBvAPgAFyV1AHIAbAB5AGUA8QA/C/EAOAuAAWFlcwA8JUElRSXwInByb3gAoLkqcQBxAACgtSppAG0AAKDoImkA7QBEC20AZQDzoDIgIguAAUVhcwBDJVclRSXwAEAlgAFkZnAATwtfJXElgAFhbHMAZSVpJW0l7CFhcgCgLiPpIW5lAKASI/UhcmYAoBMjdKAdIu8AWQvyIWVsAKCwIgABY2l9JYElcgAA4DXYxdzIY24iY3NwAACgCCAAA2Zpb3BzdZElKxuVJZolnyWkJXIAAOA12C7dcABmAADgNdhi3XIiaW1lAACgVyBjAHIAAOA12MbcgAFhZW8AqiW6JcAldAAAAWVpryW2JXIAbgBpAG8AbgDzABkFbgB0AACgFipzAHQAZaA/APEACRj0AG0LgApBQkhhYmNkZWZoaWxtbm9wcnN0dXgA4yXyJfYl+iVpJpAmpia9JtUm5ib4JlonaCdxJ3UnnietJ7EnyCfiJ+cngAFhcnQA6SXsJe4lcgDyAJkM8gD6AuEhaWwAoBwpYQByAPIA3BVhAHIAAKBkKYADY2RlbnFydAAGJhAmEyYYJiYmKyZaJgABZXUKJg0mAOA9IjEDdABlAFVhaQDjACAN7SJwdHl2AKCzKWcAgKHpJ2RlbAAgJiImJCYAoJIpAKClKeUA9wt1AG8AO4C7ALtAcgAApZIhYWJjZmhscHN0dz0mQCZFJkcmSiZMJk4mUSZVJlgmcAAAoHUpZqDlIXMAAKAgKQCgMylzAACgHinrALka8ACVHmwAAKBFKWkAbQAAoHQpbAAAoKMhAKCdIQABYWleJmImaQBsAACgGilvAG6gNiJhAGwA8wB2C4ABYWJyAG8mciZ2JnIA8gAvEnIAawAAoHMnAAFha3omgSZjAAABZWt/JoAmfWBdYAABZXOFJocmAKCMKWwAAAFkdYwmjiYAoI4pAKCQKQACYWV1eZcmmiajJqUm8iFvbllhAAFkaZ4moSZpAGwAV2HsAA8M4gCAJkBkAAJjbHFzrSawJrUmuiZhAACgNylkImhhcgAAoGkpdQBvAPKgHSCjAWgAAKCzIYABYWNnAMMm0iaUC2wAgKEcIWlwcwDLJs4migxuAOUAoAxhAHIA9ADaC3QAAKCtJYABaWxyANsm3ybjJvMhaHQAoH0pbwBvAPIANgwA4DXYL90AAWFv6ib1JnIAAAFkde8m8SYAoMEhbKDAIQCgbCl2oMED8WOAAWducwD+Jk4nUCdoAHQAAANhaGxyc3QKJxInISc1Jz0nRydyInJvdwB0oJIhYQDpAFYmYSNycG9vbgAAAWR1GiceJ28AdwDuAPAmcAAAoMAh5SFmdAABYWgnJy0ncgByAG8AdwDzAAkMYQByAHAAbwBvAG4A8wATBGklZ2h0YXJyb3dzAACgySFxAHUAaQBnAGEAcgByAG8A9wBZJugkcmVldGltZXMAoMwiZwDaYmkAbgBnAGQAbwB0AHMAZQDxABwYgAFhaG0AYCdjJ2YncgDyAAkMYQDyABMEAKAPIG8idXN0AGGgsSPjIWhlAKCxI+0haWQAoO4qAAJhYnB0fCeGJ4knmScAAW5ygCeDJ2cAAKDtJ3IAAKD+IXIA6wAcDIABYWZsAI8nkieVJ3IAAKCGKQDgNdhj3XUAcwAAoC4qaSJtZXMAAKA1KgABYXCiJ6gncgBnoCkAdAAAoJQp7yJsaW50AKASKmEAcgDyADwnAAJhY2hxuCe8J6EMwCfxIXVvAKA6IHIAAOA12MfcAAFidYAmxCdvAPKgGSCoAYABaGlyAM4n0ifWJ3IAZQDlAE0n7SFlcwCgyiJpAIChuSVlZmwAXAxjEt4n9CFyaQCgzinsInVoYXIAoGgpAKAeIWENBSgJKA0oSyhVKIYoAACLKLAoAAAAAOMo5ygAABApJCkxKW0pcSmHKaYpAACYKgAAAACxKmMidXRlAFthcQB1AO8ABR+ApHsiRWFjZWlucHN5ABwoHignKCooLygyKEEoRihJKACgtCrwASMoAAAlKACguCpvAG4AYWF1AOUAgw1koLAqaQBsAF9hcgBjAF1hgAFFYXMAOCg6KD0oAKC2KnAAAKC6KmkAbQAAoOki7yJsaW50AKATKmkA7QCIDUFkbwB0AGKixSKRFgAAAABTKACgZiqAA0FhY21zdHgAYChkKG8ocyh1KHkogihyAHIAAKDYIXIAAAFocmkoayjrAJAab6CYIfcAzAd0ADuApwCnQGkAO2D3IWFyAKApKW0AAAFpbn4ozQBuAHUA8wDOAHQAAKA2J3IA7+A12DDdIxkAAmFjb3mRKJUonSisKHIAcAAAoG8mAAFoeZkonChjAHkASWRIZHIAdABtAqUoAAAAAKgoaQDkAFsPYQByAGEA7ABsJDuArQCtQAABZ22zKLsobQBhAAChwwNmdroouijCY4CjPCJkZWdsbnByAMgozCjPKNMo1yjaKN4obwB0AACgairxoEMiCw5FoJ4qAKCgKkWgnSoAoJ8qZQAAoEYi7CF1cwCgJCrhIXJyAKByKWEAcgDyAPwMAAJhZWl07Sj8KAEpCCkAAWxz8Sj4KGwAcwBlAHQAbQDpAH8oaABwAACgMyrwImFyc2wAoOQpAAFkbFoPBSllAACgIyNloKoqc6CsKgDgrCoA/oABZmxwABUpGCkfKfQhY3lMZGKgLwBhoMQpcgAAoD8jZgAA4DXYZN1hAAABZHIoKRcDZQBzAHWgYCZpAHQAAKBgJoABY3N1ADYpRilhKQABYXU6KUApcABzoJMiAOCTIgD+cABzoJQiAOCUIgD+dQAAAWJwSylWKQChjyJlcz4NUCllAHQAZaCPIvEAPw0AoZAiZXNIDVspZQB0AGWgkCLxAEkNAKGhJWFmZilbBHIAZQFrKVwEAKChJWEAcgDyAAMNAAJjZW10dyl7KX8pgilyAADgNdjI3HQAbQDuAM4AaQDsAAYpYQByAOYAVw0AAWFyiimOKXIA5qAGJhESAAFhbpIpoylpImdodAAAAWVwmSmgKXAAcwBpAGwAbwDuANkXaADpAKAkcwCvYIACYmNtbnAArin8KY4NJSooKgCkgiJFZGVtbnByc7wpvinCKcgpzCnUKdgp3CkAoMUqbwB0AACgvSpkoIYibwB0AACgwyr1IWx0AKDBKgABRWXQKdIpAKDLKgCgiiLsIXVzAKC/KuEhcnIAoHkpgAFlaXUA4inxKfQpdAAAoYIiZW7oKewpcQDxoIYivSllAHEA8aCKItEpbQAAoMcqAAFicPgp+ikAoNUqAKDTKmMAgKJ7ImFjZW5zAAcqDSoUKhYqRihwAHAAcgBvAPgAIyh1AHIAbAB5AGUA8QCDDfEAfA2AAWFlcwAcKiIqPShwAHAAcgBvAPgAPChxAPEAOShnAACgaiYApoMiMTIzRWRlaGxtbnBzPCo/KkIqRSpHKlIqWCpjKmcqaypzKncqO4C5ALlAO4CyALJAO4CzALNAAKDGKgABb3NLKk4qdAAAoL4qdQBiAACg2CpkoIcibwB0AACgxCpzAAABb3VdKmAqbAAAoMknYgAAoNcq4SFycgCgeyn1IWx0AKDCKgABRWVvKnEqAKDMKgCgiyLsIXVzAKDAKoABZWl1AH0qjCqPKnQAAKGDImVugyqHKnEA8aCHIkYqZQBxAPGgiyJwKm0AAKDIKgABYnCTKpUqAKDUKgCg1iqAAUFhbgCdKqEqrCpyAHIAAKDZIXIAAAFocqYqqCrrAJUab6CZIfcAxQf3IWFyAKAqKWwAaQBnADuA3wDfQOELzyrZKtwq6SrsKvEqAAD1KjQrAAAAAAAAAAAAAEwrbCsAAHErvSsAAAAAAADRK3IC1CoAAAAA2CrnIWV0AKAWI8RjcgDrAOUKgAFhZXkA4SrkKucq8iFvbmVh5CFpbGNhQmRvAPQAIg5sInJlYwAAoBUjcgAA4DXYMd0AAmVpa2/7KhIrKCsuK/IBACsAAAkrZQAAATRm6g0EK28AcgDlAOsNYQBzorgDECsAAAAAEit5AG0A0WMAAWNuFislK2sAAAFhcxsrIStwAHAAcgBvAPgAFw5pAG0AAKA8InMA8AD9DQABYXMsKyEr8AAXDnIAbgA7gP4A/kDsATgrOyswG2QA5QBnAmUAcwCAgdcAO2JkAEMrRCtJK9dAYaCgInIAAKAxKgCgMCqAAWVwcwBRK1MraSvhAAkh4qKkIlsrXysAAAAAYytvAHQAAKA2I2kAcgAAoPEqb+A12GXdcgBrAACg2irhAHgociJpbWUAAKA0IIABYWlwAHYreSu3K2QA5QC+DYADYWRlbXBzdACFK6MrmiunK6wrsCuzK24iZ2xlAACitSVkbHFykCuUK5ornCvvIXduAKC/JeUhZnRloMMl8QACBwCgXCJpImdodABloLkl8QBdDG8AdAAAoOwlaSJudXMAAKA6KuwhdXMAoDkqYgAAoM0p6SFtZQCgOyrlInppdW0AoOIjgAFjaHQAwivKK80rAAFyecYrySsA4DXYydxGZGMAeQBbZPIhb2tnYQABaW/UK9creAD0ANERaCJlYWQAAAFsct4r5ytlAGYAdABhAHIAcgBvAPcAXQbpJGdodGFycm93AKCgIQAJQUhhYmNkZmdobG1vcHJzdHV3CiwNLBEsHSwnLDEsQCxLLFIsYix6LIQsjyzLLOgs7Sz/LAotcgDyAAkDYQByAACgYykAAWNyFSwbLHUAdABlADuA+gD6QPIACQ1yAOMBIywAACUseQBeZHYAZQBtYQABaXkrLDAscgBjADuA+wD7QENkgAFhYmgANyw6LD0scgDyANEO7CFhY3FhYQDyAOAOAAFpckQsSCzzIWh0AKB+KQDgNdgy3XIAYQB2AGUAO4D5APlAYQFWLF8scgAAAWxyWixcLACgvyEAoL4hbABrAACggCUAAWN0Zix2LG8CbCwAAAAAcyxyAG4AZaAcI3IAAKAcI28AcAAAoA8jcgBpAACg+CUAAWFsfiyBLGMAcgBrYTuAqACoQAABZ3CILIssbwBuAHNhZgAA4DXYZt0AA2FkaGxzdZksniynLLgsuyzFLHIAcgBvAPcACQ1vAHcAbgBhAHIAcgBvAPcA2A5hI3Jwb29uAAABbHKvLLMsZQBmAPQAWyxpAGcAaAD0AF0sdQDzAKYOaQAAocUDaGzBLMIs0mNvAG4AxWPwI2Fycm93cwCgyCGAAWNpdADRLOEs5CxvAtcsAAAAAN4scgBuAGWgHSNyAACgHSNvAHAAAKAOI24AZwBvYXIAaQAAoPklYwByAADgNdjK3IABZGlyAPMs9yz6LG8AdAAAoPAi7CFkZWlhaQBmoLUlAKC0JQABYW0DLQYtcgDyAMosbAA7gPwA/EDhIm5nbGUAoKcpgAdBQkRhY2RlZmxub3Byc3oAJy0qLTAtNC2bLZ0toS2/LcMtxy3TLdgt3C3gLfwtcgDyABADYQByAHag6CoAoOkqYQBzAOgA/gIAAW5yOC08LechcnQAoJwpgANla25wcnN0AJkpSC1NLVQtXi1iLYItYQBwAHAA4QAaHG8AdABoAGkAbgDnAKEXgAFoaXIAoSmzJFotbwBwAPQAdCVooJUh7wD4JgABaXVmLWotZwBtAOEAuygAAWJwbi14LXMjZXRuZXEAceCKIgD+AODLKgD+cyNldG5lcQBx4IsiAP4A4MwqAP4AAWhyhi2KLWUAdADhABIraSNhbmdsZQAAAWxyki2WLeUhZnQAoLIiaSJnaHQAAKCzInkAMmThIXNoAKCiIoABZWxyAKcttC24LWKiKCKuLQAAAACyLWEAcgAAoLsicQAAoFoi7CFpcACg7iIAAWJ0vC1eD2EA8gBfD3IAAOA12DPddAByAOkAlS1zAHUAAAFicM0t0C0A4IIi0iAA4IMi0iBwAGYAAOA12GfdcgBvAPAAWQt0AHIA6QCaLQABY3XkLegtcgAA4DXYy9wAAWJw7C30LW4AAAFFZXUt8S0A4IoiAP5uAAABRWV/LfktAOCLIgD+6SJnemFnAKCaKYADY2Vmb3BycwANLhAuJS4pLiMuLi40LukhcmN1YQABZGkULiEuAAFiZxguHC5hAHIAAKBfKmUAcaAnIgCgWSLlIXJwAKAYIXIAAOA12DTdcABmAADgNdho3WWgQCJhAHQA6ABqD2MAcgAA4DXYzNzjCuQRUC4AAFQuAABYLmIuAAAAAGMubS5wLnQuAAAAAIguki4AAJouJxIqEnQAcgDpAB0ScgAA4DXYNd0AAUFhWy5eLnIA8gDnAnIA8gCTB75jAAFBYWYuaS5yAPIA4AJyAPIAjAdhAPAAeh5pAHMAAKD7IoABZHB0APgReS6DLgABZmx9LoAuAOA12GnddQDzAP8RaQBtAOUABBIAAUFhiy6OLnIA8gDuAnIA8gCaBwABY3GVLgoScgAA4DXYzdwAAXB0nS6hLmwAdQDzACUScgDpACASAARhY2VmaW9zdbEuvC7ELsguzC7PLtQu2S5jAAABdXm2LrsudABlADuA/QD9QE9kAAFpecAuwy5yAGMAd2FLZG4AO4ClAKVAcgAA4DXYNt1jAHkAV2RwAGYAAOA12GrdYwByAADgNdjO3AABY23dLt8ueQBOZGwAO4D/AP9AAAVhY2RlZmhpb3N38y73Lv8uAi8MLxAvEy8YLx0vIi9jInV0ZQB6YQABYXn7Lv4u8iFvbn5hN2RvAHQAfGEAAWV0Bi8KL3QAcgDmAB8QYQC2Y3IAAOA12DfdYwB5ADZk5yJyYXJyAKDdIXAAZgAA4DXYa91jAHIAAOA12M/cAAFqbiYvKC8AoA0gagAAoAwg"); - } -}); - -// node_modules/entities/dist/esm/generated/decode-data-xml.js -var xmlDecodeTree; -var init_decode_data_xml = __esm({ - "node_modules/entities/dist/esm/generated/decode-data-xml.js"() { - init_decode_shared(); - xmlDecodeTree = /* @__PURE__ */ decodeBase64("AAJhZ2xxBwARABMAFQBtAg0AAAAAAA8AcAAmYG8AcwAnYHQAPmB0ADxg9SFvdCJg"); - } -}); - -// node_modules/entities/dist/esm/internal/bin-trie-flags.js -var BinTrieFlags; -var init_bin_trie_flags = __esm({ - "node_modules/entities/dist/esm/internal/bin-trie-flags.js"() { - (function(BinTrieFlags2) { - BinTrieFlags2[BinTrieFlags2["VALUE_LENGTH"] = 49152] = "VALUE_LENGTH"; - BinTrieFlags2[BinTrieFlags2["FLAG13"] = 8192] = "FLAG13"; - BinTrieFlags2[BinTrieFlags2["BRANCH_LENGTH"] = 8064] = "BRANCH_LENGTH"; - BinTrieFlags2[BinTrieFlags2["JUMP_TABLE"] = 127] = "JUMP_TABLE"; - })(BinTrieFlags || (BinTrieFlags = {})); - } -}); - -// node_modules/entities/dist/esm/decode.js -function isNumber(code) { - return code >= CharCodes.ZERO && code <= CharCodes.NINE; -} -function isHexadecimalCharacter(code) { - return code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_F || code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_F; -} -function isAsciiAlphaNumeric(code) { - return code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_Z || code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_Z || isNumber(code); -} -function isEntityInAttributeInvalidEnd(code) { - return code === CharCodes.EQUALS || isAsciiAlphaNumeric(code); -} -function getDecoder(decodeTree) { - let returnValue2 = ""; - const decoder = new EntityDecoder(decodeTree, (data2) => returnValue2 += fromCodePoint(data2)); - return function decodeWithTrie(input, decodeMode) { - let lastIndex = 0; - let offset2 = 0; - while ((offset2 = input.indexOf("&", offset2)) >= 0) { - returnValue2 += input.slice(lastIndex, offset2); - decoder.startEntity(decodeMode); - const length2 = decoder.write( - input, - // Skip the "&" - offset2 + 1 - ); - if (length2 < 0) { - lastIndex = offset2 + decoder.end(); - break; - } - lastIndex = offset2 + length2; - offset2 = length2 === 0 ? lastIndex + 1 : lastIndex; - } - const result3 = returnValue2 + input.slice(lastIndex); - returnValue2 = ""; - return result3; - }; -} -function determineBranch(decodeTree, current, nodeIndex, char) { - const branchCount = (current & BinTrieFlags.BRANCH_LENGTH) >> 7; - const jumpOffset = current & BinTrieFlags.JUMP_TABLE; - if (branchCount === 0) { - return jumpOffset !== 0 && char === jumpOffset ? nodeIndex : -1; - } - if (jumpOffset) { - const value2 = char - jumpOffset; - return value2 < 0 || value2 >= branchCount ? -1 : decodeTree[nodeIndex + value2] - 1; - } - const packedKeySlots = branchCount + 1 >> 1; - let lo = 0; - let hi = branchCount - 1; - while (lo <= hi) { - const mid = lo + hi >>> 1; - const slot = mid >> 1; - const packed = decodeTree[nodeIndex + slot]; - const midKey = packed >> (mid & 1) * 8 & 255; - if (midKey < char) { - lo = mid + 1; - } else if (midKey > char) { - hi = mid - 1; - } else { - return decodeTree[nodeIndex + packedKeySlots + mid]; - } - } - return -1; -} -function decodeHTML(htmlString, mode2 = DecodingMode.Legacy) { - return htmlDecoder(htmlString, mode2); -} -function decodeHTMLAttribute(htmlAttribute) { - return htmlDecoder(htmlAttribute, DecodingMode.Attribute); -} -function decodeXML(xmlString) { - return xmlDecoder(xmlString, DecodingMode.Strict); -} -var CharCodes, TO_LOWER_BIT, EntityDecoderState, DecodingMode, EntityDecoder, htmlDecoder, xmlDecoder; -var init_decode = __esm({ - "node_modules/entities/dist/esm/decode.js"() { - init_decode_codepoint(); - init_decode_data_html(); - init_decode_data_xml(); - init_bin_trie_flags(); - init_decode_codepoint(); - init_decode_data_html(); - init_decode_data_xml(); - (function(CharCodes2) { - CharCodes2[CharCodes2["NUM"] = 35] = "NUM"; - CharCodes2[CharCodes2["SEMI"] = 59] = "SEMI"; - CharCodes2[CharCodes2["EQUALS"] = 61] = "EQUALS"; - CharCodes2[CharCodes2["ZERO"] = 48] = "ZERO"; - CharCodes2[CharCodes2["NINE"] = 57] = "NINE"; - CharCodes2[CharCodes2["LOWER_A"] = 97] = "LOWER_A"; - CharCodes2[CharCodes2["LOWER_F"] = 102] = "LOWER_F"; - CharCodes2[CharCodes2["LOWER_X"] = 120] = "LOWER_X"; - CharCodes2[CharCodes2["LOWER_Z"] = 122] = "LOWER_Z"; - CharCodes2[CharCodes2["UPPER_A"] = 65] = "UPPER_A"; - CharCodes2[CharCodes2["UPPER_F"] = 70] = "UPPER_F"; - CharCodes2[CharCodes2["UPPER_Z"] = 90] = "UPPER_Z"; - })(CharCodes || (CharCodes = {})); - TO_LOWER_BIT = 32; - (function(EntityDecoderState2) { - EntityDecoderState2[EntityDecoderState2["EntityStart"] = 0] = "EntityStart"; - EntityDecoderState2[EntityDecoderState2["NumericStart"] = 1] = "NumericStart"; - EntityDecoderState2[EntityDecoderState2["NumericDecimal"] = 2] = "NumericDecimal"; - EntityDecoderState2[EntityDecoderState2["NumericHex"] = 3] = "NumericHex"; - EntityDecoderState2[EntityDecoderState2["NamedEntity"] = 4] = "NamedEntity"; - })(EntityDecoderState || (EntityDecoderState = {})); - (function(DecodingMode2) { - DecodingMode2[DecodingMode2["Legacy"] = 0] = "Legacy"; - DecodingMode2[DecodingMode2["Strict"] = 1] = "Strict"; - DecodingMode2[DecodingMode2["Attribute"] = 2] = "Attribute"; - })(DecodingMode || (DecodingMode = {})); - EntityDecoder = class { - constructor(decodeTree, emitCodePoint, errors) { - this.decodeTree = decodeTree; - this.emitCodePoint = emitCodePoint; - this.errors = errors; - this.state = EntityDecoderState.EntityStart; - this.consumed = 1; - this.result = 0; - this.treeIndex = 0; - this.excess = 1; - this.decodeMode = DecodingMode.Strict; - this.runConsumed = 0; - } - /** Resets the instance to make it reusable. */ - startEntity(decodeMode) { - this.decodeMode = decodeMode; - this.state = EntityDecoderState.EntityStart; - this.result = 0; - this.treeIndex = 0; - this.excess = 1; - this.consumed = 1; - this.runConsumed = 0; - } - /** - * Write an entity to the decoder. This can be called multiple times with partial entities. - * If the entity is incomplete, the decoder will return -1. - * - * Mirrors the implementation of `getDecoder`, but with the ability to stop decoding if the - * entity is incomplete, and resume when the next string is written. - * - * @param input The string containing the entity (or a continuation of the entity). - * @param offset The offset at which the entity begins. Should be 0 if this is not the first call. - * @returns The number of characters that were consumed, or -1 if the entity is incomplete. - */ - write(input, offset2) { - switch (this.state) { - case EntityDecoderState.EntityStart: { - if (input.charCodeAt(offset2) === CharCodes.NUM) { - this.state = EntityDecoderState.NumericStart; - this.consumed += 1; - return this.stateNumericStart(input, offset2 + 1); - } - this.state = EntityDecoderState.NamedEntity; - return this.stateNamedEntity(input, offset2); - } - case EntityDecoderState.NumericStart: { - return this.stateNumericStart(input, offset2); - } - case EntityDecoderState.NumericDecimal: { - return this.stateNumericDecimal(input, offset2); - } - case EntityDecoderState.NumericHex: { - return this.stateNumericHex(input, offset2); - } - case EntityDecoderState.NamedEntity: { - return this.stateNamedEntity(input, offset2); - } - } - } - /** - * Switches between the numeric decimal and hexadecimal states. - * - * Equivalent to the `Numeric character reference state` in the HTML spec. - * - * @param input The string containing the entity (or a continuation of the entity). - * @param offset The current offset. - * @returns The number of characters that were consumed, or -1 if the entity is incomplete. - */ - stateNumericStart(input, offset2) { - if (offset2 >= input.length) { - return -1; - } - if ((input.charCodeAt(offset2) | TO_LOWER_BIT) === CharCodes.LOWER_X) { - this.state = EntityDecoderState.NumericHex; - this.consumed += 1; - return this.stateNumericHex(input, offset2 + 1); - } - this.state = EntityDecoderState.NumericDecimal; - return this.stateNumericDecimal(input, offset2); - } - /** - * Parses a hexadecimal numeric entity. - * - * Equivalent to the `Hexademical character reference state` in the HTML spec. - * - * @param input The string containing the entity (or a continuation of the entity). - * @param offset The current offset. - * @returns The number of characters that were consumed, or -1 if the entity is incomplete. - */ - stateNumericHex(input, offset2) { - while (offset2 < input.length) { - const char = input.charCodeAt(offset2); - if (isNumber(char) || isHexadecimalCharacter(char)) { - const digit = char <= CharCodes.NINE ? char - CharCodes.ZERO : (char | TO_LOWER_BIT) - CharCodes.LOWER_A + 10; - this.result = this.result * 16 + digit; - this.consumed++; - offset2++; - } else { - return this.emitNumericEntity(char, 3); - } - } - return -1; - } - /** - * Parses a decimal numeric entity. - * - * Equivalent to the `Decimal character reference state` in the HTML spec. - * - * @param input The string containing the entity (or a continuation of the entity). - * @param offset The current offset. - * @returns The number of characters that were consumed, or -1 if the entity is incomplete. - */ - stateNumericDecimal(input, offset2) { - while (offset2 < input.length) { - const char = input.charCodeAt(offset2); - if (isNumber(char)) { - this.result = this.result * 10 + (char - CharCodes.ZERO); - this.consumed++; - offset2++; - } else { - return this.emitNumericEntity(char, 2); - } - } - return -1; - } - /** - * Validate and emit a numeric entity. - * - * Implements the logic from the `Hexademical character reference start - * state` and `Numeric character reference end state` in the HTML spec. - * - * @param lastCp The last code point of the entity. Used to see if the - * entity was terminated with a semicolon. - * @param expectedLength The minimum number of characters that should be - * consumed. Used to validate that at least one digit - * was consumed. - * @returns The number of characters that were consumed. - */ - emitNumericEntity(lastCp, expectedLength) { - var _a3; - if (this.consumed <= expectedLength) { - (_a3 = this.errors) === null || _a3 === void 0 ? void 0 : _a3.absenceOfDigitsInNumericCharacterReference(this.consumed); - return 0; - } - if (lastCp === CharCodes.SEMI) { - this.consumed += 1; - } else if (this.decodeMode === DecodingMode.Strict) { - return 0; - } - this.emitCodePoint(replaceCodePoint(this.result), this.consumed); - if (this.errors) { - if (lastCp !== CharCodes.SEMI) { - this.errors.missingSemicolonAfterCharacterReference(); - } - this.errors.validateNumericCharacterReference(this.result); - } - return this.consumed; - } - /** - * Parses a named entity. - * - * Equivalent to the `Named character reference state` in the HTML spec. - * - * @param input The string containing the entity (or a continuation of the entity). - * @param offset The current offset. - * @returns The number of characters that were consumed, or -1 if the entity is incomplete. - */ - stateNamedEntity(input, offset2) { - const { decodeTree } = this; - let current = decodeTree[this.treeIndex]; - let valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; - while (offset2 < input.length) { - if (valueLength === 0 && (current & BinTrieFlags.FLAG13) !== 0) { - const runLength = (current & BinTrieFlags.BRANCH_LENGTH) >> 7; - if (this.runConsumed === 0) { - const firstChar = current & BinTrieFlags.JUMP_TABLE; - if (input.charCodeAt(offset2) !== firstChar) { - return this.result === 0 ? 0 : this.emitNotTerminatedNamedEntity(); - } - offset2++; - this.excess++; - this.runConsumed++; - } - while (this.runConsumed < runLength) { - if (offset2 >= input.length) { - return -1; - } - const charIndexInPacked = this.runConsumed - 1; - const packedWord = decodeTree[this.treeIndex + 1 + (charIndexInPacked >> 1)]; - const expectedChar = charIndexInPacked % 2 === 0 ? packedWord & 255 : packedWord >> 8 & 255; - if (input.charCodeAt(offset2) !== expectedChar) { - this.runConsumed = 0; - return this.result === 0 ? 0 : this.emitNotTerminatedNamedEntity(); - } - offset2++; - this.excess++; - this.runConsumed++; - } - this.runConsumed = 0; - this.treeIndex += 1 + (runLength >> 1); - current = decodeTree[this.treeIndex]; - valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; - } - if (offset2 >= input.length) - break; - const char = input.charCodeAt(offset2); - if (char === CharCodes.SEMI && valueLength !== 0 && (current & BinTrieFlags.FLAG13) !== 0) { - return this.emitNamedEntityData(this.treeIndex, valueLength, this.consumed + this.excess); - } - this.treeIndex = determineBranch(decodeTree, current, this.treeIndex + Math.max(1, valueLength), char); - if (this.treeIndex < 0) { - return this.result === 0 || // If we are parsing an attribute - this.decodeMode === DecodingMode.Attribute && // We shouldn't have consumed any characters after the entity, - (valueLength === 0 || // And there should be no invalid characters. - isEntityInAttributeInvalidEnd(char)) ? 0 : this.emitNotTerminatedNamedEntity(); - } - current = decodeTree[this.treeIndex]; - valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; - if (valueLength !== 0) { - if (char === CharCodes.SEMI) { - return this.emitNamedEntityData(this.treeIndex, valueLength, this.consumed + this.excess); - } - if (this.decodeMode !== DecodingMode.Strict && (current & BinTrieFlags.FLAG13) === 0) { - this.result = this.treeIndex; - this.consumed += this.excess; - this.excess = 0; - } - } - offset2++; - this.excess++; - } - return -1; - } - /** - * Emit a named entity that was not terminated with a semicolon. - * - * @returns The number of characters consumed. - */ - emitNotTerminatedNamedEntity() { - var _a3; - const { result: result3, decodeTree } = this; - const valueLength = (decodeTree[result3] & BinTrieFlags.VALUE_LENGTH) >> 14; - this.emitNamedEntityData(result3, valueLength, this.consumed); - (_a3 = this.errors) === null || _a3 === void 0 ? void 0 : _a3.missingSemicolonAfterCharacterReference(); - return this.consumed; - } - /** - * Emit a named entity. - * - * @param result The index of the entity in the decode tree. - * @param valueLength The number of bytes in the entity. - * @param consumed The number of characters consumed. - * - * @returns The number of characters consumed. - */ - emitNamedEntityData(result3, valueLength, consumed) { - const { decodeTree } = this; - this.emitCodePoint(valueLength === 1 ? decodeTree[result3] & ~(BinTrieFlags.VALUE_LENGTH | BinTrieFlags.FLAG13) : decodeTree[result3 + 1], consumed); - if (valueLength === 3) { - this.emitCodePoint(decodeTree[result3 + 2], consumed); - } - return consumed; - } - /** - * Signal to the parser that the end of the input was reached. - * - * Remaining data will be emitted and relevant errors will be produced. - * - * @returns The number of characters consumed. - */ - end() { - var _a3; - switch (this.state) { - case EntityDecoderState.NamedEntity: { - return this.result !== 0 && (this.decodeMode !== DecodingMode.Attribute || this.result === this.treeIndex) ? this.emitNotTerminatedNamedEntity() : 0; - } - // Otherwise, emit a numeric entity if we have one. - case EntityDecoderState.NumericDecimal: { - return this.emitNumericEntity(0, 2); - } - case EntityDecoderState.NumericHex: { - return this.emitNumericEntity(0, 3); - } - case EntityDecoderState.NumericStart: { - (_a3 = this.errors) === null || _a3 === void 0 ? void 0 : _a3.absenceOfDigitsInNumericCharacterReference(this.consumed); - return 0; - } - case EntityDecoderState.EntityStart: { - return 0; - } - } - } - }; - htmlDecoder = /* @__PURE__ */ getDecoder(htmlDecodeTree); - xmlDecoder = /* @__PURE__ */ getDecoder(xmlDecodeTree); - } -}); - -// node_modules/entities/dist/esm/escape.js -function getEscaper(regex, map) { - return function escape2(data2) { - let match; - let lastIndex = 0; - let result3 = ""; - while (match = regex.exec(data2)) { - if (lastIndex !== match.index) { - result3 += data2.substring(lastIndex, match.index); - } - result3 += map.get(match[0].charCodeAt(0)); - lastIndex = match.index + 1; - } - return result3 + data2.substring(lastIndex); - }; -} -var getCodePoint, escapeText; -var init_escape = __esm({ - "node_modules/entities/dist/esm/escape.js"() { - getCodePoint = // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - String.prototype.codePointAt == null ? (c, index) => (c.charCodeAt(index) & 64512) === 55296 ? (c.charCodeAt(index) - 55296) * 1024 + c.charCodeAt(index + 1) - 56320 + 65536 : c.charCodeAt(index) : ( - // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae - (input, index) => input.codePointAt(index) - ); - escapeText = /* @__PURE__ */ getEscaper(/[&<>\u00A0]/g, /* @__PURE__ */ new Map([ - [38, "&"], - [60, "<"], - [62, ">"], - [160, " "] - ])); - } -}); - -// node_modules/entities/dist/esm/internal/encode-shared.js -var init_encode_shared = __esm({ - "node_modules/entities/dist/esm/internal/encode-shared.js"() { - } -}); - -// node_modules/entities/dist/esm/generated/encode-html.js -var init_encode_html = __esm({ - "node_modules/entities/dist/esm/generated/encode-html.js"() { - init_encode_shared(); - } -}); - -// node_modules/entities/dist/esm/encode.js -var init_encode = __esm({ - "node_modules/entities/dist/esm/encode.js"() { - init_escape(); - init_encode_html(); - } -}); - -// node_modules/entities/dist/esm/index.js -var EntityLevel, EncodingMode; -var init_esm = __esm({ - "node_modules/entities/dist/esm/index.js"() { - init_decode(); - init_encode(); - init_escape(); - init_decode(); - init_encode(); - init_escape(); - (function(EntityLevel2) { - EntityLevel2[EntityLevel2["XML"] = 0] = "XML"; - EntityLevel2[EntityLevel2["HTML"] = 1] = "HTML"; - })(EntityLevel || (EntityLevel = {})); - (function(EncodingMode2) { - EncodingMode2[EncodingMode2["UTF8"] = 0] = "UTF8"; - EncodingMode2[EncodingMode2["ASCII"] = 1] = "ASCII"; - EncodingMode2[EncodingMode2["Extensive"] = 2] = "Extensive"; - EncodingMode2[EncodingMode2["Attribute"] = 3] = "Attribute"; - EncodingMode2[EncodingMode2["Text"] = 4] = "Text"; - })(EncodingMode || (EncodingMode = {})); - } -}); - -// node_modules/happy-dom/lib/utilities/XMLEncodeUtility.js -var ENCODE_XML_ATTR_REGEXP, ENCODE_HTML_ATTR_REGEXP, DECODE_TEXT_CONTENT_REGEXP, ENCODE_XML_ATTR_MAP, ENCODE_HTML_ATTR_MAP, DECODE_TEXT_CONTENT_MAP, XMLEncodeUtility; -var init_XMLEncodeUtility = __esm({ - "node_modules/happy-dom/lib/utilities/XMLEncodeUtility.js"() { - init_esm(); - ENCODE_XML_ATTR_REGEXP = /[&"<>\t\n\r]/g; - ENCODE_HTML_ATTR_REGEXP = /[&"]/g; - DECODE_TEXT_CONTENT_REGEXP = /&(?:nbsp|lt|gt|amp);/g; - ENCODE_XML_ATTR_MAP = { - "&": "&", - '"': """, - "<": "<", - ">": ">", - " ": " ", - "\n": " ", - "\r": " " - }; - ENCODE_HTML_ATTR_MAP = { - "&": "&", - '"': """ - }; - DECODE_TEXT_CONTENT_MAP = { - " ": String.fromCharCode(160), - "<": "<", - ">": ">", - "&": "&" - }; - XMLEncodeUtility = class { - /** - * Encodes attribute value. - * - * @param value Value. - * @returns Escaped value. - */ - static encodeXMLAttributeValue(value2) { - if (value2 === null) { - return ""; - } - return value2.replace(ENCODE_XML_ATTR_REGEXP, (char) => ENCODE_XML_ATTR_MAP[char]); - } - /** - * Decodes attribute value. - * - * Uses the 'entities' library for comprehensive XML character reference support. - * - * @param value Value. - * @returns Decoded value. - */ - static decodeXMLAttributeValue(value2) { - if (value2 === null) { - return ""; - } - return decodeXML(value2); - } - /** - * Encodes attribute value. - * - * @param value Value. - * @returns Escaped value. - */ - static encodeHTMLAttributeValue(value2) { - if (value2 === null) { - return ""; - } - return value2.replace(ENCODE_HTML_ATTR_REGEXP, (char) => ENCODE_HTML_ATTR_MAP[char]); - } - /** - * Decodes attribute value. - * - * Uses the 'entities' library for comprehensive HTML5 character reference support, - * including named entities, decimal numeric references ("), and - * hexadecimal numeric references ("). - * - * @param value Value. - * @returns Decoded value. - */ - static decodeHTMLAttributeValue(value2) { - if (value2 === null) { - return ""; - } - return decodeHTMLAttribute(value2); - } - /** - * Encodes text content. - * - * Uses the 'entities' library which follows the WHATWG HTML serialization spec. - * Encodes &, <, >, and non-breaking space. - * - * @param text Value. - * @returns Escaped value. - */ - static encodeTextContent(text) { - if (text === null) { - return ""; - } - return escapeText(text); - } - /** - * Decodes text content. - * - * @param text Value. - * @returns Decoded value. - */ - static decodeTextContent(text) { - if (text === null) { - return ""; - } - return text.replace(DECODE_TEXT_CONTENT_REGEXP, (entity) => DECODE_TEXT_CONTENT_MAP[entity]); - } - /** - * Decodes HTML entities. - * - * Uses the 'entities' library for comprehensive HTML5 named character reference support. - * - * @param value Value. - * @returns Decoded value. - */ - static decodeHTMLEntities(value2) { - if (value2 === null) { - return ""; - } - return decodeHTML(value2); - } - /** - * Decodes XML entities. - * - * Uses the 'entities' library for comprehensive XML character reference support, - * including named entities and numeric references. - * - * @param value Value. - * @returns Decoded value. - */ - static decodeXMLEntities(value2) { - if (value2 === null) { - return ""; - } - return decodeXML(value2); - } - }; - } -}); - -// node_modules/happy-dom/lib/html-serializer/HTMLSerializer.js -var HTMLSerializer; -var init_HTMLSerializer = __esm({ - "node_modules/happy-dom/lib/html-serializer/HTMLSerializer.js"() { - init_PropertySymbol(); - init_Node(); - init_NodeTypeEnum(); - init_HTMLElementConfig(); - init_HTMLElementConfigContentModelEnum(); - init_XMLEncodeUtility(); - HTMLSerializer = class { - options = { - serializableShadowRoots: false, - shadowRoots: null, - allShadowRoots: false, - excludeShadowRootTags: null - }; - /** - * Constructor. - * - * @param [options] Options. - * @param [options.serializableShadowRoots] If shadow roots should be serialized. - * @param [options.shadowRoots] Shadow roots to serialize. - * @param [options.allShadowRoots] If all shadow roots should be serialized. - * @param [options.excludeShadowRootTags] Tags to exclude from serialization. - */ - constructor(options2) { - if (options2) { - if (options2.serializableShadowRoots) { - this.options.serializableShadowRoots = options2.serializableShadowRoots; - } - if (options2.shadowRoots) { - this.options.shadowRoots = options2.shadowRoots; - } - if (options2.allShadowRoots) { - this.options.allShadowRoots = options2.allShadowRoots; - } - if (options2.excludeShadowRootTags) { - this.options.excludeShadowRootTags = options2.excludeShadowRootTags; - } - } - } - /** - * Renders an element as HTML. - * - * @param root Root element. - * @returns Result. - */ - serializeToString(root2) { - switch (root2[nodeType]) { - case NodeTypeEnum_default.elementNode: - const element = root2; - const prefix2 = element[prefix]; - const localName2 = element[localName]; - const config = HTMLElementConfig_default[element[localName]]; - const tagName2 = prefix2 ? `${prefix2}:${localName2}` : localName2; - if (config?.contentModel === HTMLElementConfigContentModelEnum_default.noDescendants) { - return `<${tagName2}${this.getAttributes(element)}>`; - } - let innerHTML = ""; - if (element.shadowRoot && (this.options.allShadowRoots || this.options.serializableShadowRoots && element.shadowRoot[serializable] || this.options.shadowRoots?.includes(element.shadowRoot)) && (!this.options.excludeShadowRootTags || !this.options.excludeShadowRootTags.includes(tagName2))) { - innerHTML += `"; - } - const childNodes2 = tagName2 === "template" ? root2.content[nodeArray] : root2[nodeArray]; - for (const node of childNodes2) { - innerHTML += this.serializeToString(node); - } - return `<${tagName2}${this.getAttributes(element)}>${innerHTML}`; - case Node.DOCUMENT_FRAGMENT_NODE: - case Node.DOCUMENT_NODE: - let html = ""; - for (const node of root2[nodeArray]) { - html += this.serializeToString(node); - } - return html; - case NodeTypeEnum_default.commentNode: - return ``; - case NodeTypeEnum_default.processingInstructionNode: - return ``; - case NodeTypeEnum_default.textNode: - const parentElement = root2.parentElement; - if (parentElement) { - const parentConfig = HTMLElementConfig_default[parentElement[localName]]; - if (parentConfig?.contentModel === HTMLElementConfigContentModelEnum_default.rawText) { - return root2.textContent; - } - } - return XMLEncodeUtility.encodeTextContent(root2.textContent); - case NodeTypeEnum_default.documentTypeNode: - const doctype = root2; - const identifier = doctype.publicId ? " PUBLIC" : doctype.systemId ? " SYSTEM" : ""; - const publicId2 = doctype.publicId ? ` "${doctype.publicId}"` : ""; - const systemId2 = doctype.systemId ? ` "${doctype.systemId}"` : ""; - return ``; - } - return ""; - } - /** - * Returns attributes as a string. - * - * @param element Element. - * @returns Attributes. - */ - getAttributes(element) { - let attributeString = ""; - const attributes2 = element[attributes][items]; - if (!attributes2.has(":is") && element[isValue]) { - attributeString += ' is="' + XMLEncodeUtility.encodeHTMLAttributeValue(element[isValue]) + '"'; - } - for (const attribute of attributes2.values()) { - const escapedValue = XMLEncodeUtility.encodeHTMLAttributeValue(attribute[value]); - attributeString += " " + attribute[name] + '="' + escapedValue + '"'; - } - return attributeString; - } - }; - } -}); - -// node_modules/happy-dom/lib/config/SVGElementConfig.js -var SVGElementConfig_default; -var init_SVGElementConfig = __esm({ - "node_modules/happy-dom/lib/config/SVGElementConfig.js"() { - SVGElementConfig_default = { - svg: { localName: "svg", className: "SVGSVGElement" }, - animate: { localName: "animate", className: "SVGAnimateElement" }, - animatemotion: { localName: "animateMotion", className: "SVGAnimateMotionElement" }, - animatetransform: { localName: "animateTransform", className: "SVGAnimateTransformElement" }, - circle: { localName: "circle", className: "SVGCircleElement" }, - clippath: { localName: "clipPath", className: "SVGClipPathElement" }, - defs: { localName: "defs", className: "SVGDefsElement" }, - desc: { localName: "desc", className: "SVGDescElement" }, - ellipse: { localName: "ellipse", className: "SVGEllipseElement" }, - feblend: { localName: "feBlend", className: "SVGFEBlendElement" }, - fecolormatrix: { localName: "feColorMatrix", className: "SVGFEColorMatrixElement" }, - fecomponenttransfer: { - localName: "feComponentTransfer", - className: "SVGFEComponentTransferElement" - }, - fecomposite: { localName: "feComposite", className: "SVGFECompositeElement" }, - feconvolvematrix: { localName: "feConvolveMatrix", className: "SVGFEConvolveMatrixElement" }, - fediffuselighting: { localName: "feDiffuseLighting", className: "SVGFEDiffuseLightingElement" }, - fedisplacementmap: { localName: "feDisplacementMap", className: "SVGFEDisplacementMapElement" }, - fedistantlight: { localName: "feDistantLight", className: "SVGFEDistantLightElement" }, - fedropshadow: { localName: "feDropShadow", className: "SVGFEDropShadowElement" }, - feflood: { localName: "feFlood", className: "SVGFEFloodElement" }, - fefunca: { localName: "feFuncA", className: "SVGFEFuncAElement" }, - fefuncb: { localName: "feFuncB", className: "SVGFEFuncBElement" }, - fefuncg: { localName: "feFuncG", className: "SVGFEFuncGElement" }, - fefuncr: { localName: "feFuncR", className: "SVGFEFuncRElement" }, - fegaussianblur: { localName: "feGaussianBlur", className: "SVGFEGaussianBlurElement" }, - feimage: { localName: "feImage", className: "SVGFEImageElement" }, - femerge: { localName: "feMerge", className: "SVGFEMergeElement" }, - femergenode: { localName: "feMergeNode", className: "SVGFEMergeNodeElement" }, - femorphology: { localName: "feMorphology", className: "SVGFEMorphologyElement" }, - feoffset: { localName: "feOffset", className: "SVGFEOffsetElement" }, - fepointlight: { localName: "fePointLight", className: "SVGFEPointLightElement" }, - fespecularlighting: { - localName: "feSpecularLighting", - className: "SVGFESpecularLightingElement" - }, - fespotlight: { localName: "feSpotLight", className: "SVGFESpotLightElement" }, - fetile: { localName: "feTile", className: "SVGFETileElement" }, - feturbulence: { localName: "feTurbulence", className: "SVGFETurbulenceElement" }, - filter: { localName: "filter", className: "SVGFilterElement" }, - foreignobject: { localName: "foreignObject", className: "SVGForeignObjectElement" }, - g: { localName: "g", className: "SVGGElement" }, - image: { localName: "image", className: "SVGImageElement" }, - line: { localName: "line", className: "SVGLineElement" }, - lineargradient: { localName: "linearGradient", className: "SVGLinearGradientElement" }, - marker: { localName: "marker", className: "SVGMarkerElement" }, - mask: { localName: "mask", className: "SVGMaskElement" }, - metadata: { localName: "metadata", className: "SVGMetadataElement" }, - mpath: { localName: "mpath", className: "SVGMPathElement" }, - path: { localName: "path", className: "SVGPathElement" }, - pattern: { localName: "pattern", className: "SVGPatternElement" }, - polygon: { localName: "polygon", className: "SVGPolygonElement" }, - polyline: { localName: "polyline", className: "SVGPolylineElement" }, - radialgradient: { localName: "radialGradient", className: "SVGRadialGradientElement" }, - rect: { localName: "rect", className: "SVGRectElement" }, - script: { localName: "script", className: "SVGScriptElement" }, - set: { localName: "set", className: "SVGSetElement" }, - stop: { localName: "stop", className: "SVGStopElement" }, - style: { localName: "style", className: "SVGStyleElement" }, - switch: { localName: "switch", className: "SVGSwitchElement" }, - symbol: { localName: "symbol", className: "SVGSymbolElement" }, - text: { localName: "text", className: "SVGTextElement" }, - textpath: { localName: "textPath", className: "SVGTextPathElement" }, - title: { localName: "title", className: "SVGTitleElement" }, - tspan: { localName: "tspan", className: "SVGTSpanElement" }, - use: { localName: "use", className: "SVGUseElement" }, - view: { localName: "view", className: "SVGViewElement" } - }; - } -}); - -// node_modules/happy-dom/lib/html-parser/HTMLParser.js -var MARKUP_REGEXP, ATTRIBUTE_REGEXP, DOCUMENT_TYPE_ATTRIBUTE_REGEXP, SPACE_REGEXP2, SPACE_IN_BEGINNING_REGEXP, MarkupReadStateEnum, HTMLDocumentStructureLevelEnum, HTMLParser; -var init_HTMLParser = __esm({ - "node_modules/happy-dom/lib/html-parser/HTMLParser.js"() { - init_PropertySymbol(); - init_NamespaceURI(); - init_HTMLElementConfig(); - init_HTMLElementConfigContentModelEnum(); - init_SVGElementConfig(); - init_StringUtility(); - init_XMLEncodeUtility(); - init_NodeTypeEnum(); - init_NodeFactory(); - MARKUP_REGEXP = /<([^\s/!>?]+)|<\/([^\s/!>?]+)\s*>|(|--!>)|()|(>)/gm; - ATTRIBUTE_REGEXP = /\s*([a-zA-Z0-9-_:.$@?\\<\[\]]+)\s*=\s*([^"'=<>\\`\s]+)|\s*([a-zA-Z0-9-_:.$@?\\<\[\]]+)\s*=\s*"([^"]*)("{0,1})|\s*([a-zA-Z0-9-_:.$@?\\<\[\]]+)\s*=\s*'([^']*)('{0,1})|\s*([a-zA-Z0-9-_:.$@?\\<\[\]]+)/gm; - DOCUMENT_TYPE_ATTRIBUTE_REGEXP = /"([^"]+)"/gm; - SPACE_REGEXP2 = /\s+/; - SPACE_IN_BEGINNING_REGEXP = /^\s+/; - (function(MarkupReadStateEnum3) { - MarkupReadStateEnum3["any"] = "any"; - MarkupReadStateEnum3["startTag"] = "startTag"; - MarkupReadStateEnum3["comment"] = "comment"; - MarkupReadStateEnum3["documentType"] = "documentType"; - MarkupReadStateEnum3["processingInstruction"] = "processingInstruction"; - MarkupReadStateEnum3["rawTextElement"] = "rawTextElement"; - })(MarkupReadStateEnum || (MarkupReadStateEnum = {})); - (function(HTMLDocumentStructureLevelEnum2) { - HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["root"] = 0] = "root"; - HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["doctype"] = 1] = "doctype"; - HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["documentElement"] = 2] = "documentElement"; - HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["head"] = 3] = "head"; - HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["additionalHeadWithoutBody"] = 4] = "additionalHeadWithoutBody"; - HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["body"] = 5] = "body"; - HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["afterBody"] = 6] = "afterBody"; - })(HTMLDocumentStructureLevelEnum || (HTMLDocumentStructureLevelEnum = {})); - HTMLParser = class { - window; - evaluateScripts = false; - isTemplateDocumentFragment = false; - rootNode = null; - rootDocument = null; - nodeStack = []; - tagNameStack = []; - documentStructure = null; - startTagIndex = 0; - markupRegExp = null; - nextElement = null; - currentNode = null; - readState = MarkupReadStateEnum.any; - /** - * Constructor. - * - * @param window Window. - * @param [options] Options. - * @param [options.evaluateScripts] Set to "true" to enable script execution - * @param [options.isTemplateDocumentFragment] Set to "true" if parsing a template content fragment. - */ - constructor(window2, options2) { - this.window = window2; - if (options2?.evaluateScripts) { - this.evaluateScripts = true; - } - if (options2?.isTemplateDocumentFragment) { - this.isTemplateDocumentFragment = true; - } - } - /** - * Parses HTML a root element containing nodes found. - * - * @param html HTML string. - * @param [rootNode] Root node. - * @returns Root node. - */ - parse(html, rootNode2) { - this.rootNode = rootNode2 || this.window.document.createDocumentFragment(); - this.rootDocument = this.rootNode[nodeType] === NodeTypeEnum_default.documentNode ? this.rootNode : this.window.document; - this.nodeStack = [this.rootNode]; - this.tagNameStack = [null]; - this.currentNode = this.rootNode; - this.readState = MarkupReadStateEnum.any; - this.documentStructure = null; - this.startTagIndex = 0; - this.markupRegExp = new RegExp(MARKUP_REGEXP); - if (this.rootNode[nodeType] === NodeTypeEnum_default.documentNode) { - const { doctype, documentElement, head, body: body2 } = this.rootNode; - if (!documentElement || !head || !body2) { - throw new Error('Failed to parse HTML: The root node must have "documentElement", "head" and "body".\n\nWe should not end up here and it is therefore a bug in Happy DOM. Please report this issue.'); - } - this.documentStructure = { - nodes: { - doctype: doctype || null, - documentElement, - head, - body: body2 - }, - level: HTMLDocumentStructureLevelEnum.root - }; - } - if (this.rootNode instanceof this.window.HTMLHtmlElement) { - const head = this.rootDocument.createElement("head"); - const body2 = this.rootDocument.createElement("body"); - while (this.rootNode[nodeArray].length > 0) { - this.rootNode[removeChild](this.rootNode[nodeArray][this.rootNode[nodeArray].length - 1]); - } - this.rootNode[appendChild](head); - this.rootNode[appendChild](body2); - this.documentStructure = { - nodes: { - doctype: null, - documentElement: this.rootNode, - head, - body: body2 - }, - level: HTMLDocumentStructureLevelEnum.documentElement - }; - } - let match; - let lastIndex = 0; - html = String(html); - while (match = this.markupRegExp.exec(html)) { - switch (this.readState) { - case MarkupReadStateEnum.any: - if (match.index !== lastIndex && (match[1] || match[2] || match[3] || match[4] || match[5] !== void 0 || match[6])) { - this.parsePlainText(html.substring(lastIndex, match.index)); - } - if (match[1]) { - this.nextElement = this.getStartTagElement(match[1]); - this.startTagIndex = this.markupRegExp.lastIndex; - this.readState = MarkupReadStateEnum.startTag; - } else if (match[2]) { - this.parseEndTag(match[2]); - } else if (match[3]) { - this.startTagIndex = this.markupRegExp.lastIndex; - this.readState = MarkupReadStateEnum.comment; - } else if (match[5] !== void 0) { - this.startTagIndex = this.markupRegExp.lastIndex; - this.readState = MarkupReadStateEnum.documentType; - } else if (match[6]) { - this.startTagIndex = this.markupRegExp.lastIndex; - this.readState = MarkupReadStateEnum.processingInstruction; - } else { - this.parsePlainText(html.substring(lastIndex, this.markupRegExp.lastIndex)); - } - break; - case MarkupReadStateEnum.startTag: - if (match[7] || match[8] || match[2]) { - if (this.nextElement) { - const attributeString = html.substring(this.startTagIndex, match[2] ? this.markupRegExp.lastIndex - 1 : match.index); - const isSelfClosed = !!match[7]; - this.parseEndOfStartTag(attributeString, isSelfClosed); - } else { - this.readState = MarkupReadStateEnum.any; - } - } - break; - case MarkupReadStateEnum.comment: - if (match[4]) { - this.parseComment(html.substring(this.startTagIndex, match.index)); - } - break; - case MarkupReadStateEnum.documentType: - if (match[7] || match[8]) { - this.parseDocumentType(html.substring(this.startTagIndex, match.index)); - } - break; - case MarkupReadStateEnum.processingInstruction: - if (match[7] || match[8]) { - this.parseComment("?" + html.substring(this.startTagIndex, match.index)); - } - break; - case MarkupReadStateEnum.rawTextElement: - if (match[2]) { - this.parseRawTextElementContent(match[2], html.substring(this.startTagIndex, match.index)); - } - break; - } - lastIndex = this.markupRegExp.lastIndex; - } - if (lastIndex !== html.length && this.currentNode) { - this.parsePlainText(html.substring(lastIndex)); - } - return this.rootNode; - } - /** - * Parses plain text. - * - * @param text Text. - */ - parsePlainText(text) { - if (this.documentStructure) { - const level = this.documentStructure.level; - const { documentElement, head, body: body2 } = this.documentStructure.nodes; - const htmlText = (this.currentNode === this.rootNode || this.currentNode === documentElement) && level < HTMLDocumentStructureLevelEnum.head && body2[elementArray].length === 0 ? text.replace(SPACE_IN_BEGINNING_REGEXP, "") : text; - if (htmlText) { - const textNode = this.rootDocument.createTextNode(XMLEncodeUtility.decodeHTMLEntities(htmlText)); - if (this.currentNode === head && level === HTMLDocumentStructureLevelEnum.additionalHeadWithoutBody) { - documentElement[insertBefore](textNode, body2, true); - } else if (this.currentNode === this.rootNode || this.currentNode === documentElement || this.currentNode === head && level >= HTMLDocumentStructureLevelEnum.body) { - if (level === HTMLDocumentStructureLevelEnum.head) { - documentElement[insertBefore](textNode, body2, true); - } else if (body2.lastChild?.[nodeType] === NodeTypeEnum_default.textNode) { - body2.lastChild[data] += text; - } else { - body2[appendChild](textNode, true); - } - } else { - this.currentNode[appendChild](textNode, true); - } - } - } else { - const textNode = this.rootDocument.createTextNode(XMLEncodeUtility.decodeHTMLEntities(text)); - this.currentNode[appendChild](textNode, true); - } - } - /** - * Parses end of start tag. - * - * @param attributeString Attribute string. - * @param isSelfClosed Is self closed. - */ - parseEndOfStartTag(attributeString, isSelfClosed) { - if (attributeString && (!this.documentStructure || this.nextElement !== this.documentStructure.nodes.head || this.documentStructure.level < HTMLDocumentStructureLevelEnum.body)) { - const attributeRegexp = new RegExp(ATTRIBUTE_REGEXP); - let attributeMatch; - while (attributeMatch = attributeRegexp.exec(attributeString)) { - if (attributeMatch[1] && attributeMatch[2] || attributeMatch[3] && attributeMatch[5] === '"' || attributeMatch[6] && attributeMatch[8] === "'" || attributeMatch[9]) { - const name2 = attributeMatch[1] || attributeMatch[3] || attributeMatch[6] || attributeMatch[9] || ""; - const rawValue = attributeMatch[2] || attributeMatch[4] || attributeMatch[7] || ""; - const value2 = rawValue ? XMLEncodeUtility.decodeHTMLAttributeValue(rawValue) : ""; - const attributes2 = this.nextElement[attributes]; - if (this.nextElement[namespaceURI] === NamespaceURI_default.svg) { - const nameParts = name2.split(":"); - let namespaceURI2 = null; - switch (nameParts[0]) { - case "xmlns": - namespaceURI2 = !nameParts[1] || nameParts[1] === "xlink" ? NamespaceURI_default.xmlns : null; - break; - case "xlink": - namespaceURI2 = NamespaceURI_default.xlink; - break; - } - if (!attributes2.getNamedItemNS(namespaceURI2, nameParts[1] ?? name2)) { - const attribute = NodeFactory.createNode(this.rootDocument, this.window.Attr); - attribute[namespaceURI] = namespaceURI2; - attribute[name] = name2; - attribute[localName] = namespaceURI2 && nameParts[1] ? nameParts[1] : name2; - attribute[prefix] = namespaceURI2 && nameParts[1] ? nameParts[0] : null; - attribute[value] = value2; - attributes2[setNamedItem](attribute); - } - } else if (!attributes2.getNamedItem(name2)) { - const attributeItem = this.rootDocument.createAttribute(name2); - attributeItem[value] = value2; - attributes2[setNamedItem](attributeItem); - } - this.startTagIndex += attributeMatch[0].length; - } else if (!attributeMatch[1] && (attributeMatch[3] && !attributeMatch[5] || attributeMatch[6] && !attributeMatch[8])) { - return; - } - } - } - const tagName2 = this.nextElement[tagName]; - const lowerTagName = tagName2.toLowerCase(); - const config = HTMLElementConfig_default[lowerTagName]; - let previousCurrentNode = null; - while (previousCurrentNode !== this.rootNode) { - const parentLowerTagName = this.currentNode[tagName]?.toLowerCase(); - const parentConfig = parentLowerTagName ? HTMLElementConfig_default[parentLowerTagName] : null; - if (previousCurrentNode === this.currentNode) { - throw new Error("Failed to parse HTML: The parser is stuck in an infinite loop. Please report this issue."); - } - previousCurrentNode = this.currentNode; - if (config?.contentModel === HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants && this.tagNameStack[this.tagNameStack.length - 1] === tagName2 || parentConfig?.contentModel === HTMLElementConfigContentModelEnum_default.textOrComments || parentConfig?.contentModel === HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants && parentConfig?.forbiddenDescendants?.includes(lowerTagName) || parentConfig?.contentModel === HTMLElementConfigContentModelEnum_default.permittedDescendants && !parentConfig?.permittedDescendants?.includes(lowerTagName) && (!config || !config.addPermittedParent || HTMLElementConfig_default[config.addPermittedParent].permittedParents && !HTMLElementConfig_default[config.addPermittedParent].permittedParents.includes(parentLowerTagName) || HTMLElementConfig_default[config.addPermittedParent].permittedDescendants && !HTMLElementConfig_default[config.addPermittedParent].permittedDescendants.includes(lowerTagName))) { - if (parentConfig?.contentModel === HTMLElementConfigContentModelEnum_default.permittedDescendants && parentConfig.moveForbiddenDescendant && !parentConfig.moveForbiddenDescendant.exclude.includes(lowerTagName)) { - let before = this.currentNode; - while (before) { - if (!before.parentNode || !HTMLElementConfig_default[before.parentNode[localName]]?.permittedDescendants || HTMLElementConfig_default[before.parentNode[localName]]?.permittedDescendants?.includes(lowerTagName)) { - break; - } else { - before = before.parentNode; - } - } - if (before && before.parentNode) { - before.parentNode.insertBefore(this.nextElement, before); - } else { - before.appendChild(this.nextElement); - } - this.startTagIndex = this.markupRegExp.lastIndex; - this.readState = MarkupReadStateEnum.any; - return; - } - this.nodeStack.pop(); - this.tagNameStack.pop(); - this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode; - } else if (config?.contentModel === HTMLElementConfigContentModelEnum_default.noSelfDescendants && this.tagNameStack.includes(tagName2)) { - while (this.currentNode !== this.rootNode) { - if (this.currentNode[tagName] === tagName2) { - this.nodeStack.pop(); - this.tagNameStack.pop(); - this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode; - break; - } - this.nodeStack.pop(); - this.tagNameStack.pop(); - this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode; - } - } else if (!this.isTemplateDocumentFragment && config?.permittedParents && !config.permittedParents.includes(parentLowerTagName)) { - if (!config.addPermittedParent || HTMLElementConfig_default[config.addPermittedParent].permittedParents && !HTMLElementConfig_default[config.addPermittedParent].permittedParents.includes(parentLowerTagName) || HTMLElementConfig_default[config.addPermittedParent].permittedDescendants && !HTMLElementConfig_default[config.addPermittedParent].permittedDescendants.includes(lowerTagName)) { - this.readState = MarkupReadStateEnum.any; - this.startTagIndex = this.markupRegExp.lastIndex; - return; - } - const permittedParent = this.rootDocument.createElement(config.addPermittedParent); - this.currentNode[appendChild](permittedParent, true); - this.nodeStack.push(permittedParent); - this.tagNameStack.push(permittedParent[tagName]); - this.currentNode = permittedParent; - } else { - break; - } - } - if (this.documentStructure) { - const { documentElement, head, body: body2 } = this.documentStructure.nodes; - const level = this.documentStructure.level; - if ((!config || config.contentModel !== HTMLElementConfigContentModelEnum_default.rawText) && this.nextElement !== documentElement && this.nextElement !== head && this.nextElement !== body2) { - if (documentElement && (this.currentNode === this.rootNode || this.currentNode === documentElement || this.currentNode === head && level >= HTMLDocumentStructureLevelEnum.body)) { - if (level < HTMLDocumentStructureLevelEnum.body) { - this.documentStructure.level = HTMLDocumentStructureLevelEnum.afterBody; - } - body2[appendChild](this.nextElement, true); - } else { - this.currentNode[appendChild](this.nextElement, true); - } - } - } else { - this.currentNode[appendChild](this.nextElement, true); - } - if (!this.documentStructure || this.nextElement !== this.documentStructure.nodes.body || this.documentStructure.level <= HTMLDocumentStructureLevelEnum.body) { - this.currentNode = this.nextElement; - this.nodeStack.push(this.currentNode); - this.tagNameStack.push(tagName2); - if (this.documentStructure && this.nextElement === this.documentStructure.nodes.body) { - this.documentStructure.level = HTMLDocumentStructureLevelEnum.afterBody; - } - if (config?.contentModel === HTMLElementConfigContentModelEnum_default.noDescendants || isSelfClosed && this.currentNode[namespaceURI] === NamespaceURI_default.svg) { - this.nodeStack.pop(); - this.tagNameStack.pop(); - this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode; - this.readState = MarkupReadStateEnum.any; - } else { - this.readState = config?.contentModel === HTMLElementConfigContentModelEnum_default.rawText ? MarkupReadStateEnum.rawTextElement : MarkupReadStateEnum.any; - } - } else { - this.readState = MarkupReadStateEnum.any; - } - this.startTagIndex = this.markupRegExp.lastIndex; - } - /** - * Parses end tag. - * - * @param tagName Tag name. - */ - parseEndTag(tagName2) { - const name2 = this.currentNode[namespaceURI] === NamespaceURI_default.html ? StringUtility.asciiUpperCase(tagName2) : SVGElementConfig_default[StringUtility.asciiLowerCase(tagName2)]?.localName || tagName2; - const index = this.tagNameStack.lastIndexOf(name2); - if (index !== -1) { - this.nodeStack.splice(index, this.nodeStack.length - index); - this.tagNameStack.splice(index, this.tagNameStack.length - index); - this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode; - } - } - /** - * Parses comment. - * - * @param comment Comment. - */ - parseComment(comment) { - const commentNode = this.rootDocument.createComment(XMLEncodeUtility.decodeHTMLEntities(comment)); - if (this.documentStructure) { - const level = this.documentStructure.level; - const { documentElement, head, body: body2 } = this.documentStructure.nodes; - let beforeNode = null; - if (this.currentNode === this.rootNode && level === HTMLDocumentStructureLevelEnum.root) { - beforeNode = documentElement; - } else if (this.currentNode === documentElement && level === HTMLDocumentStructureLevelEnum.documentElement) { - beforeNode = head; - } else if (this.currentNode === documentElement && level === HTMLDocumentStructureLevelEnum.head) { - beforeNode = body2; - } - this.currentNode[insertBefore](commentNode, beforeNode, true); - } else { - this.currentNode[appendChild](commentNode, true); - } - this.readState = MarkupReadStateEnum.any; - } - /** - * Parses document type. - * - * @param text Text. - */ - parseDocumentType(text) { - const decodedText = XMLEncodeUtility.decodeHTMLEntities(text); - if (this.documentStructure) { - let { doctype } = this.documentStructure.nodes; - const documentType = this.getDocumentType(decodedText); - if (documentType) { - if (this.currentNode === this.rootNode && this.documentStructure.level === HTMLDocumentStructureLevelEnum.root) { - if (doctype) { - doctype[name] = documentType.name; - doctype[publicId] = documentType.publicId; - doctype[systemId] = documentType.systemId; - } else { - doctype = this.rootNode.implementation.createDocumentType(documentType.name, documentType.publicId, documentType.systemId); - this.rootNode.insertBefore(doctype, this.rootNode.documentElement); - } - this.documentStructure.level = HTMLDocumentStructureLevelEnum.doctype; - } - } else { - this.parseComment(decodedText); - } - } else { - if (!this.getDocumentType(decodedText)) { - this.parseComment(decodedText); - } - } - this.readState = MarkupReadStateEnum.any; - } - /** - * Parses raw text content for elements such as -`; - peVmCallRegex = /55==A\?\(f=r\[n\+\+\],l=e\.pop\(\),h=e\.pop\(\),o=\[\],\w+\(f\)\.forEach\(function\(\)\{o\.unshift\(e\.pop\(\)\)\}\),p=null===h\?l\.apply\((\w+),o\):h\[l\]\.apply\(h,o\),r\[n\+\+\]&&e\.push\(p\)\):/; - GUEST_EVAL_PATCH = ` -(function() { - try { - Object.defineProperty(Event.prototype, "isTrusted", { - get() { return true; }, - configurable: true - }); - } catch (e) {} - try { - if (window.HTMLDocument) { - Object.defineProperty(window.HTMLDocument, "name", { value: "HTMLDocument", configurable: true }); - Object.defineProperty(window.HTMLDocument.prototype, Symbol.toStringTag, { value: "HTMLDocument", configurable: true }); - } - } catch (e) {} - try { - Object.defineProperty(window.Document.prototype, Symbol.toStringTag, { value: "HTMLDocument", configurable: true }); - } catch (e) {} - try { - window.addEventListener("unhandledrejection", function(e) { - var r = e && e.reason; - try { - console.error("[UH-REASON]", typeof r, r && r.stack ? r.stack.split("\\n").slice(0,6).join(" | ") : (r && r.message), JSON.stringify(r)); - } catch (e2) {} - }); - } catch (e) {} - try { - window.addEventListener("error", function(e) { - try { - console.error("[WINDOW-ERROR]", e && e.message, e && e.error && e.error.stack ? e.error.stack.split("\\n").slice(0,6).join(" | ") : ""); - } catch (e2) {} - }); - } catch (e) {} - // ---- eval/Function parse-fail instrumentation (installed before pe chain) ---- - // Catches SyntaxError from guest-side eval()/new Function() (the dynamic pe.* - // chunk is evaluated this way in some SDK paths). Host-side twin: the - // PropertySymbol.evaluateScript wrapper in installEvalInstrumentation(). - function __capFailDump(kind, code) { - try { - var src = String(code || ""); - if (typeof window.__capDebugDump === "function") { - window.__capDebugDump(window.__lastPeUrl || "?", src, kind); - } else { - console.error("[" + kind + "] url=" + (window.__lastPeUrl || "?") + " len=" + src.length + " head=" + JSON.stringify(src.slice(0, 300)) + " tail=" + JSON.stringify(src.slice(-100))); - } - } catch (e2) {} - } - try { - var _origEval2 = window.eval; - if (_origEval2) { - window.eval = function(code) { - try { return _origEval2.call(window, code); } - catch (e) { - if (e && (/unexpected|invalid|parse|syntax/i.test(String((e && e.message) || e)))) { - __capFailDump("REALM-EVAL-FAIL", code); - } - throw e; - } - }; - } - } catch (e) {} - try { - var _of = window.Function; - if (_of) { - var _WF = function() { - var args = Array.prototype.slice.call(arguments); - var body = args.length ? String(args[args.length - 1]) : ""; - try { return _of.apply(this, args); } - catch (e) { - if (e && (/unexpected|invalid|parse|syntax/i.test(String((e && e.message) || e)))) { - __capFailDump("REALM-FN-FAIL", body); - } - throw e; - } - }; - _WF.prototype = _of.prototype; - try { Object.defineProperty(_WF, "name", { value: "Function", configurable: true }); } catch (e) {} - window.Function = _WF; - } - } catch (e) {} -})(); -`; - HOST_CRITICAL_GLOBALS = /* @__PURE__ */ new Set([ - "process", - "Bun", - "console", - "performance", - "crypto", - "fetch", - "queueMicrotask", - "structuredClone", - "TextEncoder", - "TextDecoder", - "requestAnimationFrame", - "cancelAnimationFrame", - // NOTE: `print` was removed from this list (2026-08-29). The polyfill - // defines a harmless no-op on the window, but the alias pass skipped it, - // so under Bun (guest scripts run in the HOST realm) the Aliyun pe risk - // engine hit a bare `print` reference → ReferenceError → broken - // fingerprint chain → degraded solve success rate (711 WINDOW-ERRORs in - // one day). Bun's host global has no native `print`, so aliasing the - // stub shadows nothing critical. - "URL", - "URLSearchParams", - "AbortController", - "AbortSignal", - "ReadableStream", - "WritableStream", - "TransformStream", - "Blob", - "File", - "FormData", - "Headers", - "Request", - "Response", - "Event", - "EventTarget", - "MessageChannel", - "MessagePort", - "Buffer", - "global", - "globalThis", - // JS intrinsics — GlobalWindow re-exposes them as class fields; the host - // versions are fine, so never shadow them. - "Array", - "ArrayBuffer", - "Boolean", - "DataView", - "Date", - "Error", - "EvalError", - "Float32Array", - "Float64Array", - "Function", - "Infinity", - "Int8Array", - "Int16Array", - "Int32Array", - "Intl", - "JSON", - "Map", - "Math", - "NaN", - "Number", - "Object", - "Promise", - "RangeError", - "ReferenceError", - "RegExp", - "Reflect", - "Set", - "String", - "Symbol", - "SyntaxError", - "TypeError", - "URIError", - "Uint8Array", - "Uint8ClampedArray", - "Uint16Array", - "Uint32Array", - "WeakMap", - "WeakSet", - "decodeURI", - "decodeURIComponent", - "encodeURI", - "encodeURIComponent", - "escape", - "isFinite", - "isNaN", - "parseFloat", - "parseInt", - "unescape", - "eval" - ]); - EXTRA_WINDOW_PROPS = [ - "moveBy", - "moveTo", - "resizeBy", - "resizeTo", - "scrollTo", - "scrollBy", - "scroll", - "open", - "close", - "stop", - "focus", - "blur", - "print", - "alert", - "confirm", - "prompt", - "getSelection", - "find" - ]; - _aliasRefCount = 0; - _reusePool = { window: null, browserFrame: null, solves: 0, lastUsedAt: 0 }; - REUSE_MAX_SOLVES = Number(process.env.CAPTCHA_REUSE_MAX_SOLVES || 25); - REUSE_MAX_IDLE_MS = Number(process.env.CAPTCHA_REUSE_MAX_IDLE_MS || 12e4); - } -}); - -// src/proxy/captcha-solver.ts -async function runCaptchaSolve(scene, region, prefix2) { - if (BACKEND !== "happy") { - throw new Error(`captcha backend "${BACKEND}" is not available; use ZCODE_CAPTCHA_BACKEND=happy`); - } - if (!happyMod) happyMod = await Promise.resolve().then(() => (init_captcha_happy(), captcha_happy_exports)); - return happyMod.solveTraceless({ scene, region, prefix: prefix2 }); -} -function setCaptchaSolverConcurrency(_n) { -} -function shutdownCaptchaSolver() { -} -function captchaSolverConcurrency() { - return Number(process.env.CAPTCHA_DAEMON_CONCURRENCY || 4); -} -var BACKEND, happyMod; -var init_captcha_solver = __esm({ - "src/proxy/captcha-solver.ts"() { - "use strict"; - BACKEND = process.env.ZCODE_CAPTCHA_BACKEND?.trim().toLowerCase() || "happy"; - happyMod = null; - } -}); - -// src/proxy/captcha-cpu-governor.ts -async function readCpuCounters() { - try { - const stat = await import_promises.default.readFile("/proc/stat", "utf8"); - const line = stat.split("\n")[0] ?? ""; - const parts = line.split(/\s+/).slice(1).map((v) => Number(v) || 0); - const idle = (parts[3] ?? 0) + (parts[4] ?? 0); - const total = parts.reduce((sum, n) => sum + n, 0); - return { idle, total }; - } catch { - const load = import_node_os3.default.loadavg()[0] ?? 0; - const cpus = Math.max(1, import_node_os3.default.cpus().length); - const pct = load / cpus * 100; - return { idle: 100 - pct, total: 100 }; - } -} -function resolveCpuGovernorConfig(opts) { - const poolSizeMin = opts.poolSizeMin ?? Number(process.env.CAPTCHA_POOL_MIN || 40); - const poolSizeMax = Math.max( - poolSizeMin, - opts.poolSizeMax ?? Number(process.env.CAPTCHA_POOL_MAX || 120) - ); - const maxSolveConcurrency = opts.solveConcurrency ?? Number( - process.env.CAPTCHA_SOLVE_CONCURRENCY || (process.env.ZCODE_CAPTCHA_LOW_CPU === "1" ? 3 : 6) - ); - const cpuLimitPercent = opts.cpuLimitPercent ?? (process.env.CAPTCHA_CPU_GOVERNOR === "0" ? 0 : DEFAULT_CPU_LIMIT); - const intervalMs = opts.cpuGovernorIntervalSec != null ? opts.cpuGovernorIntervalSec * 1e3 : DEFAULT_INTERVAL_MS; - return { - cpuLimitPercent, - hysteresisPercent: 5, - poolSizeMin, - poolSizeMax, - maxSolveConcurrency, - intervalMs - }; -} -var import_promises, import_node_os3, DEFAULT_CPU_LIMIT, DEFAULT_INTERVAL_MS, TARGET_STEP, CaptchaCpuGovernor; -var init_captcha_cpu_governor = __esm({ - "src/proxy/captcha-cpu-governor.ts"() { - "use strict"; - import_promises = __toESM(require("node:fs/promises"), 1); - import_node_os3 = __toESM(require("node:os"), 1); - DEFAULT_CPU_LIMIT = Number(process.env.CAPTCHA_CPU_LIMIT_PCT || 100); - DEFAULT_INTERVAL_MS = Number(process.env.CAPTCHA_CPU_GOVERNOR_INTERVAL_MS || 2e3); - TARGET_STEP = 15; - CaptchaCpuGovernor = class { - constructor(cfg) { - this.cfg = cfg; - this.concurrency = 1; - this.maxEffectiveTarget = cfg.poolSizeMin; - } - cfg; - prevCpu = null; - lastCpuPercent = 0; - concurrency; - maxEffectiveTarget; - timer = null; - get enabled() { - return this.cfg.cpuLimitPercent > 0; - } - configure(partial) { - this.cfg = { ...this.cfg, ...partial }; - this.maxEffectiveTarget = Math.max( - this.cfg.poolSizeMin, - Math.min(this.maxEffectiveTarget, this.cfg.poolSizeMax) - ); - this.concurrency = Math.min(this.concurrency, this.cfg.maxSolveConcurrency); - } - start() { - if (!this.enabled || this.timer) return; - void this.tick(); - this.timer = setInterval(() => void this.tick(), this.cfg.intervalMs); - } - stop() { - if (this.timer) { - clearInterval(this.timer); - this.timer = null; - } - } - snapshot() { - const limit = this.cfg.cpuLimitPercent; - return { - cpuPercent: Math.round(this.lastCpuPercent * 10) / 10, - limitPercent: limit, - concurrency: this.concurrency, - maxEffectiveTarget: this.maxEffectiveTarget, - throttled: this.lastCpuPercent >= limit - 3 - }; - } - /** Parallel background solves allowed right now (may be 0 when pool is warm). */ - backgroundConcurrency(readyTokens) { - if (!this.enabled) return this.cfg.maxSolveConcurrency; - const cpu = this.lastCpuPercent; - const limit = this.cfg.cpuLimitPercent; - let allowed = this.concurrency; - if (cpu >= limit) { - allowed = 0; - } else if (cpu >= limit - 4) { - allowed = Math.min(allowed, 1); - } else if (cpu >= limit - 10) { - allowed = Math.min(allowed, 2); - } - if (readyTokens < this.cfg.poolSizeMin) { - return Math.max(1, allowed); - } - return allowed; - } - maxPoolTarget() { - return this.maxEffectiveTarget; - } - async tick() { - const cpu = await this.sampleCpuPercent(); - this.lastCpuPercent = cpu; - const limit = this.cfg.cpuLimitPercent; - const rampThreshold = limit - this.cfg.hysteresisPercent; - if (cpu >= limit) { - this.concurrency = 1; - this.maxEffectiveTarget = this.cfg.poolSizeMin; - } else if (cpu >= limit - 4) { - if (this.concurrency > 1) this.concurrency -= 1; - this.maxEffectiveTarget = this.cfg.poolSizeMin; - } else if (cpu >= limit - 10) { - if (this.concurrency > 2) this.concurrency -= 1; - this.maxEffectiveTarget = Math.max( - this.cfg.poolSizeMin, - this.maxEffectiveTarget - TARGET_STEP - ); - } else if (cpu <= rampThreshold) { - if (this.concurrency < this.cfg.maxSolveConcurrency) { - this.concurrency += 1; - } - if (this.maxEffectiveTarget < this.cfg.poolSizeMax) { - this.maxEffectiveTarget = Math.min( - this.cfg.poolSizeMax, - this.maxEffectiveTarget + TARGET_STEP - ); - } - } - } - async sampleCpuPercent() { - const cur = await readCpuCounters(); - if (!this.prevCpu) { - this.prevCpu = cur; - return this.lastCpuPercent; - } - const idleDelta = cur.idle - this.prevCpu.idle; - const totalDelta = cur.total - this.prevCpu.total; - this.prevCpu = cur; - if (totalDelta <= 0) return this.lastCpuPercent; - const used = (totalDelta - idleDelta) / totalDelta * 100; - return Math.max(0, Math.min(100, used)); - } - }; - } -}); - -// src/proxy/captcha-token.ts -function parseCertifyId(param) { - try { - const json = JSON.parse(Buffer.from(param, "base64").toString("utf8")); - return typeof json.certifyId === "string" && json.certifyId.length > 0 ? json.certifyId : null; - } catch { - return null; - } -} -function isCaptchaDuplicateError(message) { - return /F008|"verifyCode"\s*:\s*"F008"/i.test(message); -} -function isCaptchaIpBlockError(message) { - if (isCaptchaDuplicateError(message)) return false; - return CAPTCHA_IP_BLOCK_RE.test(message); -} -var CAPTCHA_IP_BLOCK_RE; -var init_captcha_token = __esm({ - "src/proxy/captcha-token.ts"() { - "use strict"; - CAPTCHA_IP_BLOCK_RE = /too many|request was denied|risk control|frequent|rate\s*limit|exceeded.*(?:request|limit)|ip\s*suspicious|denied due to|retry later/i; - } -}); - -// src/proxy/captcha-pool.ts -function resolvePoolOpts(opts) { - const max = opts.poolSizeMax ?? opts.poolSize ?? DEFAULT_POOL_MAX; - const min = Math.min(opts.poolSizeMin ?? DEFAULT_POOL_MIN, max); - return { - poolSizeMin: min, - poolSizeMax: max, - idleFloor: Math.min(opts.idleFloor ?? DEFAULT_IDLE_FLOOR, min), - deepIdleAfterMs: Math.max( - opts.deepIdleAfterMs ?? DEFAULT_DEEP_IDLE_AFTER_MS, - opts.scaleDownIdleMs ?? DEFAULT_SCALE_DOWN_IDLE_MS - ), - scaleDownIdleMs: opts.scaleDownIdleMs ?? DEFAULT_SCALE_DOWN_IDLE_MS, - tokenTtlMs: opts.tokenTtlMs ?? DEFAULT_TOKEN_TTL_MS, - refillIntervalMs: opts.refillIntervalMs ?? DEFAULT_REFILL_INTERVAL_MS, - solveRetries: opts.solveRetries ?? SOLVE_RETRIES, - staggerMs: opts.staggerMs ?? DEFAULT_STAGGER_MS, - solveConcurrency: opts.solveConcurrency ?? DEFAULT_SOLVE_CONCURRENCY, - emptyTakeRace: Math.max(1, opts.emptyTakeRace ?? EMPTY_TAKE_RACE), - onCaptchaIpBlock: opts.onCaptchaIpBlock - }; -} -function configureCaptchaPool(opts) { - pool.configure(opts); -} -function getCaptchaPoolStats() { - return pool.stats(); -} -function stopCaptchaPool() { - pool.stopBackgroundRefill(); - shutdownCaptchaSolver(); -} -async function takeCaptchaToken(cfg) { - if (!cfg.enabled || !cfg.prefix || !cfg.sceneId) { - throw new Error("Captcha config unavailable from ZCode API"); - } - return pool.takeToken(cfg); -} -function startCaptchaPoolRefill(cfg) { - if (!cfg.enabled || !cfg.prefix || !cfg.sceneId) return; - pool.startBackgroundRefill(cfg); -} -async function prefillCaptchaPool(cfg, count) { - if (!cfg.enabled || !cfg.prefix || !cfg.sceneId) return; - await pool.prefill(cfg, count); -} -function urgentCaptchaRefill() { - pool.requestUrgentRefill(); -} -var CertifyIdRegistry, DEFAULT_POOL_MIN, DEFAULT_POOL_MAX, DEFAULT_TOKEN_TTL_MS, DEFAULT_REFILL_INTERVAL_MS, DEFAULT_STAGGER_MS, DEFAULT_SOLVE_CONCURRENCY, DEFAULT_SCALE_DOWN_IDLE_MS, DEFAULT_IDLE_FLOOR, DEFAULT_DEEP_IDLE_AFTER_MS, EMPTY_TAKE_RACE, SOLVE_RETRIES, SCALE_UP_STEP, TAKE_RATE_WINDOW_MS, CaptchaTokenPool, pool; -var init_captcha_pool = __esm({ - "src/proxy/captcha-pool.ts"() { - "use strict"; - init_captcha_cpu_governor(); - init_captcha_solver(); - init_captcha_token(); - CertifyIdRegistry = class { - constructor(ttlMs) { - this.ttlMs = ttlMs; - } - ttlMs; - seen = /* @__PURE__ */ new Map(); - setTtlMs(ttlMs) { - this.ttlMs = ttlMs; - } - prune() { - const cutoff = Date.now() - this.ttlMs; - for (const [id2, at] of this.seen) { - if (at < cutoff) this.seen.delete(id2); - } - } - has(id2) { - this.prune(); - return this.seen.has(id2); - } - add(id2) { - this.prune(); - this.seen.set(id2, Date.now()); - } - clear() { - this.seen.clear(); - } - }; - DEFAULT_POOL_MIN = Number(process.env.CAPTCHA_POOL_MIN || 40); - DEFAULT_POOL_MAX = Number(process.env.CAPTCHA_POOL_MAX || 120); - DEFAULT_TOKEN_TTL_MS = Number(process.env.CAPTCHA_CACHE_TTL_MS || 95e3); - DEFAULT_REFILL_INTERVAL_MS = Number(process.env.CAPTCHA_REFILL_INTERVAL_MS || 1e3); - DEFAULT_STAGGER_MS = Number(process.env.CAPTCHA_SOLVE_STAGGER_MS || 0); - DEFAULT_SOLVE_CONCURRENCY = Number( - process.env.CAPTCHA_SOLVE_CONCURRENCY || (process.env.ZCODE_CAPTCHA_LOW_CPU === "1" ? 3 : 8) - ); - DEFAULT_SCALE_DOWN_IDLE_MS = Number(process.env.CAPTCHA_POOL_SCALE_DOWN_IDLE_MS || 12e4); - DEFAULT_IDLE_FLOOR = Number(process.env.CAPTCHA_POOL_IDLE_FLOOR || 1); - DEFAULT_DEEP_IDLE_AFTER_MS = Number(process.env.CAPTCHA_DEEP_IDLE_AFTER_MS || 9e5); - EMPTY_TAKE_RACE = Math.max(1, Number(process.env.CAPTCHA_EMPTY_TAKE_RACE || 3)); - SOLVE_RETRIES = Number(process.env.ZCODE_CAPTCHA_RETRIES || 4); - SCALE_UP_STEP = 20; - TAKE_RATE_WINDOW_MS = 12e4; - CaptchaTokenPool = class { - tokens = []; - opts; - effectiveTarget; - refillTimer = null; - refillInFlight = false; - lastSolveAt = 0; - activeSolves = 0; - cfg = null; - pausedUntil = 0; - lastTakeAt; - takeTimestamps = []; - certifyIds; - governor = null; - // Mint-storm detection: sliding windows of failed vs successful mint - // attempts. A burst of failures with zero successes means velocity/IP - // flagging — fire the telegram IP reset automatically. - mintFailures = []; - mintSuccesses = []; - lastStormResetAt = 0; - constructor(opts = {}) { - const hasOpts = Object.keys(opts).length > 0; - this.opts = resolvePoolOpts(opts); - this.effectiveTarget = hasOpts ? this.opts.poolSizeMin : 0; - this.lastTakeAt = Date.now(); - this.certifyIds = new CertifyIdRegistry(this.opts.tokenTtlMs); - this.initGovernor(opts); - setCaptchaSolverConcurrency(this.opts.solveConcurrency); - } - configure(opts) { - this.opts = resolvePoolOpts({ ...this.opts, ...opts }); - this.certifyIds.setTtlMs(this.opts.tokenTtlMs); - this.effectiveTarget = Math.max( - this.opts.poolSizeMin, - Math.min(this.effectiveTarget, this.opts.poolSizeMax) - ); - this.initGovernor(opts); - setCaptchaSolverConcurrency(this.opts.solveConcurrency); - this.trimToTarget(); - } - stats() { - this.pruneExpired(); - return { - ready: this.tokens.length, - target: this.effectiveTarget, - min: this.opts.poolSizeMin, - max: this.opts.poolSizeMax, - activeSolves: this.activeSolves, - solverWorkers: captchaSolverConcurrency(), - cpu: this.governor?.enabled ? this.governor.snapshot() : void 0 - }; - } - invalidate() { - this.tokens = []; - this.certifyIds.clear(); - this.pausedUntil = Date.now() + this.opts.staggerMs; - } - startBackgroundRefill(cfg) { - this.cfg = cfg; - this.stopBackgroundRefill(); - this.governor?.start(); - void this.refill({ urgent: false }); - this.refillTimer = setInterval(() => { - void this.refill({ urgent: false }); - }, this.opts.refillIntervalMs); - } - stopBackgroundRefill() { - this.governor?.stop(); - if (this.refillTimer) { - clearInterval(this.refillTimer); - this.refillTimer = null; - } - } - async takeToken(cfg) { - this.cfg = cfg; - const readyBefore = this.tokens.length; - const token = this.popFresh(); - if (token) { - this.onTokenTaken(false, readyBefore - 1); - void this.refill({ urgent: true }); - return token; - } - this.onTokenTaken(true, 0); - this.effectiveTarget = Math.max(this.effectiveTarget, this.computeActiveTarget()); - let param; - try { - const raceDeadlineMs = Number(process.env.CAPTCHA_SOLVE_RACE_DEADLINE_MS || 25e3); - param = await Promise.race([ - this.solveRaced(cfg), - new Promise( - (_, rej) => setTimeout( - () => rej(new Error(`captcha take deadline (${raceDeadlineMs}ms)`)), - Math.max(1e3, raceDeadlineMs) - ) - ) - ]); - } catch (err) { - const graceMs = Number(process.env.CAPTCHA_TAKE_GRACE_MS || 1e4); - const deadline = Date.now() + Math.max(0, graceMs); - while (Date.now() < deadline) { - await new Promise((r2) => setTimeout(r2, 400)); - const token2 = this.popFresh(); - if (token2) { - this.markParamIssued(token2); - void this.refill({ urgent: true }); - return token2; - } - } - throw err; - } - this.markParamIssued(param); - void this.refill({ urgent: true }); - return param; - } - async prefill(cfg, count) { - this.cfg = cfg; - const target2 = Math.min(count ?? this.effectiveTarget, this.effectiveTarget); - while (this.tokens.length + this.activeSolves < target2) { - const need = target2 - this.tokens.length - this.activeSolves; - if (need <= 0) break; - const concurrency = this.governor?.enabled ? this.governor.backgroundConcurrency(this.tokens.length) : this.opts.solveConcurrency; - await this.solveBatch(cfg, need, Math.max(1, concurrency)); - } - } - requestUrgentRefill() { - void this.refill({ urgent: true }); - } - poolHasCertifyId(certifyId) { - return this.tokens.some((t) => t.certifyId === certifyId); - } - isDuplicateParam(param) { - const certifyId = parseCertifyId(param); - if (!certifyId) return false; - return this.certifyIds.has(certifyId) || this.poolHasCertifyId(certifyId); - } - markParamIssued(param) { - const certifyId = parseCertifyId(param); - if (certifyId) this.certifyIds.add(certifyId); - } - popFresh() { - this.pruneExpired(); - while (this.tokens.length > 0) { - const entry = this.tokens.pop(); - if (entry.certifyId && this.certifyIds.has(entry.certifyId)) continue; - this.markParamIssued(entry.param); - return entry.param; - } - return null; - } - pushToken(param) { - this.pruneExpired(); - if (this.tokens.length >= this.effectiveTarget) return; - const certifyId = parseCertifyId(param); - if (certifyId && (this.certifyIds.has(certifyId) || this.poolHasCertifyId(certifyId))) { - return; - } - this.tokens.push({ param, cachedAt: Date.now(), certifyId }); - } - pruneExpired() { - const now = Date.now(); - this.tokens = this.tokens.filter((t) => now - t.cachedAt < this.opts.tokenTtlMs); - } - deficit() { - this.pruneExpired(); - return Math.max(0, this.effectiveTarget - this.tokens.length - this.activeSolves); - } - pruneTakeWindow() { - const cutoff = Date.now() - TAKE_RATE_WINDOW_MS; - this.takeTimestamps = this.takeTimestamps.filter((t) => t > cutoff); - } - demandTarget() { - this.pruneTakeWindow(); - if (this.takeTimestamps.length === 0) return this.opts.poolSizeMin; - const ratePerSec = this.takeTimestamps.length / (TAKE_RATE_WINDOW_MS / 1e3); - const ttlSec = this.opts.tokenTtlMs / 1e3; - return Math.ceil(ratePerSec * ttlSec * 1.25); - } - /** - * Target while traffic is recent: measured demand (take rate × TTL × - * margin) plus one token of arrival-jitter headroom, floored at - * poolSizeMin, capped by governor + poolSizeMax. This is the ONLY sizing - * authority while active — bursts raise demand, quiet periods drain it. - */ - computeActiveTarget() { - const demand = Math.max(this.demandTarget(), this.opts.poolSizeMin); - const raw = Math.ceil(demand * 1.25) + 1; - const governorMax = this.governor?.maxPoolTarget() ?? this.opts.poolSizeMax; - return Math.max( - this.currentFloor(), - Math.min(this.opts.poolSizeMax, governorMax, raw) - ); - } - onTokenTaken(wasEmpty, readyAfter) { - this.lastTakeAt = Date.now(); - this.takeTimestamps.push(this.lastTakeAt); - this.pruneTakeWindow(); - this.wakeFromIdle(); - } - maybeScaleDown() { - if (this.lastTakeAt === 0) return; - const idleMs = Date.now() - this.lastTakeAt; - if (idleMs < this.opts.scaleDownIdleMs) return; - this.pruneTakeWindow(); - const recentTakes = this.takeTimestamps.filter((t) => t > Date.now() - 6e4).length; - if (recentTakes > 1) return; - const floor = this.currentFloor(); - if (this.effectiveTarget > floor) { - this.effectiveTarget = Math.max(floor, this.effectiveTarget - SCALE_UP_STEP); - this.trimToTarget(); - } - } - /** - * Active traffic → poolSizeMin. After scaleDownIdleMs of no takes → - * idleFloor (keeper churn ≈ 1 mint/TTL). After deepIdleAfterMs → 0: - * background solving stops; the banked token still serves a wake-up take. - */ - currentFloor() { - if (this.lastTakeAt === 0) return this.opts.poolSizeMin; - const idleMs = Date.now() - this.lastTakeAt; - if (idleMs >= this.opts.deepIdleAfterMs) return 0; - if (idleMs >= this.opts.scaleDownIdleMs) { - return Math.min(this.opts.idleFloor, this.opts.poolSizeMin); - } - return this.opts.poolSizeMin; - } - /** Traffic returned: restore the full configured floor immediately. */ - wakeFromIdle() { - if (this.effectiveTarget < this.opts.poolSizeMin) { - this.effectiveTarget = this.opts.poolSizeMin; - } - } - trimToTarget() { - this.pruneExpired(); - const floor = Math.max(this.effectiveTarget, 1); - while (this.tokens.length > floor) { - this.tokens.shift(); - } - } - applyGovernorCaps() { - if (!this.governor?.enabled) return; - const governorMax = this.governor.maxPoolTarget(); - const floor = this.currentFloor(); - this.effectiveTarget = Math.max( - floor, - Math.min(this.effectiveTarget, governorMax, this.opts.poolSizeMax) - ); - } - async refill(opts) { - if (!this.cfg) return; - const idleDecay = this.lastTakeAt > 0 && Date.now() - this.lastTakeAt >= this.opts.scaleDownIdleMs; - if (!idleDecay) { - this.effectiveTarget = this.computeActiveTarget(); - } else { - this.maybeScaleDown(); - } - if (!opts.urgent && idleDecay) { - if (this.tokens.length >= Math.max(this.currentFloor(), 1)) return; - } - if (this.refillInFlight || Date.now() < this.pausedUntil) return; - this.applyGovernorCaps(); - const ready = this.tokens.length; - const concurrency = this.governor?.enabled ? opts.urgent ? Math.max(1, this.governor.backgroundConcurrency(ready) || this.governor.snapshot().concurrency) : this.governor.backgroundConcurrency(ready) : this.opts.solveConcurrency; - if (!opts.urgent && concurrency === 0 && ready >= this.opts.poolSizeMin) { - return; - } - const need = this.deficit(); - if (need <= 0) return; - this.refillInFlight = true; - try { - await this.solveBatch(this.cfg, need, Math.max(1, concurrency)); - } finally { - this.refillInFlight = false; - } - } - /** Fire up to `need` solves in parallel waves of solveConcurrency. */ - async solveBatch(cfg, need, concurrency = this.opts.solveConcurrency) { - let remaining = need; - while (remaining > 0 && this.tokens.length + this.activeSolves < this.effectiveTarget) { - const wave = Math.min(remaining, concurrency, this.deficit()); - if (wave <= 0) break; - if (this.opts.staggerMs > 0) await this.waitForStagger(); - const results = await Promise.allSettled( - Array.from({ length: wave }, () => this.solveOne(cfg)) - ); - for (const r2 of results) { - if (r2.status === "fulfilled") { - this.pushToken(r2.value); - } else { - console.warn("[captcha-pool] parallel solve failed:", r2.reason); - } - } - remaining -= wave; - if (results.every((r2) => r2.status === "rejected")) break; - } - } - async waitForStagger() { - const elapsed = Date.now() - this.lastSolveAt; - const wait = this.opts.staggerMs - elapsed; - if (wait > 0) { - await new Promise((r2) => setTimeout(r2, wait)); - } - } - noteMintFailure(reason2) { - const now = Date.now(); - this.mintFailures.push(now); - const cutoff = now - 36e4; - this.mintFailures = this.mintFailures.filter((t) => t > cutoff); - this.maybeFireMintStormReset(reason2); - } - noteMintSuccess() { - const now = Date.now(); - this.mintSuccesses.push(now); - const cutoff = now - 36e4; - this.mintSuccesses = this.mintSuccesses.filter((t) => t > cutoff); - } - /** Velocity/IP flagging signature: many failed mints in the last 5 min - * while nothing succeeded in the last 3. Fires the telegram IP reset at - * most once per cooldown — requestCaptchaIpResetSync dedupes further. */ - maybeFireMintStormReset(latestReason) { - const now = Date.now(); - const fails = this.mintFailures.filter((t) => t > now - 3e5).length; - const succs = this.mintSuccesses.filter((t) => t > now - 18e4).length; - if (fails < 8 || succs > 0) return; - if (now - this.lastStormResetAt < 12 * 6e4) return; - this.lastStormResetAt = now; - console.warn( - `[captcha] mint storm detected (${fails} failures/5min, ${succs} successes/3min; latest: ${latestReason.slice(0, 120)}) -> requesting IP reset` - ); - try { - this.opts.onCaptchaIpBlock?.(`mint storm: ${fails} failed mints in 5min`); - } catch { - } - } - async solveFresh(cfg) { - this.activeSolves += 1; - this.lastSolveAt = Date.now(); - try { - let lastErr = null; - let sawIpBlock = false; - for (let attempt = 1; attempt <= this.opts.solveRetries; attempt += 1) { - try { - const param = await runCaptchaSolve(cfg.sceneId, cfg.region, cfg.prefix); - if (!param) { - lastErr = "solver returned empty"; - continue; - } - if (this.isDuplicateParam(param)) { - lastErr = `duplicate certifyId ${parseCertifyId(param) ?? "?"}`; - continue; - } - this.noteMintSuccess(); - return param; - } catch (err) { - lastErr = err instanceof Error ? err.message : String(err); - if (isCaptchaDuplicateError(lastErr)) { - lastErr = `duplicate certifyId (F008)`; - } else if (isCaptchaIpBlockError(lastErr)) { - sawIpBlock = true; - } - this.noteMintFailure(lastErr); - } - } - if (sawIpBlock && this.opts.onCaptchaIpBlock) { - try { - this.opts.onCaptchaIpBlock(lastErr ?? "captcha ip block"); - } catch (_) { - } - } - throw new Error(`captcha failed after ${this.opts.solveRetries} attempts: ${lastErr ?? "unknown"}`); - } finally { - this.activeSolves -= 1; - } - } - async solveOne(cfg) { - return this.solveFresh(cfg); - } - /** - * Empty-pool serve: race up to `emptyTakeRace` solves in parallel and - * resolve with the first success so the client waits for one mint, not a - * sequential retry chain. Extra successes are banked into the pool instead - * of being wasted; the race only rejects when every racer fails. - */ - solveRaced(cfg) { - const racers = Math.max(1, Math.min(this.opts.emptyTakeRace, this.opts.solveConcurrency)); - if (racers <= 1) return this.solveFresh(cfg); - return new Promise((resolve, reject) => { - let pending = racers; - let served = false; - let lastErr = null; - for (let i = 0; i < racers; i += 1) { - this.solveFresh(cfg).then( - (param) => { - if (served) { - this.pushToken(param); - } else { - served = true; - resolve(param); - } - }, - (err) => { - lastErr = err ?? lastErr; - } - ).finally(() => { - pending -= 1; - if (pending === 0 && !served) { - reject( - lastErr instanceof Error ? lastErr : new Error(String(lastErr ?? "captcha race failed")) - ); - } - }); - } - }); - } - initGovernor(opts) { - const cfg = resolveCpuGovernorConfig({ - poolSizeMin: this.opts.poolSizeMin, - poolSizeMax: this.opts.poolSizeMax, - solveConcurrency: this.opts.solveConcurrency, - cpuLimitPercent: opts.cpuLimitPercent, - cpuGovernorIntervalSec: opts.cpuGovernorIntervalSec - }); - if (!this.governor) { - this.governor = new CaptchaCpuGovernor(cfg); - } else { - this.governor.configure(cfg); - } - } - }; - pool = new CaptchaTokenPool(); - } -}); - -// src/proxy/captcha.ts -var captcha_exports = {}; -__export(captcha_exports, { - RETRY_HEADERS: () => RETRY_HEADERS, - captchaPoolStats: () => captchaPoolStats, - configureCaptchaSolving: () => configureCaptchaSolving, - detectCaptchaChallenge: () => detectCaptchaChallenge, - getCaptchaToken: () => getCaptchaToken, - shutdownCaptcha: () => shutdownCaptcha, - startCaptchaPool: () => startCaptchaPool, - urgentCaptcha: () => urgentCaptcha -}); -function detectCaptchaChallenge(resp) { - const v = resp.headers.get(CAPTCHA_HEADER); - return v && v.trim().length > 0 ? v.trim() : null; -} -async function fetchCaptchaConfig(appVersion) { - if (cachedConfig.value && cachedConfig.expiresAt > Date.now()) return cachedConfig.value; - try { - const resp = await fetch(`${CONFIGS_API}?app_version=${encodeURIComponent(appVersion)}&platform=win32-x64`); - const json = await resp.json(); - const cfg = json?.data?.configs?.captcha ?? null; - cachedConfig = { value: cfg, expiresAt: Date.now() + 6e4 }; - return cfg; - } catch { - return null; - } -} -async function getCaptchaToken(appVersion) { - const cfg = await fetchCaptchaConfig(appVersion); - if (!cfg || !cfg.enabled || !cfg.prefix || !cfg.sceneId) throw new Error("Captcha config unavailable"); - const verifyParam = await takeCaptchaToken(cfg); - return { verifyParam, region: cfg.region }; -} -function shutdownCaptcha() { - try { - shutdownCaptchaSolver(); - } catch { - } - try { - stopCaptchaPool(); - } catch { - } -} -async function startCaptchaPool(appVersion) { - const cfg = await fetchCaptchaConfig(appVersion); - if (!cfg || !cfg.enabled) return; - const min = Number(process.env.CAPTCHA_POOL_MIN || 20); - const max = Number(process.env.CAPTCHA_POOL_MAX || Math.max(min * 6, 120)); - configureCaptchaPool({ poolSizeMin: min, poolSizeMax: max }); - startCaptchaPoolRefill(cfg); - await prefillCaptchaPool(cfg, min); -} -function urgentCaptcha() { - urgentCaptchaRefill(); -} -function captchaPoolStats() { - return getCaptchaPoolStats(); -} -function configureCaptchaSolving(opts) { - configureCaptchaPool(opts); -} -var CAPTCHA_HEADER, REGION_HEADER, CONFIGS_API, cachedConfig, RETRY_HEADERS; -var init_captcha = __esm({ - "src/proxy/captcha.ts"() { - "use strict"; - init_captcha_solver(); - init_captcha_pool(); - CAPTCHA_HEADER = "x-aliyun-captcha-verify-param"; - REGION_HEADER = "x-aliyun-captcha-verify-region"; - CONFIGS_API = "https://zcode.z.ai/api/v1/client/configs"; - cachedConfig = { value: null, expiresAt: 0 }; - RETRY_HEADERS = { PARAM: CAPTCHA_HEADER, REGION: REGION_HEADER }; - } -}); - -// src/auth/store.ts -function getEncryptionKey() { - const hash = new Uint8Array(new ArrayBuffer(32)); - const encoder2 = new TextEncoder(); - const seed2 = process.env[ENV_SECRET] ?? `${(0, import_node_os4.homedir)()}-${process.platform}-${process.arch}`; - const seedBytes = encoder2.encode(seed2); - for (let i = 0; i < seedBytes.length; i++) { - hash[i % 32] ^= seedBytes[i]; - } - return hash; -} -async function encrypt(plaintext) { - const key = await crypto.subtle.importKey( - "raw", - getEncryptionKey(), - { name: "AES-GCM" }, - false, - ["encrypt", "decrypt"] - ); - const iv = crypto.getRandomValues(new Uint8Array(12)); - const encoder2 = new TextEncoder(); - const encrypted = await crypto.subtle.encrypt( - { name: "AES-GCM", iv }, - key, - encoder2.encode(plaintext) - ); - const combined = new Uint8Array(iv.length + encrypted.byteLength); - combined.set(iv, 0); - combined.set(new Uint8Array(encrypted), iv.length); - return Buffer.from(combined).toString("base64"); -} -async function decrypt(ciphertext) { - const key = await crypto.subtle.importKey( - "raw", - getEncryptionKey(), - { name: "AES-GCM" }, - false, - ["encrypt", "decrypt"] - ); - const combined = Buffer.from(ciphertext, "base64"); - const iv = combined.slice(0, 12); - const data2 = combined.slice(12); - const decrypted = await crypto.subtle.decrypt( - { name: "AES-GCM", iv }, - key, - data2 - ); - return new TextDecoder().decode(decrypted); -} -async function saveCredential(cred) { - (0, import_node_fs4.mkdirSync)((0, import_node_path2.dirname)(STORE_FILE), { recursive: true }); - const json = JSON.stringify(cred); - const encrypted = await encrypt(json); - (0, import_node_fs4.writeFileSync)(STORE_FILE, JSON.stringify({ encrypted }), { mode: 384 }); -} -async function loadCredential() { - if (!(0, import_node_fs4.existsSync)(STORE_FILE)) return null; - const raw = (0, import_node_fs4.readFileSync)(STORE_FILE, "utf-8"); - const parsed = JSON.parse(raw); - if (!parsed.encrypted) return null; - try { - const json = await decrypt(parsed.encrypted); - return JSON.parse(json); - } catch (e) { - console.warn(`Ignoring corrupted or stale credentials at ${STORE_FILE}: ${e.message}`); - return null; - } -} -function clearCredential() { - if ((0, import_node_fs4.existsSync)(STORE_FILE)) { - (0, import_node_fs4.unlinkSync)(STORE_FILE); - } -} -function getStorePath() { - return STORE_FILE; -} -var import_node_fs4, import_node_path2, import_node_os4, STORE_DIR, STORE_FILE, ENV_SECRET; -var init_store = __esm({ - "src/auth/store.ts"() { - "use strict"; - import_node_fs4 = require("node:fs"); - import_node_path2 = require("node:path"); - import_node_os4 = require("node:os"); - STORE_DIR = (0, import_node_path2.join)((0, import_node_os4.homedir)(), ".zcode-proxy"); - STORE_FILE = (0, import_node_path2.join)(STORE_DIR, "credentials.json"); - ENV_SECRET = "ZCODE_PROXY_CREDENTIAL_SECRET"; - } -}); - -// src/claim/types.ts -function classifyClaimCode(code) { - switch (typeof code === "string" ? Number.parseInt(code, 10) : code) { - case 1001: - return "not_found"; - case 1002: - return "unavailable"; - case 1003: - return "already_claimed"; - case 1004: - return "ineligible"; - case 1005: - return "quota_exhausted"; - case 3001: - return "invalid_request"; - case 3007: - return "captcha"; - case 401: - return "login_required"; - default: - return "unknown"; - } -} -var init_types = __esm({ - "src/claim/types.ts"() { - "use strict"; - } -}); - -// src/claim/client.ts -function createClaimClient(opts) { - const origin = opts.origin.replace(/\/+$/, ""); - const jwt = opts.jwt?.trim() || void 0; - const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS; - const fetchImpl = opts.fetchImpl ?? globalThis.fetch; - const identityHeaders = opts.identity ? Object.fromEntries( - Object.entries(buildIdentityHeaders(opts.identity)).filter(([name2]) => name2 !== "X-ZCode-Agent") - ) : { "X-ZCode-App-Version": opts.appVersion, "X-Platform": opts.platform }; - function parseEntitlement(c) { - const entitlementId = c.entitlement_id?.trim() ?? ""; - if (!entitlementId) return null; - const e = { - entitlementId, - showName: c.show_name?.trim() ?? "", - meter: c.meter?.trim() ?? "", - unitType: c.unit_type?.trim() ?? "", - capabilities: Array.isArray(c.capabilities) ? c.capabilities : [], - grantUnits: Number.isFinite(c.grant_units) ? c.grant_units : 0, - period: c.period?.trim() ?? "", - priority: Number.isFinite(c.priority) ? c.priority : 0 - }; - if (Number.isFinite(c.effective_at)) e.effectiveAt = c.effective_at; - return e; - } - function parsePlan(p) { - const planId = p.plan_id?.trim() ?? ""; - if (!planId) return null; - const plan = { - planId, - name: p.name?.trim() || planId, - description: p.description?.trim() ?? "", - priority: Number.isFinite(p.priority) ? p.priority : 0, - entitlements: (p.entitlements ?? []).flatMap((c) => { - const e = parseEntitlement(c); - return e ? [e] : []; - }) - }; - if (Number.isFinite(p.starts_at)) plan.startsAt = p.starts_at; - if (Number.isFinite(p.ends_at)) plan.endsAt = p.ends_at; - return plan; - } - async function request(method2, path2, init) { - const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), timeoutMs); - const onExternalAbort = () => controller.abort(); - if (init.signal) { - if (init.signal.aborted) controller.abort(); - else init.signal.addEventListener("abort", onExternalAbort, { once: true }); - } - let resp; - try { - resp = await fetchImpl(`${origin}${path2}`, { - method: method2, - headers: init.headers, - body: init.body === void 0 ? void 0 : JSON.stringify(init.body), - signal: controller.signal - }); - const text = await resp.text(); - let json; - try { - const parsed = JSON.parse(text); - if (parsed && typeof parsed === "object") json = parsed; - } catch { - } - return { status: resp.status, json, text }; - } finally { - clearTimeout(timer); - init.signal?.removeEventListener("abort", onExternalAbort); - } - } - function unwrapError(json, status, text) { - const code = json?.code !== void 0 ? json.code : status >= 400 ? status : -1; - const rawMsg = json?.msg ?? json?.message; - const message = typeof rawMsg === "string" && rawMsg.trim() ? rawMsg.trim() : text.length > 0 && text.length < 200 ? text : `HTTP ${status}`; - return { code, message }; - } - return { - async getPreviews(signal2) { - const url2 = `/api/v1/zcode-plan/billing/preview?app_version=${encodeURIComponent(opts.appVersion)}&platform=${encodeURIComponent(opts.platform)}`; - const headers2 = { ...identityHeaders }; - if (jwt) headers2.authorization = `Bearer ${jwt}`; - const { status, json, text } = await request("GET", url2, { headers: headers2, signal: signal2 }); - if (status < 200 || status >= 300 || json?.code !== void 0 && json.code !== 0 || json?.data === void 0) { - const { code, message } = unwrapError(json, status, text); - throw new ClaimPreviewError(`claim preview failed (${code}): ${message}`, status, code); - } - const data2 = json.data; - return (data2.plans ?? []).flatMap((p) => { - const plan = parsePlan(p); - return plan ? [plan] : []; - }); - }, - async claim(planId, captcha, signal2) { - if (!jwt) return { ok: false, planId, failureKind: "login_required", code: 401, message: "manual_claim_login_required" }; - const headers2 = { - ...identityHeaders, - authorization: `Bearer ${jwt}`, - "content-type": "application/json", - "X-Aliyun-Captcha-Verify-Param": captcha.verifyParam - }; - if (captcha.region) headers2["X-Aliyun-Captcha-Verify-Region"] = captcha.region; - const { status, json, text } = await request("POST", "/api/v1/zcode-plan/billing/claim", { body: { plan_id: planId }, headers: headers2, signal: signal2 }); - const data2 = json?.data; - const bizCode = json?.code !== void 0 ? json.code : void 0; - const plan = data2?.plan; - if (status >= 200 && status < 300 && bizCode === 0 && plan) { - const out = { ok: true, planId }; - if (Number.isFinite(plan.starts_at)) out.startsAt = plan.starts_at; - if (Number.isFinite(plan.ends_at)) out.endsAt = plan.ends_at; - return out; - } - const { code, message } = unwrapError(json, status, text); - const failureEndsAt = Number.isFinite(plan?.ends_at) ? plan?.ends_at : void 0; - const httpDerived = status >= 400 && bizCode === void 0; - return { - ok: false, - planId, - failureKind: httpDerived ? status === 401 ? "login_required" : "http_error" : classifyClaimCode(code), - code, - message, - ...failureEndsAt !== void 0 ? { failureEndsAt } : {} - }; - } - }; -} -var DEFAULT_TIMEOUT_MS, ClaimPreviewError; -var init_client = __esm({ - "src/claim/client.ts"() { - "use strict"; - init_types(); - init_identity(); - DEFAULT_TIMEOUT_MS = 15e3; - ClaimPreviewError = class extends Error { - status; - code; - constructor(message, status, code) { - super(message); - this.name = "ClaimPreviewError"; - this.status = status; - this.code = code; - } - }; - } -}); - -// src/claim/scheduler.ts -var ClaimScheduler; -var init_scheduler = __esm({ - "src/claim/scheduler.ts"() { - "use strict"; - init_client(); - ClaimScheduler = class { - constructor(deps) { - this.deps = deps; - this.now = deps.now ?? Date.now; - this.log = deps.log ?? (() => { - }); - } - deps; - stopped = false; - holdUntil = 0; - timer = null; - now; - log; - isStopped() { - return this.stopped; - } - start() { - if (this.stopped) return; - this.scheduleNext(0); - } - stop() { - this.stopped = true; - if (this.timer !== null) { - clearTimeout(this.timer); - this.timer = null; - } - } - /** One poll→claim cycle. Exposed for tests; `start()` drives it on a timer. */ - async tick() { - if (this.stopped) return { action: "stopped" }; - const nowMs = this.now(); - if (nowMs < this.holdUntil) return { action: "skipped_hold" }; - let jwt; - try { - jwt = await this.deps.getJwt(); - } catch (err) { - return this.errorBackoff(`credential resolution failed: ${err.message}`); - } - if (!jwt) { - return this.errorBackoff("no JWT available (oauth login pending)"); - } - const client = this.deps.createClient(jwt); - let plans; - try { - plans = await client.getPreviews(); - } catch (err) { - if (err instanceof ClaimPreviewError && err.status === 404) { - this.holdUntil = nowMs + this.deps.config.pollIntervalMs; - return { action: "idle" }; - } - return this.errorBackoff(`preview failed: ${err.message}`); - } - if (plans.length === 0) { - this.holdUntil = nowMs + this.deps.config.pollIntervalMs; - return { action: "idle" }; - } - const target2 = this.pickPlan(plans); - if (!target2) { - this.holdUntil = nowMs + this.deps.config.pollIntervalMs; - return { action: "idle" }; - } - let captcha; - try { - captcha = await this.deps.getCaptcha(); - } catch (err) { - return this.errorBackoff(`captcha token failed: ${err.message}`); - } - let outcome; - try { - outcome = await client.claim(target2.planId, captcha); - } catch (err) { - return this.errorBackoff(`claim request failed: ${err.message}`); - } - if (outcome.ok) { - const endsAtMs = outcome.endsAt !== void 0 ? outcome.endsAt * 1e3 : void 0; - this.holdUntil = endsAtMs ?? nowMs + this.deps.config.pollIntervalMs; - this.log(`claim: claimed plan ${target2.planId}${outcome.startsAt !== void 0 ? ` (activates ${new Date(outcome.startsAt * 1e3).toISOString()})` : ""}`); - return { action: "claimed", planId: target2.planId, startsAt: outcome.startsAt, endsAt: outcome.endsAt }; - } - const holdMs = this.holdForFailure(outcome.failureKind, outcome.failureEndsAt, nowMs); - this.holdUntil = nowMs + holdMs; - this.log(`claim: ${outcome.failureKind} (${outcome.code}) \u2014 ${outcome.message}; retry in ${Math.round(holdMs / 1e3)}s`); - if (outcome.failureKind === "login_required") { - this.stop(); - } - return { action: "failed", outcome, holdMs }; - } - pickPlan(plans) { - const wanted = this.deps.config.planId?.trim(); - if (wanted) return plans.find((p) => p.planId === wanted) ?? null; - const sorted = [...plans].sort((a, b) => b.priority - a.priority); - return sorted[0] ?? null; - } - holdForFailure(kind2, failureEndsAtSec, nowMs) { - if ((kind2 === "already_claimed" || kind2 === "quota_exhausted") && Number.isFinite(failureEndsAtSec)) { - const untilMs = failureEndsAtSec * 1e3; - if (untilMs > nowMs) return Math.min(untilMs - nowMs, 24 * 60 * 60 * 1e3); - } - return this.deps.config.cooldownMs; - } - errorBackoff(message) { - const holdMs = this.deps.config.cooldownMs; - this.holdUntil = this.now() + holdMs; - this.log(`claim: ${message}; retry in ${Math.round(holdMs / 1e3)}s`); - return { action: "error", message, holdMs }; - } - scheduleNext(delayMs) { - if (this.stopped) return; - this.timer = setTimeout(() => { - this.timer = null; - void this.tick().finally(() => this.scheduleNext(this.nextDelay())); - }, delayMs); - } - nextDelay() { - const remaining = this.holdUntil - this.now(); - return remaining > 0 ? remaining : this.deps.config.pollIntervalMs; - } - }; - } -}); - -// src/claim/runtime.ts -var runtime_exports = {}; -__export(runtime_exports, { - claimPlatform: () => claimPlatform, - runClaimCli: () => runClaimCli, - startAutoClaim: () => startAutoClaim -}); -function claimPlatform() { - return `${process.platform}-${process.arch}`; -} -function startAutoClaim(config, auth) { - const scheduler = new ClaimScheduler({ - // AuthManager first (fresh), then the encrypted store — on Android the - // login can land in the store after boot while auth hasn't been reloaded. - getJwt: async () => { - try { - const cred = await auth.getCredential(); - if (cred.jwt) return cred.jwt; - } catch { - } - const stored = await loadCredential().catch(() => null); - return stored?.jwt; - }, - createClient: (jwt) => createClaimClient({ - origin: config.claim.origin, - jwt, - appVersion: config.identity.appVersion, - platform: claimPlatform(), - identity: config.identity - }), - getCaptcha: async () => { - const { verifyParam, region } = await getCaptchaToken(config.identity.appVersion); - return { verifyParam, region: region || void 0 }; - }, - config: { - planId: config.claim.planId || void 0, - pollIntervalMs: config.claim.pollIntervalMs, - cooldownMs: config.claim.cooldownMs - }, - log: (message) => console.log(`[claim] ${message}`) - }); - scheduler.start(); - return scheduler; -} -async function runClaimCli(config, mode2) { - const cred = await loadCredential(); - const jwt = cred?.jwt; - if (!jwt) { - console.error("Claim requires a logged-in oauth credential (no JWT stored). Run: zcode-proxy auth login "); - process.exit(1); - } - const client = createClaimClient({ - origin: config.claim.origin, - jwt, - appVersion: config.identity.appVersion, - platform: claimPlatform(), - identity: config.identity - }); - let plans; - try { - plans = await client.getPreviews(); - } catch (err) { - if (err instanceof ClaimPreviewError && err.status === 404) { - console.log("No claimable plans: the campaign endpoint is not deployed yet (404)."); - console.log("Weekend campaigns typically go live shortly before the window \u2014 keep the proxy"); - console.log("serving with claim.enabled, or re-run this command later."); - return; - } - throw err; - } - if (plans.length === 0) { - console.log("No claimable plans right now."); - return; - } - printPlans(plans); - if (mode2 === "list") return; - const wanted = config.claim.planId.trim(); - const target2 = wanted ? plans.find((p) => p.planId === wanted) : [...plans].sort((a, b) => b.priority - a.priority)[0]; - if (!target2) { - console.error(`Configured claim.planId "${wanted}" not in the preview list.`); - process.exit(1); - } - if (target2.planId !== plans[0].planId) console.log(`Claiming configured plan: ${target2.planId}`); - const captcha = await getCaptchaToken(config.identity.appVersion); - const outcome = await client.claim(target2.planId, { verifyParam: captcha.verifyParam, region: captcha.region || void 0 }); - printOutcome(outcome); - if (!outcome.ok) process.exit(1); -} -function printPlans(plans) { - console.log(`Claimable plans (${plans.length}):`); - for (const p of plans) { - const window2 = [fmtTime(p.startsAt), fmtTime(p.endsAt)].filter(Boolean).join(" \u2192 "); - console.log(` - ${p.planId} "${p.name}" priority=${p.priority}${window2 ? ` ${window2}` : ""}`); - for (const e of p.entitlements) { - const quota = e.grantUnits > 0 ? ` ${e.grantUnits} ${e.unitType}` : ""; - const activate = e.effectiveAt !== void 0 ? ` (activates ${new Date(e.effectiveAt * 1e3).toISOString()})` : ""; - console.log(` \xB7 ${e.showName || e.entitlementId}${quota}${activate}`); - } - } -} -function printOutcome(outcome) { - if (outcome.ok) { - console.log(` -Claimed: ${outcome.planId}`); - if (outcome.startsAt !== void 0) console.log(` activates: ${new Date(outcome.startsAt * 1e3).toISOString()}`); - if (outcome.endsAt !== void 0) console.log(` expires: ${new Date(outcome.endsAt * 1e3).toISOString()}`); - if (outcome.startsAt === void 0 && outcome.endsAt === void 0) console.log(" active immediately"); - return; - } - const label2 = FAILURE_LABELS[outcome.failureKind] ?? FAILURE_LABELS.unknown; - console.error(` -Claim failed: ${label2} (code ${String(outcome.code)}) \u2014 ${outcome.message}`); - if (outcome.failureEndsAt !== void 0) { - console.error(` retry window opens: ${new Date(outcome.failureEndsAt * 1e3).toISOString()}`); - } -} -function fmtTime(sec) { - return sec === void 0 ? "" : new Date(sec * 1e3).toISOString(); -} -var FAILURE_LABELS; -var init_runtime = __esm({ - "src/claim/runtime.ts"() { - "use strict"; - init_client(); - init_scheduler(); - init_captcha(); - init_store(); - FAILURE_LABELS = { - not_found: "plan does not exist", - unavailable: "campaign ended or not claimable yet", - already_claimed: "already claimed on this account", - ineligible: "account or client version not eligible (needs appVersion >= campaign minimum)", - quota_exhausted: "daily claim quota exhausted", - invalid_request: "invalid request", - captcha: "captcha verification failed", - login_required: "not logged in", - http_error: "HTTP error", - unknown: "unknown failure" - }; - } -}); - -// src/index.ts -var index_exports = {}; -__export(index_exports, { - applyAndroidIdentityDefaults: () => applyAndroidIdentityDefaults, - ensureDeviceMidInConfig: () => ensureDeviceMidInConfig, - main: () => main, - parseServeArgs: () => parseServeArgs -}); -module.exports = __toCommonJS(index_exports); - -// src/config/loader.ts -var import_node_fs = require("node:fs"); -var import_yaml = __toESM(require_dist(), 1); -var ENV = { - PORT: "ZCODE_PROXY_PORT", - PROXY_API_KEY: "ZCODE_PROXY_API_KEY", - PROVIDER: "ZCODE_PROVIDER", - APP_VERSION: "ZCODE_APP_VERSION", - SOURCE_TITLE: "ZCODE_SOURCE_TITLE", - REFERER_ORIGIN: "ZCODE_REFERER_ORIGIN", - ASYNC_ENABLED: "ZCODE_ASYNC_ENABLED", - ASYNC_ORIGIN: "ZCODE_ASYNC_ORIGIN", - ASYNC_MAX_RETRIES: "ZCODE_ASYNC_MAX_RETRIES", - ASYNC_MAX_WAIT_MS: "ZCODE_ASYNC_MAX_WAIT_MS", - CLAIM_ENABLED: "ZCODE_CLAIM_ENABLED", - CLAIM_AUTO: "ZCODE_CLAIM_AUTO", - CLAIM_ORIGIN: "ZCODE_CLAIM_ORIGIN", - CLAIM_POLL_INTERVAL_MS: "ZCODE_CLAIM_POLL_INTERVAL_MS", - ENDPOINT_ROUTING_ENABLED: "ZCODE_ENDPOINT_ROUTING", - CLIENT_SIGNING_ENABLED: "ZCODE_CLIENT_SIGNING" -}; -var DEFAULTS = { - PORT: 8080, - HOST: "0.0.0.0", - PROVIDER: "zai", - PLAN: "coding-plan", - DEFAULT_MODEL: "glm-4.6", - LOG_LEVEL: "info", - ZAI_ANTHROPIC_BASE: "https://api.z.ai/api/anthropic", - ZAI_OPENAI_BASE: "https://api.z.ai/api/coding/paas/v4", - BIGMODEL_ANTHROPIC_BASE: "https://open.bigmodel.cn/api/anthropic", - BIGMODEL_OPENAI_BASE: "https://open.bigmodel.cn/api/coding/paas/v4", - APP_VERSION: "3.10.0", - SOURCE_TITLE: "cli", - REFERER_ORIGIN: "https://zcode.z.ai", - CLIENT_IDENTITY_MODE: "observe", - CLIENT_IDENTITY_TTL_SECONDS: 900, - CLIENT_IDENTITY_MAX_SESSIONS: 1024, - RESPONSES_ENABLED: true, - RESPONSES_STORE_MAX_ENTRIES: 1e3, - RESPONSES_STORE_TTL_MS: 24 * 60 * 60 * 1e3, - MCP_ENABLED: true, - MCP_WEB_SEARCH: true, - MCP_WEB_READER: false, - MCP_ZREAD: false, - ASYNC_ENABLED: false, - ASYNC_ORIGIN: "https://zcode.z.ai", - ASYNC_POLL_INTERVAL_MS: 5e3, - ASYNC_KEEPALIVE_INTERVAL_MS: 3e3, - ASYNC_MAX_WAIT_MS: 0, - ASYNC_MAX_RETRIES: 3, - ASYNC_SETTLE_TIMEOUT_MS: 8e3, - ASYNC_CONTROL_TIMEOUT_MS: 15e3, - ASYNC_DEFAULT_MODEL: "", - CLAIM_ENABLED: false, - CLAIM_AUTO: true, - CLAIM_ORIGIN: "https://zcode.z.ai", - CLAIM_POLL_INTERVAL_MS: 3e5, - CLAIM_COOLDOWN_MS: 6e5, - CLAIM_PLAN_ID: "", - ENDPOINT_ROUTING_ENABLED: true, - ENDPOINT_ROUTING_ORIGIN: "https://zcode.z.ai", - CLIENT_SIGNING_ENABLED: true, - CLIENT_SIGNING_ORIGIN: "https://zcode.z.ai" -}; -var ASCII_PRINTABLE = /^[\x20-\x7e]+$/; -function loadConfig(path2) { - if (!(0, import_node_fs.existsSync)(path2)) { - throw new Error(`Config file not found: ${path2}`); - } - const raw = (0, import_node_fs.readFileSync)(path2, "utf-8"); - const parsed = (0, import_yaml.parse)(raw) ?? {}; - const port = resolvePort(process.env[ENV.PORT] ?? parsed?.server?.port); - const host2 = typeof parsed?.server?.host === "string" ? parsed.server.host : DEFAULTS.HOST; - const proxyApiKey = process.env[ENV.PROXY_API_KEY] ?? parsed?.auth?.proxyApiKey; - const oauthCredentialsPath = parsed?.auth?.oauthCredentialsPath; - const provider = resolveProvider(process.env[ENV.PROVIDER] ?? parsed?.provider); - const plan = resolvePlan(parsed?.plan); - const zai = { - anthropicBase: parsed?.providers?.zai?.anthropicBase ?? DEFAULTS.ZAI_ANTHROPIC_BASE, - openaiBase: parsed?.providers?.zai?.openaiBase ?? DEFAULTS.ZAI_OPENAI_BASE - }; - const bigmodel = { - anthropicBase: parsed?.providers?.bigmodel?.anthropicBase ?? DEFAULTS.BIGMODEL_ANTHROPIC_BASE, - openaiBase: parsed?.providers?.bigmodel?.openaiBase ?? DEFAULTS.BIGMODEL_OPENAI_BASE - }; - const defaultModel = typeof parsed?.defaultModel === "string" ? parsed.defaultModel : DEFAULTS.DEFAULT_MODEL; - const models = Array.isArray(parsed?.models) ? parsed.models : [defaultModel]; - const logLevel = resolveLogLevel(parsed?.logging?.level); - const identity = resolveIdentity({ - appVersionEnv: process.env[ENV.APP_VERSION], - appVersionYaml: parsed?.identity?.appVersion, - sourceTitleEnv: process.env[ENV.SOURCE_TITLE], - sourceTitleYaml: parsed?.identity?.sourceTitle, - refererEnv: process.env[ENV.REFERER_ORIGIN], - refererYaml: parsed?.identity?.refererOrigin, - deviceMidYaml: parsed?.identity?.deviceMid - }); - const clientIdentity = resolveClientIdentity(parsed?.clientIdentity); - const responses = resolveResponsesConfig(parsed?.responses); - const mcp = resolveMcpConfig(parsed?.mcp); - const asyncCfg = resolveAsyncConfig(parsed?.async); - const claimCfg = resolveClaimConfig(parsed?.claim); - const endpointRouting = resolveEndpointRoutingConfig(parsed?.endpointRouting); - const clientSigning = resolveClientSigningConfig(parsed?.clientSigning); - const config = { - server: { port, host: host2 }, - auth: { proxyApiKey, oauthCredentialsPath }, - provider, - plan, - providers: { zai, bigmodel }, - defaultModel, - models, - identity, - clientIdentity, - responses, - endpointRouting, - clientSigning, - mcp, - async: asyncCfg, - claim: claimCfg, - logging: { level: logLevel } - }; - validate(config); - return config; -} -function resolveClientIdentity(raw) { - const obj = raw && typeof raw === "object" ? raw : {}; - const mode2 = resolveClientIdentityMode(obj.mode); - const ttlSeconds = resolvePositiveInt(obj.ttlSeconds, DEFAULTS.CLIENT_IDENTITY_TTL_SECONDS, "clientIdentity.ttlSeconds"); - const maxSessions = resolvePositiveInt(obj.maxSessions, DEFAULTS.CLIENT_IDENTITY_MAX_SESSIONS, "clientIdentity.maxSessions"); - return { mode: mode2, ttlSeconds, maxSessions }; -} -function resolveClientIdentityMode(raw) { - if (raw === void 0 || raw === null) return DEFAULTS.CLIENT_IDENTITY_MODE; - if (raw === "off" || raw === "observe" || raw === "enforce") return raw; - throw new Error(`Invalid clientIdentity.mode "${String(raw)}": must be "off", "observe", or "enforce"`); -} -function resolveResponsesConfig(raw) { - const obj = raw && typeof raw === "object" ? raw : {}; - const storeRaw = obj.store && typeof obj.store === "object" ? obj.store : {}; - return { - enabled: resolveBool(obj.enabled, DEFAULTS.RESPONSES_ENABLED), - storeMaxEntries: resolvePositiveInt(storeRaw.maxEntries, DEFAULTS.RESPONSES_STORE_MAX_ENTRIES, "responses.store.maxEntries"), - storeTtlMs: resolvePositiveInt(storeRaw.ttlMs, DEFAULTS.RESPONSES_STORE_TTL_MS, "responses.store.ttlMs") - }; -} -function resolveMcpConfig(raw) { - const obj = raw && typeof raw === "object" ? raw : {}; - return { - enabled: resolveBool(obj.enabled, DEFAULTS.MCP_ENABLED), - webSearch: resolveBool(obj.webSearch ?? obj.web_search, DEFAULTS.MCP_WEB_SEARCH), - webReader: resolveBool(obj.webReader ?? obj.web_reader, DEFAULTS.MCP_WEB_READER), - zread: resolveBool(obj.zread, DEFAULTS.MCP_ZREAD) - }; -} -function resolveAsyncConfig(raw) { - const obj = raw && typeof raw === "object" ? raw : {}; - const enabledEnv = process.env[ENV.ASYNC_ENABLED]; - const originEnv = process.env[ENV.ASYNC_ORIGIN]; - const maxRetriesEnv = process.env[ENV.ASYNC_MAX_RETRIES]; - const maxWaitMsEnv = process.env[ENV.ASYNC_MAX_WAIT_MS]; - const origin = (originEnv ?? (typeof obj.origin === "string" ? obj.origin : DEFAULTS.ASYNC_ORIGIN)).trim() || DEFAULTS.ASYNC_ORIGIN; - validateOrigin(origin, "async.origin"); - return { - enabled: enabledEnv !== void 0 ? resolveBool(enabledEnv, DEFAULTS.ASYNC_ENABLED) : resolveBool(obj.enabled, DEFAULTS.ASYNC_ENABLED), - origin, - pollIntervalMs: resolvePositiveInt(obj.pollIntervalMs ?? obj.poll_interval_ms, DEFAULTS.ASYNC_POLL_INTERVAL_MS, "async.pollIntervalMs"), - keepAliveIntervalMs: resolvePositiveInt(obj.keepAliveIntervalMs ?? obj.keepalive_interval_ms, DEFAULTS.ASYNC_KEEPALIVE_INTERVAL_MS, "async.keepAliveIntervalMs"), - maxWaitMs: resolveNonNegativeInt(maxWaitMsEnv ?? obj.maxWaitMs ?? obj.max_wait_ms, DEFAULTS.ASYNC_MAX_WAIT_MS, "async.maxWaitMs"), - maxRetries: resolveNonNegativeInt(maxRetriesEnv ?? obj.maxRetries ?? obj.max_retries, DEFAULTS.ASYNC_MAX_RETRIES, "async.maxRetries"), - settleTimeoutMs: resolvePositiveInt(obj.settleTimeoutMs ?? obj.settle_timeout_ms, DEFAULTS.ASYNC_SETTLE_TIMEOUT_MS, "async.settleTimeoutMs"), - controlTimeoutMs: resolvePositiveInt(obj.controlTimeoutMs ?? obj.control_timeout_ms, DEFAULTS.ASYNC_CONTROL_TIMEOUT_MS, "async.controlTimeoutMs"), - defaultModel: typeof obj.defaultModel === "string" ? obj.defaultModel : DEFAULTS.ASYNC_DEFAULT_MODEL - }; -} -function validateOrigin(origin, name2) { - let parsed; - try { - parsed = new URL(origin); - } catch { - throw new Error(`${name2} "${origin}" is not a valid URL`); - } - if (parsed.protocol !== "https:" && parsed.protocol !== "http:") { - throw new Error(`${name2} must use http: or https: scheme (got ${parsed.protocol})`); - } - const hostname = parsed.hostname.replace(/^\[|\]$/g, ""); - const isLoopback2 = hostname === "127.0.0.1" || hostname === "localhost" || hostname === "::1"; - if (parsed.protocol === "http:" && !isLoopback2) { - throw new Error(`${name2} http:// is only allowed for loopback hosts (got ${hostname}). Use https:// for remote origins.`); - } - if (parsed.username || parsed.password) { - throw new Error(`${name2} must not contain userinfo`); - } - if (parsed.hash) { - throw new Error(`${name2} must not contain a fragment`); - } - if (parsed.pathname !== "/" && parsed.pathname !== "") { - throw new Error(`${name2} must not contain a path (got "${parsed.pathname}"); clients append their own paths`); - } - if (parsed.search) { - throw new Error(`${name2} must not contain a query string`); - } -} -function resolveEndpointRoutingConfig(raw) { - const obj = raw && typeof raw === "object" ? raw : {}; - const enabledEnv = process.env[ENV.ENDPOINT_ROUTING_ENABLED]; - const origin = (typeof obj.origin === "string" ? obj.origin : DEFAULTS.ENDPOINT_ROUTING_ORIGIN).trim() || DEFAULTS.ENDPOINT_ROUTING_ORIGIN; - validateOrigin(origin, "endpointRouting.origin"); - return { - enabled: enabledEnv !== void 0 ? resolveBool(enabledEnv, DEFAULTS.ENDPOINT_ROUTING_ENABLED) : resolveBool(obj.enabled, DEFAULTS.ENDPOINT_ROUTING_ENABLED), - origin - }; -} -function resolveClientSigningConfig(raw) { - const obj = raw && typeof raw === "object" ? raw : {}; - const enabledEnv = process.env[ENV.CLIENT_SIGNING_ENABLED]; - const origin = (typeof obj.origin === "string" ? obj.origin : DEFAULTS.CLIENT_SIGNING_ORIGIN).trim() || DEFAULTS.CLIENT_SIGNING_ORIGIN; - validateOrigin(origin, "clientSigning.origin"); - return { - enabled: enabledEnv !== void 0 ? resolveBool(enabledEnv, DEFAULTS.CLIENT_SIGNING_ENABLED) : resolveBool(obj.enabled, DEFAULTS.CLIENT_SIGNING_ENABLED), - origin - }; -} -function resolveBool(raw, fallback) { - if (typeof raw === "boolean") return raw; - if (typeof raw === "string") return raw === "true" || raw === "1"; - return fallback; -} -function resolvePositiveInt(raw, fallback, name2) { - if (raw === void 0 || raw === null) return fallback; - const n = typeof raw === "number" ? raw : parseInt(String(raw), 10); - if (!Number.isInteger(n) || n < 1) { - throw new Error(`${name2} must be a positive integer`); - } - return n; -} -function resolveNonNegativeInt(raw, fallback, name2) { - if (raw === void 0 || raw === null) return fallback; - const n = typeof raw === "number" ? raw : parseInt(String(raw), 10); - if (!Number.isInteger(n) || n < 0) { - throw new Error(`${name2} must be a non-negative integer`); - } - return n; -} -function resolvePort(raw) { - if (raw === void 0 || raw === null) return DEFAULTS.PORT; - const n = typeof raw === "number" ? raw : parseInt(String(raw), 10); - if (!Number.isFinite(n)) { - throw new Error("server.port must be a valid number"); - } - return n; -} -function resolveProvider(raw) { - const v = typeof raw === "string" ? raw : DEFAULTS.PROVIDER; - if (v !== "zai" && v !== "bigmodel") { - throw new Error(`Invalid provider "${v}": must be "zai" or "bigmodel"`); - } - return v; -} -function resolvePlan(raw) { - if (raw === "start-plan") return "start-plan"; - return DEFAULTS.PLAN; -} -function resolveLogLevel(raw) { - const levels = ["debug", "info", "warn", "error"]; - if (typeof raw === "string" && levels.includes(raw)) { - return raw; - } - return DEFAULTS.LOG_LEVEL; -} -function resolveIdentity(inp) { - const rawVersion = (inp.appVersionEnv ?? inp.appVersionYaml ?? DEFAULTS.APP_VERSION).trim(); - const appVersion = ASCII_PRINTABLE.test(rawVersion) ? rawVersion : DEFAULTS.APP_VERSION; - const sourceTitle = (inp.sourceTitleEnv ?? inp.sourceTitleYaml ?? DEFAULTS.SOURCE_TITLE).trim() || DEFAULTS.SOURCE_TITLE; - const refererOrigin = (inp.refererEnv ?? inp.refererYaml ?? DEFAULTS.REFERER_ORIGIN).trim() || DEFAULTS.REFERER_ORIGIN; - const deviceMid = typeof inp.deviceMidYaml === "string" ? inp.deviceMidYaml.trim() : ""; - return { appVersion, sourceTitle, refererOrigin, ...deviceMid ? { deviceMid } : {} }; -} -function resolveClaimConfig(raw) { - const obj = raw && typeof raw === "object" ? raw : {}; - const enabledEnv = process.env[ENV.CLAIM_ENABLED]; - const autoEnv = process.env[ENV.CLAIM_AUTO]; - const originEnv = process.env[ENV.CLAIM_ORIGIN]; - const pollIntervalEnv = process.env[ENV.CLAIM_POLL_INTERVAL_MS]; - const origin = (originEnv ?? (typeof obj.origin === "string" ? obj.origin : DEFAULTS.CLAIM_ORIGIN)).trim() || DEFAULTS.CLAIM_ORIGIN; - validateOrigin(origin, "claim.origin"); - return { - enabled: enabledEnv !== void 0 ? resolveBool(enabledEnv, DEFAULTS.CLAIM_ENABLED) : resolveBool(obj.enabled, DEFAULTS.CLAIM_ENABLED), - auto: autoEnv !== void 0 ? resolveBool(autoEnv, DEFAULTS.CLAIM_AUTO) : resolveBool(obj.auto, DEFAULTS.CLAIM_AUTO), - origin, - pollIntervalMs: resolvePositiveInt(pollIntervalEnv ?? obj.pollIntervalMs ?? obj.poll_interval_ms, DEFAULTS.CLAIM_POLL_INTERVAL_MS, "claim.pollIntervalMs"), - cooldownMs: resolvePositiveInt(obj.cooldownMs ?? obj.cooldown_ms, DEFAULTS.CLAIM_COOLDOWN_MS, "claim.cooldownMs"), - planId: typeof obj.planId === "string" ? obj.planId.trim() : DEFAULTS.CLAIM_PLAN_ID - }; -} -function validate(config) { - if (config.server.port < 1 || config.server.port > 65535) { - throw new Error(`server.port ${config.server.port} is out of range (1-65535)`); - } - if (!config.models.includes(config.defaultModel)) { - config.models.push(config.defaultModel); - } -} - -// src/config/template.ts -var EXAMPLE_CONFIG_YAML = `server: - port: 8080 - host: "0.0.0.0" - -auth: - # Key that clients must provide to use the proxy. - # Set to null/omit to disable client auth. - proxyApiKey: "your-proxy-secret" - - # Upstream credentials come from the OAuth login flow \u2014 run this first: - # bun run src/index.ts auth login - # Path to the stored credentials (default shown): - # oauthCredentialsPath: "~/.zcode-proxy/credentials.json" - -# Which upstream provider to use: "zai" or "bigmodel" -provider: zai - -# Which plan tier to use: -# "coding-plan" (default) \u2014 direct upstream endpoints, permanent API key -# "start-plan" \u2014 routes through zcode.z.ai with JWT auth (requires \`auth login\`) -plan: coding-plan - -providers: - zai: - anthropicBase: "https://api.z.ai/api/anthropic" - openaiBase: "https://api.z.ai/api/coding/paas/v4" - bigmodel: - anthropicBase: "https://open.bigmodel.cn/api/anthropic" - openaiBase: "https://open.bigmodel.cn/api/coding/paas/v4" - -defaultModel: glm-4.6 - -models: - - glm-4.5-air - - glm-4.6 - - glm-4.6v - - glm-4.7 - - glm-5 - - glm-5-turbo - - glm-5v-turbo - - glm-5.1 - - glm-5.2 - - glm-5.3 - -# Configurable identity headers injected on every upstream request to mimic the -# ZCode desktop client (User-Agent, X-ZCode-App-Version, X-Title, -# X-ZCode-Agent, HTTP-Referer). Runtime platform headers (X-Platform, -# X-Os-Category, X-Os-Version) are detected dynamically and are not configured -# here. All fields below are optional; env vars override YAML, which overrides -# defaults. -identity: - # Mirrors process.env.ZCODE_APP_VERSION in the ZCode bundle. - # Must be printable ASCII; non-conforming values fall back to the default. - # Default: "3.10.0" (current ZCode release). Override to match your real client. - appVersion: "3.10.0" - # X-Title suffix \u2192 "Z Code@{sourceTitle}". Default "cli". - sourceTitle: "cli" - # HTTP-Referer URL. Default "https://zcode.z.ai". - refererOrigin: "https://zcode.z.ai" - # Device identity (X-Device-Mid) \u2014 random UUIDv4, generated ONCE and reused - # forever (mirrors ZCode's telemetry deviceMid; no hardware values involved). - # Auto-generated into this file at first \`auth login\` or config creation. - # Leave empty on Android \u2014 the app injects ZCODE_IDENTITY_DEVICE_MID instead. - deviceMid: "" - -# Local client-session inference for cache-affinity experiments. -# "observe" (default) logs inferred sessions in debug mode but does not change -# upstream x-session-id. "enforce" reuses a stable x-session-id for inferred -# coding-plan sessions. "off" disables inference entirely. -clientIdentity: - mode: observe - ttlSeconds: 900 - maxSessions: 1024 - -# Server-controlled upstream URL remapping (mirrors the ZCode client's -# ProviderEndpointRoutingService). The proxy periodically fetches -# {origin}/api/v1/agent/configs and rewrites matching upstream URLs per the -# returned proxyEndpoint.mapping table (currently the coding-plan Anthropic -# endpoints -> zcode.z.ai ultra endpoints). Fail-open: any fetch/parse error -# keeps the original URLs. Env override: ZCODE_ENDPOINT_ROUTING=false. -endpointRouting: - enabled: true - origin: "https://zcode.z.ai" - -# Client request signing V4 (mirrors the ZCode 3.9.1 ClientRequestSigningV4Signer). -# When enabled, the proxy probes {origin}/api/v1/agent/configs (cached 1h) and, -# only if the server sets data.codingPlanSignature.enable=true, signs coding-plan -# requests: handshake against {provider}/api/paas/c1f3a7e2/v2/client, Ed25519 -# signature + proof-of-work headers on every request, fail-open retry ladder -# (two 401 VERIFY rejections -> permanent unsigned bypass). Start-plan and -# off-peak paths are never signed. Env override: ZCODE_CLIENT_SIGNING=false. -clientSigning: - enabled: true - origin: "https://zcode.z.ai" - -logging: - level: info -`; - -// src/auth/manager.ts -var AuthManager = class { - oauthCred = null; - /** Returns the current credential, refreshing if necessary. */ - async getCredential() { - if (this.oauthCred) { - if (this.oauthCred.expiresAt && Date.now() >= this.oauthCred.expiresAt) { - this.oauthCred = null; - throw new Error("OAuth credential expired; re-authentication required \u2014 run: zcode-proxy auth login"); - } - return this.oauthCred; - } - throw new Error("OAuth credential not available \u2014 run: zcode-proxy auth login"); - } - /** Set the OAuth credential (used by the `auth login` flow). */ - setOAuthCredential(cred) { - this.oauthCred = cred; - } -}; - -// src/server/server.ts -var import_node_http = require("node:http"); -var import_node_stream = require("node:stream"); - // src/server/webui.txt -var webui_default = `\r +var webui_default; +var init_webui = __esm({ + "src/server/webui.txt"() { + webui_default = `\r \r \r \r @@ -112240,6566 +9043,111074 @@ var webui_default = `\r if (force || nearBottom()) messages.scrollTop = messages.scrollHeight;\r }\r \r - // =========================================================\r - // composer helpers\r - // =========================================================\r - function autoGrow() {\r - inputEl.style.height = "auto";\r - inputEl.style.height = Math.min(inputEl.scrollHeight, 200) + "px";\r - }\r - function renderAttachPreview() {\r - var box = $("attach-preview"); box.innerHTML = "";\r - pendingImages.forEach(function (p, i) {\r - var w = document.createElement("div"); w.className = "ap";\r - var img = document.createElement("img"); img.src = p.dataUrl;\r - var rm = document.createElement("button"); rm.className = "ap-rm"; rm.innerHTML = "\\u2715";\r - rm.onclick = function () { pendingImages.splice(i, 1); renderAttachPreview(); };\r - w.appendChild(img); w.appendChild(rm); box.appendChild(w);\r - });\r - }\r - function readImages(files) {\r - Array.from(files).forEach(function (f) {\r - if (!/image\\//.test(f.type)) return;\r - var r = new FileReader();\r - r.onload = function () { pendingImages.push({ name: f.name, dataUrl: r.result }); renderAttachPreview(); };\r - r.readAsDataURL(f);\r - });\r - }\r + // =========================================================\r + // composer helpers\r + // =========================================================\r + function autoGrow() {\r + inputEl.style.height = "auto";\r + inputEl.style.height = Math.min(inputEl.scrollHeight, 200) + "px";\r + }\r + function renderAttachPreview() {\r + var box = $("attach-preview"); box.innerHTML = "";\r + pendingImages.forEach(function (p, i) {\r + var w = document.createElement("div"); w.className = "ap";\r + var img = document.createElement("img"); img.src = p.dataUrl;\r + var rm = document.createElement("button"); rm.className = "ap-rm"; rm.innerHTML = "\\u2715";\r + rm.onclick = function () { pendingImages.splice(i, 1); renderAttachPreview(); };\r + w.appendChild(img); w.appendChild(rm); box.appendChild(w);\r + });\r + }\r + function readImages(files) {\r + Array.from(files).forEach(function (f) {\r + if (!/image\\//.test(f.type)) return;\r + var r = new FileReader();\r + r.onload = function () { pendingImages.push({ name: f.name, dataUrl: r.result }); renderAttachPreview(); };\r + r.readAsDataURL(f);\r + });\r + }\r +\r + // =========================================================\r + // settings modal\r + // =========================================================\r + function openSettings() { syncSettingsForm(); renderMcpStatus(state.settings.mcpServers); updateMcpSummary(); overlay.classList.add("open"); }\r + function closeSettings() { overlay.classList.remove("open"); }\r + function syncSettingsForm() {\r + var s = state.settings;\r + $("s-apikey").value = s.apiKey;\r + $("s-system").value = s.systemPrompt;\r + $("s-temp").value = s.temperature; $("s-temp-val").textContent = Number(s.temperature).toFixed(2);\r + $("s-topp").value = s.topP; $("s-topp-val").textContent = Number(s.topP).toFixed(2);\r + $("s-maxtok").value = s.maxTokens;\r + $("s-dosample").checked = s.doSample;\r + $("s-mcpenable").checked = s.mcpEnabled !== false;\r + $("s-mcp").value = (s.mcpServers || []).map(function (m) {\r + return m.authKey ? (m.url + "," + m.authKey) : m.url;\r + }).join("\\n");\r + $("s-cors").value = s.mcpCorsProxy || "";\r + $("s-enter").checked = s.enterToSend;\r + $("banner").style.display = s.apiKey ? "none" : "block";\r + $("banner").textContent = "No proxy API key set. If your proxy requires one, requests will return 401.";\r + }\r + function readSettingsForm() {\r + var s = state.settings;\r + s.apiKey = $("s-apikey").value.trim();\r + s.systemPrompt = $("s-system").value;\r + s.temperature = parseFloat($("s-temp").value);\r + s.topP = parseFloat($("s-topp").value);\r + s.maxTokens = parseInt($("s-maxtok").value, 10) || 4096;\r + s.doSample = $("s-dosample").checked;\r + s.mcpEnabled = $("s-mcpenable").checked;\r + s.mcpServers = $("s-mcp").value.split("\\n").map(function (ln) {\r + var parts = ln.trim().split(",");\r + var url = (parts[0] || "").trim();\r + if (!url) return null;\r + return { url: url, authKey: (parts[1] || "").trim() };\r + }).filter(Boolean);\r + s.mcpCorsProxy = $("s-cors").value.trim();\r + s.enterToSend = $("s-enter").checked;\r + saveState();\r + }\r +\r + // =========================================================\r + // toast\r + // =========================================================\r + var toastTimer;\r + function toast(msg) {\r + toastEl.textContent = msg; toastEl.classList.add("show");\r + clearTimeout(toastTimer); toastTimer = setTimeout(function () { toastEl.classList.remove("show"); }, 2600);\r + }\r +\r + // =========================================================\r + // wiring\r + // =========================================================\r + $("btn-new").onclick = newConv;\r + $("btn-settings").onclick = openSettings;\r + $("btn-close-settings").onclick = function () { readSettingsForm(); closeSettings(); fetchModels(); populateEffort(); syncThinkButton(); };\r + $("btn-clear-all").onclick = function () {\r + if (!confirm("Delete ALL conversations and reset settings? This cannot be undone.")) return;\r + localStorage.removeItem(STORE);\r + state = loadState(); saveState(); applyTheme(); renderSidebar(); renderMessages();\r + syncSettingsForm(); populateModels(KNOWN_MODELS); toast("Reset complete.");\r + };\r + $("btn-theme").onclick = function () {\r + var cur = document.documentElement.getAttribute("data-theme");\r + state.settings.theme = cur === "dark" ? "light" : "dark";\r + saveState(); applyTheme();\r + };\r + $("btn-menu").onclick = function () { sidebar.classList.toggle("collapsed"); };\r + $("btn-mcp-connect").onclick = connectAllMcp;\r + $("btn-mcp-disconnect").onclick = disconnectMcp;\r + overlay.onclick = function (e) { if (e.target === overlay) closeSettings(); };\r +\r + $("s-temp").addEventListener("input", function () { $("s-temp-val").textContent = parseFloat($("s-temp").value).toFixed(2); });\r + $("s-topp").addEventListener("input", function () { $("s-topp-val").textContent = parseFloat($("s-topp").value).toFixed(2); });\r + $("s-apikey").addEventListener("input", function () {\r + $("banner").style.display = $("s-apikey").value.trim() ? "none" : "block";\r + });\r +\r + modelSel.onchange = function () {\r + state.settings.model = modelSel.value;\r + var c = activeConv(); if (c) c.model = modelSel.value;\r + // If images were queued for a vision model and the user switched to a\r + // non-vision one, drop them and explain.\r + if (pendingImages.length && !isVisionModel(modelSel.value)) {\r + pendingImages = []; renderAttachPreview();\r + toast("Switched to a non-vision model \\u2014 attached images were removed.");\r + }\r + saveState(); syncAttachVisibility(); populateEffort();\r + };\r + // GLM-5.2 only has two distinct reasoning-effort levels (low/medium map\r + // to high, xhigh maps to max), so expose just high and max. Other models\r + // get a disabled placeholder (reasoning_effort is GLM-5.2+ only).\r + function populateEffort() {\r + var model = modelSel.value;\r + effortSel.innerHTML = "";\r + if (isReasoningModel(model)) {\r + ["max", "high"].forEach(function (v) {\r + var o = document.createElement("option");\r + o.value = v; o.textContent = v;\r + effortSel.appendChild(o);\r + });\r + var cur = state.settings.reasoningEffort;\r + effortSel.value = (cur === "high") ? "high" : "max";\r + effortSel.disabled = !state.settings.thinkingEnabled;\r + } else {\r + var o = document.createElement("option");\r + o.value = ""; o.textContent = "n/a";\r + effortSel.appendChild(o);\r + effortSel.disabled = true;\r + }\r + }\r + function syncThinkButton() {\r + var on = state.settings.thinkingEnabled;\r + btnThink.classList.toggle("on", on);\r + btnThink.textContent = on ? "Think: on" : "Think: off";\r + btnThink.title = on ? "Deep thinking on \\u2014 click to turn off" : "Deep thinking off \\u2014 click to turn on";\r + // Repopulate so the effort dropdown's disabled state tracks the toggle\r + // (populateEffort sets disabled = !thinkingEnabled for reasoning models).\r + populateEffort();\r + }\r + effortSel.onchange = function () {\r + state.settings.reasoningEffort = effortSel.value || "max";\r + saveState();\r + };\r + btnThink.onclick = function () {\r + state.settings.thinkingEnabled = !state.settings.thinkingEnabled;\r + saveState(); syncThinkButton();\r + };\r +\r + attachBtn.onclick = function () { $("attach-input").click(); };\r + $("attach-input").onchange = function (e) { readImages(e.target.files); e.target.value = ""; };\r + // drag & drop onto composer\r + var composer = document.querySelector(".composer");\r + ["dragover", "dragenter"].forEach(function (ev) {\r + composer.addEventListener(ev, function (e) { e.preventDefault(); composer.style.borderColor = "var(--accent)"; });\r + });\r + ["dragleave", "drop"].forEach(function (ev) {\r + composer.addEventListener(ev, function (e) { e.preventDefault(); composer.style.borderColor = ""; });\r + });\r + composer.addEventListener("drop", function (e) {\r + if (!isVisionModel(modelSel.value)) { toast("Select a vision model (name contains 'v') to attach images."); return; }\r + if (e.dataTransfer && e.dataTransfer.files) readImages(e.dataTransfer.files);\r + });\r +\r + inputEl.addEventListener("input", autoGrow);\r + inputEl.addEventListener("keydown", function (e) {\r + if (e.key === "Enter" && !e.shiftKey && state.settings.enterToSend && !e.isComposing) { e.preventDefault(); send(); }\r + else if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) { e.preventDefault(); send(); }\r + });\r + sendBtn.onclick = function () { if (busy) stop(); else send(); };\r +\r + // =========================================================\r + // boot\r + // =========================================================\r + applyTheme();\r + populateModels(KNOWN_MODELS);\r + renderSidebar(); renderMessages();\r + populateEffort(); syncThinkButton();\r + fetchModels();\r + autoGrow();\r + inputEl.focus();\r + if (!state.conversations.length) newConv();\r + })();\r + \r + \r +\r +`; + } +}); + +// src/provider/providers.ts +function getProvider(id2) { + const def = PROVIDERS[id2]; + if (!def) { + throw new Error(`Unknown provider: "${id2}"`); + } + return def; +} +var ZAI_PROVIDER, BIGMODEL_PROVIDER, PROVIDERS; +var init_providers = __esm({ + "src/provider/providers.ts"() { + "use strict"; + ZAI_PROVIDER = { + id: "zai", + displayName: "Z.AI", + anthropicBaseURL: "https://api.z.ai/api/anthropic", + openaiBaseURL: "https://api.z.ai/api/coding/paas/v4", + bizHost: "https://api.z.ai" + }; + BIGMODEL_PROVIDER = { + id: "bigmodel", + displayName: "BigModel / \u667A\u8C31", + anthropicBaseURL: "https://open.bigmodel.cn/api/anthropic", + openaiBaseURL: "https://open.bigmodel.cn/api/coding/paas/v4", + bizHost: "https://open.bigmodel.cn" + }; + PROVIDERS = { + zai: ZAI_PROVIDER, + bigmodel: BIGMODEL_PROVIDER + }; + } +}); + +// src/auth/types.ts +function credentialString(cred) { + if (cred.secret) { + return `${cred.apiKey}.${cred.secret}`; + } + return cred.apiKey; +} +var init_types = __esm({ + "src/auth/types.ts"() { + "use strict"; + } +}); + +// src/proxy/identity.ts +function resolveAppVersion(raw) { + if (typeof raw !== "string") return void 0; + const v = raw.trim(); + return v.length > 0 && ASCII_PRINTABLE2.test(v) ? v : void 0; +} +function normalizePrintableHeaderValue(raw) { + if (typeof raw !== "string") return void 0; + const v = raw.trim(); + return v.length > 0 && ASCII_PRINTABLE2.test(v) ? v : void 0; +} +function normalizeOsCategory(platform) { + switch (platform) { + case "darwin": + return "macos"; + case "win32": + return "windows"; + default: + return "linux"; + } +} +function resolveClientLanguage() { + const override = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_CLIENT_LANGUAGE); + if (override) return override; + try { + return Intl.DateTimeFormat().resolvedOptions().locale || void 0; + } catch { + return void 0; + } +} +function resolveClientTimezone() { + const override = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_CLIENT_TIMEZONE); + if (override) return override; + try { + return Intl.DateTimeFormat().resolvedOptions().timeZone || void 0; + } catch { + return void 0; + } +} +function buildIdentityHeaders(id2) { + const n = resolveAppVersion(id2.appVersion); + const platform = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_PLATFORM ?? process.platform); + const arch = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_ARCH ?? import_node_os.default.arch()); + const release = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_RELEASE ?? import_node_os.default.release()); + const platformForCategory = process.env.ZCODE_IDENTITY_PLATFORM ?? process.platform; + const releaseChannel = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_RELEASE_CHANNEL) ?? (process.env.ZCODE_ENV?.trim().toLowerCase() === "test" ? "test" : "production"); + const clientLanguage = resolveClientLanguage(); + const clientTimezone = resolveClientTimezone(); + const deviceMid = normalizePrintableHeaderValue(process.env.ZCODE_IDENTITY_DEVICE_MID) ?? normalizePrintableHeaderValue(id2.deviceMid); + const headers2 = { + "HTTP-Referer": id2.refererOrigin, + "User-Agent": `ZCode/${n ?? "unknown"}`, + ...n ? { "X-ZCode-App-Version": n } : {}, + "X-Title": `Z Code@${id2.sourceTitle}`, + "X-ZCode-Agent": "glm", + ...platform && arch ? { "X-Platform": `${platform}-${arch}` } : {}, + ...releaseChannel ? { "X-Release-Channel": releaseChannel } : {}, + ...clientLanguage ? { "X-Client-Language": clientLanguage } : {}, + ...clientTimezone ? { "X-Client-Timezone": clientTimezone } : {}, + ...platform ? { "X-Os-Category": normalizeOsCategory(platformForCategory) } : {}, + ...release ? { "X-Os-Version": release } : {}, + ...deviceMid ? { "X-Device-Mid": deviceMid } : {} + }; + return headers2; +} +var import_node_os, ASCII_PRINTABLE2; +var init_identity = __esm({ + "src/proxy/identity.ts"() { + "use strict"; + import_node_os = __toESM(require("node:os"), 1); + ASCII_PRINTABLE2 = /^[\x20-\x7e]+$/; + } +}); + +// src/proxy/trace-headers.ts +function resolveSessionType(ctx) { + const explicit = ctx.sessionType?.trim(); + if (explicit === "main" || explicit === "subagent" || explicit === "other") return explicit; + if (ctx.sessionId?.startsWith(SUBAGENT_PREFIX) && ctx.sessionId.length > SUBAGENT_PREFIX.length) return "subagent"; + return "main"; +} +function buildZcodeTraceHeaders(ctx = {}) { + const queryId = ctx.queryId ? stripHeaderInternalPrefixes(ctx.queryId, [QUERY_PREFIX]) : void 0; + const sessionId = ctx.sessionId ? stripHeaderInternalPrefixes(ctx.sessionId, SESSION_PREFIXES) : void 0; + return { + "x-request-id": ctx.requestId ?? crypto.randomUUID(), + "x-zcode-session-type": resolveSessionType(ctx), + "x-zcode-trace-id": ctx.traceId ?? crypto.randomUUID(), + ...queryId ? { "x-query-id": queryId } : {}, + ...sessionId ? { "x-session-id": sessionId } : {} + }; +} +function stripHeaderInternalPrefixes(value2, prefixes) { + let out = value2; + for (const prefix2 of prefixes) { + if (out.startsWith(prefix2) && out.length > prefix2.length) out = out.slice(prefix2.length); + } + return out || value2; +} +var QUERY_PREFIX, SUBAGENT_PREFIX, SESSION_PREFIXES; +var init_trace_headers = __esm({ + "src/proxy/trace-headers.ts"() { + "use strict"; + QUERY_PREFIX = "query_"; + SUBAGENT_PREFIX = "subagent_agent_"; + SESSION_PREFIXES = ["sess_", SUBAGENT_PREFIX]; + } +}); + +// src/proxy/client-session.ts +function createClientSessionResolver(now = () => Date.now()) { + const nodes = /* @__PURE__ */ new Map(); + const sessions = /* @__PURE__ */ new Map(); + function remember(nodeHash, session, config) { + const stored = { ...session, nodeHash, lastSeenAt: now() }; + nodes.set(nodeHash, stored); + sessions.set(stored.sessionId, stored); + prune(config); + } + function prune(config) { + const cutoff = now() - config.ttlSeconds * 1e3; + for (const [hash, node] of nodes.entries()) { + if (node.lastSeenAt < cutoff) nodes.delete(hash); + } + for (const [id2, node] of sessions.entries()) { + if (node.lastSeenAt < cutoff) sessions.delete(id2); + } + while (sessions.size > config.maxSessions) { + let oldestId = ""; + let oldestAt = Infinity; + for (const [id2, node] of sessions.entries()) { + if (node.lastSeenAt < oldestAt) { + oldestAt = node.lastSeenAt; + oldestId = id2; + } + } + if (!oldestId) break; + sessions.delete(oldestId); + for (const [hash, node] of nodes.entries()) { + if (node.sessionId === oldestId) nodes.delete(hash); + } + } + } + function action(config) { + return config.mode; + } + return { + resolve(req, body2, format, model, config) { + if (config.mode === "off") return { source: "none", action: "off", confidence: 0 }; + prune(config); + const explicitTrace = requestTraceContext(req, body2); + if (explicitTrace.sessionId) return explicitResult(explicitTrace, config); + const canonical = canonicalize(body2, format, model); + if (!canonical) { + if (hasTraceContext(explicitTrace)) return explicitResult(explicitTrace, config); + return { source: "none", action: action(config), confidence: 0 }; + } + const nodeHash = hashJson(canonical.identity); + const existing = nodes.get(nodeHash); + if (existing) { + remember(nodeHash, existing, config); + return withTraceContext(result("lineage", action(config), existing, 0.95), explicitTrace); + } + const parent2 = findLinearParent(canonical, nodes); + if (parent2) { + remember(nodeHash, parent2, config); + return withTraceContext(result("lineage", action(config), parent2, 0.9), explicitTrace); + } + const fresh = newSession(); + remember(nodeHash, fresh, config); + return withTraceContext(result("lineage", action(config), fresh, 0.75), explicitTrace); + } + }; +} +function result(source, action, node, confidence) { + return { + source, + action, + confidence, + sessionId: node.sessionId, + upstreamSessionId: node.upstreamSessionId + }; +} +function requestTraceContext(req, body2) { + const bodyTrace = bodyMetadataTrace(body2); + return { + requestId: firstHeader(req.headers, ["x-request-id"]) ?? bodyTrace.requestId, + traceId: firstHeader(req.headers, ["x-zcode-trace-id"]) ?? bodyTrace.traceId, + queryId: firstHeader(req.headers, ["x-query-id"]) ?? bodyTrace.queryId, + sessionId: firstHeader(req.headers, ["x-opencode-session", "x-claude-code-session-id", "x-session-id", "x-parent-session-id", "helicone-session-id"]) ?? bodyTrace.sessionId + }; +} +function explicitResult(trace, config) { + return { + source: "explicit", + action: config.mode, + confidence: 1, + ...trace.requestId ? { requestId: trace.requestId } : {}, + ...trace.traceId ? { traceId: trace.traceId } : {}, + ...trace.queryId ? { queryId: trace.queryId } : {}, + ...trace.sessionId ? { sessionId: trace.sessionId, upstreamSessionId: trace.sessionId } : {} + }; +} +function withTraceContext(session, trace) { + if (!trace.requestId && !trace.traceId && !trace.queryId) return session; + return { + ...session, + ...trace.requestId ? { requestId: trace.requestId } : {}, + ...trace.traceId ? { traceId: trace.traceId } : {}, + ...trace.queryId ? { queryId: trace.queryId } : {} + }; +} +function hasTraceContext(trace) { + return Boolean(trace.requestId || trace.traceId || trace.queryId || trace.sessionId); +} +function firstHeader(headers2, names) { + for (const name2 of names) { + const value2 = headers2.get(name2); + if (value2 && value2.trim()) return value2.trim(); + } + return null; +} +function bodyMetadataTrace(body2) { + if (!body2) return {}; + try { + const parsed = JSON.parse(body2); + const metadata = parsed?.metadata; + if (!metadata || typeof metadata !== "object") return {}; + return { + requestId: stringProperty(metadata, ["requestId", "request_id"]), + traceId: stringProperty(metadata, ["traceId", "trace_id"]), + queryId: stringProperty(metadata, ["queryId", "query_id"]), + sessionId: stringProperty(metadata, ["sessionId", "session_id", "conversationId", "conversation_id"]) + }; + } catch { + return {}; + } +} +function stringProperty(obj, names) { + for (const name2 of names) { + const value2 = obj[name2]; + if (typeof value2 === "string" && value2.trim()) return value2.trim(); + } + return void 0; +} +function canonicalize(body2, format, fallbackModel) { + if (!body2) return null; + let parsed; + try { + parsed = JSON.parse(body2); + } catch { + return null; + } + if (!parsed || typeof parsed !== "object") return null; + const model = typeof parsed.model === "string" ? parsed.model : fallbackModel; + const messages = Array.isArray(parsed.messages) ? parsed.messages : []; + if (messages.length === 0) return null; + const identity = { + format, + model, + system: parsed.system, + developer: messages.filter((m) => typeof m === "object" && m !== null && m.role === "developer"), + tools: parsed.tools, + tool_choice: parsed.tool_choice, + messages + }; + return { model, identity, messages }; +} +function findLinearParent(canonical, nodes) { + if (canonical.messages.length < 3) return null; + const prefix2 = { + ...canonical.identity, + messages: canonical.messages.slice(0, -2) + }; + if (prefix2.messages.length === 0) return null; + return nodes.get(hashJson(prefix2)) ?? null; +} +function newSession() { + const upstreamSessionId = crypto.randomUUID(); + return { + nodeHash: "", + sessionId: `ses_${upstreamSessionId.replace(/-/g, "").slice(0, 12)}`, + upstreamSessionId, + lastSeenAt: Date.now() + }; +} +function hashJson(value2) { + return hashString(stableStringify(value2)); +} +function hashString(value2) { + return import_node_crypto.default.createHash("sha256").update(value2, "utf-8").digest("hex"); +} +function stableStringify(value2) { + if (value2 === null || typeof value2 !== "object") return JSON.stringify(value2); + if (Array.isArray(value2)) return `[${value2.map(stableStringify).join(",")}]`; + const obj = value2; + return `{${Object.keys(obj).sort().map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(",")}}`; +} +var import_node_crypto, defaultClientSessionResolver; +var init_client_session = __esm({ + "src/proxy/client-session.ts"() { + "use strict"; + import_node_crypto = __toESM(require("node:crypto"), 1); + defaultClientSessionResolver = createClientSessionResolver(); + } +}); + +// src/proxy/session-context.ts +function resolveSessionContext(input) { + if (input.config.clientIdentity.mode === "off") return void 0; + const resolver = input.resolver ?? defaultClientSessionResolver; + return resolver.resolve(input.clientReq, input.body, input.upstreamFormat, input.model, input.config.clientIdentity); +} +function shouldUseExactTraceHeaders(plan, session) { + return plan === "start-plan" || hasExplicitTraceHeaders(session) || shouldForwardSessionId(session); +} +function shouldForwardSessionId(session) { + return session?.source === "explicit" || session?.action === "enforce"; +} +function sessionIdForHeader(session) { + if (!session || !shouldForwardSessionId(session)) return void 0; + return session.upstreamSessionId ?? session.sessionId; +} +function hasExplicitTraceHeaders(session) { + return Boolean(session?.requestId || session?.traceId || session?.queryId); +} +var init_session_context = __esm({ + "src/proxy/session-context.ts"() { + "use strict"; + init_client_session(); + } +}); + +// src/proxy/upstream.ts +function buildUpstreamURL(format, provider, plan = "coding-plan") { + if (plan === "start-plan") { + return `${STARTPLAN_ANTHROPIC_BASE}/anthropic/v1/messages`; + } + if (format === "anthropic") { + return `${provider.anthropicBaseURL}/v1/messages`; + } + return `${provider.openaiBaseURL}/chat/completions`; +} +function buildAuthHeaders(format, cred, identity, plan = "coding-plan", clientSession) { + const credStr = plan === "start-plan" && cred.jwt ? cred.jwt : credentialString(cred); + const base = { + ...buildIdentityHeaders(identity), + ...buildTraceHeaders(plan, clientSession) + }; + if (format === "anthropic") { + if (plan === "start-plan" && cred.jwt) { + base["authorization"] = `Bearer ${cred.jwt}`; + } else { + base["x-api-key"] = credStr; + } + base["anthropic-version"] = ANTHROPIC_VERSION; + } else { + base["authorization"] = `Bearer ${credStr}`; + } + return base; +} +function buildTraceHeaders(plan, clientSession) { + if (shouldUseExactTraceHeaders(plan, clientSession)) { + return buildZcodeTraceHeaders({ + requestId: clientSession?.requestId, + traceId: clientSession?.traceId, + queryId: clientSession?.queryId, + sessionId: sessionIdForHeader(clientSession) + }); + } + const headers2 = { + "x-request-id": crypto.randomUUID(), + // ZCode 3.9.1 attributes every model request; a forwarded conversation turn is the main-agent loop. + "x-zcode-session-type": "main", + "x-zcode-trace-id": crypto.randomUUID() + }; + if (plan !== "start-plan") { + headers2["x-query-id"] = crypto.randomUUID(); + headers2["x-session-id"] = crypto.randomUUID(); + } + return headers2; +} +function collectPassthroughHeaders(req) { + const result3 = {}; + for (const [key, value2] of req.headers.entries()) { + const lower = key.toLowerCase(); + if (STRIP_HEADERS.has(lower)) continue; + if (lower === "anthropic-beta") { + result3[lower] = value2; + } + } + return result3; +} +function buildUpstreamHeaderPairs(clientReq, format, cred, identity, plan = "coding-plan", extraHeaders, clientSession) { + const clientAcceptEncoding = clientReq.headers.get("accept-encoding") ?? "gzip"; + return [ + ["content-type", "application/json"], + ["accept-encoding", clientAcceptEncoding], + ...Object.entries(collectPassthroughHeaders(clientReq)), + ...Object.entries(buildAuthHeaders(format, cred, identity, plan, clientSession)), + ...Object.entries(extraHeaders ?? {}) + ]; +} +function buildUpstreamRequest(clientReq, format, provider, cred, body2, identity, plan = "coding-plan", extraHeaders, clientSession) { + const url2 = buildUpstreamURL(format, provider, plan); + const headerPairs = buildUpstreamHeaderPairs(clientReq, format, cred, identity, plan, extraHeaders, clientSession); + const init = { + method: "POST", + headers: Object.fromEntries(headerPairs) + }; + if (body2 !== void 0) { + init.body = body2; + } + return new Request(url2, init); +} +var ANTHROPIC_VERSION, STARTPLAN_ANTHROPIC_BASE, STRIP_HEADERS; +var init_upstream = __esm({ + "src/proxy/upstream.ts"() { + "use strict"; + init_types(); + init_identity(); + init_trace_headers(); + init_session_context(); + ANTHROPIC_VERSION = "2023-06-01"; + STARTPLAN_ANTHROPIC_BASE = "https://zcode.z.ai/api/v1/zcode-plan"; + STRIP_HEADERS = /* @__PURE__ */ new Set([ + "host", + "authorization", + "x-api-key", + "anthropic-version", + "content-length", + "connection", + "proxy-authorization", + "proxy-authenticate", + "transfer-encoding", + "x-request-id", + "x-zcode-trace-id", + "x-zcode-session-type", + "x-query-id", + "x-session-id", + // V4 signing headers are proxy-generated only; inbound copies must never + // reach the upstream (spoofed values would either fail verification or + // silently disable proxy signing via the existing-header guard). + "x-client-ts", + "x-client-version", + "x-client-sig", + "x-client-nonce", + "x-app-id", + "x-client-pow", + "x-client-sign-verified" + ]); + } +}); + +// src/proxy/endpoint-routing.ts +function normalizePath(pathname) { + if (pathname === "/") return "/"; + return pathname.replace(/\/+$/u, "") || "/"; +} +function routingKey(url2) { + const port = url2.port || "443"; + return `${url2.protocol}//${url2.hostname.toLowerCase()}:${port}${normalizePath(url2.pathname)}`; +} +function parseMappingUrl(value2, field) { + if (typeof value2 !== "string") throw new Error(`mapping.${field} must be a string`); + const parsed = new URL(value2); + if (parsed.protocol !== "https:" || parsed.username || parsed.password || parsed.search || parsed.hash) { + throw new Error(`mapping.${field} URL is not a plain https URL`); + } + return parsed; +} +function identityCacheKey(identity) { + return JSON.stringify([identity.appVersion, identity.sourceTitle, identity.refererOrigin, identity.deviceMid ?? ""]); +} +function getDefaultEndpointRouting(config) { + if (!config.endpointRouting.enabled) return null; + const key = `${config.endpointRouting.origin} +${identityCacheKey(config.identity)}`; + if (!defaultRouting || key !== defaultRoutingKey) { + defaultRouting = new EndpointRoutingService({ + origin: config.endpointRouting.origin, + identity: config.identity + }); + defaultRoutingKey = key; + } + return defaultRouting; +} +var DEFAULT_ORIGIN, CONFIG_PATH, SUCCESS_TTL_MS, FAILURE_COOLDOWN_MS, REQUEST_TIMEOUT_MS, MAX_MAPPING_ENTRIES, EndpointRoutingService, defaultRouting, defaultRoutingKey; +var init_endpoint_routing = __esm({ + "src/proxy/endpoint-routing.ts"() { + "use strict"; + init_identity(); + DEFAULT_ORIGIN = "https://zcode.z.ai"; + CONFIG_PATH = "/api/v1/agent/configs"; + SUCCESS_TTL_MS = 3e5; + FAILURE_COOLDOWN_MS = 3e4; + REQUEST_TIMEOUT_MS = 3e3; + MAX_MAPPING_ENTRIES = 256; + EndpointRoutingService = class { + configUrl; + identity; + credential; + fetchImpl; + now; + successTtlMs; + failureCooldownMs; + requestTimeoutMs; + onSnapshot; + snapshot; + retryAfter = 0; + refreshPromise; + constructor(opts) { + this.configUrl = `${(opts.origin?.trim() || DEFAULT_ORIGIN).replace(/\/+$/u, "")}${CONFIG_PATH}`; + this.identity = opts.identity; + this.credential = opts.credential; + this.fetchImpl = opts.fetchImpl ?? fetch; + this.now = opts.now ?? Date.now; + this.successTtlMs = opts.successTtlMs ?? SUCCESS_TTL_MS; + this.failureCooldownMs = opts.failureCooldownMs ?? FAILURE_COOLDOWN_MS; + this.requestTimeoutMs = opts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS; + this.onSnapshot = opts.onSnapshot; + } + /** True when at least one successful snapshot has been fetched. */ + hasSnapshot() { + return this.snapshot !== void 0; + } + /** + * Resolve a request URL through the mapping table. Never throws: any error + * resolves to `{ routed: false, url }` so the caller keeps the original URL. + * The optional `credential` (coding-plan key) is attached as `x-api-key` on + * a mapping refresh fetch, mirroring the client's `sourceHeaders`. + */ + async resolve(url2, credential) { + let parsed; + try { + parsed = new URL(url2); + } catch { + return { routed: false, url: url2 }; + } + try { + await this.ensureFresh(credential); + } catch { + } + const target2 = this.snapshot?.mapping.get(routingKey(parsed)); + if (!target2) return { routed: false, url: url2 }; + const rewritten = new URL(target2); + rewritten.search = parsed.search; + return { routed: true, url: rewritten.href }; + } + async ensureFresh(credential) { + const now = this.now(); + if (this.snapshot && this.snapshot.expiresAt > now || this.retryAfter > now) return; + const pending = this.refreshPromise ?? this.beginRefresh(credential); + await pending; + } + beginRefresh(credential) { + const promise = this.refresh(credential).finally(() => { + if (this.refreshPromise === promise) this.refreshPromise = void 0; + }); + this.refreshPromise = promise; + return promise; + } + async refresh(credential) { + const identityHeaders = Object.fromEntries( + Object.entries(buildIdentityHeaders(this.identity)).filter(([name2]) => name2 !== "X-ZCode-Agent") + ); + const headers2 = { + ...identityHeaders, + Accept: "application/json" + }; + const key = credential ?? this.credential?.(); + if (key) headers2["x-api-key"] = key; + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs); + try { + const resp = await this.fetchImpl(this.configUrl, { + method: "GET", + headers: headers2, + redirect: "manual", + signal: controller.signal + }); + if (resp.status < 200 || resp.status >= 300) throw new Error(`agent_configs_http_${resp.status}`); + const parsed = await resp.json(); + const envelope = parsed; + if (!envelope || typeof envelope !== "object" || envelope.code !== 0) { + throw new Error("agent_configs_nonzero_code"); + } + const data2 = envelope.data; + const entries2 = data2?.proxyEndpoint?.mapping; + const list = Array.isArray(entries2) ? entries2 : []; + if (list.length > MAX_MAPPING_ENTRIES) throw new Error("agent_configs_too_many_mappings"); + const mapping = /* @__PURE__ */ new Map(); + for (const entry of list) { + const raw = entry; + const from = parseMappingUrl(raw.from, "from"); + const to = parseMappingUrl(raw.to, "to"); + const key2 = routingKey(from); + if (mapping.has(key2)) throw new Error("agent_configs_duplicate_from"); + mapping.set(key2, to.href); + } + this.snapshot = { expiresAt: this.now() + this.successTtlMs, mapping }; + this.retryAfter = 0; + this.onSnapshot?.(mapping.size); + } catch { + this.retryAfter = this.now() + this.failureCooldownMs; + } finally { + clearTimeout(timer); + } + } + }; + defaultRouting = null; + defaultRoutingKey = ""; + } +}); + +// src/proxy/client-signing.ts +function encodeUtf8(value2) { + const bytes = encoder.encode(value2); + const out = new Uint8Array(bytes.byteLength); + out.set(bytes); + return out; +} +function bytesToBase64(bytes) { + let binary = ""; + for (const b of bytes) binary += String.fromCharCode(b); + return btoa(binary); +} +function bytesToHex(bytes) { + return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(""); +} +function randomHex(byteCount) { + return bytesToHex(crypto.getRandomValues(new Uint8Array(byteCount))); +} +function base64ToBytes(value2) { + if (!value2 || value2.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(value2)) { + throw new Error("invalid base64"); + } + const binary = atob(value2); + const out = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i); + return out; +} +async function hkdfBytes(secret, info) { + const key = await crypto.subtle.importKey("raw", encodeUtf8(secret), "HKDF", false, ["deriveBits"]); + return new Uint8Array(await crypto.subtle.deriveBits( + { name: "HKDF", hash: "SHA-256", salt: encodeUtf8(KDF_SALT), info: encodeUtf8(info) }, + key, + 256 + )); +} +async function handshakeSignature(secret, message) { + const bits = await hkdfBytes(secret, KDF_INFO_HMAC); + try { + const key = await crypto.subtle.importKey("raw", bits, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]); + const mac = new Uint8Array(await crypto.subtle.sign("HMAC", key, encodeUtf8(message))); + try { + return bytesToBase64(mac); + } finally { + mac.fill(0); + } + } finally { + bits.fill(0); + } +} +async function decryptSigningPrivateKey(apiKeyId, secret, privateCipher) { + const cipher = base64ToBytes(privateCipher); + if (cipher.byteLength <= 12 + 16) throw new Error("privateCipher is too short"); + const aesKeyBits = await hkdfBytes(secret, KDF_INFO_ED25519); + try { + const aesKey = await crypto.subtle.importKey("raw", aesKeyBits, "AES-GCM", false, ["decrypt"]); + const plain = new Uint8Array( + await crypto.subtle.decrypt( + { name: "AES-GCM", iv: cipher.slice(0, 12), additionalData: encodeUtf8(apiKeyId), tagLength: 128 }, + aesKey, + cipher.slice(12) + ) + ); + try { + const pkcs8 = base64ToBytes(new TextDecoder().decode(plain)); + return await crypto.subtle.importKey("pkcs8", pkcs8, "Ed25519", false, ["sign"]); + } finally { + plain.fill(0); + } + } finally { + aesKeyBits.fill(0); + } +} +async function signBusinessMessage(privateKey, message) { + const sig = new Uint8Array(await crypto.subtle.sign("Ed25519", privateKey, encodeUtf8(message))); + try { + return bytesToBase64(sig); + } finally { + sig.fill(0); + } +} +function hasLeadingZeroBits(bytes, bits) { + const fullBytes = Math.floor(bits / 8); + for (let i = 0; i < fullBytes; i++) { + if (bytes[i] !== 0) return false; + } + const remainder = bits % 8; + if (remainder === 0) return true; + const mask = 255 << 8 - remainder & 255; + return ((bytes[fullBytes] ?? 255) & mask) === 0; +} +async function createProofOfWork(apiKeyId, sessionId, ts, signal2) { + const seedDigest = new Uint8Array( + await crypto.subtle.digest("SHA-256", encodeUtf8(`${apiKeyId} +${APP_ID} +${sessionId} +${ts}`)) + ); + const seed2 = bytesToHex(seedDigest).slice(0, 32); + const nonce = randomHex(POW_NONCE_BYTES); + for (let counter = 0; counter <= 4294967295; counter++) { + signal2?.throwIfAborted(); + const candidate = `${nonce}${counter.toString(16).padStart(8, "0")}`; + const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", encodeUtf8(`${seed2} +${candidate}`))); + if (hasLeadingZeroBits(digest, POW_BITS)) return candidate; + } + throw new Error("Unable to solve client request proof of work"); +} +function parseSigningCredential(credential) { + const dot = credential.indexOf("."); + if (dot <= 0 || dot !== credential.lastIndexOf(".")) return void 0; + const apiKeyId = credential.slice(0, dot); + const apiKeySecret = credential.slice(dot + 1); + if (!apiKeyId.trim() || !apiKeySecret.trim()) return void 0; + return { apiKeyId, apiKeySecret }; +} +function isUnsignedPath(pathname) { + let path2 = pathname; + try { + path2 = decodeURIComponent(pathname); + } catch { + } + path2 = path2.replace(/\/+$/u, ""); + return UNSIGNED_PATHS.has(path2); +} +function findHeader(pairs, name2) { + const lower = name2.toLowerCase(); + for (const [key, value2] of pairs) { + if (key.toLowerCase() === lower) return value2; + } + return void 0; +} +async function sendWithClientSigning(signer, params) { + const { url: url2, headerPairs, credential, appVersion, send, debug } = params; + if (!signer) return send(headerPairs); + const first = await signer.signWithStatus(url2, headerPairs, { credential, appVersion }); + let resp = await send(first.pairs); + if (!first.signed || !await signer.isVerifyFailure(resp)) return resp; + debug?.("401 VERIFY_SIGNATURE_* \u2014 invalidating signing key and retrying once"); + signer.invalidate(url2, credential); + const second = await signer.signWithStatus(url2, headerPairs, { credential, appVersion }); + resp = await send(second.pairs); + if (!second.signed || !await signer.isVerifyFailure(resp)) return resp; + signer.setBypass(url2, credential); + debug?.("401 VERIFY_SIGNATURE_* twice \u2014 sending unsigned (signing bypassed)"); + return send(headerPairs); +} +function identityCacheKey2(identity) { + return JSON.stringify([identity.appVersion, identity.sourceTitle, identity.refererOrigin, identity.deviceMid ?? ""]); +} +function getDefaultClientSigning(config) { + if (!config.clientSigning.enabled) return null; + const key = `${config.clientSigning.origin} +${identityCacheKey2(config.identity)}`; + if (!defaultSigner || key !== defaultSignerKey) { + defaultSigner = new ClientSigningManager({ + identity: config.identity, + origin: config.clientSigning.origin + }); + defaultSignerKey = key; + } + return defaultSigner; +} +var DEFAULT_ORIGIN2, GATE_PATH, HANDSHAKE_PATH, APP_ID, POW_BITS, NONCE_BYTES, POW_NONCE_BYTES, KDF_SALT, KDF_INFO_HMAC, KDF_INFO_ED25519, HANDSHAKE_METHOD, GATE_TTL_MS, GATE_FAILURE_COOLDOWN_MS, GATE_UNAVAILABLE_COOLDOWN_MS, GATE_TIMEOUT_MS, HANDSHAKE_TIMEOUT_MS, VERIFY_SIGNATURE_INVALID, VERIFY_APIKEY_EXPIRED, UNSIGNED_PATHS, SIGNING_HEADER_NAMES, encoder, ClientSigningManager, defaultSigner, defaultSignerKey; +var init_client_signing = __esm({ + "src/proxy/client-signing.ts"() { + "use strict"; + init_identity(); + DEFAULT_ORIGIN2 = "https://zcode.z.ai"; + GATE_PATH = "/api/v1/agent/configs"; + HANDSHAKE_PATH = "/api/paas/c1f3a7e2/v2/client"; + APP_ID = "zcode"; + POW_BITS = 8; + NONCE_BYTES = 16; + POW_NONCE_BYTES = 12; + KDF_SALT = "WD_CLIENT_SIGN_KDF_SALT"; + KDF_INFO_HMAC = "getSignKey_hmac"; + KDF_INFO_ED25519 = "ed25519_priv"; + HANDSHAKE_METHOD = "get_sign_key"; + GATE_TTL_MS = 36e5; + GATE_FAILURE_COOLDOWN_MS = 6e4; + GATE_UNAVAILABLE_COOLDOWN_MS = 3e4; + GATE_TIMEOUT_MS = 15e3; + HANDSHAKE_TIMEOUT_MS = 1e4; + VERIFY_SIGNATURE_INVALID = "VERIFY_SIGNATURE_INVALID"; + VERIFY_APIKEY_EXPIRED = "VERIFY_APIKEY_EXPIRED"; + UNSIGNED_PATHS = /* @__PURE__ */ new Set([ + "/api/v1/zcode-plan/anthropic/v1/messages", + "/api/v1/zcode-plan/chat/completions", + "/api/v1/off-peak/anthropic/v1/messages" + ]); + SIGNING_HEADER_NAMES = /* @__PURE__ */ new Set([ + "x-client-ts", + "x-client-version", + "x-client-sig", + "x-client-nonce", + "x-app-id", + "x-client-pow", + "x-client-sign-verified" + ]); + encoder = new TextEncoder(); + ClientSigningManager = class { + gateUrl; + identity; + fetchImpl; + now; + states = /* @__PURE__ */ new Map(); + notedKeys = /* @__PURE__ */ new Set(); + onEvent; + constructor(opts) { + this.gateUrl = `${(opts.origin?.trim() || DEFAULT_ORIGIN2).replace(/\/+$/u, "")}${GATE_PATH}`; + this.identity = opts.identity; + this.fetchImpl = opts.fetchImpl ?? fetch; + this.now = opts.now ?? Date.now; + this.onEvent = opts.onEvent; + } + /** + * Add the V4 signing headers to an upstream header-pair list. Returns the + * input pairs unchanged whenever signing does not apply: exempt path, + * bypass, non-signable credential, missing session id, gate off/unreachable, + * or handshake failure. Never throws. + */ + async sign(url2, pairs, cred) { + return (await this.signWithStatus(url2, pairs, cred)).pairs; + } + /** + * `sign` with a `signed` flag so the retry ladder can distinguish + * "signed but rejected" from "never signed" without identity checks on the + * returned array reference. Cheap local eligibility checks (credential + * separator, session id) run BEFORE the gate probe so non-signable + * credentials never pay for network fetches. + */ + async signWithStatus(url2, pairs, cred) { + let parsed; + try { + parsed = new URL(url2); + } catch { + return { pairs, signed: false }; + } + if (parsed.protocol !== "https:") return { pairs, signed: false }; + if (isUnsignedPath(parsed.pathname)) return { pairs, signed: false }; + if (pairs.some(([k]) => k.toLowerCase() === "x-client-sig")) return { pairs, signed: false }; + const stateKey = `${parsed.origin} +${cred.credential}`; + const state2 = this.stateFor(stateKey); + if (state2.bypass) return { pairs, signed: false }; + const parsedCred = parseSigningCredential(cred.credential); + if (!parsedCred) { + this.noteOnce(stateKey, "credential has no {apiKeyId}.{apiKeySecret} separator \u2014 signing skipped"); + return { pairs, signed: false }; + } + const sessionId = findHeader(pairs, "x-session-id")?.trim(); + if (!sessionId) { + this.noteOnce(stateKey, "upstream request has no x-session-id \u2014 signing skipped"); + return { pairs, signed: false }; + } + if (!await this.gateEnabled(state2, cred)) return { pairs, signed: false }; + let privateKey; + try { + privateKey = await this.ensurePrivateKey(state2, stateKey, parsedCred, parsed.origin); + } catch { + this.noteOnce(stateKey, "signing handshake failed \u2014 sending unsigned"); + this.invalidateState(stateKey); + return { pairs, signed: false }; + } + const signedPairs = await this.buildSignedPairs(stateKey, pairs, privateKey, parsedCred, sessionId, cred.appVersion); + return signedPairs ? { pairs: signedPairs, signed: true } : { pairs, signed: false }; + } + async buildSignedPairs(stateKey, pairs, privateKey, parsedCred, sessionId, appVersion) { + const ts = String(Date.now()); + const nonce = randomHex(NONCE_BYTES); + let pow; + let sig; + try { + pow = await createProofOfWork(parsedCred.apiKeyId, sessionId, ts); + sig = await signBusinessMessage( + privateKey, + `${parsedCred.apiKeyId} +${ts} +${appVersion} +${sessionId} +${nonce}` + ); + } catch (err) { + if (err.name !== "AbortError") { + this.noteOnce(stateKey, `signing failed (${err.message}) \u2014 sending unsigned`); + } + return null; + } + const cleaned = pairs.filter(([k]) => { + const lower = k.toLowerCase(); + return !SIGNING_HEADER_NAMES.has(lower) && lower !== "x-session-id"; + }); + return [ + ...cleaned, + ["X-Client-Ts", ts], + ["X-Client-Version", appVersion], + ["X-Client-Sig", sig], + // canonical case replaces the lowercase trace copy in this append position + // (mirrors the client's i.set("X-Session-Id") Headers.set semantics) + ["X-Session-Id", sessionId], + ["X-Client-Nonce", nonce], + ["X-App-Id", APP_ID], + ["X-Client-Pow", pow] + ]; + } + /** + * True when the response is a signing rejection the client retries on: + * HTTP 401 whose envelope mentions VERIFY_SIGNATURE_INVALID / VERIFY_APIKEY_EXPIRED. + * Reads a clone; the response body stays consumable by the caller. + */ + async isVerifyFailure(resp) { + if (resp.status !== 401) return false; + try { + const body2 = await resp.clone().json(); + if (!body2 || typeof body2 !== "object" || Array.isArray(body2)) return false; + const data2 = body2.data; + const error2 = body2.error; + const candidates = [body2.msg, body2.reason, data2?.reason, error2?.reason, error2?.message]; + return candidates.some((v) => v === VERIFY_SIGNATURE_INVALID || v === VERIFY_APIKEY_EXPIRED); + } catch { + return false; + } + } + /** Drop the cached signing key for a (origin, credential) pair after a VERIFY rejection. */ + invalidate(url2, credential) { + try { + const stateKey = `${new URL(url2).origin} +${credential}`; + this.invalidateState(stateKey); + } catch { + } + } + /** Permanently stop signing for a (origin, credential) pair (two VERIFY rejections). */ + setBypass(url2, credential) { + try { + const stateKey = `${new URL(url2).origin} +${credential}`; + const state2 = this.stateFor(stateKey); + state2.bypass = true; + this.invalidateState(stateKey); + this.onEvent?.("client-signing: VERIFY rejection persisted \u2014 bypassing signing for this credential"); + } catch { + } + } + invalidateState(stateKey) { + const state2 = this.states.get(stateKey); + if (!state2) return; + state2.epoch += 1; + state2.privKey = void 0; + state2.handshake = void 0; + } + stateFor(stateKey) { + let state2 = this.states.get(stateKey); + if (!state2) { + state2 = { gateEnabled: false, gateExpiresAt: 0, gateNegUntil: 0, epoch: 0, bypass: false }; + this.states.set(stateKey, state2); + } + return state2; + } + async gateEnabled(state2, cred) { + const now = this.now(); + if (state2.gateExpiresAt > now) return state2.gateEnabled; + if (state2.gateNegUntil > now) return false; + if (state2.gatePromise) return state2.gatePromise; + const promise = this.probeGate(state2, cred).finally(() => { + if (state2.gatePromise === promise) state2.gatePromise = void 0; + }); + state2.gatePromise = promise; + return promise; + } + async probeGate(state2, cred) { + const now = this.now(); + let outcome; + try { + outcome = await this.fetchGate(cred); + } catch { + state2.gateNegUntil = now + GATE_FAILURE_COOLDOWN_MS; + return false; + } + state2.gateEnabled = outcome === "enabled"; + if (outcome === "unavailable") { + state2.gateNegUntil = now + GATE_UNAVAILABLE_COOLDOWN_MS; + } else { + state2.gateExpiresAt = now + GATE_TTL_MS; + state2.gateNegUntil = 0; + } + if (state2.gateEnabled) this.onEvent?.("client-signing: server enabled codingPlanSignature \u2014 signing requests"); + return state2.gateEnabled; + } + async fetchGate(cred) { + const identityHeaders = Object.fromEntries( + Object.entries(buildIdentityHeaders(this.identity)).filter(([name2]) => name2 !== "X-ZCode-Agent" && name2 !== "X-Device-Mid") + ); + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), GATE_TIMEOUT_MS); + try { + const resp = await this.fetchImpl(this.gateUrl, { + method: "GET", + headers: { ...identityHeaders, "x-api-key": cred.credential }, + redirect: "manual", + signal: controller.signal + }); + if (!resp.ok) return "unavailable"; + const parsed = await resp.json(); + if (!parsed || parsed.code !== 0) return "unavailable"; + const data2 = parsed.data; + if (!data2 || !Object.prototype.hasOwnProperty.call(data2, "codingPlanSignature")) return "disabled"; + const signature = data2.codingPlanSignature; + return signature?.enable === true ? "enabled" : "disabled"; + } finally { + clearTimeout(timer); + } + } + async ensurePrivateKey(state2, stateKey, parsedCred, origin) { + if (state2.privKey) return state2.privKey; + if (state2.handshake) return state2.handshake; + const epoch = state2.epoch; + const handshake = this.performHandshake(parsedCred, origin).then((key) => { + if (state2.epoch !== epoch) throw new Error("signing key changed during handshake"); + state2.privKey = key; + return key; + }); + const clear = () => { + if (state2.handshake === handshake) state2.handshake = void 0; + }; + handshake.then(clear, clear); + state2.handshake = handshake; + return handshake; + } + async performHandshake(parsedCred, origin) { + const ts = String(Date.now()); + const nonce = randomHex(NONCE_BYTES); + const sig = await handshakeSignature( + parsedCred.apiKeySecret, + `${HANDSHAKE_METHOD} +${parsedCred.apiKeyId} +${ts} +${nonce}` + ); + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), HANDSHAKE_TIMEOUT_MS); + try { + const resp = await this.fetchImpl(`${origin}${HANDSHAKE_PATH}`, { + method: "POST", + headers: { Authorization: `${parsedCred.apiKeyId}.${parsedCred.apiKeySecret}`, "Content-Type": "application/json" }, + body: JSON.stringify({ apiKey: `${parsedCred.apiKeyId}.${parsedCred.apiKeySecret}`, nonce, sig, ts }), + redirect: "manual", + signal: controller.signal + }); + if (resp.status !== 200) throw new Error(`handshake_http_${resp.status}`); + const envelope = await resp.json(); + if (envelope.code === 500) throw new Error("handshake_server_500"); + if (envelope.code !== 200) throw new Error(`handshake_rejected: ${String(envelope.msg)}`); + const cipher = envelope.data?.privateCipher; + if (typeof cipher !== "string" || !cipher) throw new Error("handshake_omitted_privateCipher"); + return await decryptSigningPrivateKey(parsedCred.apiKeyId, parsedCred.apiKeySecret, cipher); + } finally { + clearTimeout(timer); + } + } + noteOnce(stateKey, message) { + if (this.notedKeys.has(stateKey)) return; + this.notedKeys.add(stateKey); + this.onEvent?.(`client-signing: ${message}`); + } + }; + defaultSigner = null; + defaultSignerKey = ""; + } +}); + +// src/proxy/ordered-transport.ts +async function sendOrderedUpstreamRequest(req) { + const url2 = new URL(req.url); + const bodyBytes = bodyToBytes(req.body); + const requestHead = buildRequestHead(url2, req.method ?? "POST", req.headers, bodyBytes.byteLength); + const socket = await openSocket(url2); + return await new Promise((resolve, reject) => { + let headerBuffer = new Uint8Array(0); + let responseStarted = false; + let postWrite = false; + let bodyController = null; + let chunkedDecoder = null; + let remainingContentLength = null; + const bodyStream = new ReadableStream({ + start(controller) { + bodyController = controller; + }, + cancel() { + socket.destroy(); + } + }); + function fail(err) { + if (!responseStarted && postWrite) { + try { + err.postWrite = true; + } catch { + } + } + if (responseStarted) bodyController?.error(err); + else reject(err); + socket.destroy(); + } + function finish() { + if (chunkedDecoder && !chunkedDecoder.done) { + try { + bodyController?.error(new Error("upstream chunked body truncated")); + } catch { + } + socket.destroy(); + return; + } + try { + bodyController?.close(); + } catch { + } + } + function pushBody(bytes) { + if (!bodyController || bytes.byteLength === 0) return; + if (chunkedDecoder) { + chunkedDecoder.push(bytes, bodyController); + if (chunkedDecoder.done) finish(); + return; + } + if (remainingContentLength !== null) { + const next = bytes.slice(0, remainingContentLength); + remainingContentLength -= next.byteLength; + if (next.byteLength > 0) bodyController.enqueue(next); + if (remainingContentLength === 0) finish(); + return; + } + bodyController.enqueue(bytes); + } + socket.on("data", (chunk) => { + try { + const bytes = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); + if (!responseStarted) { + headerBuffer = concatBytes(headerBuffer, bytes); + const headerEnd = indexOfBytes(headerBuffer, HEADER_END); + if (headerEnd < 0) return; + const headerBytes = headerBuffer.slice(0, headerEnd); + const rest = headerBuffer.slice(headerEnd + HEADER_END.byteLength); + const parsed = parseResponseHeaders(headerBytes); + responseStarted = true; + const transferEncoding = parsed.headers.get("transfer-encoding")?.toLowerCase() ?? ""; + if (transferEncoding.split(",").map((s) => s.trim()).includes("chunked")) { + parsed.headers.delete("transfer-encoding"); + chunkedDecoder = new ChunkedDecoder(); + } else { + const contentLength2 = parsed.headers.get("content-length"); + remainingContentLength = contentLength2 ? Number.parseInt(contentLength2, 10) : null; + if (!Number.isFinite(remainingContentLength)) remainingContentLength = null; + } + let responseBody = bodyStream; + if (req.decompress && parsed.headers.get("content-encoding")?.toLowerCase() === "gzip") { + parsed.headers.delete("content-encoding"); + parsed.headers.delete("content-length"); + const gzip = new DecompressionStream("gzip"); + responseBody = bodyStream.pipeThrough(gzip); + } + resolve(new Response(responseBody, { + status: parsed.status, + statusText: parsed.statusText, + headers: parsed.headers + })); + pushBody(rest); + return; + } + pushBody(bytes); + } catch (err) { + fail(err); + } + }); + socket.once("error", fail); + socket.once("end", () => { + if (!responseStarted) { + reject(new Error("upstream closed before sending response headers")); + return; + } + finish(); + }); + socket.write(requestHead); + if (bodyBytes.byteLength > 0) socket.write(bodyBytes); + postWrite = true; + }); +} +function openSocket(url2) { + const isHttps = url2.protocol === "https:"; + if (!isHttps && url2.protocol !== "http:") { + return Promise.reject(new Error(`Unsupported upstream protocol: ${url2.protocol}`)); + } + const port = Number(url2.port || (isHttps ? 443 : 80)); + return new Promise((resolve, reject) => { + const onConnect = () => { + socket.off("error", reject); + resolve(socket); + }; + const socket = isHttps ? (0, import_node_tls.connect)({ host: url2.hostname, port, servername: url2.hostname }, onConnect) : (0, import_node_net.connect)({ host: url2.hostname, port }, onConnect); + socket.once("error", reject); + }); +} +function buildRequestHead(url2, method2, headers2, contentLength2) { + const path2 = `${url2.pathname || "/"}${url2.search}`; + const lines = [ + `${method2} ${path2} HTTP/1.1`, + `Host: ${url2.host}`, + ...headers2.map(headerLine), + `Content-Length: ${contentLength2}`, + "Connection: close", + "", + "" + ]; + return lines.join(CRLF); +} +function headerLine([name2, value2]) { + if (!HEADER_NAME.test(name2)) throw new Error(`Invalid upstream header name: ${name2}`); + if (/[\r\n]/.test(value2)) throw new Error(`Invalid upstream header value for ${name2}`); + return `${name2}: ${value2}`; +} +function bodyToBytes(body2) { + if (body2 === void 0) return new Uint8Array(0); + if (typeof body2 === "string") return new TextEncoder().encode(body2); + return body2; +} +function parseResponseHeaders(bytes) { + const text = new TextDecoder("latin1").decode(bytes); + const lines = text.split(CRLF); + const statusLine = lines.shift() ?? ""; + const match = /^HTTP\/\d(?:\.\d)?\s+(\d{3})(?:\s+(.*))?$/.exec(statusLine); + if (!match) throw new Error(`Invalid upstream status line: ${statusLine}`); + const headers2 = new Headers(); + for (const line of lines) { + if (!line) continue; + const idx = line.indexOf(":"); + if (idx <= 0) continue; + headers2.append(line.slice(0, idx), line.slice(idx + 1).trimStart()); + } + return { status: Number(match[1]), statusText: match[2] ?? "", headers: headers2 }; +} +function concatBytes(a, b) { + const out = new Uint8Array(a.byteLength + b.byteLength); + if (a.byteLength > 0) out.set(a, 0); + if (b.byteLength > 0) out.set(b, a.byteLength); + return out; +} +function indexOfBytes(haystack, needle) { + outer: for (let i = 0; i <= haystack.byteLength - needle.byteLength; i++) { + for (let j = 0; j < needle.byteLength; j++) { + if (haystack[i + j] !== needle[j]) continue outer; + } + return i; + } + return -1; +} +function indexOfCrlf(bytes) { + for (let i = 0; i < bytes.byteLength - 1; i++) { + if (bytes[i] === 13 && bytes[i + 1] === 10) return i; + } + return -1; +} +var import_node_net, import_node_tls, CRLF, HEADER_END, HEADER_NAME, ChunkedDecoder; +var init_ordered_transport = __esm({ + "src/proxy/ordered-transport.ts"() { + "use strict"; + import_node_net = require("node:net"); + import_node_tls = require("node:tls"); + CRLF = "\r\n"; + HEADER_END = new Uint8Array([13, 10, 13, 10]); + HEADER_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/; + ChunkedDecoder = class { + buffer = new Uint8Array(0); + expectedSize = null; + done = false; + push(bytes, controller) { + if (this.done) return; + this.buffer = concatBytes(this.buffer, bytes); + while (!this.done) { + if (this.expectedSize === null) { + const lineEnd = indexOfCrlf(this.buffer); + if (lineEnd < 0) return; + const line = new TextDecoder("latin1").decode(this.buffer.slice(0, lineEnd)); + const sizeHex = line.split(";", 1)[0].trim(); + const size = Number.parseInt(sizeHex, 16); + if (!Number.isFinite(size)) throw new Error(`Invalid chunk size: ${line}`); + this.buffer = this.buffer.slice(lineEnd + 2); + this.expectedSize = size; + if (size === 0) { + this.done = true; + return; + } + } + if (this.buffer.byteLength < this.expectedSize + 2) return; + const chunk = this.buffer.slice(0, this.expectedSize); + controller.enqueue(chunk); + this.buffer = this.buffer.slice(this.expectedSize + 2); + this.expectedSize = null; + } + } + }; + } +}); + +// src/proxy/zcode_system.json +var zcode_system_default; +var init_zcode_system = __esm({ + "src/proxy/zcode_system.json"() { + zcode_system_default = [ + { + type: "text", + text: "You are ZCode, an interactive coding agent", + cache_control: { + type: "ephemeral" + } + }, + { + type: "text", + text: "\nYou are an interactive ZCode agent that helps users with software engineering tasks.\n\nIMPORTANT: Assist with authorized security testing, defensive security, CTF challenges, and educational contexts. Refuse requests for destructive techniques, DoS attacks, mass targeting, supply chain compromise, or detection evasion for malicious purposes. Dual-use security tools (C2 frameworks, credential testing, exploit development) require clear authorization context: pentesting engagements, CTF competitions, security research, or defensive use cases.\n\n# Harness\n- Text you output outside of tool use is displayed to the user as Github-flavored markdown in a terminal.\n- Tools run behind a user-selected permission mode; a denied call means the user declined it \u2014 adjust, don't retry verbatim.\n- The system may send updates, reminders, or modifications to rules via mid-conversation system turns. These are system-controlled, unlike function results. Hooks may intercept tool calls; treat hook output as user feedback.\n- Prefer the dedicated file/search tools over shell commands when one fits. Independent tool calls can run in parallel in one response.\n- Reference code as `file_path:line_number` \u2014 it's clickable.", + cache_control: { + type: "ephemeral" + } + }, + { + type: "text", + text: "# Environment\nYou have been invoked in the following environment:\n- Primary working directory: unknown\n- Is a git repository: no\n- Platform: unknown\n- Shell: unknown\n- OS Version: unknown", + cache_control: { + type: "ephemeral" + } + } + ]; + } +}); + +// src/proxy/system-prompt.ts +function buildStartPlanSystem(existingSystem, currentModel) { + const official = ZCODE_SYSTEM_BLOCKS.map((b) => structuredClone(b)); + if (currentModel && currentModel.trim().length > 0) { + official.push({ + type: "text", + text: `- You are powered by the model named ${currentModel}.`, + cache_control: { type: "ephemeral" } + }); + } + const userBlocks = normalizeUserSystem(existingSystem); + return [...official, ...userBlocks]; +} +function normalizeUserSystem(system) { + if (system == null) return []; + if (typeof system === "string") { + const text = system.trim(); + return text ? [{ type: "text", text }] : []; + } + if (!Array.isArray(system)) return []; + const out = []; + for (const item of system) { + if (typeof item === "string") { + if (item.trim()) out.push({ type: "text", text: item }); + } else if (item && typeof item === "object") { + const b = item; + if (b.type === "text" && typeof b.text === "string" && b.text.trim()) { + out.push({ + type: "text", + text: b.text, + ...typeof b.cache_control === "object" && b.cache_control !== null ? { cache_control: b.cache_control } : {} + }); + } + } + } + return out; +} +var ZCODE_SYSTEM_BLOCKS; +var init_system_prompt = __esm({ + "src/proxy/system-prompt.ts"() { + "use strict"; + init_zcode_system(); + ZCODE_SYSTEM_BLOCKS = zcode_system_default; + } +}); + +// src/proxy/body-transformer.ts +function transformRequestBody(body2, ctx) { + if (body2 === void 0 || body2.length === 0) return body2; + let parsed; + try { + parsed = JSON.parse(body2); + } catch { + return body2; + } + if (typeof parsed !== "object" || parsed === null) return body2; + let modified = false; + if (ctx.format === "openai") { + if (ctx.startPlan) { + modified = applyStartPlanOpenAISystem(parsed) || modified; + } + modified = applyStreamOptionsIncludeUsage(parsed) || modified; + } + if (ctx.format === "anthropic") { + const obj = parsed; + if (ctx.startPlan) { + modified = applyStartPlanSystem(obj) || modified; + } + modified = applyAnthropicCacheControl(obj) || modified; + if (ctx.userId) { + modified = applyAnthropicUserId(obj, ctx.userId) || modified; + } + } + return modified ? JSON.stringify(parsed) : body2; +} +function applyStreamOptionsIncludeUsage(body2) { + if (body2.stream !== true) return false; + const existing = body2.stream_options; + if (isPlainObject(existing) && existing.include_usage === true) { + return false; + } + const merged = isPlainObject(existing) ? { ...existing } : {}; + merged.include_usage = true; + body2.stream_options = merged; + return true; +} +function isPlainObject(v) { + return typeof v === "object" && v !== null; +} +function applyAnthropicCacheControl(body2) { + const messages = body2.messages; + if (!Array.isArray(messages) || messages.length === 0) return false; + for (let i = messages.length - 1; i >= 0; i--) { + const msg = messages[i]; + if (typeof msg !== "object" || msg === null) continue; + if (msg.role === "system") continue; + if (typeof msg.content === "string") { + msg.content = [{ type: "text", text: msg.content, cache_control: { type: "ephemeral" } }]; + return true; + } + if (Array.isArray(msg.content) && msg.content.length > 0) { + const lastBlock = msg.content[msg.content.length - 1]; + if (typeof lastBlock === "object" && lastBlock !== null && !lastBlock.cache_control) { + lastBlock.cache_control = { type: "ephemeral" }; + return true; + } + } + return false; + } + return false; +} +function applyAnthropicUserId(body2, userId) { + const existing = body2.metadata; + if (isPlainObject(existing) && existing.user_id === userId) { + return false; + } + body2.metadata = { + ...isPlainObject(existing) ? existing : {}, + user_id: userId + }; + return true; +} +function applyStartPlanSystem(body2) { + const model = typeof body2.model === "string" ? body2.model : void 0; + body2.system = buildStartPlanSystem(body2.system, model); + return true; +} +function applyStartPlanOpenAISystem(body2) { + const messages = body2.messages; + if (!Array.isArray(messages)) return false; + const model = typeof body2.model === "string" ? body2.model : void 0; + const official = buildStartPlanSystem(void 0, model).map((block) => ({ + role: "system", + content: typeof block === "object" && block !== null && "text" in block ? String(block.text) : "" + })); + body2.messages = [...official, ...messages]; + return true; +} +var init_body_transformer = __esm({ + "src/proxy/body-transformer.ts"() { + "use strict"; + init_system_prompt(); + } +}); + +// src/provider/models.ts +var MODELS; +var init_models = __esm({ + "src/provider/models.ts"() { + "use strict"; + MODELS = [ + { id: "glm-4.5-air", name: "GLM 4.5 Air", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, + { id: "glm-4.6", name: "GLM 4.6", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, + { id: "glm-4.6v", name: "GLM 4.6V", contextWindow: 2e5, maxOutputTokens: 128e3 }, + { id: "glm-4.7", name: "GLM 4.7", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, + { id: "glm-5", name: "GLM 5", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, + { id: "glm-5-turbo", name: "GLM 5 Turbo", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, + { id: "glm-5v-turbo", name: "GLM 5V Turbo", contextWindow: 2e5, maxOutputTokens: 128e3 }, + { id: "glm-5.1", name: "GLM 5.1", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, + { id: "glm-5.2", name: "GLM 5.2", contextWindow: 1e6, maxOutputTokens: 128e3, reasoning: true }, + { id: "glm-5.3", name: "GLM 5.3", contextWindow: 1e6, maxOutputTokens: 128e3, reasoning: true }, + // start-plan gateway serves the -flash variant (used by claimed trial plans + // like the weekend package); advertised so client-side discovery lists it. + { id: "glm-5.3-flash", name: "GLM 5.3 Flash", contextWindow: 1e6, maxOutputTokens: 128e3, reasoning: true } + ]; + } +}); + +// src/provider/reasoning.ts +function isGlm53Model(model) { + if (!model) return false; + return GLM53_MODEL_PATTERN.test(model); +} +function normalizeGlm53Effort(effort) { + switch (effort) { + case "none": + case "minimal": + case "light": + case "low": + return "low"; + case "medium": + case "high": + return "high"; + case "xhigh": + case "max": + case "ultra": + return "max"; + default: + return GLM53_DEFAULT_EFFORT; + } +} +function buildGlm53Reasoning(effort) { + return { + thinking: { type: "enabled", budget_tokens: GLM53_THINKING_BUDGETS[effort] }, + output_config: { effort } + }; +} +function fitGlm53Budget(budget, maxTokens) { + if (typeof maxTokens !== "number" || !Number.isFinite(maxTokens)) return budget; + const clamped = Math.min(budget, Math.floor(maxTokens) - GLM53_ANSWER_RESERVE); + return clamped >= GLM53_MIN_THINKING_BUDGET ? clamped : void 0; +} +var GLM53_DEFAULT_EFFORT, GLM53_THINKING_BUDGETS, GLM53_MIN_THINKING_BUDGET, GLM53_ANSWER_RESERVE, GLM53_MODEL_PATTERN; +var init_reasoning = __esm({ + "src/provider/reasoning.ts"() { + "use strict"; + GLM53_DEFAULT_EFFORT = "max"; + GLM53_THINKING_BUDGETS = { + low: 8e3, + high: 16e3, + max: 32e3 + }; + GLM53_MIN_THINKING_BUDGET = 1024; + GLM53_ANSWER_RESERVE = 1024; + GLM53_MODEL_PATTERN = /glm-5\.3(?![0-9])/i; + } +}); + +// src/translator/openai-to-anthropic.ts +function translateRequestOpenAIToAnthropic(req) { + const systemMessages = req.messages.filter((m) => m.role === "system"); + const nonSystemMessages = req.messages.filter((m) => m.role !== "system"); + const system = systemMessages.length > 0 ? systemMessages.map((m) => extractText(m)).join("\n\n") : void 0; + const anthropicMessages = translateMessagesWithToolCoalescing(nonSystemMessages); + const result3 = { + model: req.model, + messages: anthropicMessages, + max_tokens: req.max_tokens ?? resolveDefaultMaxTokens(req.model) + }; + if (system) result3.system = system; + if (req.temperature !== void 0) result3.temperature = req.temperature; + if (req.top_p !== void 0) result3.top_p = req.top_p; + if (req.stream !== void 0) result3.stream = req.stream; + if (req.stop) result3.stop_sequences = Array.isArray(req.stop) ? req.stop : [req.stop]; + if (isGlm53Model(req.model)) { + const { thinking, output_config } = translateGlm53Reasoning(req, result3.max_tokens); + result3.thinking = thinking; + if (output_config) result3.output_config = output_config; + } else { + const thinking = translateThinking(req); + if (thinking) result3.thinking = thinking; + } + if (req.tools?.length && req.tool_choice !== "none") { + result3.tools = req.tools.map(translateToolOpenAIToAnthropic); + } + if (req.tool_choice !== void 0 && req.tool_choice !== "none") { + const translated = translateToolChoice(req.tool_choice); + if (translated) result3.tool_choice = translated; + } + return result3; +} +function translateThinking(req) { + const explicit = req.thinking; + if (explicit && typeof explicit === "object") { + if (explicit.type === "disabled") return { type: "disabled" }; + if (explicit.type === "enabled" || explicit.type === "adaptive") { + const budget = explicit.budget_tokens ?? explicit.budgetTokens; + return { + type: explicit.type, + ...typeof budget === "number" && Number.isFinite(budget) && budget > 0 ? { budget_tokens: Math.floor(budget) } : {}, + ...explicit.type === "adaptive" && typeof explicit.display === "boolean" ? { display: explicit.display } : {} + }; + } + } + if (req.reasoning_effort === "none") return { type: "disabled" }; + if (isReasoningModel(req.model)) return { type: "enabled" }; + return void 0; +} +function isReasoningModel(model) { + return MODELS.some((m) => m.id === model && m.reasoning === true); +} +function resolveDefaultMaxTokens(model) { + if (!isGlm53Model(model)) return DEFAULT_MAX_TOKENS; + const catalogEntry = MODELS.find((m) => m.id === model); + return catalogEntry?.maxOutputTokens ?? DEFAULT_MAX_TOKENS; +} +function translateGlm53Reasoning(req, maxTokens) { + const explicit = req.thinking; + if (explicit && typeof explicit === "object" && explicit.type === "disabled") { + return { thinking: { type: "disabled" } }; + } + const effort = normalizeGlm53Effort(req.reasoning_effort); + const base = buildGlm53Reasoning(effort); + let budget = base.thinking.budget_tokens; + if (explicit && typeof explicit === "object" && (explicit.type === "enabled" || explicit.type === "adaptive")) { + const explicitBudget = explicit.budget_tokens ?? explicit.budgetTokens; + if (typeof explicitBudget === "number" && Number.isFinite(explicitBudget)) { + const floored = Math.floor(explicitBudget); + if (floored > 0) budget = floored; + } + } + const fitted = fitGlm53Budget(budget, maxTokens); + return { + thinking: fitted !== void 0 ? { type: "enabled", budget_tokens: fitted } : { type: "enabled" }, + output_config: base.output_config + }; +} +function translateToolChoice(choice) { + if (choice === "auto") return { type: "auto" }; + if (choice === "required") return { type: "any" }; + if (typeof choice === "object" && choice.type === "function") { + return { type: "tool", name: choice.function.name }; + } + return void 0; +} +function translateMessagesWithToolCoalescing(messages) { + const out = []; + let i = 0; + while (i < messages.length) { + const m = messages[i]; + if (m.role === "tool" && m.tool_call_id) { + const results = []; + while (i < messages.length) { + const tool = messages[i]; + const toolCallId = tool.tool_call_id; + if (tool.role !== "tool" || !toolCallId) break; + results.push({ + type: "tool_result", + tool_use_id: toolCallId, + content: toolResultContent(tool) + }); + i++; + } + out.push({ role: "user", content: results }); + continue; + } + out.push(translateMessageOpenAIToAnthropic(m)); + i++; + } + return out; +} +function translateMessageOpenAIToAnthropic(msg) { + if (msg.role === "assistant" && msg.tool_calls?.length) { + const blocks = []; + const text = extractText(msg); + if (text.length > 0) blocks.push({ type: "text", text }); + for (const tc of msg.tool_calls) { + blocks.push({ + type: "tool_use", + id: tc.id, + name: tc.function.name, + input: parseToolArguments(tc.function.arguments) + }); + } + return { role: "assistant", content: blocks }; + } + return { + role: msg.role === "assistant" ? "assistant" : "user", + content: translateContentOpenAIToAnthropic(msg) + }; +} +function parseToolArguments(raw) { + if (!raw) return {}; + try { + const parsed = JSON.parse(raw); + return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {}; + } catch { + return {}; + } +} +function toolResultContent(msg) { + if (typeof msg.content === "string") return msg.content; + if (!Array.isArray(msg.content)) return ""; + if (msg.content.every((c) => c.type === "text")) { + const joined = msg.content.map((c) => c.text ?? "").join(""); + return joined; + } + return msg.content.map((c) => { + if (c.type === "text") return { type: "text", text: c.text ?? "" }; + if (c.type === "image_url" && c.image_url?.url) { + return imageUrlToAnthropicBlock(c.image_url.url); + } + return { type: "text", text: "" }; + }); +} +function parseDataUrl(url2) { + const m = /^data:([^;]+);base64,(.*)$/s.exec(url2); + if (!m) return void 0; + return { mediaType: m[1], data: m[2] }; +} +function imageUrlToAnthropicBlock(url2) { + const parsed = parseDataUrl(url2); + if (parsed) { + return { + type: "image", + source: { type: "base64", media_type: parsed.mediaType, data: parsed.data } + }; + } + if (/^https?:\/\//i.test(url2)) { + return { type: "image", source: { type: "url", url: url2 } }; + } + return { type: "text", text: url2 }; +} +function anthropicUsageToOpenAI(usage) { + const inputTokens = usage?.input_tokens ?? 0; + const outputTokens = usage?.output_tokens ?? 0; + const cacheRead = usage?.cache_read_input_tokens ?? 0; + const cacheCreation = usage?.cache_creation_input_tokens ?? 0; + const promptTokens = inputTokens + cacheRead + cacheCreation; + return { + prompt_tokens: promptTokens, + completion_tokens: outputTokens, + total_tokens: promptTokens + outputTokens, + // Presence-preserving: an upstream explicitly reporting 0 cache reads stays + // distinguishable from one reporting no cache breakdown at all. + ...usage?.cache_read_input_tokens != null ? { prompt_tokens_details: { cached_tokens: cacheRead } } : {} + }; +} +function translateResponseAnthropicToOpenAI(resp, model) { + const textBlocks = resp.content.filter((b) => b.type === "text"); + const toolUseBlocks = resp.content.filter((b) => b.type === "tool_use"); + const thinkingBlocks = resp.content.filter((b) => b.type === "thinking"); + const content2 = textBlocks.map((b) => b.text).join("") || null; + const reasoningContent = thinkingBlocks.map((b) => b.thinking ?? "").join("") || void 0; + const toolCalls = toolUseBlocks.length > 0 ? toolUseBlocks.map((b, i) => ({ + id: b.id, + type: "function", + function: { + name: b.name, + arguments: JSON.stringify(b.input ?? {}) + } + })) : void 0; + const finishReason = mapStopReasonToFinishReason(resp.stop_reason); + return { + id: resp.id, + object: "chat.completion", + created: Math.floor(Date.now() / 1e3), + model, + choices: [{ + index: 0, + message: { + role: "assistant", + content: content2, + ...reasoningContent ? { reasoning_content: reasoningContent } : {}, + ...toolCalls ? { tool_calls: toolCalls } : {} + }, + finish_reason: finishReason + }], + usage: anthropicUsageToOpenAI(resp.usage) + }; +} +function extractText(msg) { + if (typeof msg.content === "string") return msg.content; + if (Array.isArray(msg.content)) { + return msg.content.filter((c) => c.type === "text").map((c) => c.text ?? "").join(""); + } + return ""; +} +function translateContentOpenAIToAnthropic(msg) { + if (typeof msg.content === "string") return msg.content; + if (msg.content === null) return ""; + if (Array.isArray(msg.content)) { + return msg.content.map((c) => { + if (c.type === "text") return { type: "text", text: c.text ?? "" }; + if (c.type === "image_url" && c.image_url?.url) { + return imageUrlToAnthropicBlock(c.image_url.url); + } + return { type: "text", text: "" }; + }); + } + return ""; +} +function translateToolOpenAIToAnthropic(tool) { + return { + name: tool.function.name, + ...tool.function.description ? { description: tool.function.description } : {}, + ...tool.function.parameters ? { input_schema: tool.function.parameters } : {} + }; +} +function mapStopReasonToFinishReason(stopReason) { + switch (stopReason) { + case "end_turn": + case "stop_sequence": + return "stop"; + case "max_tokens": + return "length"; + case "tool_use": + return "tool_calls"; + default: + return null; + } +} +var DEFAULT_MAX_TOKENS; +var init_openai_to_anthropic = __esm({ + "src/translator/openai-to-anthropic.ts"() { + "use strict"; + init_models(); + init_reasoning(); + DEFAULT_MAX_TOKENS = 4096; + } +}); + +// src/translator/anthropic-to-openai.ts +function translateRequestAnthropicToOpenAI(req) { + const messages = []; + if (req.system) { + const systemText = typeof req.system === "string" ? req.system : req.system.map((s) => s.text).join("\n"); + messages.push({ role: "system", content: systemText }); + } + for (const m of req.messages) { + messages.push(...translateMessageAnthropicToOpenAI(m)); + } + const result3 = { + model: req.model, + messages, + ...req.temperature !== void 0 ? { temperature: req.temperature } : {}, + ...req.top_p !== void 0 ? { top_p: req.top_p } : {}, + ...req.stream !== void 0 ? { stream: req.stream } : {}, + ...req.max_tokens !== void 0 ? { max_tokens: req.max_tokens } : {} + }; + if (req.stop_sequences?.length) { + result3.stop = req.stop_sequences.length === 1 ? req.stop_sequences[0] : req.stop_sequences; + } + if (req.thinking) { + result3.thinking = req.thinking; + } + if (isGlm53Model(req.model) && req.output_config?.effort) { + result3.reasoning_effort = req.output_config.effort; + } + if (req.tools?.length) { + result3.tools = req.tools.map((t) => ({ + type: "function", + function: { + name: t.name, + ...t.description ? { description: t.description } : {}, + ...t.input_schema ? { parameters: t.input_schema } : {} + } + })); + } + if (req.tool_choice) { + const translated = mapToolChoiceAnthropicToOpenAI(req.tool_choice); + if (translated !== void 0) result3.tool_choice = translated; + } + return result3; +} +function mapToolChoiceAnthropicToOpenAI(choice) { + switch (choice.type) { + case "auto": + return "auto"; + case "any": + return "required"; + case "tool": + return { type: "function", function: { name: choice.name } }; + default: + return void 0; + } +} +function translateResponseOpenAIToAnthropic(resp) { + const choice = resp.choices?.[0]; + const content2 = []; + if (choice?.message?.reasoning_content) { + content2.push({ type: "thinking", thinking: choice.message.reasoning_content }); + } + if (choice?.message?.content) { + const textContent = typeof choice.message.content === "string" ? choice.message.content : Array.isArray(choice.message.content) ? choice.message.content.filter((c) => c.type === "text").map((c) => c.text ?? "").join("") : ""; + if (textContent) content2.push({ type: "text", text: textContent }); + } + if (choice?.message?.tool_calls) { + for (const tc of choice.message.tool_calls) { + let input = {}; + try { + input = JSON.parse(tc.function.arguments); + } catch { + input = {}; + } + content2.push({ + type: "tool_use", + id: tc.id, + name: tc.function.name, + input + }); + } + } + const stopReason = mapFinishReasonToStopReason(choice?.finish_reason); + return { + id: resp.id, + type: "message", + role: "assistant", + content: content2.length > 0 ? content2 : [{ type: "text", text: "" }], + model: resp.model, + stop_reason: stopReason, + stop_sequence: null, + usage: openaiUsageToAnthropic(resp.usage) + }; +} +function translateMessageAnthropicToOpenAI(m) { + if (typeof m.content === "string") { + return [{ role: m.role, content: m.content }]; + } + const result3 = []; + const contentParts = []; + const toolCalls = []; + const reasoningParts = []; + for (const block of m.content) { + switch (block.type) { + case "text": { + contentParts.push({ type: "text", text: block.text }); + break; + } + case "image": { + if (block.source.type === "base64") { + contentParts.push({ + type: "image_url", + image_url: { url: `data:${block.source.media_type};base64,${block.source.data}` } + }); + } else if (block.source.type === "url") { + contentParts.push({ + type: "image_url", + image_url: { url: block.source.url } + }); + } + break; + } + case "tool_use": { + toolCalls.push({ + id: block.id, + type: "function", + function: { name: block.name, arguments: JSON.stringify(block.input ?? {}) } + }); + break; + } + case "tool_result": { + result3.push({ + role: "tool", + tool_call_id: block.tool_use_id, + content: toolResultContentToOpenAI(block.content, block.is_error === true) + }); + break; + } + case "thinking": { + if (block.thinking.length > 0) reasoningParts.push(block.thinking); + break; + } + default: + break; + } + } + const hasReasoning = m.role === "assistant" && reasoningParts.length > 0; + if (contentParts.length > 0 || toolCalls.length > 0 || hasReasoning) { + const content2 = contentParts.length === 0 ? null : contentParts.length === 1 && contentParts[0].type === "text" ? contentParts[0].text ?? "" : contentParts; + result3.push({ + role: m.role, + content: content2, + ...hasReasoning ? { reasoning_content: reasoningParts.join("\n") } : {}, + ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {} + }); + } + if (result3.length === 0) { + result3.push({ role: m.role, content: null }); + } + return result3; +} +function toolResultContentToOpenAI(content2, isError) { + const body2 = flattenToolResultContent(content2); + return isError && body2.length > 0 ? `[tool_error] ${body2}` : body2; +} +function flattenToolResultContent(content2) { + if (typeof content2 === "string") return content2; + if (!Array.isArray(content2)) return ""; + const texts = content2.filter((b) => b.type === "text").map((b) => b.text); + if (texts.length > 0) return texts.join(""); + return JSON.stringify(content2); +} +function mapFinishReasonToStopReason(finishReason) { + switch (finishReason) { + case "stop": + return "end_turn"; + case "length": + return "max_tokens"; + case "tool_calls": + return "tool_use"; + case "content_filter": + return "end_turn"; + default: + return null; + } +} +function openaiUsageToAnthropic(usage) { + const promptTokens = usage?.prompt_tokens ?? 0; + const cacheRead = usage?.cache_read_input_tokens ?? usage?.prompt_tokens_details?.cached_tokens ?? 0; + const cacheCreation = usage?.cache_creation_input_tokens ?? 0; + const inputTokens = Math.max(0, promptTokens - cacheRead - cacheCreation); + const result3 = { + input_tokens: inputTokens, + output_tokens: usage?.completion_tokens ?? 0 + }; + if (cacheRead > 0) result3.cache_read_input_tokens = cacheRead; + if (cacheCreation > 0) result3.cache_creation_input_tokens = cacheCreation; + return result3; +} +var init_anthropic_to_openai = __esm({ + "src/translator/anthropic-to-openai.ts"() { + "use strict"; + init_reasoning(); + } +}); + +// src/translator/sse-translator.ts +function parseSSEChunk(raw) { + const results = []; + const blocks = raw.split("\n\n"); + for (const block of blocks) { + const lines = block.trim().split("\n").filter(Boolean); + if (lines.length === 0) continue; + let eventType = ""; + let dataStr = ""; + for (const line of lines) { + if (line.startsWith("event: ")) { + eventType = line.slice(7).trim(); + } else if (line.startsWith("data: ")) { + dataStr = line.slice(6); + } + } + if (dataStr) { + try { + results.push({ event: eventType, data: JSON.parse(dataStr) }); + } catch { + } + } + } + return results; +} +function initState(model) { + return { + messageId: "", + model, + roleSent: false, + usage: { input_tokens: 0, output_tokens: 0 }, + toolCallIndex: 0, + blockIndexToToolCallIndex: /* @__PURE__ */ new Map(), + finishReasonSent: false + }; +} +function mergeAnthropicUsage(target2, patch) { + if (!patch) return; + if (patch.input_tokens != null) target2.input_tokens = patch.input_tokens; + if (patch.output_tokens != null) target2.output_tokens = patch.output_tokens; + if (patch.cache_read_input_tokens != null) target2.cache_read_input_tokens = patch.cache_read_input_tokens; + if (patch.cache_creation_input_tokens != null) target2.cache_creation_input_tokens = patch.cache_creation_input_tokens; +} +function makeChunk(state2, delta, finishReason = null, usage) { + const chunk = { + id: state2.messageId || "chatcmpl-stream", + object: "chat.completion.chunk", + created: Math.floor(Date.now() / 1e3), + model: state2.model, + choices: [{ + index: 0, + delta, + finish_reason: finishReason + }] + }; + if (usage) chunk.usage = usage; + return `data: ${JSON.stringify(chunk)} + +`; +} +function anthropicSseToOpenaiSse(upstream, model = "glm-4.6") { + const state2 = initState(model); + const decoder = new TextDecoder(); + const encoder2 = new TextEncoder(); + let buffer2 = ""; + return new ReadableStream({ + async start(controller) { + const reader = upstream.getReader(); + let errored = false; + try { + while (true) { + const { done, value: value2 } = await reader.read(); + if (done) break; + buffer2 += decoder.decode(value2, { stream: true }); + const blocks = buffer2.split("\n\n"); + buffer2 = blocks.pop() ?? ""; + for (const block of blocks) { + const parsed = parseSSEChunk(block); + for (const p of parsed) { + const output = translateEvent(state2, p); + if (output) { + controller.enqueue(encoder2.encode(output)); + } + } + } + } + if (buffer2.trim()) { + const parsed = parseSSEChunk(buffer2); + for (const p of parsed) { + const output = translateEvent(state2, p); + if (output) controller.enqueue(encoder2.encode(output)); + } + } + controller.enqueue(encoder2.encode("data: [DONE]\n\n")); + } catch (err) { + errored = true; + try { + controller.error(err); + } catch { + } + } finally { + if (!errored) { + try { + controller.close(); + } catch { + } + } + reader.releaseLock(); + } + } + }); +} +function translateEvent(state2, sse) { + const data2 = sse.data; + switch (data2.type) { + case "message_start": { + const msg = data2.message; + state2.messageId = msg?.id ?? "msg_stream"; + state2.model = msg?.model ?? state2.model; + mergeAnthropicUsage(state2.usage, msg?.usage); + if (!state2.roleSent) { + state2.roleSent = true; + return makeChunk(state2, { role: "assistant" }); + } + return null; + } + case "content_block_start": { + if (data2.type !== "content_block_start") return null; + const block = data2.content_block; + const blockIdx = data2.index; + if (block.type === "tool_use") { + const myIndex = state2.toolCallIndex++; + state2.blockIndexToToolCallIndex.set(blockIdx, myIndex); + return makeChunk(state2, { + tool_calls: [{ + index: myIndex, + id: block.id, + type: "function", + function: { name: block.name, arguments: "" } + }] + }); + } + return null; + } + case "content_block_delta": { + if (data2.type !== "content_block_delta") return null; + const delta = data2.delta; + const blockIdx = data2.index; + if (delta.type === "text_delta") { + return makeChunk(state2, { content: delta.text }); + } + if (delta.type === "thinking_delta") { + return makeChunk(state2, { reasoning_content: delta.thinking }); + } + if (delta.type === "signature_delta") { + return null; + } + if (delta.type === "input_json_delta") { + const myIndex = state2.blockIndexToToolCallIndex.get(blockIdx); + if (myIndex === void 0) return null; + return makeChunk(state2, { + tool_calls: [{ + index: myIndex, + function: { arguments: delta.partial_json ?? "" } + }] + }); + } + return null; + } + case "message_delta": { + mergeAnthropicUsage(state2.usage, data2.usage); + if (data2.delta?.stop_reason && !state2.finishReasonSent) { + const finishReason = mapStopReason(data2.delta.stop_reason); + state2.finishReasonSent = true; + return makeChunk(state2, {}, finishReason, anthropicUsageToOpenAI(state2.usage)); + } + return null; + } + case "message_stop": { + if (state2.finishReasonSent) return null; + state2.finishReasonSent = true; + return makeChunk(state2, {}, "stop", anthropicUsageToOpenAI(state2.usage)); + } + case "ping": + case "content_block_stop": + return null; + default: + return null; + } +} +function mapStopReason(stopReason) { + switch (stopReason) { + case "end_turn": + case "stop_sequence": + return "stop"; + case "max_tokens": + return "length"; + case "tool_use": + return "tool_calls"; + default: + return "stop"; + } +} +function openaiSseToAnthropicSse(upstream, model = "glm-4.6") { + const encoder2 = new TextEncoder(); + const decoder = new TextDecoder(); + let buffer2 = ""; + let messageStarted = false; + let blockIndex = 0; + let activeBlock = null; + const toolBlocks = /* @__PURE__ */ new Map(); + const openToolBlockIndices = []; + let outputTokens = 0; + let latestUsage; + let pendingStopReason = null; + let contentClosed = false; + let messageDeltaSent = false; + let messageStopped = false; + const messageId = `msg_${Date.now()}`; + return new ReadableStream({ + async start(controller) { + const reader = upstream.getReader(); + let errored = false; + const enqueueAnthropicEvent = (eventType, data2) => { + controller.enqueue(encoder2.encode(formatAnthropicSSE(eventType, data2))); + }; + const closeActiveBlock = () => { + if (!activeBlock) return; + enqueueAnthropicEvent("content_block_stop", { + type: "content_block_stop", + index: activeBlock.index + }); + activeBlock = null; + }; + const closeToolBlocks = () => { + for (const idx of openToolBlockIndices) { + enqueueAnthropicEvent("content_block_stop", { + type: "content_block_stop", + index: idx + }); + } + openToolBlockIndices.length = 0; + }; + const ensureActiveBlock = (type2) => { + if (activeBlock?.type === type2) return activeBlock.index; + closeActiveBlock(); + const index = blockIndex++; + activeBlock = { type: type2, index }; + enqueueAnthropicEvent("content_block_start", { + type: "content_block_start", + index, + content_block: type2 === "text" ? { type: "text", text: "" } : { type: "thinking", thinking: "", signature: "" } + }); + return index; + }; + const handleToolCalls = (toolCalls) => { + closeActiveBlock(); + for (const tc of toolCalls) { + const idx = tc.index ?? 0; + let state2 = toolBlocks.get(idx); + if (!state2) { + state2 = { index: blockIndex++, id: "", name: "", started: false, pendingArgs: "" }; + toolBlocks.set(idx, state2); + } + if (tc.id) state2.id = tc.id; + if (tc.function?.name) state2.name = tc.function.name; + if (!state2.started && state2.id && state2.name) { + state2.started = true; + enqueueAnthropicEvent("content_block_start", { + type: "content_block_start", + index: state2.index, + content_block: { type: "tool_use", id: state2.id, name: state2.name, input: {} } + }); + openToolBlockIndices.push(state2.index); + if (state2.pendingArgs.length > 0) { + enqueueAnthropicEvent("content_block_delta", { + type: "content_block_delta", + index: state2.index, + delta: { type: "input_json_delta", partial_json: state2.pendingArgs } + }); + state2.pendingArgs = ""; + } + } + const argsDelta = tc.function?.arguments; + if (argsDelta) { + if (state2.started) { + enqueueAnthropicEvent("content_block_delta", { + type: "content_block_delta", + index: state2.index, + delta: { type: "input_json_delta", partial_json: argsDelta } + }); + } else { + state2.pendingArgs += argsDelta; + } + } + } + }; + const startPendingToolBlocks = () => { + const lateStarts = []; + for (const [openaiIdx, state2] of toolBlocks) { + if (state2.started) continue; + if (!state2.pendingArgs && !state2.id && !state2.name) continue; + state2.started = true; + lateStarts.push({ + index: state2.index, + id: state2.id || `tool_call_${openaiIdx}`, + name: state2.name || "unknown_tool", + args: state2.pendingArgs + }); + state2.pendingArgs = ""; + openToolBlockIndices.push(state2.index); + } + lateStarts.sort((a, b) => a.index - b.index); + for (const ls of lateStarts) { + enqueueAnthropicEvent("content_block_start", { + type: "content_block_start", + index: ls.index, + content_block: { type: "tool_use", id: ls.id, name: ls.name, input: {} } + }); + if (ls.args.length > 0) { + enqueueAnthropicEvent("content_block_delta", { + type: "content_block_delta", + index: ls.index, + delta: { type: "input_json_delta", partial_json: ls.args } + }); + } + } + }; + const closeContent = () => { + if (contentClosed) return; + contentClosed = true; + closeActiveBlock(); + startPendingToolBlocks(); + closeToolBlocks(); + }; + const finalizeStream = () => { + closeContent(); + if (!messageDeltaSent) { + messageDeltaSent = true; + const usage = openaiUsageToAnthropic(latestUsage); + if (!latestUsage) usage.output_tokens = outputTokens; + enqueueAnthropicEvent("message_delta", { + type: "message_delta", + delta: { + stop_reason: pendingStopReason ?? "end_turn", + stop_sequence: null + }, + usage + }); + } + if (!messageStopped) { + messageStopped = true; + enqueueAnthropicEvent("message_stop", { type: "message_stop" }); + } + }; + try { + while (true) { + const { done, value: value2 } = await reader.read(); + if (done) break; + buffer2 += decoder.decode(value2, { stream: true }); + const lines = buffer2.split("\n"); + buffer2 = lines.pop() ?? ""; + for (const line of lines) { + if (!line.startsWith("data: ")) continue; + const dataStr = line.slice(6).trim(); + if (dataStr === "[DONE]") { + finalizeStream(); + continue; + } + try { + const chunk = JSON.parse(dataStr); + const choice = chunk.choices?.[0]; + if (chunk.usage) { + latestUsage = chunk.usage; + outputTokens = chunk.usage.completion_tokens ?? outputTokens; + } + if (!messageStarted) { + messageStarted = true; + const startUsage = openaiUsageToAnthropic(chunk.usage); + enqueueAnthropicEvent("message_start", { + type: "message_start", + message: { + id: chunk.id ?? messageId, + type: "message", + role: "assistant", + content: [], + model: chunk.model || model, + stop_reason: null, + stop_sequence: null, + usage: startUsage + } + }); + } + if (choice?.delta?.content) { + const index = ensureActiveBlock("text"); + enqueueAnthropicEvent("content_block_delta", { + type: "content_block_delta", + index, + delta: { type: "text_delta", text: choice.delta.content } + }); + } + if (choice?.delta?.reasoning_content) { + const index = ensureActiveBlock("thinking"); + enqueueAnthropicEvent("content_block_delta", { + type: "content_block_delta", + index, + delta: { type: "thinking_delta", thinking: choice.delta.reasoning_content } + }); + } + if (choice?.delta?.tool_calls?.length) { + handleToolCalls(choice.delta.tool_calls); + } + if (choice?.finish_reason) { + pendingStopReason = mapFinishReason(choice.finish_reason); + closeContent(); + } + } catch { + } + } + } + finalizeStream(); + } catch (err) { + errored = true; + try { + controller.error(err); + } catch { + } + } finally { + if (!errored) { + try { + controller.close(); + } catch { + } + } + reader.releaseLock(); + } + } + }); +} +function formatAnthropicSSE(eventType, data2) { + return `event: ${eventType} +data: ${JSON.stringify(data2)} + +`; +} +function mapFinishReason(finishReason) { + switch (finishReason) { + case "stop": + return "end_turn"; + case "length": + return "max_tokens"; + case "tool_calls": + return "tool_use"; + default: + return "end_turn"; + } +} +var init_sse_translator = __esm({ + "src/translator/sse-translator.ts"() { + "use strict"; + init_anthropic_to_openai(); + init_openai_to_anthropic(); + } +}); + +// src/proxy/dump.ts +function maskHeaderValue(key, value2) { + if (!SENSITIVE_HEADERS.has(key.toLowerCase())) return value2; + if (value2.length <= 12) return ""; + return `${value2.slice(0, 8)}\u2026${value2.slice(-4)} (len=${value2.length})`; +} +function dumpHeaders(headers2) { + const out = {}; + for (const [k, v] of headers2.entries()) { + out[k] = maskHeaderValue(k, v); + } + return out; +} +function dumpBody(body2) { + if (body2 === void 0 || body2 === null) return void 0; + if (body2.length === 0) return ""; + try { + return JSON.parse(body2); + } catch { + return body2; + } +} +function dumpPhase(reqId, phase, data2) { + if (!DUMP_PATH) return; + try { + const line = { + ts: (/* @__PURE__ */ new Date()).toISOString(), + reqId, + phase, + ...data2 + }; + (0, import_node_fs2.appendFileSync)(DUMP_PATH, JSON.stringify(line) + "\n", "utf-8"); + } catch { + } +} +function dumpEnabled() { + return !!DUMP_PATH; +} +var import_node_fs2, DUMP_PATH, SENSITIVE_HEADERS; +var init_dump = __esm({ + "src/proxy/dump.ts"() { + "use strict"; + import_node_fs2 = require("node:fs"); + DUMP_PATH = process.env.ZCODE_DUMP_UPSTREAM; + SENSITIVE_HEADERS = /* @__PURE__ */ new Set([ + "authorization", + "x-api-key", + "proxy-authorization", + "proxy-api-key", + "x-zcode-captcha-verify-param", + "x-zcode-captcha-verify-region", + "cookie" + ]); + } +}); + +// node_modules/happy-dom/lib/PropertySymbol.js +var PropertySymbol_exports = {}; +__export(PropertySymbol_exports, { + abort: () => abort, + aborted: () => aborted, + accessKey: () => accessKey, + accessKeyLabel: () => accessKeyLabel, + activeCues: () => activeCues, + activeElement: () => activeElement, + adoptedStyleSheets: () => adoptedStyleSheets, + affectsCache: () => affectsCache, + affectsComputedStyleCache: () => affectsComputedStyleCache, + amplitude: () => amplitude, + angle: () => angle, + animVal: () => animVal, + animatedPoints: () => animatedPoints, + appendChild: () => appendChild, + areas: () => areas, + assignedNodes: () => assignedNodes, + assignedToSlot: () => assignedToSlot, + asyncTaskManager: () => asyncTaskManager, + attributeName: () => attributeName, + attributeValue: () => attributeValue, + attributes: () => attributes, + attributesProxy: () => attributesProxy, + azimuth: () => azimuth, + baseFrequencyX: () => baseFrequencyX, + baseFrequencyY: () => baseFrequencyY, + baseVal: () => baseVal, + bias: () => bias, + bindMethods: () => bindMethods, + blocking: () => blocking, + body: () => body, + bodyBuffer: () => bodyBuffer, + bodyUsed: () => bodyUsed, + browserFrames: () => browserFrames, + bubbles: () => bubbles, + buffer: () => buffer, + buffered: () => buffered, + cache: () => cache, + cachedResponse: () => cachedResponse, + callbacks: () => callbacks, + cancelable: () => cancelable, + canvas: () => canvas, + capabilities: () => capabilities, + cells: () => cells, + checked: () => checked, + childNodes: () => childNodes, + children: () => children, + classList: () => classList, + classRegistry: () => classRegistry, + clearCache: () => clearCache, + clientHeight: () => clientHeight, + clientLeft: () => clientLeft, + clientTop: () => clientTop, + clientWidth: () => clientWidth, + clipPathUnits: () => clipPathUnits, + clonable: () => clonable, + clone: () => clone, + cloneNode: () => cloneNode, + complete: () => complete, + composed: () => composed, + computedStyle: () => computedStyle, + conditionText: () => conditionText, + connectedToDocument: () => connectedToDocument, + connectedToNode: () => connectedToNode, + constraints: () => constraints, + content: () => content, + contentLength: () => contentLength, + contentType: () => contentType, + context: () => context, + controlsList: () => controlsList, + cookieStore: () => cookieStore, + credentials: () => credentials, + crossOrigin: () => crossOrigin, + cssParser: () => cssParser, + cssRule: () => cssRule, + cssRules: () => cssRules, + cssText: () => cssText, + cues: () => cues, + currentNode: () => currentNode, + currentScale: () => currentScale, + currentScript: () => currentScript, + currentTarget: () => currentTarget, + currentTime: () => currentTime, + customElementReactionStack: () => customElementReactionStack, + cx: () => cx, + cy: () => cy, + data: () => data, + dataset: () => dataset, + defaultChecked: () => defaultChecked, + defaultMuted: () => defaultMuted, + defaultPlaybackRate: () => defaultPlaybackRate, + defaultPrevented: () => defaultPrevented, + defaultValue: () => defaultValue, + defaultView: () => defaultView, + delegatesFocus: () => delegatesFocus, + destroy: () => destroy, + destroyed: () => destroyed, + detail: () => detail, + diffuseConstant: () => diffuseConstant, + dirtyness: () => dirtyness, + disableEvaluation: () => disableEvaluation, + disabled: () => disabled, + disconnectedFromDocument: () => disconnectedFromDocument, + disconnectedFromNode: () => disconnectedFromNode, + dispatchError: () => dispatchError, + dispatching: () => dispatching, + divisor: () => divisor, + domMatrix: () => domMatrix, + duration: () => duration, + dx: () => dx, + dy: () => dy, + edgeMode: () => edgeMode, + elementArray: () => elementArray, + elementIdMap: () => elementIdMap, + elements: () => elements, + elevation: () => elevation, + end: () => end, + ended: () => ended, + entries: () => entries, + error: () => error, + evaluateCSS: () => evaluateCSS, + evaluateScript: () => evaluateScript, + eventPhase: () => eventPhase, + exceptionObserver: () => exceptionObserver, + exponent: () => exponent, + files: () => files, + filterNode: () => filterNode, + filterUnits: () => filterUnits, + flipXSelf: () => flipXSelf, + flipYSelf: () => flipYSelf, + formNode: () => formNode, + forms: () => forms, + frames: () => frames, + fromArray: () => fromArray, + fromString: () => fromString, + fx: () => fx, + fy: () => fy, + getAttribute: () => getAttribute, + getDOMMatrix: () => getDOMMatrix, + getFormControlItems: () => getFormControlItems, + getFormControlNamedItem: () => getFormControlNamedItem, + getItemList: () => getItemList, + getLength: () => getLength, + getNamedItemKey: () => getNamedItemKey, + getNamespaceItemKey: () => getNamespaceItemKey, + getTokenList: () => getTokenList, + globalObject: () => globalObject, + gradientTransform: () => gradientTransform, + gradientUnits: () => gradientUnits, + headers: () => headers, + height: () => height, + history: () => history, + host: () => host, + href: () => href, + id: () => id, + illegalConstructor: () => illegalConstructor, + immediatePropagationStopped: () => immediatePropagationStopped, + implementation: () => implementation, + in1: () => in1, + in2: () => in2, + indeterminate: () => indeterminate, + insertBefore: () => insertBefore, + intercept: () => intercept, + internalId: () => internalId, + invertSelf: () => invertSelf, + isConnected: () => isConnected, + isFirstWrite: () => isFirstWrite, + isFirstWriteAfterOpen: () => isFirstWriteAfterOpen, + isInPassiveEventListener: () => isInPassiveEventListener, + isValue: () => isValue, + items: () => items, + itemsByName: () => itemsByName, + itemsByNamespaceURI: () => itemsByNamespaceURI, + kernelMatrix: () => kernelMatrix, + kernelUnitLengthX: () => kernelUnitLengthX, + kernelUnitLengthY: () => kernelUnitLengthY, + keyText: () => keyText, + kind: () => kind, + label: () => label, + language: () => language, + length: () => length, + lengthAdjust: () => lengthAdjust, + limitingConeAngle: () => limitingConeAngle, + links: () => links, + listenerOptions: () => listenerOptions, + listeners: () => listeners, + loading: () => loading, + localName: () => localName, + localStorage: () => localStorage, + location: () => location, + m11: () => m11, + m12: () => m12, + m13: () => m13, + m14: () => m14, + m21: () => m21, + m22: () => m22, + m23: () => m23, + m24: () => m24, + m31: () => m31, + m32: () => m32, + m33: () => m33, + m34: () => m34, + m41: () => m41, + m42: () => m42, + m43: () => m43, + m44: () => m44, + markerHeight: () => markerHeight, + markerUnits: () => markerUnits, + markerWidth: () => markerWidth, + maskContentUnits: () => maskContentUnits, + maskUnits: () => maskUnits, + matrix: () => matrix, + media: () => media, + mediaKeys: () => mediaKeys, + method: () => method, + mode: () => mode, + moduleCache: () => moduleCache, + moduleImportMap: () => moduleImportMap, + modules: () => modules, + multiplySelf: () => multiplySelf, + mutationListeners: () => mutationListeners, + mutationObservers: () => mutationObservers, + muted: () => muted, + name: () => name, + namespaceURI: () => namespaceURI, + naturalHeight: () => naturalHeight, + naturalWidth: () => naturalWidth, + navigator: () => navigator, + networkState: () => networkState, + nextActiveElement: () => nextActiveElement, + nodeArray: () => nodeArray, + nodeStream: () => nodeStream, + nodeType: () => nodeType, + numOctaves: () => numOctaves, + observeMutations: () => observeMutations, + offset: () => offset, + offsetHeight: () => offsetHeight, + offsetLeft: () => offsetLeft, + offsetTop: () => offsetTop, + offsetWidth: () => offsetWidth, + onRemoveAttribute: () => onRemoveAttribute, + onSetAttribute: () => onSetAttribute, + openWebSockets: () => openWebSockets, + openerFrame: () => openerFrame, + openerWindow: () => openerWindow, + operator: () => operator, + options: () => options, + orderX: () => orderX, + orderY: () => orderY, + orientAngle: () => orientAngle, + orientType: () => orientType, + ownerDocument: () => ownerDocument, + ownerElement: () => ownerElement, + parent: () => parent, + parentNode: () => parentNode, + parentRule: () => parentRule, + parentStyleSheet: () => parentStyleSheet, + pathLength: () => pathLength, + patternContentUnits: () => patternContentUnits, + patternTransform: () => patternTransform, + patternUnits: () => patternUnits, + paused: () => paused, + playbackRate: () => playbackRate, + played: () => played, + pointerCaptures: () => pointerCaptures, + points: () => points, + pointsAtX: () => pointsAtX, + pointsAtY: () => pointsAtY, + pointsAtZ: () => pointsAtZ, + popoverTargetElement: () => popoverTargetElement, + popup: () => popup, + prefix: () => prefix, + preloads: () => preloads, + preserveAlpha: () => preserveAlpha, + preserveAspectRatio: () => preserveAspectRatio, + preservesPitch: () => preservesPitch, + primitiveUnits: () => primitiveUnits, + propagationStopped: () => propagationStopped, + propertyEventListeners: () => propertyEventListeners, + proxy: () => proxy, + publicId: () => publicId, + query: () => query, + querySelectorCache: () => querySelectorCache, + r: () => r, + radiusX: () => radiusX, + radiusY: () => radiusY, + readOnly: () => readOnly, + readyState: () => readyState, + readyStateManager: () => readyStateManager, + reason: () => reason, + redirect: () => redirect, + refX: () => refX, + refY: () => refY, + referrer: () => referrer, + referrerPolicy: () => referrerPolicy, + registry: () => registry, + relList: () => relList, + remote: () => remote, + removeChild: () => removeChild, + removeNamedItem: () => removeNamedItem, + replaceChild: () => replaceChild, + reportMutation: () => reportMutation, + requiredExtensions: () => requiredExtensions, + resetSelection: () => resetSelection, + result: () => result2, + returnValue: () => returnValue, + root: () => root, + rootNode: () => rootNode, + rotate: () => rotate, + rotateAxisAngleSelf: () => rotateAxisAngleSelf, + rotateFromVectorSelf: () => rotateFromVectorSelf, + rotateSelf: () => rotateSelf, + rows: () => rows, + rulePrefix: () => rulePrefix, + rx: () => rx, + ry: () => ry, + sandbox: () => sandbox, + scale: () => scale, + scale3dSelf: () => scale3dSelf, + scaleNonUniformSelf: () => scaleNonUniformSelf, + scaleSelf: () => scaleSelf, + screen: () => screen, + scrollHeight: () => scrollHeight, + scrollLeft: () => scrollLeft, + scrollTop: () => scrollTop, + scrollWidth: () => scrollWidth, + seed: () => seed, + seekable: () => seekable, + seeking: () => seeking, + selectNode: () => selectNode, + selectedIndex: () => selectedIndex, + selectedOptions: () => selectedOptions, + selectedness: () => selectedness, + selection: () => selection, + selectorText: () => selectorText, + self: () => self, + serializable: () => serializable, + sessionStorage: () => sessionStorage, + setAttribute: () => setAttribute, + setDOMMatrix: () => setDOMMatrix, + setMatrixValue: () => setMatrixValue, + setNamedItem: () => setNamedItem, + setURL: () => setURL, + settings: () => settings, + setupVMContext: () => setupVMContext, + shadowRoot: () => shadowRoot, + sheet: () => sheet, + signal: () => signal, + sinkId: () => sinkId, + skewXSelf: () => skewXSelf, + skewYSelf: () => skewYSelf, + slope: () => slope, + slotAssignment: () => slotAssignment, + spacing: () => spacing, + specified: () => specified, + specularConstant: () => specularConstant, + specularExponent: () => specularExponent, + spreadMethod: () => spreadMethod, + srcObject: () => srcObject, + start: () => start, + startOffset: () => startOffset, + state: () => state, + stdDeviationX: () => stdDeviationX, + stdDeviationY: () => stdDeviationY, + stitchTiles: () => stitchTiles, + style: () => style, + styleMap: () => styleMap, + styleNode: () => styleNode, + supports: () => supports, + surfaceScale: () => surfaceScale, + systemId: () => systemId, + systemLanguage: () => systemLanguage, + tBodies: () => tBodies, + tableValues: () => tableValues, + tagName: () => tagName, + target: () => target, + targetX: () => targetX, + targetY: () => targetY, + textAreaNode: () => textAreaNode, + textLength: () => textLength, + textTracks: () => textTracks, + timeStamp: () => timeStamp, + toArray: () => toArray, + top: () => top, + track: () => track, + tracks: () => tracks, + transform: () => transform, + translateSelf: () => translateSelf, + type: () => type, + unitType: () => unitType, + unobserveMutations: () => unobserveMutations, + updateSelectedness: () => updateSelectedness, + updateSheet: () => updateSheet, + url: () => url, + validateJavaScriptExecutionEnvironment: () => validateJavaScriptExecutionEnvironment, + validationMessage: () => validationMessage, + validity: () => validity, + value: () => value, + values: () => values, + viewBox: () => viewBox, + virtualServerFile: () => virtualServerFile, + volume: () => volume, + w: () => w, + webSocket: () => webSocket, + width: () => width, + window: () => window, + windowInternalId: () => windowInternalId, + windowResizeListener: () => windowResizeListener, + x: () => x, + x1: () => x1, + x2: () => x2, + xChannelSelector: () => xChannelSelector, + xmlProcessingInstruction: () => xmlProcessingInstruction, + y: () => y, + y1: () => y1, + y2: () => y2, + yChannelSelector: () => yChannelSelector, + z: () => z +}); +var abort, activeElement, asyncTaskManager, bodyBuffer, buffer, cachedResponse, callbacks, checked, childNodes, children, classList, connectedToNode, disconnectedFromNode, connectedToDocument, disconnectedFromDocument, contentLength, contentType, cssText, currentScript, currentTarget, data, defaultView, destroy, dirtyness, end, entries, evaluateCSS, evaluateScript, exceptionObserver, formNode, internalId, height, immediatePropagationStopped, indeterminate, isFirstWrite, isFirstWriteAfterOpen, isInPassiveEventListener, isValue, listenerOptions, listeners, itemsByName, nextActiveElement, observeMutations, mutationListeners, ownerDocument, ownerElement, propagationStopped, readyStateManager, referrer, registry, relList, resetSelection, rootNode, selectNode, selectedness, selection, setupVMContext, shadowRoot, start, style, target, textAreaNode, unobserveMutations, reportMutation, updateSelectedness, url, value, width, window, windowResizeListener, mutationObservers, openerFrame, openerWindow, pointerCaptures, popup, isConnected, parentNode, nodeType, tagName, prefix, scrollHeight, scrollWidth, scrollTop, scrollLeft, attributes, attributesProxy, namespaceURI, accessKey, accessKeyLabel, offsetHeight, offsetWidth, offsetLeft, offsetTop, clientHeight, clientWidth, clientLeft, clientTop, name, specified, adoptedStyleSheets, implementation, readyState, publicId, systemId, validationMessage, validity, returnValue, elements, length, complete, naturalHeight, naturalWidth, loading, x, y, defaultChecked, files, sheet, volume, paused, currentTime, playbackRate, defaultPlaybackRate, muted, defaultMuted, preservesPitch, buffered, duration, error, ended, networkState, textTracks, seeking, seekable, played, options, content, mode, host, setURL, localName, classRegistry, nodeStream, location, history, navigator, screen, sessionStorage, localStorage, sandbox, cloneNode, appendChild, removeChild, insertBefore, replaceChild, tracks, constraints, capabilities, settings, clone, removeNamedItem, items, selectedOptions, styleNode, updateSheet, clearCache, onSetAttribute, onRemoveAttribute, nodeArray, elementArray, cache, affectsCache, forms, links, affectsComputedStyleCache, query, computedStyle, getFormControlItems, getFormControlNamedItem, dataset, getNamespaceItemKey, getNamedItemKey, itemsByNamespaceURI, proxy, setNamedItem, getTokenList, attributeName, selectedIndex, self, parent, top, areas, defaultValue, elementIdMap, clonable, delegatesFocus, serializable, slotAssignment, assignedNodes, assignedToSlot, cells, rows, headers, tBodies, track, controlsList, mediaKeys, remote, sinkId, srcObject, cues, activeCues, kind, label, language, id, illegalConstructor, state, canvas, popoverTargetElement, composed, bubbles, cancelable, defaultPrevented, eventPhase, timeStamp, type, detail, globalObject, destroyed, aborted, browserFrames, windowInternalId, getItemList, requiredExtensions, systemLanguage, transform, baseVal, animVal, pathLength, unitType, viewBox, markerUnits, markerWidth, markerHeight, values, orientType, orientAngle, refX, refY, readOnly, preserveAspectRatio, animatedPoints, points, rx, ry, cx, cy, r, clipPathUnits, maskUnits, maskContentUnits, filterUnits, primitiveUnits, href, x1, y1, x2, y2, gradientUnits, gradientTransform, spreadMethod, patternUnits, patternContentUnits, patternTransform, fx, fy, offset, disabled, textLength, lengthAdjust, getAttribute, setAttribute, z, w, toArray, fromString, fromArray, angle, m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44, setMatrixValue, translateSelf, rotateSelf, rotateAxisAngleSelf, scaleSelf, scale3dSelf, scaleNonUniformSelf, skewXSelf, skewYSelf, multiplySelf, matrix, domMatrix, getDOMMatrix, setDOMMatrix, attributeValue, startOffset, method, spacing, in1, in2, result2, bias, divisor, edgeMode, kernelMatrix, kernelUnitLengthX, kernelUnitLengthY, orderX, orderY, preserveAlpha, targetX, targetY, diffuseConstant, surfaceScale, scale, xChannelSelector, yChannelSelector, azimuth, elevation, dx, dy, stdDeviationX, stdDeviationY, tableValues, slope, intercept, amplitude, exponent, crossOrigin, operator, radiusX, radiusY, specularConstant, specularExponent, pointsAtX, pointsAtY, pointsAtZ, limitingConeAngle, baseFrequencyX, baseFrequencyY, numOctaves, seed, stitchTiles, rotateFromVectorSelf, flipXSelf, flipYSelf, invertSelf, getLength, currentScale, rotate, bindMethods, xmlProcessingInstruction, root, filterNode, customElementReactionStack, dispatching, modules, preloads, body, redirect, referrerPolicy, signal, bodyUsed, credentials, blocking, moduleImportMap, dispatchError, supports, reason, propertyEventListeners, cssRules, parentRule, parentStyleSheet, conditionText, keyText, media, styleMap, selectorText, cssParser, cssRule, rulePrefix, virtualServerFile, frames, disableEvaluation, validateJavaScriptExecutionEnvironment, currentNode, openWebSockets, webSocket, moduleCache, cookieStore, context, querySelectorCache; +var init_PropertySymbol = __esm({ + "node_modules/happy-dom/lib/PropertySymbol.js"() { + abort = /* @__PURE__ */ Symbol("abort"); + activeElement = /* @__PURE__ */ Symbol("activeElement"); + asyncTaskManager = /* @__PURE__ */ Symbol("asyncTaskManager"); + bodyBuffer = /* @__PURE__ */ Symbol("bodyBuffer"); + buffer = /* @__PURE__ */ Symbol("buffer"); + cachedResponse = /* @__PURE__ */ Symbol("cachedResponse"); + callbacks = /* @__PURE__ */ Symbol("callbacks"); + checked = /* @__PURE__ */ Symbol("checked"); + childNodes = /* @__PURE__ */ Symbol("childNodes"); + children = /* @__PURE__ */ Symbol("children"); + classList = /* @__PURE__ */ Symbol("classList"); + connectedToNode = /* @__PURE__ */ Symbol("connectedToNode"); + disconnectedFromNode = /* @__PURE__ */ Symbol("disconnectedFromNode"); + connectedToDocument = /* @__PURE__ */ Symbol("connectedToDocument"); + disconnectedFromDocument = /* @__PURE__ */ Symbol("disconnectedFromDocument"); + contentLength = /* @__PURE__ */ Symbol("contentLength"); + contentType = /* @__PURE__ */ Symbol("contentType"); + cssText = /* @__PURE__ */ Symbol("cssText"); + currentScript = /* @__PURE__ */ Symbol("currentScript"); + currentTarget = /* @__PURE__ */ Symbol("currentTarget"); + data = /* @__PURE__ */ Symbol("data"); + defaultView = /* @__PURE__ */ Symbol("defaultView"); + destroy = /* @__PURE__ */ Symbol("destroy"); + dirtyness = /* @__PURE__ */ Symbol("dirtyness"); + end = /* @__PURE__ */ Symbol("end"); + entries = /* @__PURE__ */ Symbol("entries"); + evaluateCSS = /* @__PURE__ */ Symbol("evaluateCSS"); + evaluateScript = /* @__PURE__ */ Symbol("evaluateScript"); + exceptionObserver = /* @__PURE__ */ Symbol("exceptionObserver"); + formNode = /* @__PURE__ */ Symbol("formNode"); + internalId = /* @__PURE__ */ Symbol("internalId"); + height = /* @__PURE__ */ Symbol("height"); + immediatePropagationStopped = /* @__PURE__ */ Symbol("immediatePropagationStopped"); + indeterminate = /* @__PURE__ */ Symbol("indeterminate"); + isFirstWrite = /* @__PURE__ */ Symbol("isFirstWrite"); + isFirstWriteAfterOpen = /* @__PURE__ */ Symbol("isFirstWriteAfterOpen"); + isInPassiveEventListener = /* @__PURE__ */ Symbol("isInPassiveEventListener"); + isValue = /* @__PURE__ */ Symbol("isValue"); + listenerOptions = /* @__PURE__ */ Symbol("listenerOptions"); + listeners = /* @__PURE__ */ Symbol("listeners"); + itemsByName = /* @__PURE__ */ Symbol("itemsByName"); + nextActiveElement = /* @__PURE__ */ Symbol("nextActiveElement"); + observeMutations = /* @__PURE__ */ Symbol("observeMutations"); + mutationListeners = /* @__PURE__ */ Symbol("mutationListeners"); + ownerDocument = /* @__PURE__ */ Symbol("ownerDocument"); + ownerElement = /* @__PURE__ */ Symbol("ownerElement"); + propagationStopped = /* @__PURE__ */ Symbol("propagationStopped"); + readyStateManager = /* @__PURE__ */ Symbol("readyStateManager"); + referrer = /* @__PURE__ */ Symbol("referrer"); + registry = /* @__PURE__ */ Symbol("registry"); + relList = /* @__PURE__ */ Symbol("relList"); + resetSelection = /* @__PURE__ */ Symbol("resetSelection"); + rootNode = /* @__PURE__ */ Symbol("rootNode"); + selectNode = /* @__PURE__ */ Symbol("selectNode"); + selectedness = /* @__PURE__ */ Symbol("selectedness"); + selection = /* @__PURE__ */ Symbol("selection"); + setupVMContext = /* @__PURE__ */ Symbol("setupVMContext"); + shadowRoot = /* @__PURE__ */ Symbol("shadowRoot"); + start = /* @__PURE__ */ Symbol("start"); + style = /* @__PURE__ */ Symbol("style"); + target = /* @__PURE__ */ Symbol("target"); + textAreaNode = /* @__PURE__ */ Symbol("textAreaNode"); + unobserveMutations = /* @__PURE__ */ Symbol("unobserveMutations"); + reportMutation = /* @__PURE__ */ Symbol("reportMutation"); + updateSelectedness = /* @__PURE__ */ Symbol("updateSelectedness"); + url = /* @__PURE__ */ Symbol("url"); + value = /* @__PURE__ */ Symbol("value"); + width = /* @__PURE__ */ Symbol("width"); + window = /* @__PURE__ */ Symbol("window"); + windowResizeListener = /* @__PURE__ */ Symbol("windowResizeListener"); + mutationObservers = /* @__PURE__ */ Symbol("mutationObservers"); + openerFrame = /* @__PURE__ */ Symbol("openerFrame"); + openerWindow = /* @__PURE__ */ Symbol("openerWindow"); + pointerCaptures = /* @__PURE__ */ Symbol("pointerCaptures"); + popup = /* @__PURE__ */ Symbol("popup"); + isConnected = /* @__PURE__ */ Symbol("isConnected"); + parentNode = /* @__PURE__ */ Symbol("parentNode"); + nodeType = /* @__PURE__ */ Symbol("nodeType"); + tagName = /* @__PURE__ */ Symbol("tagName"); + prefix = /* @__PURE__ */ Symbol("prefix"); + scrollHeight = /* @__PURE__ */ Symbol("scrollHeight"); + scrollWidth = /* @__PURE__ */ Symbol("scrollWidth"); + scrollTop = /* @__PURE__ */ Symbol("scrollTop"); + scrollLeft = /* @__PURE__ */ Symbol("scrollLeft"); + attributes = /* @__PURE__ */ Symbol("attributes"); + attributesProxy = /* @__PURE__ */ Symbol("attributesProxy"); + namespaceURI = /* @__PURE__ */ Symbol("namespaceURI"); + accessKey = /* @__PURE__ */ Symbol("accessKey"); + accessKeyLabel = /* @__PURE__ */ Symbol("accessKeyLabel"); + offsetHeight = /* @__PURE__ */ Symbol("offsetHeight"); + offsetWidth = /* @__PURE__ */ Symbol("offsetWidth"); + offsetLeft = /* @__PURE__ */ Symbol("offsetLeft"); + offsetTop = /* @__PURE__ */ Symbol("offsetTop"); + clientHeight = /* @__PURE__ */ Symbol("clientHeight"); + clientWidth = /* @__PURE__ */ Symbol("clientWidth"); + clientLeft = /* @__PURE__ */ Symbol("clientLeft"); + clientTop = /* @__PURE__ */ Symbol("clientTop"); + name = /* @__PURE__ */ Symbol("name"); + specified = /* @__PURE__ */ Symbol("specified"); + adoptedStyleSheets = /* @__PURE__ */ Symbol("adoptedStyleSheets"); + implementation = /* @__PURE__ */ Symbol("implementation"); + readyState = /* @__PURE__ */ Symbol("readyState"); + publicId = /* @__PURE__ */ Symbol("publicId"); + systemId = /* @__PURE__ */ Symbol("systemId"); + validationMessage = /* @__PURE__ */ Symbol("validationMessage"); + validity = /* @__PURE__ */ Symbol("validity"); + returnValue = /* @__PURE__ */ Symbol("returnValue"); + elements = /* @__PURE__ */ Symbol("elements"); + length = /* @__PURE__ */ Symbol("length"); + complete = /* @__PURE__ */ Symbol("complete"); + naturalHeight = /* @__PURE__ */ Symbol("naturalHeight"); + naturalWidth = /* @__PURE__ */ Symbol("naturalWidth"); + loading = /* @__PURE__ */ Symbol("loading"); + x = /* @__PURE__ */ Symbol("x"); + y = /* @__PURE__ */ Symbol("y"); + defaultChecked = /* @__PURE__ */ Symbol("defaultChecked"); + files = /* @__PURE__ */ Symbol("files"); + sheet = /* @__PURE__ */ Symbol("sheet"); + volume = /* @__PURE__ */ Symbol("volume"); + paused = /* @__PURE__ */ Symbol("paused"); + currentTime = /* @__PURE__ */ Symbol("currentTime"); + playbackRate = /* @__PURE__ */ Symbol("playbackRate"); + defaultPlaybackRate = /* @__PURE__ */ Symbol("defaultPlaybackRate"); + muted = /* @__PURE__ */ Symbol("muted"); + defaultMuted = /* @__PURE__ */ Symbol("defaultMuted"); + preservesPitch = /* @__PURE__ */ Symbol("preservesPitch"); + buffered = /* @__PURE__ */ Symbol("buffered"); + duration = /* @__PURE__ */ Symbol("duration"); + error = /* @__PURE__ */ Symbol("error"); + ended = /* @__PURE__ */ Symbol("ended"); + networkState = /* @__PURE__ */ Symbol("networkState"); + textTracks = /* @__PURE__ */ Symbol("textTracks"); + seeking = /* @__PURE__ */ Symbol("seeking"); + seekable = /* @__PURE__ */ Symbol("seekable"); + played = /* @__PURE__ */ Symbol("played"); + options = /* @__PURE__ */ Symbol("options"); + content = /* @__PURE__ */ Symbol("content"); + mode = /* @__PURE__ */ Symbol("mode"); + host = /* @__PURE__ */ Symbol("host"); + setURL = /* @__PURE__ */ Symbol("setURL"); + localName = /* @__PURE__ */ Symbol("localName"); + classRegistry = /* @__PURE__ */ Symbol("classRegistry"); + nodeStream = /* @__PURE__ */ Symbol("nodeStream"); + location = /* @__PURE__ */ Symbol("location"); + history = /* @__PURE__ */ Symbol("history"); + navigator = /* @__PURE__ */ Symbol("navigator"); + screen = /* @__PURE__ */ Symbol("screen"); + sessionStorage = /* @__PURE__ */ Symbol("sessionStorage"); + localStorage = /* @__PURE__ */ Symbol("localStorage"); + sandbox = /* @__PURE__ */ Symbol("sandbox"); + cloneNode = /* @__PURE__ */ Symbol("cloneNode"); + appendChild = /* @__PURE__ */ Symbol("appendChild"); + removeChild = /* @__PURE__ */ Symbol("removeChild"); + insertBefore = /* @__PURE__ */ Symbol("insertBefore"); + replaceChild = /* @__PURE__ */ Symbol("replaceChild"); + tracks = /* @__PURE__ */ Symbol("tracks"); + constraints = /* @__PURE__ */ Symbol("constraints"); + capabilities = /* @__PURE__ */ Symbol("capabilities"); + settings = /* @__PURE__ */ Symbol("settings"); + clone = /* @__PURE__ */ Symbol("clone"); + removeNamedItem = /* @__PURE__ */ Symbol("removeNamedItem"); + items = /* @__PURE__ */ Symbol("items"); + selectedOptions = /* @__PURE__ */ Symbol("selectedOptions"); + styleNode = /* @__PURE__ */ Symbol("styleNode"); + updateSheet = /* @__PURE__ */ Symbol("updateSheet"); + clearCache = /* @__PURE__ */ Symbol("clearCache"); + onSetAttribute = /* @__PURE__ */ Symbol("onSetAttribute"); + onRemoveAttribute = /* @__PURE__ */ Symbol("onRemoveAttribute"); + nodeArray = /* @__PURE__ */ Symbol("nodeArray"); + elementArray = /* @__PURE__ */ Symbol("elementArray"); + cache = /* @__PURE__ */ Symbol("cache"); + affectsCache = /* @__PURE__ */ Symbol("affectsCache"); + forms = /* @__PURE__ */ Symbol("forms"); + links = /* @__PURE__ */ Symbol("links"); + affectsComputedStyleCache = /* @__PURE__ */ Symbol("affectsComputedStyleCache"); + query = /* @__PURE__ */ Symbol("query"); + computedStyle = /* @__PURE__ */ Symbol("computedStyle"); + getFormControlItems = /* @__PURE__ */ Symbol("getFormControlItems"); + getFormControlNamedItem = /* @__PURE__ */ Symbol("getFormControlNamedItem"); + dataset = /* @__PURE__ */ Symbol("dataset"); + getNamespaceItemKey = /* @__PURE__ */ Symbol("getNamespaceItemKey"); + getNamedItemKey = /* @__PURE__ */ Symbol("getNamedItemKey"); + itemsByNamespaceURI = /* @__PURE__ */ Symbol("itemsByNamespaceURI"); + proxy = /* @__PURE__ */ Symbol("proxy"); + setNamedItem = /* @__PURE__ */ Symbol("setNamedItem"); + getTokenList = /* @__PURE__ */ Symbol("getTokenList"); + attributeName = /* @__PURE__ */ Symbol("attributeName"); + selectedIndex = /* @__PURE__ */ Symbol("selectedIndex"); + self = /* @__PURE__ */ Symbol("self"); + parent = /* @__PURE__ */ Symbol("parent"); + top = /* @__PURE__ */ Symbol("top"); + areas = /* @__PURE__ */ Symbol("areas"); + defaultValue = /* @__PURE__ */ Symbol("defaultValue"); + elementIdMap = /* @__PURE__ */ Symbol("elementIdMap"); + clonable = /* @__PURE__ */ Symbol("clonable"); + delegatesFocus = /* @__PURE__ */ Symbol("delegatesFocus"); + serializable = /* @__PURE__ */ Symbol("serializable"); + slotAssignment = /* @__PURE__ */ Symbol("slotAssignment"); + assignedNodes = /* @__PURE__ */ Symbol("assignedNodes"); + assignedToSlot = /* @__PURE__ */ Symbol("assignedToSlot"); + cells = /* @__PURE__ */ Symbol("cells"); + rows = /* @__PURE__ */ Symbol("rows"); + headers = /* @__PURE__ */ Symbol("headers"); + tBodies = /* @__PURE__ */ Symbol("tBodies"); + track = /* @__PURE__ */ Symbol("track"); + controlsList = /* @__PURE__ */ Symbol("controlsList"); + mediaKeys = /* @__PURE__ */ Symbol("mediaKeys"); + remote = /* @__PURE__ */ Symbol("remote"); + sinkId = /* @__PURE__ */ Symbol("sinkId"); + srcObject = /* @__PURE__ */ Symbol("srcObject"); + cues = /* @__PURE__ */ Symbol("cues"); + activeCues = /* @__PURE__ */ Symbol("activeCues"); + kind = /* @__PURE__ */ Symbol("kind"); + label = /* @__PURE__ */ Symbol("label"); + language = /* @__PURE__ */ Symbol("language"); + id = /* @__PURE__ */ Symbol("id"); + illegalConstructor = /* @__PURE__ */ Symbol("illegalConstructor"); + state = /* @__PURE__ */ Symbol("state"); + canvas = /* @__PURE__ */ Symbol("canvas"); + popoverTargetElement = /* @__PURE__ */ Symbol("popoverTargetElement"); + composed = /* @__PURE__ */ Symbol("composed"); + bubbles = /* @__PURE__ */ Symbol("bubbles"); + cancelable = /* @__PURE__ */ Symbol("cancelable"); + defaultPrevented = /* @__PURE__ */ Symbol("defaultPrevented"); + eventPhase = /* @__PURE__ */ Symbol("eventPhase"); + timeStamp = /* @__PURE__ */ Symbol("timeStamp"); + type = /* @__PURE__ */ Symbol("type"); + detail = /* @__PURE__ */ Symbol("detail"); + globalObject = /* @__PURE__ */ Symbol("globalObject"); + destroyed = /* @__PURE__ */ Symbol("destroyed"); + aborted = /* @__PURE__ */ Symbol("aborted"); + browserFrames = /* @__PURE__ */ Symbol("browserFrames"); + windowInternalId = /* @__PURE__ */ Symbol("windowInternalId"); + getItemList = /* @__PURE__ */ Symbol("getItemList"); + requiredExtensions = /* @__PURE__ */ Symbol("requiredExtensions"); + systemLanguage = /* @__PURE__ */ Symbol("systemLanguage"); + transform = /* @__PURE__ */ Symbol("transform"); + baseVal = /* @__PURE__ */ Symbol("baseVal"); + animVal = /* @__PURE__ */ Symbol("animVal"); + pathLength = /* @__PURE__ */ Symbol("pathLength"); + unitType = /* @__PURE__ */ Symbol("unitType"); + viewBox = /* @__PURE__ */ Symbol("viewBox"); + markerUnits = /* @__PURE__ */ Symbol("markerUnits"); + markerWidth = /* @__PURE__ */ Symbol("markerWidth"); + markerHeight = /* @__PURE__ */ Symbol("markerHeight"); + values = /* @__PURE__ */ Symbol("values"); + orientType = /* @__PURE__ */ Symbol("orientType"); + orientAngle = /* @__PURE__ */ Symbol("orientAngle"); + refX = /* @__PURE__ */ Symbol("refX"); + refY = /* @__PURE__ */ Symbol("refY"); + readOnly = /* @__PURE__ */ Symbol("readOnly"); + preserveAspectRatio = /* @__PURE__ */ Symbol("preserveAspectRatio"); + animatedPoints = /* @__PURE__ */ Symbol("animatedPoints"); + points = /* @__PURE__ */ Symbol("points"); + rx = /* @__PURE__ */ Symbol("rx"); + ry = /* @__PURE__ */ Symbol("ry"); + cx = /* @__PURE__ */ Symbol("cx"); + cy = /* @__PURE__ */ Symbol("cy"); + r = /* @__PURE__ */ Symbol("r"); + clipPathUnits = /* @__PURE__ */ Symbol("clipPathUnits"); + maskUnits = /* @__PURE__ */ Symbol("maskUnits"); + maskContentUnits = /* @__PURE__ */ Symbol("maskContentUnits"); + filterUnits = /* @__PURE__ */ Symbol("filterUnits"); + primitiveUnits = /* @__PURE__ */ Symbol("primitiveUnits"); + href = /* @__PURE__ */ Symbol("href"); + x1 = /* @__PURE__ */ Symbol("x1"); + y1 = /* @__PURE__ */ Symbol("y1"); + x2 = /* @__PURE__ */ Symbol("x2"); + y2 = /* @__PURE__ */ Symbol("y2"); + gradientUnits = /* @__PURE__ */ Symbol("gradientUnits"); + gradientTransform = /* @__PURE__ */ Symbol("gradientTransform"); + spreadMethod = /* @__PURE__ */ Symbol("spreadMethod"); + patternUnits = /* @__PURE__ */ Symbol("patternUnits"); + patternContentUnits = /* @__PURE__ */ Symbol("patternContentUnits"); + patternTransform = /* @__PURE__ */ Symbol("patternTransform"); + fx = /* @__PURE__ */ Symbol("fx"); + fy = /* @__PURE__ */ Symbol("fy"); + offset = /* @__PURE__ */ Symbol("offset"); + disabled = /* @__PURE__ */ Symbol("disabled"); + textLength = /* @__PURE__ */ Symbol("textLength"); + lengthAdjust = /* @__PURE__ */ Symbol("lengthAdjust"); + getAttribute = /* @__PURE__ */ Symbol("getAttribute"); + setAttribute = /* @__PURE__ */ Symbol("setAttribute"); + z = /* @__PURE__ */ Symbol("z"); + w = /* @__PURE__ */ Symbol("w"); + toArray = /* @__PURE__ */ Symbol("toArray"); + fromString = /* @__PURE__ */ Symbol("fromString"); + fromArray = /* @__PURE__ */ Symbol("fromArray"); + angle = /* @__PURE__ */ Symbol("angle"); + m11 = /* @__PURE__ */ Symbol("m11"); + m12 = /* @__PURE__ */ Symbol("m12"); + m13 = /* @__PURE__ */ Symbol("m13"); + m14 = /* @__PURE__ */ Symbol("m14"); + m21 = /* @__PURE__ */ Symbol("m21"); + m22 = /* @__PURE__ */ Symbol("m22"); + m23 = /* @__PURE__ */ Symbol("m23"); + m24 = /* @__PURE__ */ Symbol("m24"); + m31 = /* @__PURE__ */ Symbol("m31"); + m32 = /* @__PURE__ */ Symbol("m32"); + m33 = /* @__PURE__ */ Symbol("m33"); + m34 = /* @__PURE__ */ Symbol("m34"); + m41 = /* @__PURE__ */ Symbol("m41"); + m42 = /* @__PURE__ */ Symbol("m42"); + m43 = /* @__PURE__ */ Symbol("m43"); + m44 = /* @__PURE__ */ Symbol("m44"); + setMatrixValue = /* @__PURE__ */ Symbol("setMatrixValue"); + translateSelf = /* @__PURE__ */ Symbol("translateSelf"); + rotateSelf = /* @__PURE__ */ Symbol("rotateSelf"); + rotateAxisAngleSelf = /* @__PURE__ */ Symbol("rotateAxisAngleSelf"); + scaleSelf = /* @__PURE__ */ Symbol("scaleSelf"); + scale3dSelf = /* @__PURE__ */ Symbol("scale3dSelf"); + scaleNonUniformSelf = /* @__PURE__ */ Symbol("scaleNonUniformSelf"); + skewXSelf = /* @__PURE__ */ Symbol("skewXSelf"); + skewYSelf = /* @__PURE__ */ Symbol("skewYSelf"); + multiplySelf = /* @__PURE__ */ Symbol("multiplySelf"); + matrix = /* @__PURE__ */ Symbol("matrix"); + domMatrix = /* @__PURE__ */ Symbol("domMatrix"); + getDOMMatrix = /* @__PURE__ */ Symbol("getDOMMatrix"); + setDOMMatrix = /* @__PURE__ */ Symbol("setDOMMatrix"); + attributeValue = /* @__PURE__ */ Symbol("attributeValue"); + startOffset = /* @__PURE__ */ Symbol("startOffset"); + method = /* @__PURE__ */ Symbol("method"); + spacing = /* @__PURE__ */ Symbol("spacing"); + in1 = /* @__PURE__ */ Symbol("in1"); + in2 = /* @__PURE__ */ Symbol("in2"); + result2 = /* @__PURE__ */ Symbol("result"); + bias = /* @__PURE__ */ Symbol("bias"); + divisor = /* @__PURE__ */ Symbol("divisor"); + edgeMode = /* @__PURE__ */ Symbol("edgeMode"); + kernelMatrix = /* @__PURE__ */ Symbol("kernelMatrix"); + kernelUnitLengthX = /* @__PURE__ */ Symbol("kernelUnitLengthX"); + kernelUnitLengthY = /* @__PURE__ */ Symbol("kernelUnitLengthY"); + orderX = /* @__PURE__ */ Symbol("orderX"); + orderY = /* @__PURE__ */ Symbol("orderY"); + preserveAlpha = /* @__PURE__ */ Symbol("preserveAlpha"); + targetX = /* @__PURE__ */ Symbol("targetX"); + targetY = /* @__PURE__ */ Symbol("targetY"); + diffuseConstant = /* @__PURE__ */ Symbol("diffuseConstant"); + surfaceScale = /* @__PURE__ */ Symbol("surfaceScale"); + scale = /* @__PURE__ */ Symbol("scale"); + xChannelSelector = /* @__PURE__ */ Symbol("xChannelSelector"); + yChannelSelector = /* @__PURE__ */ Symbol("yChannelSelector"); + azimuth = /* @__PURE__ */ Symbol("azimuth"); + elevation = /* @__PURE__ */ Symbol("elevation"); + dx = /* @__PURE__ */ Symbol("dx"); + dy = /* @__PURE__ */ Symbol("dy"); + stdDeviationX = /* @__PURE__ */ Symbol("stdDeviationX"); + stdDeviationY = /* @__PURE__ */ Symbol("stdDeviationY"); + tableValues = /* @__PURE__ */ Symbol("tableValues"); + slope = /* @__PURE__ */ Symbol("slope"); + intercept = /* @__PURE__ */ Symbol("intercept"); + amplitude = /* @__PURE__ */ Symbol("amplitude"); + exponent = /* @__PURE__ */ Symbol("exponent"); + crossOrigin = /* @__PURE__ */ Symbol("crossOrigin"); + operator = /* @__PURE__ */ Symbol("operator"); + radiusX = /* @__PURE__ */ Symbol("radiusX"); + radiusY = /* @__PURE__ */ Symbol("radiusY"); + specularConstant = /* @__PURE__ */ Symbol("specularConstant"); + specularExponent = /* @__PURE__ */ Symbol("specularExponent"); + pointsAtX = /* @__PURE__ */ Symbol("pointsAtX"); + pointsAtY = /* @__PURE__ */ Symbol("pointsAtY"); + pointsAtZ = /* @__PURE__ */ Symbol("pointsAtZ"); + limitingConeAngle = /* @__PURE__ */ Symbol("limitingConeAngle"); + baseFrequencyX = /* @__PURE__ */ Symbol("baseFrequencyX"); + baseFrequencyY = /* @__PURE__ */ Symbol("baseFrequencyY"); + numOctaves = /* @__PURE__ */ Symbol("numOctaves"); + seed = /* @__PURE__ */ Symbol("seed"); + stitchTiles = /* @__PURE__ */ Symbol("stitchTiles"); + rotateFromVectorSelf = /* @__PURE__ */ Symbol("rotateFromVectorSelf"); + flipXSelf = /* @__PURE__ */ Symbol("flipXSelf"); + flipYSelf = /* @__PURE__ */ Symbol("flipYSelf"); + invertSelf = /* @__PURE__ */ Symbol("invertSelf"); + getLength = /* @__PURE__ */ Symbol("getLength"); + currentScale = /* @__PURE__ */ Symbol("currentScale"); + rotate = /* @__PURE__ */ Symbol("rotate"); + bindMethods = /* @__PURE__ */ Symbol("bindMethods"); + xmlProcessingInstruction = /* @__PURE__ */ Symbol("xmlProcessingInstruction"); + root = /* @__PURE__ */ Symbol("root"); + filterNode = /* @__PURE__ */ Symbol("filterNode"); + customElementReactionStack = /* @__PURE__ */ Symbol("customElementReactionStack"); + dispatching = /* @__PURE__ */ Symbol("dispatching"); + modules = /* @__PURE__ */ Symbol("modules"); + preloads = /* @__PURE__ */ Symbol("preloads"); + body = /* @__PURE__ */ Symbol("body"); + redirect = /* @__PURE__ */ Symbol("redirect"); + referrerPolicy = /* @__PURE__ */ Symbol("referrerPolicy"); + signal = /* @__PURE__ */ Symbol("signal"); + bodyUsed = /* @__PURE__ */ Symbol("bodyUsed"); + credentials = /* @__PURE__ */ Symbol("credentials"); + blocking = /* @__PURE__ */ Symbol("blocking"); + moduleImportMap = /* @__PURE__ */ Symbol("moduleImportMap"); + dispatchError = /* @__PURE__ */ Symbol("dispatchError"); + supports = /* @__PURE__ */ Symbol("supports"); + reason = /* @__PURE__ */ Symbol("reason"); + propertyEventListeners = /* @__PURE__ */ Symbol("propertyEventListeners"); + cssRules = /* @__PURE__ */ Symbol("cssRules"); + parentRule = /* @__PURE__ */ Symbol("parentRule"); + parentStyleSheet = /* @__PURE__ */ Symbol("parentStyleSheet"); + conditionText = /* @__PURE__ */ Symbol("conditionText"); + keyText = /* @__PURE__ */ Symbol("keyText"); + media = /* @__PURE__ */ Symbol("media"); + styleMap = /* @__PURE__ */ Symbol("styleMap"); + selectorText = /* @__PURE__ */ Symbol("selectorText"); + cssParser = /* @__PURE__ */ Symbol("cssParser"); + cssRule = /* @__PURE__ */ Symbol("cssRule"); + rulePrefix = /* @__PURE__ */ Symbol("rulePrefix"); + virtualServerFile = /* @__PURE__ */ Symbol("virtualServerFile"); + frames = /* @__PURE__ */ Symbol("frames"); + disableEvaluation = /* @__PURE__ */ Symbol("disableEvaluation"); + validateJavaScriptExecutionEnvironment = /* @__PURE__ */ Symbol("validateJavaScriptExecutionEnvironment"); + currentNode = /* @__PURE__ */ Symbol("currentNode"); + openWebSockets = /* @__PURE__ */ Symbol("openWebSockets"); + webSocket = /* @__PURE__ */ Symbol("webSocket"); + moduleCache = /* @__PURE__ */ Symbol("moduleCache"); + cookieStore = /* @__PURE__ */ Symbol("cookieStore"); + context = /* @__PURE__ */ Symbol("context"); + querySelectorCache = /* @__PURE__ */ Symbol("querySelectorCache"); + } +}); + +// node_modules/happy-dom/lib/cookie/enums/CookieSameSiteEnum.js +var CookieSameSiteEnum, CookieSameSiteEnum_default; +var init_CookieSameSiteEnum = __esm({ + "node_modules/happy-dom/lib/cookie/enums/CookieSameSiteEnum.js"() { + (function(CookieSameSiteEnum2) { + CookieSameSiteEnum2["strict"] = "Strict"; + CookieSameSiteEnum2["lax"] = "Lax"; + CookieSameSiteEnum2["none"] = "None"; + })(CookieSameSiteEnum || (CookieSameSiteEnum = {})); + CookieSameSiteEnum_default = CookieSameSiteEnum; + } +}); + +// node_modules/happy-dom/lib/cookie/DefaultCookie.js +var DefaultCookie_default; +var init_DefaultCookie = __esm({ + "node_modules/happy-dom/lib/cookie/DefaultCookie.js"() { + init_CookieSameSiteEnum(); + DefaultCookie_default = { + // Required + key: null, + originURL: null, + // Optional + value: null, + domain: "", + path: "", + expires: null, + httpOnly: false, + secure: false, + sameSite: CookieSameSiteEnum_default.lax + }; + } +}); + +// node_modules/happy-dom/lib/cookie/urilities/CookieExpireUtility.js +var CookieExpireUtility; +var init_CookieExpireUtility = __esm({ + "node_modules/happy-dom/lib/cookie/urilities/CookieExpireUtility.js"() { + CookieExpireUtility = class { + /** + * Returns "true" if cookie has expired. + * + * @param cookie Cookie. + * @returns "true" if cookie has expired. + */ + static hasExpired(cookie) { + return cookie.expires && cookie.expires.getTime() < Date.now(); + } + }; + } +}); + +// node_modules/happy-dom/lib/cookie/urilities/CookieURLUtility.js +var CookieURLUtility; +var init_CookieURLUtility = __esm({ + "node_modules/happy-dom/lib/cookie/urilities/CookieURLUtility.js"() { + init_CookieSameSiteEnum(); + CookieURLUtility = class { + /** + * Returns "true" if cookie matches URL. + * + * @param cookie Cookie. + * @param url URL. + * @returns "true" if cookie matches URL. + */ + static cookieMatchesURL(cookie, url2) { + const isLocalhost = url2.hostname === "localhost" || url2.hostname?.endsWith(".localhost"); + return (!cookie.secure || url2.protocol === "https:" || isLocalhost) && (!cookie.domain || url2.hostname?.endsWith(cookie.domain)) && (!cookie.path || url2.pathname?.startsWith(cookie.path)) && // @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value + (cookie.sameSite === CookieSameSiteEnum_default.none && cookie.secure || cookie.originURL?.hostname === url2.hostname); + } + }; + } +}); + +// node_modules/happy-dom/lib/cookie/CookieContainer.js +var CookieContainer; +var init_CookieContainer = __esm({ + "node_modules/happy-dom/lib/cookie/CookieContainer.js"() { + init_DefaultCookie(); + init_CookieExpireUtility(); + init_CookieURLUtility(); + CookieContainer = class { + #cookies = []; + /** + * Adds or replaces cookies. + * + * @param cookies Cookies. + * @returns Changed cookies. + */ + addCookies(cookies) { + const changedCookies = { + changed: [], + deleted: [] + }; + const allCookies = this.#cookies; + for (const cookie of cookies) { + const newCookie = Object.assign({}, DefaultCookie_default, cookie); + if (newCookie && newCookie.key && newCookie.originURL) { + const hasExpired = CookieExpireUtility.hasExpired(newCookie); + for (let i = 0, max = allCookies.length; i < max; i++) { + const existingCookie = allCookies[i]; + if (existingCookie.key === newCookie.key && existingCookie.originURL.hostname === newCookie.originURL.hostname && existingCookie.path === newCookie.path && typeof existingCookie.value === typeof newCookie.value) { + if (hasExpired) { + changedCookies.deleted.push(existingCookie); + } + allCookies.splice(i, 1); + break; + } + } + if (!hasExpired) { + allCookies.push(newCookie); + changedCookies.changed.push(newCookie); + } + } + } + return changedCookies; + } + /** + * Returns cookies. + * + * @param [url] URL. + * @param [clientSide] "true" if "httpOnly" cookies should be filtered out. + * @returns Cookies. + */ + getCookies(url2 = null, clientSide = false) { + const cookies = []; + for (const cookie of this.#cookies) { + if (!CookieExpireUtility.hasExpired(cookie) && (!clientSide || !cookie.httpOnly) && (!url2 || CookieURLUtility.cookieMatchesURL(cookie, url2))) { + cookies.push(cookie); + } + } + return cookies; + } + /** + * Clears all cookies. + */ + clearCookies() { + this.#cookies = []; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/cache/response/CachedResponseStateEnum.js +var CachedResponseStateEnum, CachedResponseStateEnum_default; +var init_CachedResponseStateEnum = __esm({ + "node_modules/happy-dom/lib/fetch/cache/response/CachedResponseStateEnum.js"() { + (function(CachedResponseStateEnum2) { + CachedResponseStateEnum2["fresh"] = "fresh"; + CachedResponseStateEnum2["stale"] = "stale"; + })(CachedResponseStateEnum || (CachedResponseStateEnum = {})); + CachedResponseStateEnum_default = CachedResponseStateEnum; + } +}); + +// node_modules/happy-dom/lib/exception/DOMExceptionNameEnum.js +var DOMExceptionNameEnum, DOMExceptionNameEnum_default; +var init_DOMExceptionNameEnum = __esm({ + "node_modules/happy-dom/lib/exception/DOMExceptionNameEnum.js"() { + (function(DOMExceptionNameEnum2) { + DOMExceptionNameEnum2["invalidStateError"] = "InvalidStateError"; + DOMExceptionNameEnum2["indexSizeError"] = "IndexSizeError"; + DOMExceptionNameEnum2["syntaxError"] = "SyntaxError"; + DOMExceptionNameEnum2["hierarchyRequestError"] = "HierarchyRequestError"; + DOMExceptionNameEnum2["notSupportedError"] = "NotSupportedError"; + DOMExceptionNameEnum2["wrongDocumentError"] = "WrongDocumentError"; + DOMExceptionNameEnum2["invalidNodeTypeError"] = "InvalidNodeTypeError"; + DOMExceptionNameEnum2["invalidCharacterError"] = "InvalidCharacterError"; + DOMExceptionNameEnum2["notFoundError"] = "NotFoundError"; + DOMExceptionNameEnum2["securityError"] = "SecurityError"; + DOMExceptionNameEnum2["networkError"] = "NetworkError"; + DOMExceptionNameEnum2["domException"] = "DOMException"; + DOMExceptionNameEnum2["invalidAccessError"] = "InvalidAccessError"; + DOMExceptionNameEnum2["unknownError"] = "UnknownError"; + DOMExceptionNameEnum2["abortError"] = "AbortError"; + DOMExceptionNameEnum2["timeoutError"] = "TimeoutError"; + DOMExceptionNameEnum2["encodingError"] = "EncodingError"; + DOMExceptionNameEnum2["uriMismatchError"] = "URIMismatchError"; + DOMExceptionNameEnum2["inUseAttributeError"] = "InUseAttributeError"; + DOMExceptionNameEnum2["namespaceError"] = "NamespaceError"; + })(DOMExceptionNameEnum || (DOMExceptionNameEnum = {})); + DOMExceptionNameEnum_default = DOMExceptionNameEnum; + } +}); + +// node_modules/happy-dom/lib/exception/DOMException.js +var DOMException2; +var init_DOMException = __esm({ + "node_modules/happy-dom/lib/exception/DOMException.js"() { + init_DOMExceptionNameEnum(); + DOMException2 = class extends Error { + /** + * Constructor. + * + * @param message Message. + * @param name Name. + */ + constructor(message, name2 = null) { + super(message); + this.name = name2 || DOMExceptionNameEnum_default.domException; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/Headers.js +var Headers2; +var init_Headers = __esm({ + "node_modules/happy-dom/lib/fetch/Headers.js"() { + init_DOMException(); + init_PropertySymbol(); + init_DOMExceptionNameEnum(); + Headers2 = class _Headers { + [entries] = {}; + /** + * Constructor. + * + * @param init Headers init. + */ + constructor(init) { + if (init) { + if (init instanceof _Headers) { + this[entries] = JSON.parse(JSON.stringify(init[entries])); + } else if (Array.isArray(init)) { + for (const entry of init) { + if (entry.length !== 2) { + throw new DOMException2('Failed to construct "Headers": The provided init is not a valid array.', DOMExceptionNameEnum_default.invalidStateError); + } + this.append(entry[0], entry[1]); + } + } else { + for (const name2 of Object.keys(init)) { + this.set(name2, init[name2]); + } + } + } + } + /** + * Appends a new value onto an existing header inside a Headers object, or adds the header if it does not already exist. + * + * @param name Name. + * @param value Value. + */ + append(name2, value2) { + const lowerName = name2.toLowerCase(); + if (this[entries][lowerName]) { + this[entries][lowerName].value.push(value2); + } else { + this[entries][lowerName] = { + name: name2, + value: [value2] + }; + } + } + /** + * Removes an header. + * + * @param name Name. + */ + delete(name2) { + delete this[entries][name2.toLowerCase()]; + } + /** + * Returns header value. + * + * @param name Name. + * @returns Value. + */ + get(name2) { + return this[entries][name2.toLowerCase()]?.value.join(", ") ?? null; + } + /** + * Sets a new value for an existing header inside a Headers object, or adds the header if it does not already exist. + * + * @param name Name. + * @param value Value. + */ + set(name2, value2) { + this[entries][name2.toLowerCase()] = { + name: name2, + value: [value2] + }; + } + /** + * Returns an array containing the values of all Set-Cookie headers associated with a response. + * + * @returns An array of strings representing the values of all the different Set-Cookie headers. + */ + getSetCookie() { + const entry = this[entries]["set-cookie"]; + if (!entry) { + return []; + } + return entry.value; + } + /** + * Returns whether an Headers object contains a certain key. + * + * @param name Name. + * @returns "true" if the Headers object contains the key. + */ + has(name2) { + return !!this[entries][name2.toLowerCase()]; + } + /** + * Executes a callback function once per each key/value pair in the Headers object. + * + * @param callback Callback. + * @param thisArg thisArg. + */ + forEach(callback, thisArg) { + const thisArgValue = thisArg ?? this[window]; + for (const header of Object.values(this[entries])) { + callback.call(thisArgValue, header.value.join(", "), header.name, this); + } + } + /** + * Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object. + * + * @returns Iterator. + */ + *keys() { + for (const header of Object.values(this[entries])) { + yield header.name; + } + } + /** + * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. + * + * @returns Iterator. + */ + *values() { + for (const header of Object.values(this[entries])) { + yield header.value.join(", "); + } + } + /** + * Returns an iterator, allowing you to go through all key/value pairs contained in this object. + * + * @returns Iterator. + */ + *entries() { + for (const header of Object.values(this[entries])) { + yield [header.name, header.value.join(", ")]; + } + } + /** + * Iterator. + * + * @returns Iterator. + */ + *[Symbol.iterator]() { + for (const header of Object.values(this[entries])) { + yield [header.name, header.value.join(", ")]; + } + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/cache/response/ResponseCacheFileSystem.js +var import_fs, import_path, import_crypto, ResponseCacheFileSystem; +var init_ResponseCacheFileSystem = __esm({ + "node_modules/happy-dom/lib/fetch/cache/response/ResponseCacheFileSystem.js"() { + init_Headers(); + import_fs = __toESM(require("fs"), 1); + import_path = __toESM(require("path"), 1); + import_crypto = __toESM(require("crypto"), 1); + ResponseCacheFileSystem = class { + #createdDirectories = /* @__PURE__ */ new Set(); + #hashes = /* @__PURE__ */ new Set(); + #entries; + /** + * Constructor. + * + * @param entries Map of URL to cached responses. + */ + constructor(entries2) { + this.#entries = entries2; + } + /** + * Loads cache from file system. + * + * @param directory Directory to load from. + */ + async load(directory) { + if (!directory) { + throw new Error("Failed to execute 'load' on 'ResponseCacheFileSystem': Directory is not specified."); + } + const absoluteDirectory = import_path.default.resolve(directory); + let files2 = []; + try { + files2 = await import_fs.default.promises.readdir(absoluteDirectory); + } catch (error2) { + return; + } + const promises = []; + const entries2 = this.#entries; + for (const file of files2) { + if (file.endsWith(".json")) { + promises.push(import_fs.default.promises.readFile(import_path.default.join(absoluteDirectory, file), "utf8").then((content2) => { + const cachedResponse2 = JSON.parse(content2); + if (cachedResponse2.response && cachedResponse2.request && !cachedResponse2.virtual) { + cachedResponse2.response.headers = new Headers2(cachedResponse2.response.headers); + cachedResponse2.request.headers = new Headers2(cachedResponse2.request.headers); + return import_fs.default.promises.readFile(import_path.default.join(absoluteDirectory, file.split(".")[0] + ".data")).then((body2) => { + cachedResponse2.response.body = body2; + let entry = entries2.get(cachedResponse2.response.url); + if (!entry) { + entry = []; + entries2.set(cachedResponse2.response.url, entry); + } + entry.push(cachedResponse2); + }).catch(() => { + let entry = entries2.get(cachedResponse2.response.url); + if (!entry) { + entry = []; + entries2.set(cachedResponse2.response.url, entry); + } + entry.push(cachedResponse2); + }); + } + }).catch(() => { + })); + } + } + await Promise.all(promises); + } + /** + * Saves the cache to file system. + * + * @param directory Directory to store to. + */ + async save(directory) { + if (!directory) { + throw new Error("Failed to execute 'store' on 'ResponseCacheFileSystem': Directory is not specified."); + } + if (!this.#entries.size) { + return; + } + const absoluteDirectory = import_path.default.resolve(directory); + const isDirectoryCreated = this.#createdDirectories.has(absoluteDirectory); + if (!isDirectoryCreated) { + this.#createdDirectories.add(absoluteDirectory); + try { + await import_fs.default.promises.mkdir(absoluteDirectory, { + recursive: true + }); + } catch (error2) { + } + } + const entries2 = this.#entries; + const promises = []; + for (const entry of entries2.values()) { + for (const cachedResponse2 of entry) { + if (!cachedResponse2.virtual) { + const responseHeaders = {}; + const requestHeaders = {}; + for (const [key, value2] of cachedResponse2.response.headers.entries()) { + responseHeaders[key] = value2; + } + for (const [key, value2] of cachedResponse2.request.headers.entries()) { + requestHeaders[key] = value2; + } + const cacheableEntry = { + ...cachedResponse2, + response: { + ...cachedResponse2.response, + headers: responseHeaders, + body: null + }, + request: { + ...cachedResponse2.request, + headers: requestHeaders + } + }; + const json = JSON.stringify(cacheableEntry, null, 3); + const hash = import_crypto.default.createHash("md5").update(json).digest("hex"); + if (!this.#hashes.has(hash)) { + this.#hashes.add(hash); + promises.push(import_fs.default.promises.writeFile(import_path.default.join(absoluteDirectory, `${hash}.json`), json)); + if (cachedResponse2.response.body) { + promises.push(import_fs.default.promises.writeFile(import_path.default.join(absoluteDirectory, `${hash}.data`), cachedResponse2.response.body)); + } + } + } + } + } + await Promise.all(promises); + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/cache/response/ResponseCache.js +var UPDATE_RESPONSE_HEADERS, ResponseCache; +var init_ResponseCache = __esm({ + "node_modules/happy-dom/lib/fetch/cache/response/ResponseCache.js"() { + init_CachedResponseStateEnum(); + init_Headers(); + init_ResponseCacheFileSystem(); + UPDATE_RESPONSE_HEADERS = ["Cache-Control", "Last-Modified", "Vary", "ETag"]; + ResponseCache = class { + fileSystem; + #entries = /* @__PURE__ */ new Map(); + /** + * Constructor. + */ + constructor() { + this.fileSystem = new ResponseCacheFileSystem(this.#entries); + } + /** + * Returns cached response. + * + * @param request Request. + * @returns Cached response. + */ + get(request) { + if (request.headers.get("Cache-Control")?.includes("no-cache")) { + return null; + } + const url2 = request.url; + const entries2 = this.#entries.get(url2); + if (entries2) { + for (let i = 0, max = entries2.length; i < max; i++) { + const entry = entries2[i]; + let isMatch = entry.request.method === request.method; + if (isMatch) { + for (const header of Object.keys(entry.vary)) { + const requestHeader = request.headers.get(header); + if (requestHeader !== null && entry.vary[header] !== requestHeader) { + isMatch = false; + break; + } + } + } + if (isMatch) { + if (entry.expires && entry.expires < Date.now()) { + if (entry.lastModified) { + entry.state = CachedResponseStateEnum_default.stale; + } else if (!entry.etag) { + entries2.splice(i, 1); + return null; + } + } + return entry; + } + } + } + return null; + } + /** + * Adds a cache entity. + * + * @param request Request. + * @param response Response. + * @returns Cached response. + */ + add(request, response) { + if (request.method !== "GET" && request.method !== "HEAD" || request.headers.get("Cache-Control")?.includes("no-cache")) { + return null; + } + const url2 = request.url; + let cachedResponse2 = this.get(request); + if (response.status === 304) { + if (!cachedResponse2) { + throw new Error("ResponseCache: Cached response not found."); + } + for (const name2 of UPDATE_RESPONSE_HEADERS) { + if (response.headers.has(name2)) { + cachedResponse2.response.headers.set(name2, response.headers.get(name2)); + } + } + cachedResponse2.cacheUpdateTime = Date.now(); + cachedResponse2.state = CachedResponseStateEnum_default.fresh; + } else { + if (cachedResponse2) { + const entries3 = this.#entries.get(url2); + if (entries3) { + const index = entries3.indexOf(cachedResponse2); + if (index !== -1) { + entries3.splice(index, 1); + } + } + } + cachedResponse2 = { + response: { + status: response.status, + statusText: response.statusText, + url: response.url, + headers: new Headers2(response.headers), + // We need to wait for the body to be consumed and then populated if set to true (e.g. by using Response.text()). + waitingForBody: response.waitingForBody, + body: response.body ?? null + }, + request: { + headers: request.headers, + method: request.method + }, + vary: {}, + expires: null, + etag: null, + cacheUpdateTime: Date.now(), + lastModified: null, + mustRevalidate: false, + staleWhileRevalidate: false, + state: CachedResponseStateEnum_default.fresh, + virtual: response.virtual ?? false + }; + let entries2 = this.#entries.get(url2); + if (!entries2) { + entries2 = []; + this.#entries.set(url2, entries2); + } + entries2.push(cachedResponse2); + } + if (response.headers.has("Cache-Control")) { + const age = response.headers.get("Age"); + for (const part of response.headers.get("Cache-Control").split(",")) { + const [key, value2] = part.trim().split("="); + switch (key) { + case "max-age": + cachedResponse2.expires = Date.now() + parseFloat(value2) * 1e3 - (age ? parseFloat(age) * 1e3 : 0); + break; + case "no-cache": + case "no-store": + const entries2 = this.#entries.get(url2); + if (entries2) { + const index = entries2.indexOf(cachedResponse2); + if (index !== -1) { + entries2.splice(index, 1); + } + } + return null; + case "must-revalidate": + cachedResponse2.mustRevalidate = true; + break; + case "stale-while-revalidate": + cachedResponse2.staleWhileRevalidate = true; + break; + } + } + } + if (response.headers.has("Last-Modified")) { + cachedResponse2.lastModified = Date.parse(response.headers.get("Last-Modified")); + } + if (response.headers.has("Vary")) { + for (const header of response.headers.get("Vary").split(",")) { + const name2 = header.trim(); + const value2 = request.headers.get(name2); + if (value2) { + cachedResponse2.vary[name2] = value2; + } + } + } + if (response.headers.has("ETag")) { + cachedResponse2.etag = response.headers.get("ETag"); + } + if (!cachedResponse2.expires) { + const expires = response.headers.get("Expires"); + if (expires) { + cachedResponse2.expires = Date.parse(expires); + } + } + if (!cachedResponse2.etag && (!cachedResponse2.expires || cachedResponse2.expires < Date.now())) { + const entries2 = this.#entries.get(url2); + if (entries2) { + const index = entries2.indexOf(cachedResponse2); + if (index !== -1) { + entries2.splice(index, 1); + } + } + return null; + } + return cachedResponse2; + } + /** + * Clears the cache. + * + * @param [options] Options. + * @param [options.url] URL. + * @param [options.toTime] Removes all entries that are older than this time. Time in MS. + */ + clear(options2) { + if (options2) { + if (options2.toTime) { + for (const key of options2.url ? [options2.url] : this.#entries.keys()) { + const entry = this.#entries.get(key); + if (entry) { + for (let i = 0, max = entry.length; i < max; i++) { + if (entry[i].cacheUpdateTime < options2.toTime) { + entry.splice(i, 1); + i--; + max--; + } + } + } + } + } else if (options2.url) { + this.#entries.delete(options2.url); + } + } else { + this.#entries.clear(); + } + } + }; + } +}); + +// node_modules/happy-dom/lib/console/enums/VirtualConsoleLogLevelEnum.js +var VirtualConsoleLogLevelEnum, VirtualConsoleLogLevelEnum_default; +var init_VirtualConsoleLogLevelEnum = __esm({ + "node_modules/happy-dom/lib/console/enums/VirtualConsoleLogLevelEnum.js"() { + (function(VirtualConsoleLogLevelEnum2) { + VirtualConsoleLogLevelEnum2[VirtualConsoleLogLevelEnum2["log"] = 0] = "log"; + VirtualConsoleLogLevelEnum2[VirtualConsoleLogLevelEnum2["info"] = 1] = "info"; + VirtualConsoleLogLevelEnum2[VirtualConsoleLogLevelEnum2["warn"] = 2] = "warn"; + VirtualConsoleLogLevelEnum2[VirtualConsoleLogLevelEnum2["error"] = 3] = "error"; + })(VirtualConsoleLogLevelEnum || (VirtualConsoleLogLevelEnum = {})); + VirtualConsoleLogLevelEnum_default = VirtualConsoleLogLevelEnum; + } +}); + +// node_modules/happy-dom/lib/nodes/node/NodeTypeEnum.js +var NodeTypeEnum, NodeTypeEnum_default; +var init_NodeTypeEnum = __esm({ + "node_modules/happy-dom/lib/nodes/node/NodeTypeEnum.js"() { + (function(NodeTypeEnum2) { + NodeTypeEnum2[NodeTypeEnum2["elementNode"] = 1] = "elementNode"; + NodeTypeEnum2[NodeTypeEnum2["attributeNode"] = 2] = "attributeNode"; + NodeTypeEnum2[NodeTypeEnum2["textNode"] = 3] = "textNode"; + NodeTypeEnum2[NodeTypeEnum2["cdataSectionNode"] = 4] = "cdataSectionNode"; + NodeTypeEnum2[NodeTypeEnum2["commentNode"] = 8] = "commentNode"; + NodeTypeEnum2[NodeTypeEnum2["documentNode"] = 9] = "documentNode"; + NodeTypeEnum2[NodeTypeEnum2["documentTypeNode"] = 10] = "documentTypeNode"; + NodeTypeEnum2[NodeTypeEnum2["documentFragmentNode"] = 11] = "documentFragmentNode"; + NodeTypeEnum2[NodeTypeEnum2["processingInstructionNode"] = 7] = "processingInstructionNode"; + })(NodeTypeEnum || (NodeTypeEnum = {})); + NodeTypeEnum_default = NodeTypeEnum; + } +}); + +// node_modules/happy-dom/lib/event/EventPhaseEnum.js +var EventPhaseEnum, EventPhaseEnum_default; +var init_EventPhaseEnum = __esm({ + "node_modules/happy-dom/lib/event/EventPhaseEnum.js"() { + (function(EventPhaseEnum2) { + EventPhaseEnum2[EventPhaseEnum2["none"] = 0] = "none"; + EventPhaseEnum2[EventPhaseEnum2["capturing"] = 1] = "capturing"; + EventPhaseEnum2[EventPhaseEnum2["atTarget"] = 2] = "atTarget"; + EventPhaseEnum2[EventPhaseEnum2["bubbling"] = 3] = "bubbling"; + })(EventPhaseEnum || (EventPhaseEnum = {})); + EventPhaseEnum_default = EventPhaseEnum; + } +}); + +// node_modules/happy-dom/lib/event/Event.js +var Event2; +var init_Event = __esm({ + "node_modules/happy-dom/lib/event/Event.js"() { + init_PropertySymbol(); + init_NodeTypeEnum(); + init_EventPhaseEnum(); + Event2 = class _Event { + static NONE = EventPhaseEnum_default.none; + static CAPTURING_PHASE = EventPhaseEnum_default.capturing; + static AT_TARGET = EventPhaseEnum_default.atTarget; + static BUBBLING_PHASE = EventPhaseEnum_default.bubbling; + NONE = _Event.NONE; + CAPTURING_PHASE = _Event.CAPTURING_PHASE; + AT_TARGET = _Event.AT_TARGET; + BUBBLING_PHASE = _Event.BUBBLING_PHASE; + [composed] = false; + [bubbles] = false; + [cancelable] = false; + [defaultPrevented] = false; + [eventPhase] = EventPhaseEnum_default.none; + [timeStamp] = performance.now(); + [type]; + [dispatching] = false; + [immediatePropagationStopped] = false; + [propagationStopped] = false; + [target] = null; + [currentTarget] = null; + [isInPassiveEventListener] = false; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + this[type] = type2; + this[bubbles] = eventInit?.bubbles ?? false; + this[cancelable] = eventInit?.cancelable ?? false; + this[composed] = eventInit?.composed ?? false; + } + /** + * Returns composed. + * + * @returns Composed. + */ + get composed() { + return this[composed]; + } + /** + * Returns bubbles. + * + * @returns Bubbles. + */ + get bubbles() { + return this[bubbles]; + } + /** + * Returns cancelable. + * + * @returns Cancelable. + */ + get cancelable() { + return this[cancelable]; + } + /** + * Returns defaultPrevented. + * + * @returns Default prevented. + */ + get defaultPrevented() { + return this[defaultPrevented]; + } + /** + * Returns eventPhase. + * + * @returns Event phase. + */ + get eventPhase() { + return this[eventPhase]; + } + /** + * Returns timeStamp. + * + * @returns Time stamp. + */ + get timeStamp() { + return this[timeStamp]; + } + /** + * Returns type. + * + * @returns Type. + */ + get type() { + return this[type]; + } + /** + * Returns target. + * + * @returns Target. + */ + get target() { + return this[target]; + } + /** + * Returns target. + * + * @returns Target. + */ + get currentTarget() { + return this[currentTarget]; + } + /** + * Returns "true" if propagation has been stopped. + * + * @returns "true" if propagation has been stopped. + */ + get cancelBubble() { + return this[propagationStopped]; + } + /** + * Returns composed path. + * + * @returns Composed path. + */ + composedPath() { + if (!this[target]) { + return []; + } + const composedPath = []; + let eventTarget = this[target]; + while (eventTarget) { + composedPath.push(eventTarget); + if (eventTarget.parentNode) { + eventTarget = eventTarget.parentNode; + } else if (this[composed] && eventTarget[nodeType] === NodeTypeEnum_default.documentFragmentNode && eventTarget.host) { + eventTarget = eventTarget.host; + } else if (eventTarget[nodeType] === NodeTypeEnum_default.documentNode && // The "load" event is a special case. It should not bubble up to the window. + this[type] !== "load") { + eventTarget = eventTarget[window]; + } else { + break; + } + } + return composedPath; + } + /** + * Init event. + * + * @deprecated + * @param type Type. + * @param [bubbles=false] "true" if it bubbles. + * @param [cancelable=false] "true" if it cancelable. + */ + initEvent(type2, bubbles2 = false, cancelable2 = false) { + this[type] = type2; + this[bubbles] = bubbles2; + this[cancelable] = cancelable2; + this[propagationStopped] = false; + this[immediatePropagationStopped] = false; + this[defaultPrevented] = false; + } + /** + * Prevents default. + */ + preventDefault() { + if (!this[isInPassiveEventListener] && this.cancelable) { + this[defaultPrevented] = true; + } + } + /** + * Stops immediate propagation. + */ + stopImmediatePropagation() { + this[immediatePropagationStopped] = true; + } + /** + * Stops propagation. + */ + stopPropagation() { + this[propagationStopped] = true; + } + }; + } +}); + +// node_modules/happy-dom/lib/console/enums/VirtualConsoleLogTypeEnum.js +var VirtualConsoleLogTypeEnum, VirtualConsoleLogTypeEnum_default; +var init_VirtualConsoleLogTypeEnum = __esm({ + "node_modules/happy-dom/lib/console/enums/VirtualConsoleLogTypeEnum.js"() { + (function(VirtualConsoleLogTypeEnum2) { + VirtualConsoleLogTypeEnum2["log"] = "log"; + VirtualConsoleLogTypeEnum2["table"] = "table"; + VirtualConsoleLogTypeEnum2["trace"] = "trace"; + VirtualConsoleLogTypeEnum2["dir"] = "dir"; + VirtualConsoleLogTypeEnum2["dirxml"] = "dirxml"; + VirtualConsoleLogTypeEnum2["group"] = "group"; + VirtualConsoleLogTypeEnum2["groupCollapsed"] = "groupCollapsed"; + VirtualConsoleLogTypeEnum2["debug"] = "debug"; + VirtualConsoleLogTypeEnum2["timeLog"] = "timeLog"; + VirtualConsoleLogTypeEnum2["info"] = "info"; + VirtualConsoleLogTypeEnum2["count"] = "count"; + VirtualConsoleLogTypeEnum2["timeEnd"] = "timeEnd"; + VirtualConsoleLogTypeEnum2["warn"] = "warn"; + VirtualConsoleLogTypeEnum2["countReset"] = "countReset"; + VirtualConsoleLogTypeEnum2["error"] = "error"; + VirtualConsoleLogTypeEnum2["assert"] = "assert"; + })(VirtualConsoleLogTypeEnum || (VirtualConsoleLogTypeEnum = {})); + VirtualConsoleLogTypeEnum_default = VirtualConsoleLogTypeEnum; + } +}); + +// node_modules/happy-dom/lib/console/utilities/VirtualConsoleLogEntryStringifier.js +var VirtualConsoleLogEntryStringifier; +var init_VirtualConsoleLogEntryStringifier = __esm({ + "node_modules/happy-dom/lib/console/utilities/VirtualConsoleLogEntryStringifier.js"() { + init_VirtualConsoleLogTypeEnum(); + VirtualConsoleLogEntryStringifier = class { + /** + * Stringifies a log entry. + * + * @param logEntry Log entry. + * @returns Stringified message. + */ + static toString(logEntry) { + if (this.isLogEntryCollapsed(logEntry)) { + return ""; + } + const tabbing = this.getLogEntryGroupTabbing(logEntry); + let output = tabbing; + for (const part of logEntry.message) { + output += output !== "" && output !== tabbing ? " " : ""; + if (typeof part === "object" && (part === null || part.constructor.name === "Object" || Array.isArray(part))) { + try { + output += JSON.stringify(part); + } catch (error2) { + output += new Error("Failed to JSON stringify object in log entry.").stack.replace(/\n at/gm, "\n " + tabbing + "at"); + } + } else if (typeof part === "object" && part["message"] && part["stack"]) { + output += part["stack"].replace(/\n at/gm, "\n " + tabbing + "at"); + } else { + output += this.getLogEntryIcon(logEntry) + String(part); + } + } + return output + "\n"; + } + /** + * Gets the log entry icon. + * + * @param logEntry Log entry. + * @returns Icon. + */ + static getLogEntryIcon(logEntry) { + switch (logEntry.type) { + case VirtualConsoleLogTypeEnum_default.group: + return "\u25BC "; + case VirtualConsoleLogTypeEnum_default.groupCollapsed: + return "\u25B6 "; + } + return ""; + } + /** + * Gets the log entry group tabbing. + * + * @param logEntry Log entry. + * @returns Tabbing. + */ + static getLogEntryGroupTabbing(logEntry) { + let tabs = ""; + let group = logEntry.type === VirtualConsoleLogTypeEnum_default.group || logEntry.type === VirtualConsoleLogTypeEnum_default.groupCollapsed ? logEntry.group?.parent : logEntry.group; + while (group) { + tabs += " "; + group = group.parent; + } + return tabs; + } + /** + * Checks if the log entry content is collapsed. + * + * @param logEntry Log entry. + * @returns True if collapsed. + */ + static isLogEntryCollapsed(logEntry) { + let group = logEntry.type === VirtualConsoleLogTypeEnum_default.group || logEntry.type === VirtualConsoleLogTypeEnum_default.groupCollapsed ? logEntry.group?.parent : logEntry.group; + while (group) { + if (group.collapsed) { + return true; + } + group = group.parent; + } + return false; + } + }; + } +}); + +// node_modules/happy-dom/lib/console/VirtualConsolePrinter.js +var VirtualConsolePrinter; +var init_VirtualConsolePrinter = __esm({ + "node_modules/happy-dom/lib/console/VirtualConsolePrinter.js"() { + init_VirtualConsoleLogLevelEnum(); + init_Event(); + init_VirtualConsoleLogEntryStringifier(); + VirtualConsolePrinter = class { + #logEntries = []; + #listeners = { print: [], clear: [] }; + #closed = false; + /** + * Returns closed state. + * + * @returns True if the printer is closed. + */ + get closed() { + return this.#closed; + } + /** + * Writes to the output. + * + * @param logEntry Log entry. + */ + print(logEntry) { + if (this.#closed) { + return; + } + this.#logEntries.push(logEntry); + this.dispatchEvent(new Event2("print")); + } + /** + * Clears the output. + */ + clear() { + if (this.#closed) { + return; + } + this.#logEntries = []; + this.dispatchEvent(new Event2("clear")); + } + /** + * Clears and closes the virtual console printer. + */ + close() { + if (this.#closed) { + return; + } + this.#logEntries = []; + this.#listeners = { print: [], clear: [] }; + this.#closed = true; + } + /** + * Adds an event listener. + * + * @param eventType Event type ("print" or "clear"). + * @param listener Listener. + */ + addEventListener(eventType, listener) { + if (this.#closed) { + return; + } + if (!this.#listeners[eventType]) { + throw new Error(`Event type "${eventType}" is not supported.`); + } + this.#listeners[eventType].push(listener); + } + /** + * Removes an event listener. + * + * @param eventType Event type ("print" or "clear"). + * @param listener Listener. + */ + removeEventListener(eventType, listener) { + if (this.#closed) { + return; + } + if (!this.#listeners[eventType]) { + throw new Error(`Event type "${eventType}" is not supported.`); + } + const index = this.#listeners[eventType].indexOf(listener); + if (index !== -1) { + this.#listeners[eventType].splice(index, 1); + } + } + /** + * Dispatches an event. + * + * @param event Event. + */ + dispatchEvent(event) { + if (this.#closed) { + return; + } + switch (event.type) { + case "print": + case "clear": + for (const listener of this.#listeners[event.type]) { + listener(event); + } + break; + default: + throw new Error(`Event type "${event.type}" is not supported.`); + } + } + /** + * Reads the buffer. + * + * @returns Console log entries. + */ + read() { + const logEntries = this.#logEntries; + this.#logEntries = []; + return logEntries; + } + /** + * Returns the buffer as a string. + * + * @param [logLevel] Log level. + * @returns Buffer as a string of concatenated log entries. + */ + readAsString(logLevel = VirtualConsoleLogLevelEnum_default.log) { + const logEntries = this.read(); + let output = ""; + for (const logEntry of logEntries) { + if (logEntry.level >= logLevel) { + output += VirtualConsoleLogEntryStringifier.toString(logEntry); + } + } + return output; + } + }; + } +}); + +// node_modules/happy-dom/lib/async-task-manager/AsyncTaskManagerDebugError.js +var AsyncTaskManagerDebugError; +var init_AsyncTaskManagerDebugError = __esm({ + "node_modules/happy-dom/lib/async-task-manager/AsyncTaskManagerDebugError.js"() { + AsyncTaskManagerDebugError = class extends Error { + /** + * Constructor. + * + * @param message Message. + */ + constructor(message) { + super(message); + this.name = "AsyncTaskManagerDebugError"; + } + }; + } +}); + +// node_modules/happy-dom/lib/async-task-manager/AsyncTaskManager.js +var TIMER, AsyncTaskManager; +var init_AsyncTaskManager = __esm({ + "node_modules/happy-dom/lib/async-task-manager/AsyncTaskManager.js"() { + init_AsyncTaskManagerDebugError(); + TIMER = { + setTimeout: globalThis.setTimeout.bind(globalThis), + clearTimeout: globalThis.clearTimeout.bind(globalThis), + clearImmediate: globalThis.clearImmediate.bind(globalThis) + }; + AsyncTaskManager = class { + static taskID = 0; + runningTasks = {}; + runningTaskCount = 0; + runningTimers = []; + runningImmediates = []; + debugTrace = /* @__PURE__ */ new Map(); + waitUntilCompleteTimer = null; + waitUntilCompleteResolvers = []; + destroyed = false; + #debugTimeout = null; + #browserFrame; + /** + * Constructor. + * + * @param browserFrame Browser frame. + */ + constructor(browserFrame) { + this.#browserFrame = browserFrame; + } + /** + * Returns a promise that is resolved when async tasks are complete. + * + * @returns Promise. + */ + waitUntilComplete() { + return new Promise((resolve, reject) => { + this.waitUntilCompleteResolvers.push({ resolve, reject }); + this.resolveWhenComplete(); + }); + } + /** + * Aborts all tasks. + */ + abort() { + if (this.destroyed) { + return new Promise((resolve, reject) => { + this.waitUntilCompleteResolvers.push({ resolve, reject }); + this.resolveWhenComplete(); + }); + } + return this.abortAll(false); + } + /** + * Destroys the manager. + */ + destroy() { + if (this.destroyed) { + return new Promise((resolve, reject) => { + this.waitUntilCompleteResolvers.push({ resolve, reject }); + this.resolveWhenComplete(); + }); + } + return this.abortAll(true); + } + /** + * Starts a timer. + * + * @param timerID Timer ID. + */ + startTimer(timerID) { + if (this.destroyed) { + TIMER.clearTimeout(timerID); + return; + } + if (this.waitUntilCompleteTimer) { + TIMER.clearTimeout(this.waitUntilCompleteTimer); + this.waitUntilCompleteTimer = null; + } + this.runningTimers.push(timerID); + if (this.#browserFrame.page.context.browser.settings.debug.traceWaitUntilComplete > 0) { + this.debugTrace.set(timerID, new AsyncTaskManagerDebugError().stack); + } + } + /** + * Ends a timer. + * + * @param timerID Timer ID. + */ + endTimer(timerID) { + if (this.destroyed) { + TIMER.clearTimeout(timerID); + return; + } + const index = this.runningTimers.indexOf(timerID); + if (index !== -1) { + this.runningTimers.splice(index, 1); + this.resolveWhenComplete(); + } + if (this.#browserFrame.page.context.browser.settings.debug.traceWaitUntilComplete > 0) { + this.debugTrace.delete(timerID); + } + } + /** + * Starts an immediate. + * + * @param immediateID Immediate ID. + */ + startImmediate(immediateID) { + if (this.destroyed) { + TIMER.clearImmediate(immediateID); + return; + } + if (this.waitUntilCompleteTimer) { + TIMER.clearTimeout(this.waitUntilCompleteTimer); + this.waitUntilCompleteTimer = null; + } + this.runningImmediates.push(immediateID); + if (this.#browserFrame.page?.context?.browser?.settings?.debug?.traceWaitUntilComplete > 0) { + this.debugTrace.set(immediateID, new AsyncTaskManagerDebugError().stack); + } + } + /** + * Ends an immediate. + * + * @param immediateID Immediate ID. + */ + endImmediate(immediateID) { + if (this.destroyed) { + TIMER.clearImmediate(immediateID); + return; + } + const index = this.runningImmediates.indexOf(immediateID); + if (index !== -1) { + this.runningImmediates.splice(index, 1); + this.resolveWhenComplete(); + } + if (this.#browserFrame.page.context.browser.settings.debug.traceWaitUntilComplete > 0) { + this.debugTrace.delete(immediateID); + } + } + /** + * Starts an async task. + * + * @param abortHandler Abort handler. + * @returns Task ID. + */ + startTask(abortHandler) { + if (this.destroyed) { + if (abortHandler) { + abortHandler(this.destroyed); + } + throw new this.#browserFrame.window.Error(`Failed to execute 'startTask()' on 'AsyncTaskManager': The asynchronous task manager has been destroyed. This error can be thrown if scripts continue to run while a browser frame is closed.`); + } + if (this.waitUntilCompleteTimer) { + TIMER.clearTimeout(this.waitUntilCompleteTimer); + this.waitUntilCompleteTimer = null; + } + const taskID = this.newTaskID(); + this.runningTasks[taskID] = abortHandler ? abortHandler : () => { + }; + this.runningTaskCount++; + if (this.#browserFrame.page.context.browser.settings.debug.traceWaitUntilComplete > 0) { + this.debugTrace.set(taskID, new AsyncTaskManagerDebugError().stack); + } + return taskID; + } + /** + * Ends an async task. + * + * @param taskID Task ID. + */ + endTask(taskID) { + if (this.destroyed) { + return; + } + if (this.runningTasks[taskID]) { + delete this.runningTasks[taskID]; + this.runningTaskCount--; + this.resolveWhenComplete(); + } + if (this.#browserFrame.page.context.browser.settings.debug.traceWaitUntilComplete > 0) { + this.debugTrace.delete(taskID); + } + } + /** + * Returns the amount of running tasks. + * + * @returns Count. + */ + getTaskCount() { + return this.runningTaskCount; + } + /** + * Returns a new task ID. + * + * @returns Task ID. + */ + newTaskID() { + this.constructor.taskID++; + return this.constructor.taskID; + } + /** + * Resolves when complete. + */ + resolveWhenComplete() { + this.applyDebugging(); + if (this.runningTaskCount || this.runningTimers.length || this.runningImmediates.length) { + return; + } + if (this.waitUntilCompleteTimer) { + TIMER.clearTimeout(this.waitUntilCompleteTimer); + this.waitUntilCompleteTimer = null; + } + this.waitUntilCompleteTimer = TIMER.setTimeout(() => { + this.waitUntilCompleteTimer = null; + if (!this.runningTaskCount && !this.runningTimers.length && !this.runningImmediates.length) { + if (this.#debugTimeout) { + TIMER.clearTimeout(this.#debugTimeout); + } + const resolvers = this.waitUntilCompleteResolvers; + this.waitUntilCompleteResolvers = []; + for (const resolver of resolvers) { + resolver.resolve(); + } + this.destroyed = false; + } else { + this.applyDebugging(); + } + }, 1); + } + /** + * Applies debugging. + */ + applyDebugging() { + const debug = this.#browserFrame.page.context.browser.settings.debug; + if (!debug?.traceWaitUntilComplete || debug.traceWaitUntilComplete < 1) { + return; + } + if (this.#debugTimeout) { + return; + } + this.#debugTimeout = TIMER.setTimeout(() => { + this.#debugTimeout = null; + let errorMessage = `The maximum time was reached for "waitUntilComplete()". + +${this.debugTrace.size} task${this.debugTrace.size === 1 ? "" : "s"} did not end in time. + +The following traces were recorded: + +`; + let number = 1; + for (const [key, value2] of this.debugTrace.entries()) { + const type2 = typeof key === "number" ? "Task" : "Timer"; + errorMessage += `${type2} #${number} +\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E\u203E${value2.replace(/AsyncTaskManagerDebugError:{0,1}/, "").replace(/\s+at /gm, "\n> ")} + +`; + number++; + } + const error2 = new Error(errorMessage); + for (const resolver of this.waitUntilCompleteResolvers) { + resolver.reject(error2); + } + this.abortAll(true); + }, debug.traceWaitUntilComplete); + } + /** + * Aborts all tasks. + * + * @param destroy Destroy. + */ + abortAll(destroy2) { + const runningTimers = this.runningTimers; + const runningImmediates = this.runningImmediates; + const runningTasks = this.runningTasks; + if (destroy2) { + this.destroyed = true; + } + this.runningTasks = {}; + this.runningTaskCount = 0; + this.runningImmediates = []; + this.runningTimers = []; + this.debugTrace = /* @__PURE__ */ new Map(); + if (this.waitUntilCompleteTimer) { + TIMER.clearTimeout(this.waitUntilCompleteTimer); + this.waitUntilCompleteTimer = null; + } + for (const immediate of runningImmediates) { + TIMER.clearImmediate(immediate); + } + for (const timer of runningTimers) { + TIMER.clearTimeout(timer); + } + for (const key of Object.keys(runningTasks)) { + runningTasks[key](destroy2); + } + return new Promise((resolve, reject) => { + this.waitUntilCompleteResolvers.push({ resolve, reject }); + this.resolveWhenComplete(); + }); + } + }; + } +}); + +// node_modules/happy-dom/lib/base64/Base64.js +var BASE64_CHARS, Base64; +var init_Base64 = __esm({ + "node_modules/happy-dom/lib/base64/Base64.js"() { + init_DOMException(); + init_DOMExceptionNameEnum(); + BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + Base64 = class { + /** + * Creates a Base64-encoded ASCII string from a binary string (i.e., a string in which each character in the string is treated as a byte of binary data). + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/btoa + * @param data Binay data. + * @returns Base64-encoded string. + */ + static btoa(data2) { + const str = data2.toString(); + if (/[^\u0000-\u00ff]/.test(str)) { + throw new DOMException2("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.", DOMExceptionNameEnum_default.invalidCharacterError); + } + let t = ""; + let p = -6; + let a = 0; + let i = 0; + let v = 0; + let c; + while (i < str.length || p > -6) { + if (p < 0) { + if (i < str.length) { + c = str.charCodeAt(i++); + v += 8; + } else { + c = 0; + } + a = (a & 255) << 8 | c & 255; + p += 8; + } + t += BASE64_CHARS.charAt(v > 0 ? a >> p & 63 : 64); + p -= 6; + v -= 6; + } + return t; + } + /** + * Decodes a string of data which has been encoded using Base64 encoding. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/atob + * @see https://infra.spec.whatwg.org/#forgiving-base64-encode. + * @see Https://html.spec.whatwg.org/multipage/webappapis.html#btoa. + * @param data Binay string. + * @returns An ASCII string containing decoded data from encodedData. + */ + static atob(data2) { + const str = data2.toString(); + if (/[^\u0000-\u00ff]/.test(str)) { + throw new DOMException2("Failed to execute 'atob' on 'Window': The string to be decoded contains characters outside of the Latin1 range.", DOMExceptionNameEnum_default.invalidCharacterError); + } + if (/[^A-Za-z\d+/=]/.test(str) || str.length % 4 == 1) { + throw new DOMException2("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.", DOMExceptionNameEnum_default.invalidCharacterError); + } + let t = ""; + let p = -8; + let a = 0; + let c; + let d; + for (let i = 0; i < str.length; i++) { + if ((c = BASE64_CHARS.indexOf(str.charAt(i))) < 0) { + continue; + } + a = a << 6 | c & 63; + if ((p += 6) >= 0) { + d = a >> p & 255; + if (c !== 64) { + t += String.fromCharCode(d); + } + a &= 63; + p -= 8; + } + } + return t; + } + }; + } +}); + +// node_modules/happy-dom/lib/browser/enums/BrowserErrorCaptureEnum.js +var BrowserErrorCaptureEnum, BrowserErrorCaptureEnum_default; +var init_BrowserErrorCaptureEnum = __esm({ + "node_modules/happy-dom/lib/browser/enums/BrowserErrorCaptureEnum.js"() { + (function(BrowserErrorCaptureEnum2) { + BrowserErrorCaptureEnum2["tryAndCatch"] = "tryAndCatch"; + BrowserErrorCaptureEnum2["processLevel"] = "processLevel"; + BrowserErrorCaptureEnum2["disabled"] = "disabled"; + })(BrowserErrorCaptureEnum || (BrowserErrorCaptureEnum = {})); + BrowserErrorCaptureEnum_default = BrowserErrorCaptureEnum; + } +}); + +// node_modules/happy-dom/lib/file/Blob.js +var import_buffer, import_web, Blob2; +var init_Blob = __esm({ + "node_modules/happy-dom/lib/file/Blob.js"() { + import_buffer = require("buffer"); + import_web = require("stream/web"); + init_PropertySymbol(); + Blob2 = class _Blob { + type = ""; + [buffer]; + /** + * Constructor. + * + * @param [bits] Bits. + * @param [options] Options. + * @param [options.type] MIME type. + */ + constructor(bits, options2) { + const buffers = []; + if (bits) { + for (const bit of bits) { + let buffer2; + if (bit instanceof ArrayBuffer) { + buffer2 = import_buffer.Buffer.from(new Uint8Array(bit)); + } else if (bit instanceof _Blob) { + buffer2 = bit[buffer]; + } else if (bit instanceof import_buffer.Buffer) { + buffer2 = bit; + } else if (ArrayBuffer.isView(bit)) { + buffer2 = import_buffer.Buffer.from(new Uint8Array(bit.buffer, bit.byteOffset, bit.byteLength)); + } else { + buffer2 = import_buffer.Buffer.from(typeof bit === "string" ? bit : String(bit)); + } + buffers.push(buffer2); + } + } + this[buffer] = import_buffer.Buffer.concat(buffers); + if (options2 && options2.type && options2.type.match(/^[\u0020-\u007E]*$/)) { + this.type = String(options2.type).toLowerCase(); + } + } + /** + * Returns size. + * + * @returns Size. + */ + get size() { + return this[buffer].length; + } + /** + * Slices the blob. + * + * @param start Start. + * @param end End. + * @param contentType Content type. + * @returns New Blob. + */ + slice(start2 = 0, end2 = null, contentType2 = "") { + const size = this.size; + let relativeStart; + let relativeEnd; + let relativeContentType; + if (start2 === void 0) { + relativeStart = 0; + } else if (start2 < 0) { + relativeStart = Math.max(size + start2, 0); + } else { + relativeStart = Math.min(start2, size); + } + if (end2 === null) { + relativeEnd = size; + } else if (end2 < 0) { + relativeEnd = Math.max(size + end2, 0); + } else { + relativeEnd = Math.min(end2, size); + } + if (contentType2 === void 0) { + relativeContentType = ""; + } else { + relativeContentType = contentType2; + } + const span = Math.max(relativeEnd - relativeStart, 0); + const buffer2 = this[buffer]; + const slicedBuffer = buffer2.slice(relativeStart, relativeStart + span); + const blob = new _Blob([], { type: relativeContentType }); + blob[buffer] = slicedBuffer; + return blob; + } + /** + * Returns a Promise that resolves to a ArrayBuffer. + * + * @returns ArrayBuffer. + */ + // Reference: + // https://github.com/web-std/io/blob/c88170bf24f064adfbb3586a21fb76650ca5a9ab/packages/blob/src/blob.js#L139-L148 + // https://stackoverflow.com/questions/8609289/convert-a-binary-nodejs-buffer-to-javascript-arraybuffer + /** + * + */ + async arrayBuffer() { + return new Uint8Array(this[buffer]).buffer; + } + /** + * Returns a Promise that resolves to a text. + * + * @returns Text. + */ + async text() { + return this[buffer].toString(); + } + /** + * Returns returns a ReadableStream which upon reading returns the data contained within the Blob. + * + * @returns ReadableStream + */ + stream() { + const buffer2 = this[buffer]; + return new import_web.ReadableStream({ + start(controller) { + controller.enqueue(buffer2); + controller.close(); + } + }); + } + /** + * Returns the object converted to string. + * + * @returns String. + */ + toString() { + return "[object Blob]"; + } + }; + } +}); + +// node_modules/happy-dom/lib/clipboard/Clipboard.js +var Clipboard; +var init_Clipboard = __esm({ + "node_modules/happy-dom/lib/clipboard/Clipboard.js"() { + init_Blob(); + Clipboard = class { + #window; + #data = []; + /** + * Constructor. + * + * @param window Owner window. + */ + constructor(window2) { + if (!window2) { + throw new TypeError("Illegal constructor"); + } + this.#window = window2; + } + /** + * Returns data. + * + * @returns Data. + */ + async read() { + const permissionStatus = await this.#window.navigator.permissions.query({ + name: "clipboard-read" + }); + if (permissionStatus.state === "denied") { + throw new this.#window.DOMException(`Failed to execute 'read' on 'Clipboard': The request is not allowed`); + } + return this.#data; + } + /** + * Returns text. + * + * @returns Text. + */ + async readText() { + const permissionStatus = await this.#window.navigator.permissions.query({ + name: "clipboard-read" + }); + if (permissionStatus.state === "denied") { + throw new this.#window.DOMException(`Failed to execute 'readText' on 'Clipboard': The request is not allowed`); + } + let text = ""; + for (const item of this.#data) { + if (item.types.includes("text/plain")) { + const data2 = await item.getType("text/plain"); + if (typeof data2 === "string") { + text += data2; + } else { + text += await data2.text(); + } + } + } + return text; + } + /** + * Writes data. + * + * @param data Data. + */ + async write(data2) { + const permissionStatus = await this.#window.navigator.permissions.query({ + name: "clipboard-write" + }); + if (permissionStatus.state === "denied") { + throw new this.#window.DOMException(`Failed to execute 'write' on 'Clipboard': The request is not allowed`); + } + this.#data = data2; + } + /** + * Writes text. + * + * @param text Text. + */ + async writeText(text) { + const permissionStatus = await this.#window.navigator.permissions.query({ + name: "clipboard-write" + }); + if (permissionStatus.state === "denied") { + throw new this.#window.DOMException(`Failed to execute 'writeText' on 'Clipboard': The request is not allowed`); + } + this.#data = [ + new this.#window.ClipboardItem({ "text/plain": new Blob2([text], { type: "text/plain" }) }) + ]; + } + }; + } +}); + +// node_modules/happy-dom/lib/clipboard/ClipboardItem.js +var ClipboardItem; +var init_ClipboardItem = __esm({ + "node_modules/happy-dom/lib/clipboard/ClipboardItem.js"() { + init_DOMException(); + init_Blob(); + ClipboardItem = class { + presentationStyle = "unspecified"; + #data; + /** + * Constructor. + * + * @param data Data. + * @param [options] Options. + * @param [options.presentationStyle] Presentation style. + */ + constructor(data2, options2) { + this.#data = data2; + if (options2?.presentationStyle) { + this.presentationStyle = options2.presentationStyle; + } + } + /** + * Returns types. + * + * @returns Types. + */ + get types() { + return Object.keys(this.#data); + } + /** + * Returns data by type. + * + * @param type Type. + * @returns Data. + */ + async getType(type2) { + if (!this.#data[type2]) { + throw new DOMException2(`Failed to execute 'getType' on 'ClipboardItem': The type '${type2}' was not found`); + } + if (this.#data[type2] instanceof Blob2) { + return this.#data[type2]; + } + return new Blob2([await this.#data[type2]], { type: type2 }); + } + }; + } +}); + +// node_modules/happy-dom/lib/window/WindowBrowserContext.js +var WindowBrowserContext; +var init_WindowBrowserContext = __esm({ + "node_modules/happy-dom/lib/window/WindowBrowserContext.js"() { + init_PropertySymbol(); + WindowBrowserContext = class { + static [browserFrames] = /* @__PURE__ */ new Map(); + static [windowInternalId] = 0; + #window; + /** + * Browser window. + * + * @param window Window. + */ + constructor(window2) { + this.#window = window2; + } + /** + * Returns the browser settings of the window. + * + * @returns Browser settings. + */ + getSettings() { + return this.getBrowserFrame()?.page.context.browser.settings || null; + } + /** + * Returns the browser. + * + * @returns Browser. + */ + getBrowser() { + return this.getBrowserFrame()?.page.context.browser || null; + } + /** + * Returns the browser page. + * + * @returns Browser page. + */ + getBrowserPage() { + return this.getBrowserFrame()?.page || null; + } + /** + * Returns the browser context. + * + * @returns Browser context. + */ + getBrowserContext() { + return this.getBrowserFrame()?.page.context || null; + } + /** + * Returns the browser frame of the window. + * + * @returns Browser frame. + */ + getBrowserFrame() { + if (!this.#window) { + return null; + } + return this.constructor[browserFrames].get(this.#window[internalId]) || null; + } + /** + * Returns the async task manager of the window. + * + * @returns Async task manager. + */ + getAsyncTaskManager() { + return this.getBrowserFrame()?.[asyncTaskManager] || null; + } + /** + * Assigns the window to a browser frame. + * + * @param window Window. + * @param browserFrame Browser frame. + */ + static setWindowBrowserFrameRelation(window2, browserFrame) { + const browserFrames2 = this[browserFrames]; + if (window2[internalId] === -1) { + window2[internalId] = this[windowInternalId]; + this[windowInternalId]++; + } + browserFrames2.set(window2[internalId], browserFrame); + } + /** + * Assigns the window to a browser frame. + * + * @param window Window. + * @param browserFrame Browser frame. + */ + static removeWindowBrowserFrameRelation(window2) { + this[browserFrames].delete(window2[internalId]); + } + }; + } +}); + +// node_modules/happy-dom/lib/event/EventTarget.js +var EventTarget2; +var init_EventTarget = __esm({ + "node_modules/happy-dom/lib/event/EventTarget.js"() { + init_PropertySymbol(); + init_Event(); + init_EventPhaseEnum(); + init_WindowBrowserContext(); + init_BrowserErrorCaptureEnum(); + EventTarget2 = class { + [listeners] = { + capturing: /* @__PURE__ */ new Map(), + bubbling: /* @__PURE__ */ new Map() + }; + [listenerOptions] = { + capturing: /* @__PURE__ */ new Map(), + bubbling: /* @__PURE__ */ new Map() + }; + /** + * Return a default description for the EventTarget class. + */ + get [Symbol.toStringTag]() { + return "EventTarget"; + } + /** + * Adds an event listener. + * + * @param type Event type. + * @param listener Listener. + * @param options An object that specifies characteristics about the event listener.(currently only once) + * @param options.once + * @param options.signal An AbortSignal. The listener will be removed when the given AbortSignal object's abort() method is called. + */ + addEventListener(type2, listener, options2) { + options2 = typeof options2 === "boolean" ? { capture: options2 } : options2 || {}; + const eventPhase2 = options2.capture ? "capturing" : "bubbling"; + let listeners2 = this[listeners][eventPhase2].get(type2); + let listenerOptions2; + if (listeners2) { + listenerOptions2 = this[listenerOptions][eventPhase2].get(type2); + } else { + listeners2 = []; + listenerOptions2 = []; + this[listeners][eventPhase2].set(type2, listeners2); + this[listenerOptions][eventPhase2].set(type2, listenerOptions2); + } + if (listeners2.includes(listener)) { + return; + } + listeners2.push(listener); + listenerOptions2.push(options2); + if (options2.signal && !options2.signal.aborted) { + options2.signal.addEventListener("abort", () => { + this.removeEventListener(type2, listener); + }); + } + } + /** + * Adds an event listener. + * + * @param type Event type. + * @param listener Listener. + */ + removeEventListener(type2, listener) { + const bubblingListeners = this[listeners].bubbling.get(type2); + if (bubblingListeners) { + const index = bubblingListeners.indexOf(listener); + if (index !== -1) { + bubblingListeners.splice(index, 1); + this[listenerOptions].bubbling.get(type2).splice(index, 1); + return; + } + } + const capturingListeners = this[listeners].capturing.get(type2); + if (capturingListeners) { + const index = capturingListeners.indexOf(listener); + if (index !== -1) { + capturingListeners.splice(index, 1); + this[listenerOptions].capturing.get(type2).splice(index, 1); + } + } + } + /** + * Dispatches an event. + * + * @see https://www.w3.org/TR/DOM-Level-3-Events/#event-flow + * @see https://www.quirksmode.org/js/events_order.html#link4 + * @param event Event. + * @returns The return value is false if event is cancelable and at least one of the event handlers which handled this event called Event.preventDefault(). + */ + dispatchEvent(event) { + if (!(event instanceof Event2)) { + throw new this[window].TypeError(`Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'.`); + } + if (!event[dispatching] && (event[type] !== "load" || !event[target])) { + event[dispatching] = true; + event[target] = this[proxy] || this; + this.#goThroughDispatchEventPhases(event); + event[dispatching] = false; + return !(event[cancelable] && event[defaultPrevented]); + } + this.#callDispatchEventListeners(event); + return !(event[cancelable] && event[defaultPrevented]); + } + /** + * Adds an event listener. + * + * TODO: + * Was used by with IE8- and Opera. React believed Happy DOM was a legacy browser and used them, but that is no longer the case, so we should remove this method after that this is verified. + * + * @deprecated + * @param type Event type. + * @param listener Listener. + */ + attachEvent(type2, listener) { + this.addEventListener(type2.replace("on", ""), listener); + } + /** + * Removes an event listener. + * + * TODO: + * Was used by IE8- and Opera. React believed Happy DOM was a legacy browser and used them, but that is no longer the case, so we should remove this method after that this is verified. + * + * @deprecated + * @param type Event type. + * @param listener Listener. + */ + detachEvent(type2, listener) { + this.removeEventListener(type2.replace("on", ""), listener); + } + /** + * Destroys the node. + */ + [destroy]() { + this[listeners].capturing.clear(); + this[listeners].bubbling.clear(); + this[listenerOptions].capturing.clear(); + this[listenerOptions].bubbling.clear(); + } + /** + * Goes through dispatch event phases. + * + * @param event Event. + */ + #goThroughDispatchEventPhases(event) { + const composedPath = event.composedPath(); + event[eventPhase] = EventPhaseEnum_default.capturing; + for (let i = composedPath.length - 1; i >= 0; i--) { + event[currentTarget] = composedPath[i]; + composedPath[i].dispatchEvent(event); + if (event[propagationStopped] || event[immediatePropagationStopped]) { + event[eventPhase] = EventPhaseEnum_default.none; + event[currentTarget] = null; + return; + } + } + event[eventPhase] = EventPhaseEnum_default.atTarget; + event[currentTarget] = this[proxy] || this; + event[target].dispatchEvent(event); + event[eventPhase] = EventPhaseEnum_default.bubbling; + if (event[bubbles] && !event[propagationStopped] && !event[immediatePropagationStopped]) { + for (let i = 1, max = composedPath.length; i < max; i++) { + event[currentTarget] = composedPath[i]; + composedPath[i].dispatchEvent(event); + if (event[propagationStopped] || event[immediatePropagationStopped]) { + event[eventPhase] = EventPhaseEnum_default.none; + event[currentTarget] = null; + return; + } + } + } + event[eventPhase] = EventPhaseEnum_default.none; + event[currentTarget] = null; + } + /** + * Handles dispatch event listeners. + * + * @param event Event. + */ + #callDispatchEventListeners(event) { + const window2 = this[window]; + const browserSettings = window2 ? new WindowBrowserContext(window2).getSettings() : null; + const eventPhase2 = event.eventPhase === EventPhaseEnum_default.capturing ? "capturing" : "bubbling"; + const listeners2 = this[listeners][eventPhase2].get(event.type)?.slice(); + if (listeners2 && listeners2.length) { + const listenerOptions2 = this[listenerOptions][eventPhase2].get(event.type).slice(); + for (let i = 0, max = listeners2.length; i < max; i++) { + const listener = listeners2[i]; + const options2 = listenerOptions2[i]; + if (options2?.passive) { + event[isInPassiveEventListener] = true; + } + if (window2 && (this !== window2 || event.type !== "error") && !browserSettings?.disableErrorCapturing && browserSettings?.errorCapture === BrowserErrorCaptureEnum_default.tryAndCatch) { + if (listener.handleEvent) { + let result3; + try { + result3 = listener.handleEvent.call(listener, event); + } catch (error2) { + window2[dispatchError](error2); + } + if (result3 instanceof Promise) { + result3.catch((error2) => window2[dispatchError](error2)); + } + } else { + let result3; + try { + result3 = listener.call(this, event); + } catch (error2) { + window2[dispatchError](error2); + } + if (result3 instanceof Promise) { + result3.catch((error2) => window2[dispatchError](error2)); + } + } + } else { + if (listener.handleEvent) { + listener.handleEvent.call(listener, event); + } else { + listener.call(this, event); + } + } + event[isInPassiveEventListener] = false; + if (options2?.once) { + listeners2.splice(i, 1); + listenerOptions2.splice(i, 1); + this.removeEventListener(event.type, listener); + i--; + max--; + } + if (event[immediatePropagationStopped]) { + return; + } + } + } + if (event.eventPhase !== EventPhaseEnum_default.capturing) { + const onEventName = "on" + event.type.toLowerCase(); + const propertyEventListeners2 = this[propertyEventListeners]; + const hasClassDefinedHandler = !propertyEventListeners2 && Object.hasOwn(this, onEventName) && this.constructor.name !== "EventTarget"; + if (propertyEventListeners2 || hasClassDefinedHandler) { + const eventListener = propertyEventListeners2?.get(onEventName) ?? this[onEventName]; + if (typeof eventListener === "function") { + if (window2 && (this !== window2 || event.type !== "error") && !browserSettings?.disableErrorCapturing && browserSettings?.errorCapture === BrowserErrorCaptureEnum_default.tryAndCatch) { + let result3; + try { + result3 = eventListener(event); + } catch (error2) { + window2[dispatchError](error2); + } + if (result3 instanceof Promise) { + result3.catch((error2) => window2[dispatchError](error2)); + } + } else { + eventListener(event); + } + } + } + } + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/CookieChangeEvent.js +var CookieChangeEvent; +var init_CookieChangeEvent = __esm({ + "node_modules/happy-dom/lib/event/events/CookieChangeEvent.js"() { + init_Event(); + CookieChangeEvent = class extends Event2 { + changed; + deleted; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.changed = eventInit?.changed ?? []; + this.deleted = eventInit?.deleted ?? []; + } + }; + } +}); + +// node_modules/happy-dom/lib/url/URL.js +var import_url, import_buffer2, URL2; +var init_URL = __esm({ + "node_modules/happy-dom/lib/url/URL.js"() { + import_url = require("url"); + init_PropertySymbol(); + import_buffer2 = require("buffer"); + init_Blob(); + URL2 = class extends import_url.URL { + /** + * Constructor. + * + * @param url URL. + * @param [base] Base URL. + */ + constructor(url2, base) { + try { + super(url2, base); + } catch (error2) { + super("about:blank"); + if (this[window]) { + throw new this[window].TypeError("Invalid URL"); + } + throw error2; + } + } + /** + * Creates a string containing a URL representing the object given in the parameter. + * + * @param object Object. + * @returns URL. + */ + static createObjectURL(object) { + if (object instanceof Blob2) { + const blob = new import_buffer2.Blob([object[buffer]], { type: object.type }); + return super.createObjectURL(blob); + } + return super.createObjectURL(object); + } + }; + } +}); + +// node_modules/happy-dom/lib/cookie-store/CookieStore.js +var CookieStore; +var init_CookieStore = __esm({ + "node_modules/happy-dom/lib/cookie-store/CookieStore.js"() { + init_EventTarget(); + init_DOMExceptionNameEnum(); + init_CookieSameSiteEnum(); + init_CookieChangeEvent(); + init_URL(); + init_WindowBrowserContext(); + init_PropertySymbol(); + CookieStore = class extends EventTarget2 { + // Internal properties + #window; + /** + * Constructor. + * + * @param illegalConstructorSymbol Illegal constructor symbol. + * @param window Window. + */ + constructor(illegalConstructorSymbol, window2) { + super(); + if (illegalConstructorSymbol !== illegalConstructor) { + throw new TypeError("Illegal constructor"); + } + this.#window = window2; + } + /** + * Returns a cookie. + * + * @param [nameOrOptions] Name or options. + * @returns Cookie. + */ + async get(nameOrOptions) { + const cookies = await this.getAll(nameOrOptions); + return cookies.length > 0 ? cookies[0] : null; + } + /** + * Returns all cookies. + * + * @param [nameOrOptions] Name or options. + * @returns Cookies. + */ + async getAll(nameOrOptions) { + const browserFrame = new WindowBrowserContext(this.#window).getBrowserFrame(); + if (!browserFrame) { + return []; + } + const options2 = typeof nameOrOptions === "string" ? { name: nameOrOptions } : nameOrOptions || {}; + let targetURL; + if (options2.url) { + targetURL = new URL2(options2.url, this.#window.location.href); + if (targetURL.origin !== this.#window.location.origin) { + throw new this.#window.DOMException(`Failed to execute 'getAll' on 'CookieStore': URL must match the document origin`, DOMExceptionNameEnum_default.securityError); + } + } else { + targetURL = this.#window.location; + } + const internalCookies = browserFrame.page.context.cookieContainer.getCookies(targetURL, true); + const result3 = []; + for (const cookie of internalCookies) { + if (!options2.name || cookie.key === options2.name) { + result3.push(this.#convertToStoreItem(cookie)); + } + } + return result3; + } + /** + * Sets a cookie. + * + * @param nameOrOptions Name or options. + * @param [value] Value. + * @returns Promise. + */ + async set(nameOrOptions, value2) { + const browserFrame = new WindowBrowserContext(this.#window).getBrowserFrame(); + if (!browserFrame) { + return; + } + let options2; + if (typeof nameOrOptions === "string") { + if (value2 === void 0) { + throw new this.#window.TypeError(`Failed to execute 'set' on 'CookieStore': Value is required when name is provided as a string.`); + } + options2 = { name: nameOrOptions, value: value2 }; + } else { + options2 = { ...nameOrOptions, value: nameOrOptions.value ?? "" }; + } + if (!options2.name) { + throw new this.#window.TypeError(`Failed to execute 'set' on 'CookieStore': Required member name is undefined.`); + } + const originURL = this.#window.location; + let expires = null; + if (options2.expires !== void 0 && options2.expires !== null) { + expires = options2.expires instanceof Date ? options2.expires : new Date(options2.expires); + } + let sameSite = CookieSameSiteEnum_default.strict; + if (options2.sameSite) { + switch (options2.sameSite.toLowerCase()) { + case "strict": + sameSite = CookieSameSiteEnum_default.strict; + break; + case "lax": + sameSite = CookieSameSiteEnum_default.lax; + break; + case "none": + sameSite = CookieSameSiteEnum_default.none; + break; + } + } + const cookie = { + key: options2.name, + value: options2.value ?? "", + originURL, + domain: options2.domain || "", + path: options2.path || "/", + expires, + httpOnly: false, + // CookieStore API cannot set httpOnly cookies + secure: true, + sameSite + }; + const cookieContainer = browserFrame.page.context.cookieContainer; + const changedCookies = cookieContainer.addCookies([cookie]); + if (changedCookies.changed.length > 0 || changedCookies.deleted.length > 0) { + this.dispatchEvent(new CookieChangeEvent("change", { + changed: changedCookies.changed.map((cookie2) => this.#convertToStoreItem(cookie2)), + deleted: changedCookies.deleted.map((cookie2) => this.#convertToStoreItem(cookie2)) + })); + } + } + /** + * Deletes a cookie. + * + * @param nameOrOptions Name or options. + * @returns Promise. + */ + async delete(nameOrOptions) { + const options2 = typeof nameOrOptions === "string" ? { name: nameOrOptions } : nameOrOptions; + await this.set({ + name: options2.name, + value: "", + domain: options2.domain ?? void 0, + path: options2.path, + partitioned: options2.partitioned, + expires: /* @__PURE__ */ new Date(0) + }); + } + /** + * Converts an internal cookie to a CookieStore item. + * + * @param cookie Internal cookie. + * @returns CookieStore item. + */ + #convertToStoreItem(cookie) { + let sameSite = "lax"; + switch (cookie.sameSite) { + case CookieSameSiteEnum_default.strict: + sameSite = "strict"; + break; + case CookieSameSiteEnum_default.lax: + sameSite = "lax"; + break; + case CookieSameSiteEnum_default.none: + sameSite = "none"; + break; + } + return { + name: cookie.key, + value: cookie.value ?? "", + domain: cookie.domain, + path: cookie.path, + expires: cookie.expires ? cookie.expires.getTime() : null, + secure: cookie.secure, + sameSite, + partitioned: false + // Not supported yet + }; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/utilities/CSSEscaper.js +var CSSEscaper; +var init_CSSEscaper = __esm({ + "node_modules/happy-dom/lib/css/utilities/CSSEscaper.js"() { + CSSEscaper = class { + /** + * Escapes CSS. + * + * Based on: + * https://github.com/mathiasbynens/CSS.escape + * + * @param cssText CSS. + * @returns Escaped CSS. + */ + static escape(cssText2) { + if (arguments.length == 0) { + throw new TypeError("`CSS.escape` requires an argument."); + } + const returnValue2 = String(cssText2); + const length2 = returnValue2.length; + let index = -1; + let codeUnit; + let result3 = ""; + const firstCodeUnit = returnValue2.charCodeAt(0); + if ( + // If the character is the first character and is a `-` (U+002D), and + // There is no second character, […] + length2 == 1 && firstCodeUnit == 45 + ) { + return "\\" + returnValue2; + } + while (++index < length2) { + codeUnit = returnValue2.charCodeAt(index); + if (codeUnit == 0) { + result3 += "\uFFFD"; + continue; + } + if ( + // If the character is in the range [\1-\1F] (U+0001 to U+001F) or is + // U+007F, […] + codeUnit >= 1 && codeUnit <= 31 || codeUnit == 127 || // If the character is the first character and is in the range [0-9] + // (U+0030 to U+0039), […] + index == 0 && codeUnit >= 48 && codeUnit <= 57 || // If the character is the second character and is in the range [0-9] + // (U+0030 to U+0039) and the first character is a `-` (U+002D), […] + index == 1 && codeUnit >= 48 && codeUnit <= 57 && firstCodeUnit == 45 + ) { + result3 += "\\" + codeUnit.toString(16) + " "; + continue; + } + if (codeUnit >= 128 || codeUnit == 45 || codeUnit == 95 || codeUnit >= 48 && codeUnit <= 57 || codeUnit >= 65 && codeUnit <= 90 || codeUnit >= 97 && codeUnit <= 122) { + result3 += returnValue2.charAt(index); + continue; + } + result3 += "\\" + returnValue2.charAt(index); + } + return result3; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/CSSUnits.js +var CSSUnits_default; +var init_CSSUnits = __esm({ + "node_modules/happy-dom/lib/css/CSSUnits.js"() { + CSSUnits_default = [ + "Hz", + "Q", + "ch", + "cm", + "deg", + "dpcm", + "dpi", + "dppx", + "em", + "ex", + "fr", + "grad", + "in", + "kHz", + "mm", + "ms", + "number", + "pc", + "percent", + "pt", + "px", + "rad", + "rem", + "s", + "turn", + "vh", + "vmax", + "vmin", + "vw" + ]; + } +}); + +// node_modules/happy-dom/lib/css/CSSUnitValue.js +var CSSUnitValue; +var init_CSSUnitValue = __esm({ + "node_modules/happy-dom/lib/css/CSSUnitValue.js"() { + init_CSSUnits(); + CSSUnitValue = class { + unit; + value; + /** + * Constructor. + * + * @param value Value. + * @param unit Unit. + */ + constructor(value2, unit) { + if (typeof value2 !== "number") { + throw new TypeError("The provided double value is non-finite"); + } + if (!CSSUnits_default.includes(unit)) { + throw new TypeError("Invalid unit: " + unit); + } + this.value = value2; + this.unit = unit; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/CSS.js +var CSS; +var init_CSS = __esm({ + "node_modules/happy-dom/lib/css/CSS.js"() { + init_CSSEscaper(); + init_CSSUnitValue(); + CSS = class { + Hz = (value2) => new CSSUnitValue(value2, "Hz"); + Q = (value2) => new CSSUnitValue(value2, "Q"); + ch = (value2) => new CSSUnitValue(value2, "ch"); + cm = (value2) => new CSSUnitValue(value2, "cm"); + deg = (value2) => new CSSUnitValue(value2, "deg"); + dpcm = (value2) => new CSSUnitValue(value2, "dpcm"); + dpi = (value2) => new CSSUnitValue(value2, "dpi"); + dppx = (value2) => new CSSUnitValue(value2, "dppx"); + em = (value2) => new CSSUnitValue(value2, "em"); + ex = (value2) => new CSSUnitValue(value2, "ex"); + fr = (value2) => new CSSUnitValue(value2, "fr"); + grad = (value2) => new CSSUnitValue(value2, "grad"); + in = (value2) => new CSSUnitValue(value2, "in"); + kHz = (value2) => new CSSUnitValue(value2, "kHz"); + mm = (value2) => new CSSUnitValue(value2, "mm"); + ms = (value2) => new CSSUnitValue(value2, "ms"); + number = (value2) => new CSSUnitValue(value2, "number"); + pc = (value2) => new CSSUnitValue(value2, "pc"); + percent = (value2) => new CSSUnitValue(value2, "percent"); + pt = (value2) => new CSSUnitValue(value2, "pt"); + px = (value2) => new CSSUnitValue(value2, "px"); + rad = (value2) => new CSSUnitValue(value2, "rad"); + rem = (value2) => new CSSUnitValue(value2, "rem"); + s = (value2) => new CSSUnitValue(value2, "s"); + turn = (value2) => new CSSUnitValue(value2, "turn"); + vh = (value2) => new CSSUnitValue(value2, "vh"); + vmax = (value2) => new CSSUnitValue(value2, "vmax"); + vmin = (value2) => new CSSUnitValue(value2, "vmin"); + vw = (value2) => new CSSUnitValue(value2, "vw"); + /** + * Returns a Boolean indicating if the pair property-value, or the condition, given in parameter is supported. + * + * TODO: Always returns "true" for now, but it should probably be improved in the future. + * + * @param _condition Property name or condition. + * @param [_value] Value when using property name. + * @returns "true" if supported. + */ + supports(_condition, _value) { + return true; + } + /** + * Escapes a value. + * + * @param value Value to escape. + * @returns Escaped string. + */ + escape(value2) { + return CSSEscaper.escape(value2); + } + }; + } +}); + +// node_modules/happy-dom/lib/css/CSSRuleTypeEnum.js +var CSSRuleTypeEnum, CSSRuleTypeEnum_default; +var init_CSSRuleTypeEnum = __esm({ + "node_modules/happy-dom/lib/css/CSSRuleTypeEnum.js"() { + (function(CSSRuleTypeEnum2) { + CSSRuleTypeEnum2[CSSRuleTypeEnum2["containerRule"] = 0] = "containerRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["styleRule"] = 1] = "styleRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["importRule"] = 3] = "importRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["mediaRule"] = 4] = "mediaRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["fontFaceRule"] = 5] = "fontFaceRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["pageRule"] = 6] = "pageRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["keyframesRule"] = 7] = "keyframesRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["keyframeRule"] = 8] = "keyframeRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["namespaceRule"] = 10] = "namespaceRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["counterStyleRule"] = 11] = "counterStyleRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["supportsRule"] = 12] = "supportsRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["documentRule"] = 13] = "documentRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["fontFeatureValuesRule"] = 14] = "fontFeatureValuesRule"; + CSSRuleTypeEnum2[CSSRuleTypeEnum2["regionStyleRule"] = 16] = "regionStyleRule"; + })(CSSRuleTypeEnum || (CSSRuleTypeEnum = {})); + CSSRuleTypeEnum_default = CSSRuleTypeEnum; + } +}); + +// node_modules/happy-dom/lib/css/CSSRule.js +var CSSRule; +var init_CSSRule = __esm({ + "node_modules/happy-dom/lib/css/CSSRule.js"() { + init_CSSRuleTypeEnum(); + init_PropertySymbol(); + CSSRule = class { + // Static properties + static CONTAINER_RULE = CSSRuleTypeEnum_default.containerRule; + static STYLE_RULE = CSSRuleTypeEnum_default.styleRule; + static IMPORT_RULE = CSSRuleTypeEnum_default.importRule; + static MEDIA_RULE = CSSRuleTypeEnum_default.mediaRule; + static FONT_FACE_RULE = CSSRuleTypeEnum_default.fontFaceRule; + static PAGE_RULE = CSSRuleTypeEnum_default.pageRule; + static KEYFRAMES_RULE = CSSRuleTypeEnum_default.keyframesRule; + static KEYFRAME_RULE = CSSRuleTypeEnum_default.keyframeRule; + static NAMESPACE_RULE = CSSRuleTypeEnum_default.namespaceRule; + static COUNTER_STYLE_RULE = CSSRuleTypeEnum_default.counterStyleRule; + static SUPPORTS_RULE = CSSRuleTypeEnum_default.supportsRule; + static DOCUMENT_RULE = CSSRuleTypeEnum_default.documentRule; + static FONT_FEATURE_VALUES_RULE = CSSRuleTypeEnum_default.fontFeatureValuesRule; + static REGION_STYLE_RULE = CSSRuleTypeEnum_default.regionStyleRule; + // Internal properties + [window]; + [cssParser]; + // Public properties + [parentRule] = null; + [parentStyleSheet] = null; + /** + * Constructor. + * + * @param illegalConstructorSymbol Illegal constructor symbol. + * @param window Window. + * @param cssParser CSS parser. + */ + constructor(illegalConstructorSymbol, window2, cssParser2) { + if (illegalConstructorSymbol !== illegalConstructor) { + throw new TypeError("Illegal constructor"); + } + this[window] = window2; + this[cssParser] = cssParser2; + } + /** + * Returns parent rule. + * + * @returns Parent rule. + */ + get parentRule() { + return this[parentRule]; + } + /** + * Returns parent style sheet. + * + * @returns Parent style sheet. + */ + get parentStyleSheet() { + return this[parentStyleSheet]; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationValueUtility.js +var SPLIT_BY_COMMA_REGEXP, SPLIT_BY_SPACE_REGEXP, CSSStyleDeclarationValueUtility; +var init_CSSStyleDeclarationValueUtility = __esm({ + "node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationValueUtility.js"() { + SPLIT_BY_COMMA_REGEXP = /[,()]/gm; + SPLIT_BY_SPACE_REGEXP = /[()]|\s+/gm; + CSSStyleDeclarationValueUtility = class { + /** + * Splits by comma while respecting nested parentheses. + * + * @param value Value to split. + * @returns Array of parts. + */ + static splitByComma(value2) { + const parts = []; + const regexp = new RegExp(SPLIT_BY_COMMA_REGEXP); + let match; + let depth = 0; + let lastIndex = 0; + while (match = regexp.exec(value2)) { + switch (match[0]) { + case "(": + depth++; + break; + case ")": + depth--; + break; + case ",": + if (depth === 0) { + const part = value2.substring(lastIndex, match.index).trim(); + if (part) { + parts.push(part); + } + lastIndex = regexp.lastIndex; + } + break; + } + } + if (lastIndex < value2.length) { + parts.push(value2.substring(lastIndex).trim()); + } + return parts; + } + /** + * Splits by space while respecting nested parentheses. + * + * @param value Value to split. + * @returns Array of parts. + */ + static splitBySpace(value2) { + const parts = []; + const regexp = new RegExp(SPLIT_BY_SPACE_REGEXP); + let match; + let depth = 0; + let lastIndex = 0; + while (match = regexp.exec(value2)) { + switch (match[0]) { + case "(": + depth++; + break; + case ")": + depth--; + break; + default: + if (depth === 0) { + const part = value2.substring(lastIndex, match.index).trim(); + if (part) { + parts.push(part); + } + lastIndex = regexp.lastIndex; + } + break; + } + } + if (lastIndex < value2.length) { + const part = value2.substring(lastIndex).trim(); + if (part) { + parts.push(part); + } + } + return parts; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationValueParser.js +var COLOR_REGEXP, LENGTH_REGEXP, PERCENTAGE_REGEXP, DEGREE_REGEXP, URL_REGEXP, INTEGER_REGEXP, FLOAT_REGEXP, CALC_REGEXP, CSS_VARIABLE_REGEXP, FIT_CONTENT_REGEXP, GRADIENT_REGEXP, GLOBALS, COLORS, CSSStyleDeclarationValueParser; +var init_CSSStyleDeclarationValueParser = __esm({ + "node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationValueParser.js"() { + init_CSSStyleDeclarationValueUtility(); + COLOR_REGEXP = /^#([0-9a-fA-F]{3,4}){1,2}$|^rgb\(([^)]*)\)$|^rgba\(([^)]*)\)$|^hsla?\(\s*(-?\d+|-?\d*.\d+)\s*,\s*(-?\d+|-?\d*.\d+)%\s*,\s*(-?\d+|-?\d*.\d+)%\s*(,\s*(-?\d+|-?\d*.\d+)\s*)?\)|(?:(rgba?|hsla?)\((var\(\s*(--[^)\s]+)\))\))/; + LENGTH_REGEXP = /^(0|[-+]?[0-9]*\.?[0-9]+)(in|cm|em|mm|pt|pc|px|ex|rem|vh|vw|ch|vw|vh|vmin|vmax|Q)$/; + PERCENTAGE_REGEXP = /^[-+]?[0-9]*\.?[0-9]+%$/; + DEGREE_REGEXP = /^[0-9]+deg$/; + URL_REGEXP = /^url\(\s*([^)]*)\s*\)$/; + INTEGER_REGEXP = /^[0-9]+$/; + FLOAT_REGEXP = /^[0-9.]+$/; + CALC_REGEXP = /^calc\([^^)]+\)$/; + CSS_VARIABLE_REGEXP = /^var\(\s*(--[^)\s]+)\)$/; + FIT_CONTENT_REGEXP = /^fit-content\([^^)]+\)$/; + GRADIENT_REGEXP = /^((repeating-linear|linear|radial|repeating-radial|conic|repeating-conic)-gradient)\(((?:[^()]|\([^()]*\))*)\)$/; + GLOBALS = ["inherit", "initial", "unset", "revert"]; + COLORS = [ + "none", + "currentcolor", + "transparent", + "silver", + "gray", + "white", + "maroon", + "red", + "purple", + "fuchsia", + "green", + "lime", + "olive", + "yellow", + "navy", + "blue", + "teal", + "aliceblue", + "aqua", + "antiquewhite", + "aquamarine", + "azure", + "beige", + "bisque", + "black", + "blanchedalmond", + "blueviolet", + "brown", + "burlywood", + "cadetblue", + "chartreuse", + "chocolate", + "coral", + "cornflowerblue", + "cornsilk", + "crimson", + "cyan", + "darkblue", + "darkcyan", + "darkgoldenrod", + "darkgray", + "darkgreen", + "darkgrey", + "darkkhaki", + "darkmagenta", + "darkolivegreen", + "darkorange", + "darkorchid", + "darkred", + "darksalmon", + "darkseagreen", + "darkslateblue", + "darkslategray", + "darkslategrey", + "darkturquoise", + "darkviolet", + "deeppink", + "deepskyblue", + "dimgray", + "dimgrey", + "dodgerblue", + "firebrick", + "floralwhite", + "forestgreen", + "gainsboro", + "ghostwhite", + "gold", + "goldenrod", + "greenyellow", + "grey", + "honeydew", + "hotpink", + "indianred", + "indigo", + "ivory", + "khaki", + "lavender", + "lavenderblush", + "lawngreen", + "lemonchiffon", + "lightblue", + "lightcoral", + "lightcyan", + "lightgoldenrodyellow", + "lightgray", + "lightgreen", + "lightgrey", + "lightpink", + "lightsalmon", + "lightseagreen", + "lightskyblue", + "lightslategray", + "lightslategrey", + "lightsteelblue", + "lightyellow", + "limegreen", + "linen", + "magenta", + "mediumaquamarine", + "mediumblue", + "mediumorchid", + "mediumpurple", + "mediumseagreen", + "mediumslateblue", + "mediumspringgreen", + "mediumturquoise", + "mediumvioletred", + "midnightblue", + "mintcream", + "mistyrose", + "moccasin", + "navajowhite", + "oldlace", + "olivedrab", + "orange", + "orangered", + "orchid", + "palegoldenrod", + "palegreen", + "paleturquoise", + "palevioletred", + "papayawhip", + "peachpuff", + "peru", + "pink", + "plum", + "powderblue", + "rebeccapurple", + "rosybrown", + "royalblue", + "saddlebrown", + "salmon", + "sandybrown", + "seagreen", + "seashell", + "sienna", + "skyblue", + "slateblue", + "slategray", + "slategrey", + "snow", + "springgreen", + "steelblue", + "tan", + "thistle", + "tomato", + "turquoise", + "violet", + "wheat", + "whitesmoke", + "yellowgreen" + ]; + CSSStyleDeclarationValueParser = class { + /** + * Returns length. + * + * @param value Value. + * @returns Parsed value. + */ + static getLength(value2) { + if (value2 === "0") { + return "0px"; + } + const match = value2.match(LENGTH_REGEXP); + if (match) { + const number = parseFloat(match[1]); + if (isNaN(number)) { + return null; + } + const unit = match[2]; + return `${Math.round(number * 1e6) / 1e6}${unit}`; + } + return null; + } + /** + * Returns percentance. + * + * @param value Value. + * @returns Parsed value. + */ + static getPercentage(value2) { + if (value2 === "0") { + return "0%"; + } + if (PERCENTAGE_REGEXP.test(value2)) { + return value2; + } + return null; + } + /** + * Returns degree. + * + * @param value Value. + * @returns Parsed value. + */ + static getDegree(value2) { + if (value2 === "0") { + return "0deg"; + } + if (DEGREE_REGEXP.test(value2)) { + return value2; + } + return null; + } + /** + * Returns calc. + * + * @param value Value. + * @returns Parsed value. + */ + static getCalc(value2) { + if (CALC_REGEXP.test(value2)) { + return value2; + } + return null; + } + /** + * Returns fit content. + * + * @param value Value. + * @returns Parsed value. + */ + static getFitContent(value2) { + const lowerValue = value2.toLowerCase(); + if (lowerValue === "auto" || lowerValue === "max-content" || lowerValue === "min-content" || lowerValue === "fit-content") { + return lowerValue; + } + if (FIT_CONTENT_REGEXP.test(lowerValue)) { + return lowerValue; + } + return null; + } + /** + * Returns measurement. + * + * @param value Value. + * @returns Parsed value. + */ + static getMeasurement(value2) { + return this.getLength(value2) || this.getPercentage(value2) || this.getCalc(value2); + } + /** + * Returns measurement or auto, min-content, max-content or fit-content. + * + * @param value Value. + * @returns Parsed value. + */ + static getContentMeasurement(value2) { + return this.getFitContent(value2) || this.getMeasurement(value2); + } + /** + * Returns measurement or auto, min-content, max-content or fit-content. + * + * @param value Value. + * @returns Parsed value. + */ + static getAutoMeasurement(value2) { + if (value2.toLocaleLowerCase() === "auto") { + return "auto"; + } + return this.getMeasurement(value2); + } + /** + * Returns integer. + * + * @param value Value. + * @returns Parsed value. + */ + static getInteger(value2) { + if (INTEGER_REGEXP.test(value2)) { + return value2; + } + return null; + } + /** + * Returns float. + * + * @param value Value. + * @returns Parsed value. + */ + static getFloat(value2) { + if (FLOAT_REGEXP.test(value2)) { + const number = parseFloat(value2); + if (isNaN(number)) { + return null; + } + return String(Math.round(number * 1e6) / 1e6); + } + return null; + } + /** + * Returns gradient. + * + * @param value Value. + * @returns Parsed value. + */ + static getGradient(value2) { + const match = value2.match(GRADIENT_REGEXP); + if (match) { + const args = match[3].trim(); + const parts = CSSStyleDeclarationValueUtility.splitByComma(args); + return `${match[1]}(${parts.join(", ")})`; + } + return null; + } + /** + * Returns color. + * + * @param value Value. + * @returns Parsed value. + */ + static getColor(value2) { + const lowerValue = value2.toLowerCase(); + if (COLORS.includes(lowerValue)) { + return lowerValue; + } + if (COLOR_REGEXP.test(value2)) { + return value2.replace(/,([^ ])/g, ", $1"); + } + return null; + } + /** + * Returns URL. + * + * Based on: + * https://github.com/jsdom/cssstyle/blob/master/lib/parsers.js#L222 + * + * @param value Value. + * @returns Parsed value. + */ + static getURL(value2) { + if (!value2) { + return null; + } + if (value2.toLowerCase() === "none") { + return "none"; + } + const result3 = URL_REGEXP.exec(value2); + if (!result3) { + return null; + } + let url2 = result3[1].trim(); + if ((url2[0] === '"' || url2[0] === "'") && url2[0] !== url2[url2.length - 1]) { + return null; + } + if (url2[0] === '"' || url2[0] === "'") { + url2 = url2.substring(1, url2.length - 1); + } + for (let i = 0; i < url2.length; i++) { + switch (url2[i]) { + case "(": + case ")": + case " ": + case " ": + case "\n": + case "'": + case '"': + return null; + case "\\": + i++; + break; + } + } + return `url("${url2}")`; + } + /** + * Returns global initial value. + * + * @param value Value. + * @returns Parsed value. + */ + static getInitial(value2) { + return value2.toLowerCase() === "initial" ? "initial" : null; + } + /** + * Returns CSS variable. + * + * @param value Value. + * @returns Parsed value. + */ + static getVariable(value2) { + const cssVariableMatch = value2.match(CSS_VARIABLE_REGEXP); + if (cssVariableMatch) { + return `var(${cssVariableMatch[1]})`; + } + return null; + } + /** + * Returns global. + * + * @param value Value. + * @returns Parsed value. + */ + static getGlobal(value2) { + const lowerValue = value2.toLowerCase(); + return GLOBALS.includes(lowerValue) ? lowerValue : null; + } + /** + * Returns global, unless it is not set to 'initial' as it is sometimes treated different. + * + * @param value Value. + * @returns Parsed value. + */ + static getGlobalExceptInitial(value2) { + const lowerValue = value2.toLowerCase(); + return lowerValue !== "initial" && GLOBALS.includes(lowerValue) ? lowerValue : null; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertySetParser.js +var RECT_REGEXP, SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP, SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP, WHITE_SPACE_GLOBAL_REGEXP, BORDER_STYLE, BORDER_WIDTH, BORDER_COLLAPSE, BACKGROUND_REPEAT, BACKGROUND_ORIGIN, BACKGROUND_CLIP, BACKGROUND_ATTACHMENT, FLEX_BASIS, CLEAR, FLOAT, SYSTEM_FONT, FONT_WEIGHT, FONT_STYLE, FONT_SIZE, FONT_STRETCH, DISPLAY, BORDER_IMAGE_REPEAT, TEXT_TRANSFORM, VISIBILITY, CSSStyleDeclarationPropertySetParser; +var init_CSSStyleDeclarationPropertySetParser = __esm({ + "node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertySetParser.js"() { + init_CSSStyleDeclarationValueParser(); + init_CSSStyleDeclarationValueUtility(); + RECT_REGEXP = /^rect\((.*)\)$/i; + SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP = /,(?=(?:(?:(?!\))[\s\S])*\()|[^\(\)]*$)/; + SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP = /\s+(?=(?:(?:(?!\))[\s\S])*\()|[^\(\)]*$)/; + WHITE_SPACE_GLOBAL_REGEXP = /\s+/gm; + BORDER_STYLE = [ + "none", + "hidden", + "dotted", + "dashed", + "solid", + "double", + "groove", + "ridge", + "inset", + "outset" + ]; + BORDER_WIDTH = ["thin", "medium", "thick"]; + BORDER_COLLAPSE = ["separate", "collapse"]; + BACKGROUND_REPEAT = ["repeat", "repeat-x", "repeat-y", "no-repeat"]; + BACKGROUND_ORIGIN = ["border-box", "padding-box", "content-box"]; + BACKGROUND_CLIP = ["border-box", "padding-box", "content-box"]; + BACKGROUND_ATTACHMENT = ["scroll", "fixed"]; + FLEX_BASIS = ["auto", "fill", "content"]; + CLEAR = ["none", "left", "right", "both"]; + FLOAT = ["none", "left", "right", "inline-start", "inline-end"]; + SYSTEM_FONT = ["caption", "icon", "menu", "message-box", "small-caption", "status-bar"]; + FONT_WEIGHT = ["normal", "bold", "bolder", "lighter"]; + FONT_STYLE = ["normal", "italic", "oblique"]; + FONT_SIZE = [ + "xx-small", + "x-small", + "small", + "medium", + "large", + "x-large", + "xx-large", + "xxx-large", + "smaller", + "larger" + ]; + FONT_STRETCH = [ + "ultra-condensed", + "extra-condensed", + "condensed", + "semi-condensed", + "normal", + "semi-expanded", + "expanded", + "extra-expanded", + "ultra-expanded" + ]; + DISPLAY = [ + /* Legacy values */ + "block", + "inline", + "inline-block", + "flex", + "inline-flex", + "grid", + "inline-grid", + "flow-root", + /* Box generation */ + "none", + "contents", + /* Two-value syntax */ + "block flow", + "inline flow", + "inline flow-root", + "block flex", + "inline flex", + "block grid", + "inline grid", + "block flow-root", + /* Other values */ + "table", + "table-row", + "list-item" + ]; + BORDER_IMAGE_REPEAT = ["stretch", "repeat", "round", "space"]; + TEXT_TRANSFORM = [ + "capitalize", + "uppercase", + "lowercase", + "none", + "full-width", + "full-size-kana" + ]; + VISIBILITY = ["visible", "hidden", "collapse"]; + CSSStyleDeclarationPropertySetParser = class { + /** + * Returns border collapse. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderCollapse(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-collapse": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_COLLAPSE.includes(lowerValue)) { + return { "border-collapse": { value: lowerValue, important } }; + } + return null; + } + /** + * Returns display. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getDisplay(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { display: { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || DISPLAY.includes(lowerValue)) { + return { display: { value: lowerValue, important } }; + } + return null; + } + /** + * Returns direction. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getDirection(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { direction: { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "ltr" || lowerValue === "rtl") { + return { direction: { value: lowerValue, important } }; + } + return null; + } + /** + * Returns letter spacing. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getLetterSpacing(value2, important) { + const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); + return parsedValue ? { "letter-spacing": { value: parsedValue, important } } : null; + } + /** + * Returns word spacing. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getWordSpacing(value2, important) { + const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); + return parsedValue ? { "word-spacing": { value: parsedValue, important } } : null; + } + /** + * Returns text indent. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getTextIndent(value2, important) { + const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); + return parsedValue ? { "text-indent": { value: parsedValue, important } } : null; + } + /** + * Returns width. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getWidth(value2, important) { + const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); + return parsedValue ? { width: { value: parsedValue, important } } : null; + } + /** + * Returns height. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getHeight(value2, important) { + const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); + return parsedValue ? { height: { value: parsedValue, important } } : null; + } + /** + * Returns top. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getTop(value2, important) { + const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); + return parsedValue ? { top: { value: parsedValue, important } } : null; + } + /** + * Returns top. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getRight(value2, important) { + const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); + return parsedValue ? { right: { value: parsedValue, important } } : null; + } + /** + * Returns top. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBottom(value2, important) { + const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); + return parsedValue ? { bottom: { value: parsedValue, important } } : null; + } + /** + * Returns top. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getLeft(value2, important) { + const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getContentMeasurement(value2); + return parsedValue ? { left: { value: parsedValue, important } } : null; + } + /** + * Returns clear. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getClear(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { clear: { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || CLEAR.includes(lowerValue)) { + return { clear: { value: lowerValue, important } }; + } + return null; + } + /** + * Returns clip + * + * Based on: + * https://github.com/jsdom/cssstyle/blob/master/lib/properties/clip.js + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getClip(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { clip: { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "auto") { + return { clip: { value: lowerValue, important } }; + } + const matches = lowerValue.match(RECT_REGEXP); + if (!matches) { + return null; + } + const parts = matches[1].split(/\s*,\s*/); + if (parts.length !== 4) { + return null; + } + for (const part of parts) { + if (!CSSStyleDeclarationValueParser.getMeasurement(part)) { + return null; + } + } + return { clip: { value: value2, important } }; + } + /** + * Returns float. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFloat(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { float: { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FLOAT.includes(lowerValue)) { + return { float: { value: lowerValue, important } }; + } + return null; + } + /** + * Returns float. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getCSSFloat(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "css-float": { value: variable, important } }; + } + const float = this.getFloat(value2, important); + return float ? { "css-float": float["float"] } : null; + } + /** + * Returns outline. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getOutline(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { outline: { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getOutlineColor(globalValue, important), + ...this.getOutlineStyle(globalValue, important), + ...this.getOutlineWidth(globalValue, important) + }; + } + const properties = { + ...this.getOutlineColor("initial", important), + ...this.getOutlineStyle("initial", important), + ...this.getOutlineWidth("initial", important) + }; + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + for (const part of parts) { + const width2 = this.getOutlineWidth(part, important); + const style2 = this.getOutlineStyle(part, important); + const color = this.getOutlineColor(part, important); + if (width2 === null && style2 === null && color === null) { + return null; + } + Object.assign(properties, width2, style2, color); + } + return properties; + } + /** + * Returns outline color. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getOutlineColor(value2, important) { + const color = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); + return color ? { + "outline-color": { value: color, important } + } : null; + } + /** + * Returns outline offset. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getOutlineOffset(value2, important) { + const parsedValue = CSSStyleDeclarationValueParser.getVariable(value2) || CSSStyleDeclarationValueParser.getLength(value2); + return parsedValue ? { "outline-offset": { value: parsedValue, important } } : null; + } + /** + * Returns outline style. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getOutlineStyle(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "outline-style": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_STYLE.includes(lowerValue)) { + return { + "outline-style": { value: lowerValue, important } + }; + } + return null; + } + /** + * Returns outline width. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getOutlineWidth(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "outline-width": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + const parsedValue = BORDER_WIDTH.includes(lowerValue) || CSSStyleDeclarationValueParser.getGlobal(lowerValue) ? lowerValue : CSSStyleDeclarationValueParser.getLength(value2); + if (parsedValue) { + return { + "outline-width": { value: parsedValue, important } + }; + } + return null; + } + /** + * Returns border. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBorder(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { border: { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBorderWidth(globalValue, important), + ...this.getBorderStyle(globalValue, important), + ...this.getBorderColor(globalValue, important), + ...this.getBorderImage(globalValue, important) + }; + } + const properties = { + ...this.getBorderWidth("initial", important), + ...this.getBorderStyle("initial", important), + ...this.getBorderColor("initial", important), + ...this.getBorderImage("initial", important) + }; + const parts = value2.replace(/\s*,\s*/g, ",").split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + for (const part of parts) { + const width2 = this.getBorderWidth(part, important); + const style2 = this.getBorderStyle(part, important); + const color = this.getBorderColor(part, important); + if (width2 === null && style2 === null && color === null) { + return null; + } + Object.assign(properties, width2, style2, color); + } + return properties; + } + /** + * Returns border width. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderWidth(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-width": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBorderTopWidth(globalValue, important), + ...this.getBorderRightWidth(globalValue, important), + ...this.getBorderBottomWidth(globalValue, important), + ...this.getBorderLeftWidth(globalValue, important) + }; + } + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + const top2 = this.getBorderTopWidth(parts[0], important); + const right = this.getBorderRightWidth(parts[1] || parts[0], important); + const bottom = this.getBorderBottomWidth(parts[2] || parts[0], important); + const left = this.getBorderLeftWidth(parts[3] || parts[1] || parts[0], important); + if (!top2 || !right || !bottom || !left) { + return null; + } + return { + ...top2, + ...right, + ...bottom, + ...left + }; + } + /** + * Returns border style. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderStyle(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-style": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBorderTopStyle(globalValue, important), + ...this.getBorderRightStyle(globalValue, important), + ...this.getBorderBottomStyle(globalValue, important), + ...this.getBorderLeftStyle(globalValue, important) + }; + } + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + const top2 = this.getBorderTopStyle(parts[0], important); + const right = this.getBorderRightStyle(parts[1] || parts[0], important); + const bottom = this.getBorderBottomStyle(parts[2] || parts[0], important); + const left = this.getBorderLeftStyle(parts[3] || parts[1] || parts[0], important); + if (!top2 || !right || !bottom || !left) { + return null; + } + return { + ...top2, + ...right, + ...bottom, + ...left + }; + } + /** + * Returns border color. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderColor(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-color": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBorderTopColor(globalValue, important), + ...this.getBorderRightColor(globalValue, important), + ...this.getBorderBottomColor(globalValue, important), + ...this.getBorderLeftColor(globalValue, important) + }; + } + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + const top2 = this.getBorderTopColor(parts[0], important); + const right = this.getBorderRightColor(parts[1] || parts[0], important); + const bottom = this.getBorderBottomColor(parts[2] || parts[0], important); + const left = this.getBorderLeftColor(parts[3] || parts[1] || parts[0], important); + if (!top2 || !right || !bottom || !left) { + return null; + } + return { + ...top2, + ...right, + ...bottom, + ...left + }; + } + /** + * Returns border image. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderImage(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-image": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBorderImageSource(globalValue, important), + ...this.getBorderImageSlice(globalValue, important), + ...this.getBorderImageWidth(globalValue, important), + ...this.getBorderImageOutset(globalValue, important), + ...this.getBorderImageRepeat(globalValue, important) + }; + } + let parsedValue = value2.replace(/\s\/\s/g, "/"); + const sourceMatch = parsedValue.match(/\s*([a-zA-Z-]+\([^)]*\))\s*/); + if (sourceMatch) { + parsedValue = parsedValue.replace(sourceMatch[0], ""); + } + const parts = parsedValue.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + if (sourceMatch) { + parts.push(sourceMatch[1]); + } + const properties = { + ...this.getBorderImageSource("none", important), + ...this.getBorderImageSlice("100%", important), + ...this.getBorderImageWidth("1", important), + ...this.getBorderImageOutset("0", important), + ...this.getBorderImageRepeat("stretch", important) + }; + for (let i = 0, max = parts.length; i < max; i++) { + const part = parts[i]; + const previousPart = i > 0 ? parts[i - 1] : ""; + if (!part.startsWith("url") && part.includes("/")) { + const [slice, width2, outset] = part.split("/"); + const borderImageSlice = this.getBorderImageSlice(`${previousPart} ${slice}`, important) || this.getBorderImageSlice(slice, important); + const borderImageWidth = this.getBorderImageWidth(width2, important); + const borderImageOutset = outset && this.getBorderImageOutset(outset, important); + if (!borderImageSlice || !borderImageWidth || borderImageOutset === null) { + return null; + } + Object.assign(properties, borderImageSlice, borderImageWidth, borderImageOutset); + } else { + const slice = this.getBorderImageSlice(`${previousPart} ${part}`, important) || this.getBorderImageSlice(part, important); + const source = this.getBorderImageSource(part, important); + const repeat = this.getBorderImageRepeat(part, important); + if (!slice && !source && !repeat) { + return null; + } + Object.assign(properties, slice, source, repeat); + } + } + return properties; + } + /** + * Returns border source. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderImageSource(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-image-source": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "none") { + return { + "border-image-source": { + important, + value: lowerValue + } + }; + } + const parsedValue = CSSStyleDeclarationValueParser.getURL(value2) || CSSStyleDeclarationValueParser.getGradient(value2); + if (!parsedValue) { + return null; + } + return { + "border-image-source": { + important, + value: parsedValue + } + }; + } + /** + * Returns border slice. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderImageSlice(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-image-slice": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { + return { + "border-image-slice": { + important, + value: lowerValue + } + }; + } + if (lowerValue !== lowerValue.trim()) { + return null; + } + const regexp = /(fill)|(calc\([^^)]+\))|([0-9]+%)|([0-9]+)/g; + const values2 = []; + let match; + while (match = regexp.exec(lowerValue)) { + const previousCharacter = lowerValue[match.index - 1]; + const nextCharacter = lowerValue[match.index + match[0].length]; + if (previousCharacter && previousCharacter !== " " || nextCharacter && nextCharacter !== " ") { + return null; + } + const fill = match[1] && "fill"; + const calc = match[2] && CSSStyleDeclarationValueParser.getCalc(match[2]); + const percentage = match[3] && CSSStyleDeclarationValueParser.getPercentage(match[3]); + const integer = match[4] && CSSStyleDeclarationValueParser.getInteger(match[4]); + if (!fill && !calc && !percentage && !integer) { + return null; + } + values2.push(fill || calc || percentage || integer); + } + if (!values2.length || values2.length > 4) { + return null; + } + return { + "border-image-slice": { + important, + value: values2.join(" ") + } + }; + } + /** + * Returns border width. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderImageWidth(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-image-width": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { + return { + "border-image-width": { + important, + value: lowerValue + } + }; + } + const parts = lowerValue.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + if (parts.length > 4) { + return null; + } + for (const part of parts) { + if (!CSSStyleDeclarationValueParser.getInteger(part) && !CSSStyleDeclarationValueParser.getAutoMeasurement(part)) { + return null; + } + } + return { + "border-image-width": { + important, + value: value2 + } + }; + } + /** + * Returns border outset. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderImageOutset(value2, important) { + if (value2 === "0") { + return { + "border-image-outset": { + important, + value: value2 + } + }; + } + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-image-outset": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { + return { + "border-image-outset": { + important, + value: lowerValue + } + }; + } + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + if (parts.length > 4) { + return null; + } + const newParts = []; + for (const part of parts) { + const parsedValue = CSSStyleDeclarationValueParser.getLength(part) || CSSStyleDeclarationValueParser.getFloat(part); + if (!parsedValue) { + return null; + } + newParts.push(parsedValue === "0px" ? "0" : parsedValue); + } + return { + "border-image-outset": { + important, + value: newParts.join(" ") + } + }; + } + /** + * Returns border repeat. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderImageRepeat(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-image-repeat": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { + return { + "border-image-repeat": { + important, + value: lowerValue + } + }; + } + const parts = lowerValue.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + if (parts.length > 2) { + return null; + } + for (const part of parts) { + if (!BORDER_IMAGE_REPEAT.includes(part)) { + return null; + } + } + return { + "border-image-repeat": { + important, + value: value2 + } + }; + } + /** + * Returns border width. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderTopWidth(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-top-width": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + const parsedValue = BORDER_WIDTH.includes(lowerValue) || CSSStyleDeclarationValueParser.getGlobal(lowerValue) ? lowerValue : CSSStyleDeclarationValueParser.getLength(value2); + if (parsedValue) { + return { + "border-top-width": { value: parsedValue, important } + }; + } + return null; + } + /** + * Returns border width. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderRightWidth(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-right-width": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + const parsedValue = BORDER_WIDTH.includes(lowerValue) || CSSStyleDeclarationValueParser.getGlobal(lowerValue) ? lowerValue : CSSStyleDeclarationValueParser.getLength(value2); + if (parsedValue) { + return { + "border-right-width": { value: parsedValue, important } + }; + } + return null; + } + /** + * Returns border width. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderBottomWidth(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-bottom-width": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + const parsedValue = BORDER_WIDTH.includes(lowerValue) || CSSStyleDeclarationValueParser.getGlobal(lowerValue) ? lowerValue : CSSStyleDeclarationValueParser.getLength(value2); + if (parsedValue) { + return { + "border-bottom-width": { value: parsedValue, important } + }; + } + return null; + } + /** + * Returns border width. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderLeftWidth(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-left-width": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + const parsedValue = BORDER_WIDTH.includes(lowerValue) || CSSStyleDeclarationValueParser.getGlobal(lowerValue) ? lowerValue : CSSStyleDeclarationValueParser.getLength(value2); + if (parsedValue) { + return { + "border-left-width": { value: parsedValue, important } + }; + } + return null; + } + /** + * Returns border style. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderTopStyle(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-top-style": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_STYLE.includes(lowerValue)) { + return { + "border-top-style": { value: lowerValue, important } + }; + } + return null; + } + /** + * Returns border style. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderRightStyle(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-right-style": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_STYLE.includes(lowerValue)) { + return { + "border-right-style": { value: lowerValue, important } + }; + } + return null; + } + /** + * Returns border style. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderBottomStyle(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-bottom-style": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_STYLE.includes(lowerValue)) { + return { + "border-bottom-style": { value: lowerValue, important } + }; + } + return null; + } + /** + * Returns border style. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderLeftStyle(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-left-style": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BORDER_STYLE.includes(lowerValue)) { + return { + "border-left-style": { value: lowerValue, important } + }; + } + return null; + } + /** + * Returns border color. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderTopColor(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-top-color": { value: variable, important } }; + } + const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); + return color ? { + "border-top-color": { value: color, important } + } : null; + } + /** + * Returns border color. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderRightColor(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-right-color": { value: variable, important } }; + } + const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); + return color ? { + "border-right-color": { value: color, important } + } : null; + } + /** + * Returns border color. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderBottomColor(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-bottom-color": { value: variable, important } }; + } + const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); + return color ? { + "border-bottom-color": { value: color, important } + } : null; + } + /** + * Returns border color. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBorderLeftColor(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-left-color": { value: variable, important } }; + } + const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); + return color ? { + "border-left-color": { value: color, important } + } : null; + } + /** + * Returns border radius. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBorderRadius(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-radius": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBorderTopLeftRadius(globalValue, important), + ...this.getBorderTopRightRadius(globalValue, important), + ...this.getBorderBottomRightRadius(globalValue, important), + ...this.getBorderBottomLeftRadius(globalValue, important) + }; + } + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + const topLeft = this.getBorderTopLeftRadius(parts[0], important); + const topRight = this.getBorderTopRightRadius(parts[1] || parts[0], important); + const bottomRight = this.getBorderBottomRightRadius(parts[2] || parts[0], important); + const bottomLeft = this.getBorderBottomLeftRadius(parts[3] || parts[1] || parts[0], important); + if (!topLeft || !topRight || !bottomRight || !bottomLeft) { + return null; + } + return { + ...topLeft, + ...topRight, + ...bottomRight, + ...bottomLeft + }; + } + /** + * Returns border radius. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBorderTopLeftRadius(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-top-left-radius": { value: variable, important } }; + } + const radius = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); + return radius ? { "border-top-left-radius": { important, value: radius } } : null; + } + /** + * Returns border radius. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBorderTopRightRadius(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-top-right-radius": { value: variable, important } }; + } + const radius = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); + return radius ? { "border-top-right-radius": { important, value: radius } } : null; + } + /** + * Returns border radius. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBorderBottomRightRadius(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-bottom-right-radius": { value: variable, important } }; + } + const radius = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); + return radius ? { "border-bottom-right-radius": { important, value: radius } } : null; + } + /** + * Returns border radius. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBorderBottomLeftRadius(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-bottom-left-radius": { value: variable, important } }; + } + const radius = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); + return radius ? { "border-bottom-left-radius": { important, value: radius } } : null; + } + /** + * Returns border top, right, bottom or left. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBorderTop(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-top": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBorderTopWidth(globalValue, important), + ...this.getBorderTopStyle(globalValue, important), + ...this.getBorderTopColor(globalValue, important) + }; + } + const properties = { + ...this.getBorderTopWidth("initial", important), + ...this.getBorderTopStyle("initial", important), + ...this.getBorderTopColor("initial", important) + }; + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + for (const part of parts) { + const width2 = this.getBorderTopWidth(part, important); + const style2 = this.getBorderTopStyle(part, important); + const color = this.getBorderTopColor(part, important); + if (width2 === null && style2 === null && color === null) { + return null; + } + Object.assign(properties, width2, style2, color); + } + return properties; + } + /** + * Returns border top, right, bottom or left. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBorderRight(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-right": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBorderRightWidth(globalValue, important), + ...this.getBorderRightStyle(globalValue, important), + ...this.getBorderRightColor(globalValue, important) + }; + } + const properties = { + ...this.getBorderRightWidth("initial", important), + ...this.getBorderRightStyle("initial", important), + ...this.getBorderRightColor("initial", important) + }; + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + for (const part of parts) { + const width2 = this.getBorderRightWidth(part, important); + const style2 = this.getBorderRightStyle(part, important); + const color = this.getBorderRightColor(part, important); + if (width2 === null && style2 === null && color === null) { + return null; + } + Object.assign(properties, width2, style2, color); + } + return properties; + } + /** + * Returns border top, right, bottom or left. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBorderBottom(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-bottom": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBorderBottomWidth(globalValue, important), + ...this.getBorderBottomStyle(globalValue, important), + ...this.getBorderBottomColor(globalValue, important) + }; + } + const properties = { + ...this.getBorderBottomWidth("initial", important), + ...this.getBorderBottomStyle("initial", important), + ...this.getBorderBottomColor("initial", important) + }; + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + for (const part of parts) { + const width2 = this.getBorderBottomWidth(part, important); + const style2 = this.getBorderBottomStyle(part, important); + const color = this.getBorderBottomColor(part, important); + if (width2 === null && style2 === null && color === null) { + return null; + } + Object.assign(properties, width2, style2, color); + } + return properties; + } + /** + * Returns border top, right, bottom or left. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBorderLeft(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "border-left": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBorderLeftWidth(globalValue, important), + ...this.getBorderLeftStyle(globalValue, important), + ...this.getBorderLeftColor(globalValue, important) + }; + } + const properties = { + ...this.getBorderLeftWidth("initial", important), + ...this.getBorderLeftStyle("initial", important), + ...this.getBorderLeftColor("initial", important) + }; + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + for (const part of parts) { + const width2 = this.getBorderLeftWidth(part, important); + const style2 = this.getBorderLeftStyle(part, important); + const color = this.getBorderLeftColor(part, important); + if (width2 === null && style2 === null && color === null) { + return null; + } + Object.assign(properties, width2, style2, color); + } + return properties; + } + /** + * Returns padding. + * + * @param value Value. + * @param important Important. + */ + static getPadding(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { padding: { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getPaddingTop(globalValue, important), + ...this.getPaddingRight(globalValue, important), + ...this.getPaddingBottom(globalValue, important), + ...this.getPaddingLeft(globalValue, important) + }; + } + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + const top2 = this.getPaddingTop(parts[0], important); + const right = this.getPaddingRight(parts[1] || parts[0], important); + const bottom = this.getPaddingBottom(parts[2] || parts[0], important); + const left = this.getPaddingLeft(parts[3] || parts[1] || parts[0], important); + if (!top2 || !right || !bottom || !left) { + return null; + } + return { + ...top2, + ...right, + ...bottom, + ...left + }; + } + /** + * Returns padding top. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getPaddingTop(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "padding-top": { value: variable, important } }; + } + const padding = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); + return padding ? { "padding-top": { value: padding, important } } : null; + } + /** + * Returns padding right. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getPaddingRight(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "padding-right": { value: variable, important } }; + } + const padding = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); + return padding ? { "padding-right": { value: padding, important } } : null; + } + /** + * Returns padding bottom. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getPaddingBottom(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "padding-bottom": { value: variable, important } }; + } + const padding = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); + return padding ? { "padding-bottom": { value: padding, important } } : null; + } + /** + * Returns padding left. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getPaddingLeft(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "padding-left": { value: variable, important } }; + } + const padding = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); + return padding ? { "padding-left": { value: padding, important } } : null; + } + /** + * Returns margin. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getMargin(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { margin: { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getMarginTop(globalValue, important), + ...this.getMarginRight(globalValue, important), + ...this.getMarginBottom(globalValue, important), + ...this.getMarginLeft(globalValue, important) + }; + } + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + const top2 = this.getMarginTop(parts[0], important); + const right = this.getMarginRight(parts[1] || parts[0], important); + const bottom = this.getMarginBottom(parts[2] || parts[0], important); + const left = this.getMarginLeft(parts[3] || parts[1] || parts[0], important); + if (!top2 || !right || !bottom || !left) { + return null; + } + return { + ...top2, + ...right, + ...bottom, + ...left + }; + } + /** + * Returns margin top. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getMarginTop(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "margin-top": { value: variable, important } }; + } + const margin = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getAutoMeasurement(value2); + return margin ? { "margin-top": { value: margin, important } } : null; + } + /** + * Returns margin right. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getMarginRight(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "margin-right": { value: variable, important } }; + } + const margin = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getAutoMeasurement(value2); + return margin ? { "margin-right": { value: margin, important } } : null; + } + /** + * Returns margin right. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getMarginBottom(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "margin-bottom": { value: variable, important } }; + } + const margin = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getAutoMeasurement(value2); + return margin ? { "margin-bottom": { value: margin, important } } : null; + } + /** + * Returns margin left. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getMarginLeft(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "margin-left": { value: variable, important } }; + } + const margin = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getAutoMeasurement(value2); + return margin ? { "margin-left": { value: margin, important } } : null; + } + /** + * Returns flex. + * + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getFlex(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { flex: { value: variable, important } }; + } + const lowerValue = value2.trim().toLowerCase(); + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getFlexGrow(globalValue, important), + ...this.getFlexShrink(globalValue, important), + ...this.getFlexBasis(globalValue, important) + }; + } + switch (lowerValue) { + case "none": + return { + ...this.getFlexGrow("0", important), + ...this.getFlexShrink("0", important), + ...this.getFlexBasis("auto", important) + }; + case "auto": + return { + ...this.getFlexGrow("1", important), + ...this.getFlexShrink("1", important), + ...this.getFlexBasis("auto", important) + }; + } + const measurement = CSSStyleDeclarationValueParser.getContentMeasurement(lowerValue); + if (measurement) { + return { + ...this.getFlexGrow("1", important), + ...this.getFlexShrink("1", important), + ...this.getFlexBasis(measurement, important) + }; + } + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + const flexGrow = this.getFlexGrow(parts[0], important); + const flexShrink = this.getFlexShrink(parts[1] || "1", important); + const flexBasis = this.getFlexBasis(parts[2] || "0%", important); + if (!flexGrow || !flexShrink || !flexBasis) { + return null; + } + return { + ...flexGrow, + ...flexShrink, + ...flexBasis + }; + } + /** + * Returns flex basis. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFlexBasis(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "flex-basis": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FLEX_BASIS.includes(lowerValue)) { + return { "flex-basis": { value: lowerValue, important } }; + } + const measurement = CSSStyleDeclarationValueParser.getContentMeasurement(lowerValue); + return measurement ? { "flex-basis": { value: measurement, important } } : null; + } + /** + * Returns flex shrink. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFlexShrink(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "flex-shrink": { value: variable, important } }; + } + const parsedValue = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getFloat(value2); + return parsedValue ? { "flex-shrink": { value: parsedValue, important } } : null; + } + /** + * Returns flex grow. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFlexGrow(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "flex-grow": { value: variable, important } }; + } + const parsedValue = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getFloat(value2); + return parsedValue ? { "flex-grow": { value: parsedValue, important } } : null; + } + /** + * Returns background. + * + * @param name Name. + * @param value Value. + * @param important Important. + * @returns Property values. + */ + static getBackground(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { background: { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBackgroundImage(globalValue, important), + ...this.getBackgroundPosition(globalValue, important), + ...this.getBackgroundSize(globalValue, important), + ...this.getBackgroundRepeat(globalValue, important), + ...this.getBackgroundAttachment(globalValue, important), + ...this.getBackgroundOrigin(globalValue, important), + ...this.getBackgroundClip(globalValue, important), + ...this.getBackgroundColor(globalValue, important) + }; + } + const properties = { + ...this.getBackgroundImage("initial", important), + ...this.getBackgroundPosition("initial", important), + ...this.getBackgroundSize("initial", important), + ...this.getBackgroundRepeat("initial", important), + ...this.getBackgroundAttachment("initial", important), + ...this.getBackgroundOrigin("initial", important), + ...this.getBackgroundClip("initial", important), + ...this.getBackgroundColor("initial", important) + }; + const parts = CSSStyleDeclarationValueUtility.splitBySpace(value2.replace(/\s+\/\s+/g, "/")); + const backgroundPositions = []; + for (const part of parts) { + if (!part.startsWith("url") && part.includes("/")) { + const [position, size] = part.split("/"); + const backgroundPositionX = this.getBackgroundPositionX(position, important); + const backgroundPositionY = this.getBackgroundPositionY(position, important); + const backgroundSize = this.getBackgroundSize(size, important); + if (!backgroundPositionX && !backgroundPositionY || !backgroundSize) { + return null; + } + if (backgroundPositionY) { + backgroundPositions.push(backgroundPositionY["background-position-y"].value); + } else if (backgroundPositionX) { + backgroundPositions.push(backgroundPositionX["background-position-x"].value); + } + Object.assign(properties, backgroundSize); + } else { + const backgroundImage = this.getBackgroundImage(part, important); + const backgroundRepeat = this.getBackgroundRepeat(part, important); + const backgroundAttachment = this.getBackgroundAttachment(part, important); + const backgroundPositionX = this.getBackgroundPositionX(part, important); + const backgroundPositionY = this.getBackgroundPositionY(part, important); + const backgroundColor = this.getBackgroundColor(part, important); + const backgroundOrigin = this.getBackgroundOrigin(part, important); + const backgroundClip = this.getBackgroundClip(part, important); + if (!backgroundImage && !backgroundRepeat && !backgroundAttachment && !backgroundPositionX && !backgroundPositionY && !backgroundColor && !backgroundOrigin && !backgroundClip) { + return null; + } + if (backgroundPositionX) { + backgroundPositions.push(backgroundPositionX["background-position-x"].value); + } else if (backgroundPositionY) { + backgroundPositions.push(backgroundPositionY["background-position-y"].value); + } + Object.assign(properties, backgroundImage, backgroundRepeat, backgroundAttachment, backgroundColor, backgroundOrigin, backgroundClip); + } + } + if (backgroundPositions.length) { + Object.assign(properties, this.getBackgroundPosition(backgroundPositions.join(" "), important)); + } + return properties; + } + /** + * Returns background size. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBackgroundSize(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "background-size": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { + return { "background-size": { value: lowerValue, important } }; + } + const imageParts = lowerValue.split(SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP); + const parsed = []; + for (const imagePart of imageParts) { + const parts = imagePart.trim().split(" "); + if (parts.length !== 1 && parts.length !== 2) { + return null; + } + if (parts.length === 1) { + if (parts[0] !== "cover" && parts[0] !== "contain" && !CSSStyleDeclarationValueParser.getAutoMeasurement(parts[0])) { + return null; + } + parsed.push(parts[0]); + } else { + if (!CSSStyleDeclarationValueParser.getAutoMeasurement(parts[0]) || !CSSStyleDeclarationValueParser.getAutoMeasurement(parts[1])) { + return null; + } + parsed.push(`${parts[0]} ${parts[1]}`); + } + } + if (parsed.length === 1) { + return { "background-size": { value: parsed.join(", "), important } }; + } + return null; + } + /** + * Returns background origin. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBackgroundOrigin(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "background-origin": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BACKGROUND_ORIGIN.includes(lowerValue)) { + return { "background-origin": { value: lowerValue, important } }; + } + return null; + } + /** + * Returns background clip. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBackgroundClip(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "background-clip": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BACKGROUND_CLIP.includes(lowerValue)) { + return { "background-clip": { value: lowerValue, important } }; + } + return null; + } + /** + * Returns background repeat. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBackgroundRepeat(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "background-repeat": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BACKGROUND_REPEAT.includes(lowerValue)) { + return { "background-repeat": { value: lowerValue, important } }; + } + return null; + } + /** + * Returns background attachment. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBackgroundAttachment(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "background-attachment": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || BACKGROUND_ATTACHMENT.includes(lowerValue)) { + return { "background-attachment": { value: lowerValue, important } }; + } + return null; + } + /** + * Returns background position. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBackgroundPosition(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "background-position": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { + ...this.getBackgroundPositionX(globalValue, important), + ...this.getBackgroundPositionY(globalValue, important) + }; + } + const imageParts = value2.split(SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP); + let x3 = ""; + let y3 = ""; + for (const imagePart of imageParts) { + const parts = imagePart.trim().split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + if (x3) { + x3 += ","; + y3 += ","; + } + switch (parts.length) { + case 1: + if (parts[0] === "top" || parts[0] === "bottom") { + x3 += "center"; + y3 += parts[0]; + } else if (parts[0] === "left" || parts[0] === "right") { + x3 += parts[0]; + y3 += "center"; + } else if (parts[0] === "center") { + x3 += "center"; + y3 += "center"; + } + break; + case 2: + x3 += parts[0] === "top" || parts[0] === "bottom" ? parts[1] : parts[0]; + y3 += parts[0] === "top" || parts[0] === "bottom" ? parts[0] : parts[1]; + break; + case 3: + if (parts[0] === "top" || parts[0] === "bottom" || parts[1] === "left" || parts[1] === "right" || parts[2] === "left" || parts[2] === "right") { + if (CSSStyleDeclarationValueParser.getMeasurement(parts[1])) { + x3 += parts[2]; + y3 += `${parts[0]} ${parts[1]}`; + } else { + x3 += `${parts[1]} ${parts[2]}`; + y3 += parts[0]; + } + } else { + if (CSSStyleDeclarationValueParser.getMeasurement(parts[1])) { + x3 += `${parts[0]} ${parts[1]}`; + y3 += parts[2]; + } else { + x3 += parts[0]; + y3 += `${parts[1]} ${parts[2]}`; + } + } + break; + case 4: + x3 += parts[0] === "top" || parts[0] === "bottom" || parts[1] === "top" || parts[1] === "bottom" ? `${parts[2]} ${parts[3]}` : `${parts[0]} ${parts[1]}`; + y3 += parts[0] === "top" || parts[0] === "bottom" || parts[1] === "top" || parts[1] === "bottom" ? `${parts[0]} ${parts[1]}` : `${parts[2]} ${parts[3]}`; + break; + default: + return null; + } + } + const xValue = this.getBackgroundPositionX(x3, important); + const yValue = this.getBackgroundPositionY(y3, important); + if (xValue && yValue) { + return { + ...xValue, + ...yValue + }; + } + return null; + } + /** + * Returns background position. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBackgroundPositionX(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "background-position-x": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { + return { "background-position-x": { value: lowerValue, important } }; + } + const imageParts = lowerValue.split(SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP); + let parsedValue = ""; + for (const imagePart of imageParts) { + const parts = imagePart.trim().split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + if (parsedValue) { + parsedValue += ","; + } + for (const part of parts) { + const measurement = CSSStyleDeclarationValueParser.getMeasurement(part); + if (!measurement && part !== "left" && part !== "right" && part !== "center") { + return null; + } + if (parsedValue) { + parsedValue += " "; + } + parsedValue += measurement || part; + } + } + return { "background-position-x": { value: parsedValue, important } }; + } + /** + * Returns background position. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getBackgroundPositionY(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "background-position-y": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { + return { "background-position-y": { value: lowerValue, important } }; + } + const imageParts = lowerValue.split(SPLIT_COMMA_SEPARATED_WITH_PARANTHESES_REGEXP); + let parsedValue = ""; + for (const imagePart of imageParts) { + const parts = imagePart.trim().split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + if (parsedValue) { + parsedValue += ","; + } + for (const part of parts) { + const measurement = CSSStyleDeclarationValueParser.getMeasurement(part); + if (!measurement && part !== "top" && part !== "bottom" && part !== "center") { + return null; + } + if (parsedValue) { + parsedValue += " "; + } + parsedValue += measurement || part; + } + } + return { "background-position-y": { value: parsedValue, important } }; + } + /** + * Returns background color. + * + * @param value Value. + * @param important Important. + * @returns Property value. + */ + static getBackgroundColor(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "background-color": { value: variable, important } }; + } + const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); + return color ? { + ["background-color"]: { important, value: color } + } : null; + } + /** + * Returns background image. + * + * @param value Value. + * @param important Important. + * @returns Property value. + */ + static getBackgroundImage(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "background-image": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "none") { + return { "background-image": { value: lowerValue, important } }; + } + const parts = CSSStyleDeclarationValueUtility.splitByComma(value2); + const parsed = []; + for (const part of parts) { + const parsedValue = CSSStyleDeclarationValueParser.getURL(part.trim()) || CSSStyleDeclarationValueParser.getGradient(part.trim()); + if (!parsedValue) { + return null; + } + parsed.push(parsedValue); + } + if (parsed.length) { + return { "background-image": { value: parsed.join(", "), important } }; + } + return null; + } + /** + * Returns color. + * + * @param value Value. + * @param important Important. + * @returns Property value. + */ + static getColor(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { color: { value: variable, important } }; + } + const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); + return color ? { color: { important, value: color } } : null; + } + /** + * Returns color. + * + * @param value Value. + * @param important Important. + * @returns Property value. + */ + static getFloodColor(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "flood-color": { value: variable, important } }; + } + const color = CSSStyleDeclarationValueParser.getGlobal(value2) || CSSStyleDeclarationValueParser.getColor(value2); + return color ? { "flood-color": { important, value: color } } : null; + } + /** + * Returns font. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFont(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { font: { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { + return { + ...this.getFontStyle(lowerValue, important), + ...this.getFontVariant(lowerValue, important), + ...this.getFontWeight(lowerValue, important), + ...this.getFontStretch(lowerValue, important), + ...this.getFontSize(lowerValue, important), + ...this.getLineHeight(lowerValue, important), + ...this.getFontFamily(lowerValue, important) + }; + } + if (SYSTEM_FONT.includes(lowerValue)) { + return { font: { value: lowerValue, important } }; + } + const properties = { + ...this.getFontStyle("normal", important), + ...this.getFontVariant("normal", important), + ...this.getFontWeight("normal", important), + ...this.getFontStretch("normal", important), + ...this.getLineHeight("normal", important) + }; + const parts = value2.replace(/\s*\/\s*/g, "/").split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + for (let i = 0, max = parts.length; i < max; i++) { + const part = parts[i]; + if (part.includes("/")) { + const [size, height2] = part.split("/"); + const fontSize = this.getFontSize(size, important); + const lineHeight = this.getLineHeight(height2, important); + if (!fontSize || !lineHeight) { + return null; + } + Object.assign(properties, fontSize, lineHeight); + } else { + const fontStyle = this.getFontStyle(part, important); + const fontVariant = this.getFontVariant(part, important); + const fontWeight = this.getFontWeight(part, important); + const fontSize = this.getFontSize(part, important); + const fontStretch = this.getFontStretch(part, important); + if (fontStyle) { + Object.assign(properties, fontStyle); + } else if (fontVariant) { + Object.assign(properties, fontVariant); + } else if (fontWeight) { + Object.assign(properties, fontWeight); + } else if (fontSize) { + Object.assign(properties, fontSize); + } else if (fontStretch) { + Object.assign(properties, fontStretch); + } else { + const fontFamilyValue = parts.slice(i).join(" "); + const fontFamily = this.getFontFamily(fontFamilyValue, important); + if (!fontFamily) { + return null; + } + Object.assign(properties, fontFamily); + break; + } + } + } + return properties; + } + /** + * Returns font style. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFontStyle(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "font-style": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FONT_STYLE.includes(lowerValue)) { + return { "font-style": { value: lowerValue, important } }; + } + const parts = value2.split(SPLIT_SPACE_SEPARATED_WITH_PARANTHESES_REGEXP); + if (parts.length === 2 && parts[0] === "oblique") { + const degree = CSSStyleDeclarationValueParser.getDegree(parts[1]); + return degree ? { "font-style": { value: lowerValue, important } } : null; + } + return null; + } + /** + * Returns font variant. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFontVariant(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "font-variant": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + return CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "normal" || lowerValue === "small-caps" ? { "font-variant": { value: lowerValue, important } } : null; + } + /** + * Returns font strech. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFontStretch(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "font-stretch": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FONT_STRETCH.includes(lowerValue)) { + return { "font-stretch": { value: lowerValue, important } }; + } + const percentage = CSSStyleDeclarationValueParser.getPercentage(value2); + return percentage ? { "font-stretch": { value: percentage, important } } : null; + } + /** + * Returns font weight. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFontWeight(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "font-weight": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FONT_WEIGHT.includes(lowerValue)) { + return { "font-weight": { value: lowerValue, important } }; + } + const integer = CSSStyleDeclarationValueParser.getInteger(value2); + return integer ? { "font-weight": { value: integer, important } } : null; + } + /** + * Returns font size. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFontSize(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "font-size": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || FONT_SIZE.includes(lowerValue)) { + return { "font-size": { value: lowerValue, important } }; + } + const measurement = CSSStyleDeclarationValueParser.getMeasurement(value2); + return measurement ? { "font-size": { value: measurement, important } } : null; + } + /** + * Returns line height. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getLineHeight(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "line-height": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue) || lowerValue === "normal") { + return { "line-height": { value: lowerValue, important } }; + } + const lineHeight = CSSStyleDeclarationValueParser.getFloat(value2) || CSSStyleDeclarationValueParser.getMeasurement(value2); + return lineHeight ? { "line-height": { value: lineHeight, important } } : null; + } + /** + * Returns font family. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getFontFamily(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "font-family": { value: variable, important } }; + } + const globalValue = CSSStyleDeclarationValueParser.getGlobal(value2); + if (globalValue) { + return { "font-family": { value: globalValue, important } }; + } + const parts = value2.split(","); + let parsedValue = ""; + let endWithApostroph = false; + for (let i = 0, max = parts.length; i < max; i++) { + let trimmedPart = parts[i].trim().replace(/'/g, '"'); + if (!trimmedPart) { + return null; + } + if (trimmedPart.includes(" ")) { + const apostrophCount = (trimmedPart.match(/"/g) || []).length; + if ((trimmedPart[0] !== '"' || i !== 0) && apostrophCount !== 2 && apostrophCount !== 0) { + return null; + } + if (trimmedPart[0] === '"' && trimmedPart[trimmedPart.length - 1] !== '"') { + endWithApostroph = true; + } else if (trimmedPart[0] !== '"' && trimmedPart[trimmedPart.length - 1] !== '"') { + trimmedPart = `"${trimmedPart}"`; + } + } else { + trimmedPart = trimmedPart.replace(/"/g, ""); + } + if (i > 0) { + parsedValue += ", "; + } + parsedValue += trimmedPart; + } + if (endWithApostroph) { + parsedValue += '"'; + } + if (!parsedValue) { + return null; + } + return { + "font-family": { + important, + value: parsedValue + } + }; + } + /** + * Returns font family. + * + * @param value Value. + * @param important Important. + * @returns Property values + */ + static getTextTransform(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "text-transform": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + const parsedValue = CSSStyleDeclarationValueParser.getGlobal(lowerValue) || TEXT_TRANSFORM.includes(lowerValue) && lowerValue; + if (parsedValue) { + return { + "text-transform": { value: parsedValue, important } + }; + } + return null; + } + /** + * Returns visibility. + * + * @param value Value. + * @param important Important. + * @returns Property + */ + static getVisibility(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { visibility: { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + const parsedValue = CSSStyleDeclarationValueParser.getGlobal(lowerValue) || VISIBILITY.includes(lowerValue) && lowerValue; + if (parsedValue) { + return { + visibility: { value: parsedValue, important } + }; + } + return null; + } + /** + * Returns aspect ratio. + * + * @param value Value. + * @param important Important. + * @returns Property + */ + static getAspectRatio(value2, important) { + const variable = CSSStyleDeclarationValueParser.getVariable(value2); + if (variable) { + return { "aspect-ratio": { value: variable, important } }; + } + const lowerValue = value2.toLowerCase(); + if (CSSStyleDeclarationValueParser.getGlobal(lowerValue)) { + return { "aspect-ratio": { value: lowerValue, important } }; + } + let parsedValue = value2; + const hasAuto = parsedValue.includes("auto"); + if (hasAuto) { + parsedValue = parsedValue.replace("auto", ""); + } + parsedValue = parsedValue.replace(WHITE_SPACE_GLOBAL_REGEXP, ""); + if (!parsedValue) { + return { "aspect-ratio": { value: "auto", important } }; + } + const aspectRatio = parsedValue.split("/"); + if (aspectRatio.length > 3) { + return null; + } + const width2 = Number(aspectRatio[0]); + const height2 = aspectRatio[1] ? Number(aspectRatio[1]) : 1; + if (isNaN(width2) || isNaN(height2)) { + return null; + } + if (hasAuto) { + return { "aspect-ratio": { value: `auto ${width2} / ${height2}`, important } }; + } + return { "aspect-ratio": { value: `${width2} / ${height2}`, important } }; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyGetParser.js +var CSSStyleDeclarationPropertyGetParser; +var init_CSSStyleDeclarationPropertyGetParser = __esm({ + "node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyGetParser.js"() { + init_CSSStyleDeclarationValueParser(); + CSSStyleDeclarationPropertyGetParser = class { + /** + * Returns margin. + * + * @param properties Properties. + * @returns Property value + */ + static getMargin(properties) { + return this.getPaddingLikeProperty(["margin-top", "margin-right", "margin-bottom", "margin-left"], properties); + } + /** + * Returns padding. + * + * @param properties Properties. + * @returns Property value + */ + static getPadding(properties) { + return this.getPaddingLikeProperty(["padding-top", "padding-right", "padding-bottom", "padding-left"], properties); + } + /** + * Returns outline. + * + * @param properties Properties. + * @returns Property value + */ + static getOutline(properties) { + if (!properties["outline-color"]?.value || !properties["outline-style"]?.value || !properties["outline-width"]?.value) { + return null; + } + const important = properties["outline-color"].important && properties["outline-style"].important && properties["outline-width"].important; + if (CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["outline-width"].value) && properties["outline-width"].value === properties["outline-style"].value && properties["outline-width"].value === properties["outline-color"].value) { + return { + important, + value: properties["outline-width"].value + }; + } + const values2 = []; + if (!CSSStyleDeclarationValueParser.getInitial(properties["outline-color"]?.value)) { + values2.push(properties["outline-color"].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties["outline-style"]?.value)) { + values2.push(properties["outline-style"].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties["outline-width"].value)) { + values2.push(properties["outline-width"].value); + } + return { + important, + value: values2.join(" ") + }; + } + /** + * Returns border. + * + * @param properties Properties. + * @returns Property value + */ + static getBorder(properties) { + if (!properties["border-top-width"]?.value || properties["border-top-width"]?.value !== properties["border-right-width"]?.value || properties["border-top-width"]?.value !== properties["border-bottom-width"]?.value || properties["border-top-width"]?.value !== properties["border-left-width"]?.value || !properties["border-top-style"]?.value || properties["border-top-style"]?.value !== properties["border-right-style"]?.value || properties["border-top-style"]?.value !== properties["border-bottom-style"]?.value || properties["border-top-style"]?.value !== properties["border-left-style"]?.value || !properties["border-top-color"]?.value || properties["border-top-color"]?.value !== properties["border-right-color"]?.value || properties["border-top-color"]?.value !== properties["border-bottom-color"]?.value || properties["border-top-color"]?.value !== properties["border-left-color"]?.value || !properties["border-image-source"]?.value || !properties["border-image-slice"]?.value || !properties["border-image-width"]?.value || !properties["border-image-outset"]?.value || !properties["border-image-repeat"]?.value) { + return null; + } + const important = properties["border-top-width"].important && properties["border-right-width"].important && properties["border-bottom-width"].important && properties["border-left-width"].important && properties["border-top-style"].important && properties["border-right-style"].important && properties["border-bottom-style"].important && properties["border-left-style"].important && properties["border-top-color"].important && properties["border-right-color"].important && properties["border-bottom-color"].important && properties["border-left-color"].important && properties["border-image-source"].important && properties["border-image-slice"].important && properties["border-image-width"].important && properties["border-image-outset"].important && properties["border-image-repeat"].important; + if (CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-top-width"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-top-style"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-top-color"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-image-source"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-image-slice"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-image-width"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-image-outset"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["border-image-repeat"].value)) { + if (properties["border-top-width"].value !== properties["border-top-style"].value || properties["border-top-width"].value !== properties["border-top-color"].value || properties["border-top-width"].value !== properties["border-image-source"].value || properties["border-top-width"].value !== properties["border-image-slice"].value || properties["border-top-width"].value !== properties["border-image-width"].value || properties["border-top-width"].value !== properties["border-image-outset"].value || properties["border-top-width"].value !== properties["border-image-repeat"].value) { + return null; + } + return { + important, + value: properties["border-top-width"].value + }; + } + const values2 = []; + if (!CSSStyleDeclarationValueParser.getInitial(properties["border-top-width"].value)) { + values2.push(properties["border-top-width"].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties["border-top-style"].value)) { + values2.push(properties["border-top-style"].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties["border-top-color"].value)) { + values2.push(properties["border-top-color"].value); + } + return { + important, + value: values2.join(" ") + }; + } + /** + * Returns border. + * + * @param properties Properties. + * @returns Property value + */ + static getBorderTop(properties) { + return this.getBorderTopRightBottomLeft("top", properties); + } + /** + * Returns border. + * + * @param properties Properties. + * @returns Property value + */ + static getBorderRight(properties) { + return this.getBorderTopRightBottomLeft("right", properties); + } + /** + * Returns border. + * + * @param properties Properties. + * @returns Property value + */ + static getBorderBottom(properties) { + return this.getBorderTopRightBottomLeft("bottom", properties); + } + /** + * Returns border. + * + * @param properties Properties. + * @returns Property value + */ + static getBorderLeft(properties) { + return this.getBorderTopRightBottomLeft("left", properties); + } + /** + * Returns border. + * + * @param properties Properties. + * @returns Property value + */ + static getBorderColor(properties) { + return this.getPaddingLikeProperty(["border-top-color", "border-right-color", "border-bottom-color", "border-left-color"], properties); + } + /** + * Returns border. + * + * @param properties Properties. + * @returns Property value + */ + static getBorderWidth(properties) { + return this.getPaddingLikeProperty(["border-top-width", "border-right-width", "border-bottom-width", "border-left-width"], properties); + } + /** + * Returns border. + * + * @param properties Properties. + * @returns Property value + */ + static getBorderStyle(properties) { + return this.getPaddingLikeProperty(["border-top-style", "border-right-style", "border-bottom-style", "border-left-style"], properties); + } + /** + * Returns border radius. + * + * @param properties Properties. + * @returns Property value + */ + static getBorderRadius(properties) { + return this.getPaddingLikeProperty([ + "border-top-left-radius", + "border-top-right-radius", + "border-bottom-right-radius", + "border-bottom-left-radius" + ], properties); + } + /** + * Returns border image. + * + * @param properties Properties. + * @returns Property value + */ + static getBorderImage(properties) { + if (!properties["border-image-source"]?.value || !properties["border-image-slice"]?.value || !properties["border-image-width"]?.value || !properties["border-image-outset"]?.value || !properties["border-image-repeat"]?.value) { + return null; + } + const important = properties["border-image-source"].important && properties["border-image-slice"].important && properties["border-image-width"].important && properties["border-image-outset"].important && properties["border-image-repeat"].important; + if (CSSStyleDeclarationValueParser.getGlobal(properties["border-image-source"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["border-image-slice"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["border-image-width"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["border-image-outset"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["border-image-repeat"].value)) { + if (properties["border-image-source"].value !== properties["border-image-slice"].value || properties["border-image-source"].value !== properties["border-image-width"].value || properties["border-image-source"].value !== properties["border-image-outset"].value || properties["border-image-source"].value !== properties["border-image-repeat"].value) { + return null; + } + return { + important, + value: properties["border-image-source"].value + }; + } + return { + important, + value: `${properties["border-image-source"].value} ${properties["border-image-slice"].value} / ${properties["border-image-width"].value} / ${properties["border-image-outset"].value} ${properties["border-image-repeat"].value}` + }; + } + /** + * Returns background. + * + * @param properties Properties. + * @returns Property value + */ + static getBackground(properties) { + if (!properties["background-image"]?.value || !properties["background-repeat"]?.value || !properties["background-attachment"]?.value || !properties["background-position-x"]?.value || !properties["background-position-y"]?.value || !properties["background-color"]?.value || !properties["background-size"]?.value || !properties["background-origin"]?.value || !properties["background-clip"]?.value) { + return null; + } + const important = properties["background-image"].important && properties["background-repeat"].important && properties["background-attachment"].important && properties["background-position-x"].important && properties["background-position-y"].important && properties["background-color"].important && properties["background-size"].important && properties["background-origin"].important && properties["background-clip"].important; + if (CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-image"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-repeat"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-attachment"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-position-x"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-position-y"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-color"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-size"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-origin"].value) || CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties["background-clip"].value)) { + if (properties["background-image"].value !== properties["background-repeat"].value || properties["background-image"].value !== properties["background-attachment"].value || properties["background-image"].value !== properties["background-position-x"].value || properties["background-image"].value !== properties["background-position-y"].value || properties["background-image"].value !== properties["background-color"].value || properties["background-image"].value !== properties["background-size"].value || properties["background-image"].value !== properties["background-origin"].value || properties["background-image"].value !== properties["background-clip"].value) { + return null; + } + return { + important, + value: properties["background-image"].value + }; + } + const values2 = []; + if (!CSSStyleDeclarationValueParser.getInitial(properties["background-image"].value)) { + values2.push(properties["background-image"].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties["background-position-x"].value) && !CSSStyleDeclarationValueParser.getInitial(properties["background-position-y"].value) && !CSSStyleDeclarationValueParser.getInitial(properties["background-size"].value)) { + values2.push(`${properties["background-position-x"].value} ${properties["background-position-y"].value} / ${properties["background-size"].value}`); + } else if (!CSSStyleDeclarationValueParser.getInitial(properties["background-position-x"].value) && !CSSStyleDeclarationValueParser.getInitial(properties["background-position-y"].value)) { + values2.push(`${properties["background-position-x"].value} ${properties["background-position-y"].value}`); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties["background-repeat"].value)) { + values2.push(properties["background-repeat"].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties["background-attachment"].value)) { + values2.push(properties["background-attachment"].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties["background-origin"].value)) { + values2.push(properties["background-origin"].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties["background-clip"].value)) { + values2.push(properties["background-clip"].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties["background-color"].value)) { + values2.push(properties["background-color"].value); + } + return { + important, + value: values2.join(" ") + }; + } + /** + * Returns background position. + * + * @param properties Properties. + * @returns Property value + */ + static getBackgroundPosition(properties) { + if (!properties["background-position-x"]?.value || !properties["background-position-y"]?.value) { + return null; + } + const important = properties["background-position-x"].important && properties["background-position-y"].important; + if (CSSStyleDeclarationValueParser.getGlobal(properties["background-position-x"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["background-position-y"].value)) { + if (properties["background-position-x"].value !== properties["background-position-y"].value) { + return null; + } + return { + important, + value: properties["background-position-x"].value + }; + } + const positionX = properties["background-position-x"].value.replace(/ *, */g, ",").split(","); + const positionY = properties["background-position-y"].value.replace(/ *, */g, ",").split(","); + const parts = []; + for (let i = 0; i < positionX.length; i++) { + parts.push(`${positionX[i]} ${positionY[i]}`); + } + return { + important, + value: parts.join(", ") + }; + } + /** + * Returns flex. + * + * @param properties Properties. + * @returns Property value + */ + static getFlex(properties) { + if (!properties["flex-grow"]?.value || !properties["flex-shrink"]?.value || !properties["flex-basis"]?.value) { + return null; + } + const important = properties["flex-grow"].important && properties["flex-shrink"].important && properties["flex-basis"].important; + if (CSSStyleDeclarationValueParser.getGlobal(properties["flex-grow"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["flex-shrink"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["flex-basis"].value)) { + if (properties["flex-grow"].value !== properties["flex-shrink"].value || properties["flex-grow"].value !== properties["flex-basis"].value) { + return null; + } + return { + important, + value: properties["flex-grow"].value + }; + } + return { + important, + value: `${properties["flex-grow"].value} ${properties["flex-shrink"].value} ${properties["flex-basis"].value}` + }; + } + /** + * Returns flex. + * + * @param properties Properties. + * @returns Property value + */ + static getFont(properties) { + if (!properties["font-size"]?.value || !properties["font-family"]?.value || !properties["font-weight"]?.value || !properties["font-style"]?.value || !properties["font-variant"]?.value || !properties["font-stretch"]?.value || !properties["line-height"]?.value) { + return null; + } + const important = properties["font-size"].important && properties["font-family"].important && properties["font-weight"].important && properties["font-style"].important && properties["font-variant"].important && properties["font-stretch"].important && properties["line-height"].important; + if (CSSStyleDeclarationValueParser.getGlobal(properties["font-size"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["font-family"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["font-weight"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["font-style"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["font-variant"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["font-stretch"].value) || CSSStyleDeclarationValueParser.getGlobal(properties["line-height"].value)) { + if (properties["font-size"].value !== properties["font-family"].value || properties["font-size"].value !== properties["font-weight"].value || properties["font-size"].value !== properties["font-style"].value || properties["font-size"].value !== properties["font-variant"].value || properties["font-size"].value !== properties["font-stretch"].value || properties["font-size"].value !== properties["line-height"].value) { + return null; + } + return { + important, + value: properties["font-size"].value + }; + } + const values2 = []; + if (properties["font-style"].value !== "normal") { + values2.push(properties["font-style"].value); + } + if (properties["font-variant"].value !== "normal") { + values2.push(properties["font-variant"].value); + } + if (properties["font-weight"].value !== "normal") { + values2.push(properties["font-weight"].value); + } + if (properties["font-stretch"].value !== "normal") { + values2.push(properties["font-stretch"].value); + } + if (properties["line-height"].value !== "normal") { + values2.push(`${properties["font-size"].value} / ${properties["line-height"].value}`); + } else { + values2.push(properties["font-size"].value); + } + values2.push(properties["font-family"].value); + return { + important, + value: values2.join(" ") + }; + } + /** + * Returns border. + * + * @param properties Properties. + * @param position + * @returns Property value + */ + static getBorderTopRightBottomLeft(position, properties) { + if (!properties[`border-${position}-width`]?.value || !properties[`border-${position}-style`]?.value || !properties[`border-${position}-color`]?.value) { + return null; + } + const important = properties[`border-${position}-width`].important && properties[`border-${position}-style`].important && properties[`border-${position}-color`].important; + if (CSSStyleDeclarationValueParser.getGlobalExceptInitial(properties[`border-${position}-width`].value) && properties[`border-${position}-width`].value === properties[`border-${position}-style`].value && properties[`border-${position}-width`].value === properties[`border-${position}-color`].value) { + return { + important, + value: properties[`border-${position}-width`].value + }; + } + const values2 = []; + if (!CSSStyleDeclarationValueParser.getInitial(properties[`border-${position}-width`].value)) { + values2.push(properties[`border-${position}-width`].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties[`border-${position}-style`]?.value)) { + values2.push(properties[`border-${position}-style`].value); + } + if (!CSSStyleDeclarationValueParser.getInitial(properties[`border-${position}-color`]?.value)) { + values2.push(properties[`border-${position}-color`].value); + } + return { + important, + value: values2.join(" ") + }; + } + /** + * Returns a padding like property. + * + * @param properties Properties. + * @param position + * @param propertyNames + * @returns Property value + */ + static getPaddingLikeProperty(propertyNames, properties) { + if (!properties[propertyNames[0]]?.value || !properties[propertyNames[1]]?.value || !properties[propertyNames[2]]?.value || !properties[propertyNames[3]]?.value) { + return null; + } + const important = properties[propertyNames[0]].important && properties[propertyNames[1]].important && properties[propertyNames[2]].important && properties[propertyNames[3]].important; + if (CSSStyleDeclarationValueParser.getGlobal(properties[propertyNames[0]].value) || CSSStyleDeclarationValueParser.getGlobal(properties[propertyNames[1]].value) || CSSStyleDeclarationValueParser.getGlobal(properties[propertyNames[2]].value) || CSSStyleDeclarationValueParser.getGlobal(properties[propertyNames[3]].value)) { + if (properties[propertyNames[0]].value !== properties[propertyNames[1]].value || properties[propertyNames[0]].value !== properties[propertyNames[2]].value || properties[propertyNames[0]].value !== properties[propertyNames[3]].value) { + return null; + } + return { + important, + value: properties[propertyNames[0]].value + }; + } + const values2 = [properties[propertyNames[0]].value]; + if (properties[propertyNames[1]].value !== properties[propertyNames[0]].value || properties[propertyNames[2]].value !== properties[propertyNames[0]].value || properties[propertyNames[3]].value !== properties[propertyNames[1]].value) { + values2.push(properties[propertyNames[1]].value); + } + if (properties[propertyNames[2]].value !== properties[propertyNames[0]].value || properties[propertyNames[3]].value !== properties[propertyNames[1]].value) { + values2.push(properties[propertyNames[2]].value); + } + if (properties[propertyNames[3]].value !== properties[propertyNames[1]].value) { + values2.push(properties[propertyNames[3]].value); + } + return { + important, + value: values2.join(" ") + }; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/css-parser/CSSStyleDeclarationCSSParser.js +var SPLIT_RULES_REGEXP, CSSStyleDeclarationCSSParser; +var init_CSSStyleDeclarationCSSParser = __esm({ + "node_modules/happy-dom/lib/css/declaration/css-parser/CSSStyleDeclarationCSSParser.js"() { + SPLIT_RULES_REGEXP = /\s*([^:;]+?)\s*:\s*((?:[^(;]*?(?:\([^)]*\))?)*?)\s*(!important)?\s*(?:$|;)/g; + CSSStyleDeclarationCSSParser = class { + /** + * Class construtor. + * + * @param cssText CSS string. + * @param callback Callback. + */ + static parse(cssText2) { + const properties = {}; + const rules = []; + const regexp = new RegExp(SPLIT_RULES_REGEXP); + let match; + while (match = regexp.exec(cssText2)) { + const name2 = (match[1] ?? "").trim(); + const value2 = (match[2] ?? "").trim(); + const important = match[3] ? true : false; + if (name2 && value2) { + if (name2.startsWith("--")) { + properties[name2] = value2; + } + rules.push({ name: name2, value: value2, important }); + } + } + return { rules, properties }; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.js +var TO_STRING_SHORTHAND_PROPERTIES, CSSStyleDeclarationPropertyManager; +var init_CSSStyleDeclarationPropertyManager = __esm({ + "node_modules/happy-dom/lib/css/declaration/property-manager/CSSStyleDeclarationPropertyManager.js"() { + init_CSSStyleDeclarationPropertySetParser(); + init_CSSStyleDeclarationValueParser(); + init_CSSStyleDeclarationPropertyGetParser(); + init_CSSStyleDeclarationCSSParser(); + TO_STRING_SHORTHAND_PROPERTIES = [ + ["margin"], + ["padding"], + ["border", ["border-width", "border-style", "border-color", "border-image"]], + ["border-radius"], + ["background", "background-position"], + ["font"] + ]; + CSSStyleDeclarationPropertyManager = class { + properties = {}; + definedPropertyNames = {}; + /** + * Class construtor. + * + * @param [options] Options. + * @param [options.cssText] CSS string. + */ + constructor(options2) { + if (options2?.cssText) { + const { rules } = CSSStyleDeclarationCSSParser.parse(options2.cssText); + for (const rule of rules) { + if (rule.important || !this.get(rule.name)?.important) { + this.set(rule.name, rule.value, rule.important); + } + } + } + } + /** + * Returns property value. + * + * @param name Property name. + * @returns Property value. + */ + get(name2) { + if (this.properties[name2]) { + return this.properties[name2]; + } + switch (name2) { + case "margin": + return CSSStyleDeclarationPropertyGetParser.getMargin(this.properties); + case "padding": + return CSSStyleDeclarationPropertyGetParser.getPadding(this.properties); + case "border": + return CSSStyleDeclarationPropertyGetParser.getBorder(this.properties); + case "border-top": + return CSSStyleDeclarationPropertyGetParser.getBorderTop(this.properties); + case "border-right": + return CSSStyleDeclarationPropertyGetParser.getBorderRight(this.properties); + case "border-bottom": + return CSSStyleDeclarationPropertyGetParser.getBorderBottom(this.properties); + case "border-left": + return CSSStyleDeclarationPropertyGetParser.getBorderLeft(this.properties); + case "border-color": + return CSSStyleDeclarationPropertyGetParser.getBorderColor(this.properties); + case "border-style": + return CSSStyleDeclarationPropertyGetParser.getBorderStyle(this.properties); + case "border-width": + return CSSStyleDeclarationPropertyGetParser.getBorderWidth(this.properties); + case "border-radius": + return CSSStyleDeclarationPropertyGetParser.getBorderRadius(this.properties); + case "border-image": + return CSSStyleDeclarationPropertyGetParser.getBorderImage(this.properties); + case "outline": + return CSSStyleDeclarationPropertyGetParser.getOutline(this.properties); + case "background": + return CSSStyleDeclarationPropertyGetParser.getBackground(this.properties); + case "background-position": + return CSSStyleDeclarationPropertyGetParser.getBackgroundPosition(this.properties); + case "flex": + return CSSStyleDeclarationPropertyGetParser.getFlex(this.properties); + case "font": + return CSSStyleDeclarationPropertyGetParser.getFont(this.properties); + } + return this.properties[name2] || null; + } + /** + * Removes a property. + * + * @param name Property name. + */ + remove(name2) { + delete this.properties[name2]; + delete this.definedPropertyNames[name2]; + switch (name2) { + case "border": + delete this.properties["border-top-width"]; + delete this.properties["border-right-width"]; + delete this.properties["border-bottom-width"]; + delete this.properties["border-left-width"]; + delete this.properties["border-top-style"]; + delete this.properties["border-right-style"]; + delete this.properties["border-bottom-style"]; + delete this.properties["border-left-style"]; + delete this.properties["border-top-color"]; + delete this.properties["border-right-color"]; + delete this.properties["border-bottom-color"]; + delete this.properties["border-left-color"]; + delete this.properties["border-image-source"]; + delete this.properties["border-image-slice"]; + delete this.properties["border-image-width"]; + delete this.properties["border-image-outset"]; + delete this.properties["border-image-repeat"]; + break; + case "border-top": + delete this.properties["border-top-width"]; + delete this.properties["border-top-style"]; + delete this.properties["border-top-color"]; + delete this.properties["border-image-source"]; + delete this.properties["border-image-slice"]; + delete this.properties["border-image-width"]; + delete this.properties["border-image-outset"]; + delete this.properties["border-image-repeat"]; + break; + case "border-right": + delete this.properties["border-right-width"]; + delete this.properties["border-right-style"]; + delete this.properties["border-right-color"]; + delete this.properties["border-image-source"]; + delete this.properties["border-image-slice"]; + delete this.properties["border-image-width"]; + delete this.properties["border-image-outset"]; + delete this.properties["border-image-repeat"]; + break; + case "border-bottom": + delete this.properties["border-bottom-width"]; + delete this.properties["border-bottom-style"]; + delete this.properties["border-bottom-color"]; + delete this.properties["border-image-source"]; + delete this.properties["border-image-slice"]; + delete this.properties["border-image-width"]; + delete this.properties["border-image-outset"]; + delete this.properties["border-image-repeat"]; + break; + case "border-left": + delete this.properties["border-left-width"]; + delete this.properties["border-left-style"]; + delete this.properties["border-left-color"]; + delete this.properties["border-image-source"]; + delete this.properties["border-image-slice"]; + delete this.properties["border-image-width"]; + delete this.properties["border-image-outset"]; + delete this.properties["border-image-repeat"]; + break; + case "border-width": + delete this.properties["border-top-width"]; + delete this.properties["border-right-width"]; + delete this.properties["border-bottom-width"]; + delete this.properties["border-left-width"]; + break; + case "border-style": + delete this.properties["border-top-style"]; + delete this.properties["border-right-style"]; + delete this.properties["border-bottom-style"]; + delete this.properties["border-left-style"]; + break; + case "border-color": + delete this.properties["border-top-color"]; + delete this.properties["border-right-color"]; + delete this.properties["border-bottom-color"]; + delete this.properties["border-left-color"]; + break; + case "border-image": + delete this.properties["border-image-source"]; + delete this.properties["border-image-slice"]; + delete this.properties["border-image-width"]; + delete this.properties["border-image-outset"]; + delete this.properties["border-image-repeat"]; + break; + case "border-radius": + delete this.properties["border-top-left-radius"]; + delete this.properties["border-top-right-radius"]; + delete this.properties["border-bottom-right-radius"]; + delete this.properties["border-bottom-left-radius"]; + break; + case "outline": + delete this.properties["outline-color"]; + delete this.properties["outline-style"]; + delete this.properties["outline-width"]; + break; + case "background": + delete this.properties["background-color"]; + delete this.properties["background-image"]; + delete this.properties["background-repeat"]; + delete this.properties["background-attachment"]; + delete this.properties["background-position-x"]; + delete this.properties["background-position-y"]; + delete this.properties["background-size"]; + delete this.properties["background-origin"]; + delete this.properties["background-clip"]; + break; + case "background-position": + delete this.properties["background-position-x"]; + delete this.properties["background-position-y"]; + break; + case "flex": + delete this.properties["flex-grow"]; + delete this.properties["flex-shrink"]; + delete this.properties["flex-basis"]; + break; + case "font": + delete this.properties["font-style"]; + delete this.properties["font-variant"]; + delete this.properties["font-weight"]; + delete this.properties["font-stretch"]; + delete this.properties["font-size"]; + delete this.properties["line-height"]; + delete this.properties["font-family"]; + break; + case "padding": + delete this.properties["padding-top"]; + delete this.properties["padding-right"]; + delete this.properties["padding-bottom"]; + delete this.properties["padding-left"]; + break; + case "margin": + delete this.properties["margin-top"]; + delete this.properties["margin-right"]; + delete this.properties["margin-bottom"]; + delete this.properties["margin-left"]; + break; + } + } + /** + * Sets a property + * + * @param name Name. + * @param value Value. + * @param important Important. + */ + set(name2, value2, important) { + if (value2 === null) { + this.remove(name2); + return; + } + let properties = null; + switch (name2) { + case "border": + properties = CSSStyleDeclarationPropertySetParser.getBorder(value2, important); + break; + case "border-top": + properties = CSSStyleDeclarationPropertySetParser.getBorderTop(value2, important); + break; + case "border-right": + properties = CSSStyleDeclarationPropertySetParser.getBorderRight(value2, important); + break; + case "border-bottom": + properties = CSSStyleDeclarationPropertySetParser.getBorderBottom(value2, important); + break; + case "border-left": + properties = CSSStyleDeclarationPropertySetParser.getBorderLeft(value2, important); + break; + case "border-width": + properties = CSSStyleDeclarationPropertySetParser.getBorderWidth(value2, important); + break; + case "border-style": + properties = CSSStyleDeclarationPropertySetParser.getBorderStyle(value2, important); + break; + case "border-color": + properties = CSSStyleDeclarationPropertySetParser.getBorderColor(value2, important); + break; + case "border-image": + properties = CSSStyleDeclarationPropertySetParser.getBorderImage(value2, important); + break; + case "border-image-source": + properties = CSSStyleDeclarationPropertySetParser.getBorderImageSource(value2, important); + break; + case "border-image-slice": + properties = CSSStyleDeclarationPropertySetParser.getBorderImageSlice(value2, important); + break; + case "border-image-width": + properties = CSSStyleDeclarationPropertySetParser.getBorderImageWidth(value2, important); + break; + case "border-image-outset": + properties = CSSStyleDeclarationPropertySetParser.getBorderImageOutset(value2, important); + break; + case "border-image-repeat": + properties = CSSStyleDeclarationPropertySetParser.getBorderImageRepeat(value2, important); + break; + case "border-top-width": + properties = CSSStyleDeclarationPropertySetParser.getBorderTopWidth(value2, important); + break; + case "border-right-width": + properties = CSSStyleDeclarationPropertySetParser.getBorderRightWidth(value2, important); + break; + case "border-bottom-width": + properties = CSSStyleDeclarationPropertySetParser.getBorderBottomWidth(value2, important); + break; + case "border-left-width": + properties = CSSStyleDeclarationPropertySetParser.getBorderLeftWidth(value2, important); + break; + case "border-top-color": + properties = CSSStyleDeclarationPropertySetParser.getBorderTopColor(value2, important); + break; + case "border-right-color": + properties = CSSStyleDeclarationPropertySetParser.getBorderRightColor(value2, important); + break; + case "border-bottom-color": + properties = CSSStyleDeclarationPropertySetParser.getBorderBottomColor(value2, important); + break; + case "border-left-color": + properties = CSSStyleDeclarationPropertySetParser.getBorderLeftColor(value2, important); + break; + case "border-top-style": + properties = CSSStyleDeclarationPropertySetParser.getBorderTopStyle(value2, important); + break; + case "border-right-style": + properties = CSSStyleDeclarationPropertySetParser.getBorderRightStyle(value2, important); + break; + case "border-bottom-style": + properties = CSSStyleDeclarationPropertySetParser.getBorderBottomStyle(value2, important); + break; + case "border-left-style": + properties = CSSStyleDeclarationPropertySetParser.getBorderLeftStyle(value2, important); + break; + case "border-radius": + properties = CSSStyleDeclarationPropertySetParser.getBorderRadius(value2, important); + break; + case "border-top-left-radius": + properties = CSSStyleDeclarationPropertySetParser.getBorderTopLeftRadius(value2, important); + break; + case "border-top-right-radius": + properties = CSSStyleDeclarationPropertySetParser.getBorderTopRightRadius(value2, important); + break; + case "border-bottom-right-radius": + properties = CSSStyleDeclarationPropertySetParser.getBorderBottomRightRadius(value2, important); + break; + case "border-bottom-left-radius": + properties = CSSStyleDeclarationPropertySetParser.getBorderBottomLeftRadius(value2, important); + break; + case "border-collapse": + properties = CSSStyleDeclarationPropertySetParser.getBorderCollapse(value2, important); + break; + case "outline": + properties = CSSStyleDeclarationPropertySetParser.getOutline(value2, important); + break; + case "outline-width": + properties = CSSStyleDeclarationPropertySetParser.getOutlineWidth(value2, important); + break; + case "outline-style": + properties = CSSStyleDeclarationPropertySetParser.getOutlineStyle(value2, important); + break; + case "outline-color": + properties = CSSStyleDeclarationPropertySetParser.getOutlineColor(value2, important); + break; + case "letter-spacing": + properties = CSSStyleDeclarationPropertySetParser.getLetterSpacing(value2, important); + break; + case "word-spacing": + properties = CSSStyleDeclarationPropertySetParser.getWordSpacing(value2, important); + break; + case "clear": + properties = CSSStyleDeclarationPropertySetParser.getClear(value2, important); + break; + case "clip": + properties = CSSStyleDeclarationPropertySetParser.getClip(value2, important); + break; + case "css-float": + properties = CSSStyleDeclarationPropertySetParser.getCSSFloat(value2, important); + break; + case "float": + properties = CSSStyleDeclarationPropertySetParser.getFloat(value2, important); + break; + case "display": + properties = CSSStyleDeclarationPropertySetParser.getDisplay(value2, important); + break; + case "direction": + properties = CSSStyleDeclarationPropertySetParser.getDirection(value2, important); + break; + case "flex": + properties = CSSStyleDeclarationPropertySetParser.getFlex(value2, important); + break; + case "flex-shrink": + properties = CSSStyleDeclarationPropertySetParser.getFlexShrink(value2, important); + break; + case "flex-grow": + properties = CSSStyleDeclarationPropertySetParser.getFlexGrow(value2, important); + break; + case "flex-basis": + properties = CSSStyleDeclarationPropertySetParser.getFlexBasis(value2, important); + break; + case "padding": + properties = CSSStyleDeclarationPropertySetParser.getPadding(value2, important); + break; + case "padding-top": + properties = CSSStyleDeclarationPropertySetParser.getPaddingTop(value2, important); + break; + case "padding-right": + properties = CSSStyleDeclarationPropertySetParser.getPaddingRight(value2, important); + break; + case "padding-bottom": + properties = CSSStyleDeclarationPropertySetParser.getPaddingBottom(value2, important); + break; + case "padding-left": + properties = CSSStyleDeclarationPropertySetParser.getPaddingLeft(value2, important); + break; + case "margin": + properties = CSSStyleDeclarationPropertySetParser.getMargin(value2, important); + break; + case "margin-top": + properties = CSSStyleDeclarationPropertySetParser.getMarginTop(value2, important); + break; + case "margin-right": + properties = CSSStyleDeclarationPropertySetParser.getMarginRight(value2, important); + break; + case "margin-bottom": + properties = CSSStyleDeclarationPropertySetParser.getMarginBottom(value2, important); + break; + case "margin-left": + properties = CSSStyleDeclarationPropertySetParser.getMarginLeft(value2, important); + break; + case "background": + properties = CSSStyleDeclarationPropertySetParser.getBackground(value2, important); + break; + case "background-image": + properties = CSSStyleDeclarationPropertySetParser.getBackgroundImage(value2, important); + break; + case "background-color": + properties = CSSStyleDeclarationPropertySetParser.getBackgroundColor(value2, important); + break; + case "background-repeat": + properties = CSSStyleDeclarationPropertySetParser.getBackgroundRepeat(value2, important); + break; + case "background-attachment": + properties = CSSStyleDeclarationPropertySetParser.getBackgroundAttachment(value2, important); + break; + case "background-position": + properties = CSSStyleDeclarationPropertySetParser.getBackgroundPosition(value2, important); + break; + case "width": + properties = CSSStyleDeclarationPropertySetParser.getWidth(value2, important); + break; + case "height": + properties = CSSStyleDeclarationPropertySetParser.getHeight(value2, important); + break; + case "top": + properties = CSSStyleDeclarationPropertySetParser.getTop(value2, important); + break; + case "right": + properties = CSSStyleDeclarationPropertySetParser.getRight(value2, important); + break; + case "bottom": + properties = CSSStyleDeclarationPropertySetParser.getBottom(value2, important); + break; + case "left": + properties = CSSStyleDeclarationPropertySetParser.getLeft(value2, important); + break; + case "font": + properties = CSSStyleDeclarationPropertySetParser.getFont(value2, important); + break; + case "font-style": + properties = CSSStyleDeclarationPropertySetParser.getFontStyle(value2, important); + break; + case "font-variant": + properties = CSSStyleDeclarationPropertySetParser.getFontVariant(value2, important); + break; + case "font-weight": + properties = CSSStyleDeclarationPropertySetParser.getFontWeight(value2, important); + break; + case "font-stretch": + properties = CSSStyleDeclarationPropertySetParser.getFontStretch(value2, important); + break; + case "font-size": + properties = CSSStyleDeclarationPropertySetParser.getFontSize(value2, important); + break; + case "line-height": + properties = CSSStyleDeclarationPropertySetParser.getLineHeight(value2, important); + break; + case "text-indent": + properties = CSSStyleDeclarationPropertySetParser.getTextIndent(value2, important); + break; + case "font-family": + properties = CSSStyleDeclarationPropertySetParser.getFontFamily(value2, important); + break; + case "color": + properties = CSSStyleDeclarationPropertySetParser.getColor(value2, important); + break; + case "flood-color": + properties = CSSStyleDeclarationPropertySetParser.getFloodColor(value2, important); + break; + case "text-transform": + properties = CSSStyleDeclarationPropertySetParser.getTextTransform(value2, important); + break; + case "visibility": + properties = CSSStyleDeclarationPropertySetParser.getVisibility(value2, important); + break; + case "aspect-ratio": + properties = CSSStyleDeclarationPropertySetParser.getAspectRatio(value2, important); + break; + default: + const trimmedValue = value2.trim(); + if (trimmedValue) { + const globalValue = CSSStyleDeclarationValueParser.getGlobal(trimmedValue); + properties = { + [name2]: { value: globalValue || trimmedValue, important } + }; + } + break; + } + if (properties !== null && Object.keys(properties).length > 0) { + this.definedPropertyNames[name2] = true; + Object.assign(this.properties, properties); + } + } + /** + * Returns a clone. + * + * @returns Clone. + */ + clone() { + const _class = this.constructor; + const clone2 = new _class(); + clone2.properties = JSON.parse(JSON.stringify(this.properties)); + clone2.definedPropertyNames = Object.assign({}, this.definedPropertyNames); + return clone2; + } + /** + * Returns size. + * + * @returns Size. + */ + size() { + return Object.keys(this.properties).length; + } + /** + * Returns property name. + * + * @param index Index. + * @returns Property name. + */ + item(index) { + return Object.keys(this.properties)[index] || ""; + } + /** + * Converts properties to string. + * + * @returns String. + */ + toString() { + const result3 = []; + const clone2 = this.clone(); + const properties = {}; + for (const shorthandPropertyGroup of TO_STRING_SHORTHAND_PROPERTIES) { + for (const shorthandProperty of shorthandPropertyGroup) { + if (Array.isArray(shorthandProperty)) { + let isMatch = false; + for (const childShorthandProperty of shorthandProperty) { + const property = clone2.get(childShorthandProperty); + if (property) { + properties[childShorthandProperty] = property; + clone2.remove(childShorthandProperty); + isMatch = true; + } + } + if (isMatch) { + break; + } + } else { + const property = clone2.get(shorthandProperty); + if (property) { + properties[shorthandProperty] = property; + clone2.remove(shorthandProperty); + break; + } + } + } + } + for (const name2 of Object.keys(clone2.properties)) { + properties[name2] = clone2.get(name2); + } + for (const definedPropertyName of Object.keys(this.definedPropertyNames)) { + const property = properties[definedPropertyName]; + if (property) { + result3.push(`${definedPropertyName}: ${property.value}${property.important ? " !important" : ""};`); + delete properties[definedPropertyName]; + } + } + for (const propertyName of Object.keys(properties)) { + const property = properties[propertyName]; + if (property) { + result3.push(`${propertyName}: ${property.value}${property.important ? " !important" : ""};`); + } + } + return result3.join(" "); + } + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementDefaultCSS.js +var CSSStyleDeclarationElementDefaultCSS_default; +var init_CSSStyleDeclarationElementDefaultCSS = __esm({ + "node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementDefaultCSS.js"() { + CSSStyleDeclarationElementDefaultCSS_default = { + default: "display: inline;", + A: "", + ABBR: "", + ADDRESS: "display: block;", + AREA: "", + ARTICLE: "display: block;", + ASIDE: "display: block;", + AUDIO: "display: none;", + B: "", + BASE: "display: none;", + BDI: "", + BDO: "", + BLOCKQUAOTE: "", + BODY: "display: block;", + TEMPLATE: "display: none;", + FORM: "display: block;", + INPUT: "display: inline-block;", + TEXTAREA: "display: inline-block;", + SCRIPT: "display: none;", + IMG: "", + LINK: "display: none;", + STYLE: "display: none;", + LABEL: "", + SLOT: "display: contents;", + SVG: "", + CIRCLE: "", + ELLIPSE: "", + LINE: "", + PATH: "", + POLYGON: "", + POLYLINE: "", + RECT: "", + STOP: "", + USE: "", + META: "display: none;", + BLOCKQUOTE: "display: block;", + BR: "", + BUTTON: "display: inline-block;", + CANVAS: "", + CAPTION: "display: table-caption;", + CITE: "", + CODE: "", + COL: "display: table-column;", + COLGROUP: "display: table-column-group;", + DATA: "", + DATALIST: "display: none;", + DD: "display: block;", + DEL: "", + DETAILS: "display: block;", + DFN: "", + DIALOG: { + default: "display: none;", + open: "display: block;" + }, + DIV: "display: block;", + DL: "display: block;", + DT: "display: block;", + EM: "", + EMBED: "", + FIELDSET: "display: block;", + FIGCAPTION: "display: block;", + FIGURE: "display: block;", + FOOTER: "display: block;", + H1: "display: block;", + H2: "display: block;", + H3: "display: block;", + H4: "display: block;", + H5: "display: block;", + H6: "display: block;", + HEAD: "display: none;", + HEADER: "display: block;", + HGROUP: "display: block;", + HR: "display: block;", + HTML: 'display: block;direction: ltr;font: 16px "Times New Roman";', + I: "", + IFRAME: "", + INS: "", + KBD: "", + LEGEND: "display: block;", + LI: "display: list-item;", + MAIN: "display: block;", + MAP: "", + MARK: "", + MATH: "", + MENU: "display: block;", + MENUITEM: "", + METER: "display: inline-block;", + NAV: "display: block;", + NOSCRIPT: "", + OBJECT: "", + OL: "display: block;", + OPTGROUP: "display: block;", + OPTION: "display: block;", + OUTPUT: "unicode-bidi: isolate;", + P: "display: block;", + PARAM: "display: none;", + PICTURE: "", + PRE: "display: block;", + PROGRESS: "display: inline-block;", + Q: "", + RB: "", + RP: "display: none;", + RT: "", + RTC: "", + RUBY: "", + S: "", + SAMP: "", + SECTION: "display: block;", + SELECT: "display: inline-block;", + SMALL: "", + SOURCE: "", + SPAN: "", + STRONG: "", + SUB: "", + SUMMARY: "display: block;", + SUP: "", + TABLE: "display: table;", + TBODY: "display: table-row-group;", + TD: "display: table-cell;", + TFOOT: "display: table-footer-group;", + TH: "display: table-cell;", + THEAD: "display: table-header-group;", + TIME: "", + TITLE: "display: none;", + TR: "display: table-row;", + TRACK: "", + U: "", + UL: "display: block;", + VAR: "", + VIDEO: "", + WBR: "" + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementInheritedProperties.js +var CSSStyleDeclarationElementInheritedProperties_default; +var init_CSSStyleDeclarationElementInheritedProperties = __esm({ + "node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementInheritedProperties.js"() { + CSSStyleDeclarationElementInheritedProperties_default = { + "border-collapse": true, + "border-spacing": true, + "caption-side": true, + color: true, + cursor: true, + direction: true, + "empty-cells": true, + "font-family": true, + "font-size": true, + "font-style": true, + "font-variant": true, + "font-weight": true, + "font-size-adjust": true, + "font-stretch": true, + font: true, + "letter-spacing": true, + "line-height": true, + "list-style-image": true, + "list-style-position": true, + "list-style-type": true, + "list-style": true, + orphans: true, + quotes: true, + "tab-size": true, + "text-align": true, + "text-align-last": true, + "text-decoration-color": true, + "text-indent": true, + "text-justify": true, + "text-shadow": true, + "text-transform": true, + visibility: true, + "white-space": true, + widows: true, + "word-break": true, + "word-spacing": true, + "word-wrap": true + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementMeasurementProperties.js +var CSSStyleDeclarationElementMeasurementProperties_default; +var init_CSSStyleDeclarationElementMeasurementProperties = __esm({ + "node_modules/happy-dom/lib/css/declaration/computed-style/config/CSSStyleDeclarationElementMeasurementProperties.js"() { + CSSStyleDeclarationElementMeasurementProperties_default = [ + "background-position-x", + "background-position-y", + "background-size", + "border-image-outset", + "border-top-width", + "border-right-width", + "border-bottom-width", + "border-left-width", + "border-top-left-radius", + "border-top-right-radius", + "border-bottom-right-radius", + "border-bottom-left-radius", + "border-image-width", + "clip", + "font-size", + "padding-top", + "padding-right", + "padding-bottom", + "padding-left", + "margin-top", + "margin-right", + "margin-bottom", + "margin-left", + "width", + "height", + "min-width", + "min-height", + "max-width", + "max-height", + "top", + "right", + "bottom", + "left", + "outline-width", + "outline-offset", + "letter-spacing", + "word-spacing", + "text-indent", + "line-height" + ]; + } +}); + +// node_modules/happy-dom/lib/utilities/ClassMethodBinder.js +var ClassMethodBinder; +var init_ClassMethodBinder = __esm({ + "node_modules/happy-dom/lib/utilities/ClassMethodBinder.js"() { + ClassMethodBinder = class { + target; + classes; + cache = /* @__PURE__ */ new Map(); + /** + * Constructor. + * + * @param target Target. + * @param classes Classes. + */ + constructor(target2, classes) { + this.target = target2; + this.classes = classes; + } + /** + * Binds method, getters and setters to a target. + * + * @param name Method name. + */ + bind(name2) { + if (this.cache.has(name2) || name2 === Symbol.iterator || name2 === "constructor") { + return; + } + this.cache.set(name2, true); + const target2 = this.target; + if (!(name2 in target2)) { + return; + } + for (const _class of this.classes) { + const descriptor = Object.getOwnPropertyDescriptor(_class.prototype, name2); + if (descriptor) { + if (typeof descriptor.value === "function") { + if (descriptor.value.toString().startsWith("class ")) { + return; + } + Object.defineProperty(target2, name2, { + ...descriptor, + value: descriptor.value.bind(target2) + }); + } else if (descriptor.get !== void 0) { + Object.defineProperty(target2, name2, { + ...descriptor, + get: descriptor.get?.bind(target2), + set: descriptor.set?.bind(target2) + }); + } + return; + } + } + } + /** + * Prevents a method, getter or setter from being bound. + * + * @param name Method name. + */ + preventBinding(name2) { + this.cache.set(name2, true); + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/node/NodeList.js +var NodeList, NodeList_default; +var init_NodeList = __esm({ + "node_modules/happy-dom/lib/nodes/node/NodeList.js"() { + init_ClassMethodBinder(); + init_PropertySymbol(); + NodeList = class _NodeList { + [items]; + [proxy]; + /** + * Constructor. + * + * @param illegalConstructorSymbol Illegal constructor symbol. + * @param items Items. + */ + constructor(illegalConstructorSymbol, items2) { + if (illegalConstructorSymbol !== illegalConstructor) { + throw new TypeError("Illegal constructor"); + } + this[items] = items2; + const methodBinder = new ClassMethodBinder(this, this.constructor !== _NodeList ? [this.constructor, _NodeList] : [_NodeList]); + const proxy2 = new Proxy(this, { + get: (target2, property) => { + if (property === "length") { + return items2.length; + } + if (property in target2 || typeof property === "symbol") { + methodBinder.bind(property); + return target2[property]; + } + if (property === "") { + return void 0; + } + const index = Number(property); + if (!isNaN(index)) { + return items2[index]; + } + }, + set(target2, property, newValue) { + methodBinder.bind(property); + if (typeof property === "symbol") { + target2[property] = newValue; + return true; + } + const index = Number(property); + if (isNaN(index)) { + target2[property] = newValue; + } + return true; + }, + deleteProperty(target2, property) { + if (typeof property === "symbol") { + delete target2[property]; + return true; + } + const index = Number(property); + if (isNaN(index)) { + delete target2[property]; + } + return true; + }, + ownKeys() { + return Object.keys(items2); + }, + has(target2, property) { + if (property in target2) { + return true; + } + if (typeof property === "symbol") { + return false; + } + const index = Number(property); + return !isNaN(index) && index >= 0 && index < items2.length; + }, + defineProperty(target2, property, descriptor) { + methodBinder.preventBinding(property); + if (property in target2) { + Object.defineProperty(target2, property, descriptor); + return true; + } + return false; + }, + getOwnPropertyDescriptor(target2, property) { + if (property in target2 || typeof property === "symbol") { + return; + } + const index = Number(property); + if (!isNaN(index) && items2[index]) { + return { + value: items2[index], + writable: false, + enumerable: true, + configurable: true + }; + } + } + }); + this[proxy] = proxy2; + return proxy2; + } + /** + * Returns length. + * + * @returns Length. + */ + get length() { + return this[items].length; + } + /** + * Returns `Symbol.toStringTag`. + * + * @returns `Symbol.toStringTag`. + */ + get [Symbol.toStringTag]() { + return "NodeList"; + } + /** + * Returns `[object NodeList]`. + * + * @returns `[object NodeList]`. + */ + toLocaleString() { + return "[object NodeList]"; + } + /** + * Returns `[object NodeList]`. + * + * @returns `[object NodeList]`. + */ + toString() { + return "[object NodeList]"; + } + /** + * Returns item by index. + * + * @param index Index. + */ + item(index) { + const nodes = this[items]; + return index >= 0 && nodes[index] ? nodes[index] : null; + } + /** + * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. + * + * @returns Iterator. + */ + [Symbol.iterator]() { + const items2 = this[items]; + return items2[Symbol.iterator](); + } + /** + * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. + * + * @returns Iterator. + */ + values() { + return this[items].values(); + } + /** + * Returns an iterator, allowing you to go through all key/value pairs contained in this object. + * + * @returns Iterator. + */ + entries() { + return this[items].entries(); + } + /** + * Executes a provided callback function once for each DOMTokenList element. + * + * @param callback Function. + * @param thisArg thisArg. + */ + forEach(callback, thisArg) { + const items2 = this[items]; + const proxy2 = this[proxy] ?? this; + for (let i = 0, max = items2.length; i < max; i++) { + const item = items2[i]; + callback.call(thisArg ?? item[window], item, i, proxy2); + } + } + /** + * Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object. + * + * @returns Iterator. + */ + keys() { + return this[items].keys(); + } + }; + NodeList_default = NodeList; + } +}); + +// node_modules/happy-dom/lib/query-selector/SelectorCombinatorEnum.js +var SelectorCombinatorEnum, SelectorCombinatorEnum_default; +var init_SelectorCombinatorEnum = __esm({ + "node_modules/happy-dom/lib/query-selector/SelectorCombinatorEnum.js"() { + (function(SelectorCombinatorEnum2) { + SelectorCombinatorEnum2["none"] = "none"; + SelectorCombinatorEnum2["descendant"] = "descendant"; + SelectorCombinatorEnum2["child"] = "child"; + SelectorCombinatorEnum2["adjacentSibling"] = "adjacentSibling"; + SelectorCombinatorEnum2["subsequentSibling"] = "subsequentSibling"; + })(SelectorCombinatorEnum || (SelectorCombinatorEnum = {})); + SelectorCombinatorEnum_default = SelectorCombinatorEnum; + } +}); + +// node_modules/happy-dom/lib/query-selector/SelectorItem.js +var SelectorItem; +var init_SelectorItem = __esm({ + "node_modules/happy-dom/lib/query-selector/SelectorItem.js"() { + init_PropertySymbol(); + init_SelectorCombinatorEnum(); + SelectorItem = class { + tagName; + id; + classNames; + attributes; + pseudos; + isPseudoElement; + combinator; + /** + * Constructor. + * + * @param [options] Options. + * @param [options.combinator] Combinator. + * @param [options.tagName] Tag name. + * @param [options.id] ID. + * @param [options.classNames] Class names. + * @param [options.attributes] Attributes. + * @param [options.pseudos] Pseudos. + * @param [options.isPseudoElement] Is pseudo element. + * @param [options.ignoreErrors] Ignore errors. + */ + constructor(options2) { + this.tagName = options2?.tagName || null; + this.id = options2?.id || null; + this.classNames = options2?.classNames || null; + this.attributes = options2?.attributes || null; + this.pseudos = options2?.pseudos || null; + this.isPseudoElement = options2?.isPseudoElement || false; + this.combinator = options2?.combinator || SelectorCombinatorEnum_default.none; + } + /** + * Matches a selector against an element. + * + * @param scope Scope. + * @param element HTML element. + * @param [ignoreErrors] Ignores errors. + * @returns Result. + */ + match(scope, element, ignoreErrors) { + let priorityWeight = 0; + if (this.isPseudoElement) { + return null; + } + if (this.tagName) { + if (this.tagName !== "*" && this.tagName !== element[tagName].toUpperCase()) { + return null; + } + priorityWeight += 1; + } + if (this.id) { + if (this.id !== element.id) { + return null; + } + priorityWeight += 100; + } + if (this.classNames) { + const result3 = this.matchClass(element); + if (!result3) { + return null; + } + priorityWeight += result3.priorityWeight; + } + if (this.attributes) { + const result3 = this.matchAttributes(element); + if (!result3) { + return null; + } + priorityWeight += result3.priorityWeight; + } + if (this.pseudos) { + const result3 = this.matchPseudo(scope, element, ignoreErrors); + if (!result3) { + return null; + } + priorityWeight += result3.priorityWeight; + } + return { priorityWeight }; + } + /** + * Matches a pseudo selector. + * + * @param scope Scope. + * @param element Element. + * @param [ignoreErrors] Ignores errors. + * @returns Result. + */ + matchPseudo(scope, element, ignoreErrors) { + const parent2 = element[parentNode]; + const parentChildren = element[parentNode] ? element[parentNode][elementArray] : []; + if (!this.pseudos) { + return { priorityWeight: 0 }; + } + let priorityWeight = 0; + for (const pseudo of this.pseudos) { + switch (pseudo.name) { + case "not": + case "nth-child": + case "nth-of-type": + case "nth-last-child": + case "nth-last-of-type": + case "is": + case "where": + if (!pseudo.arguments) { + if (ignoreErrors) { + return null; + } + throw new element[window].DOMException(`Failed to execute 'matches' on '${element.constructor.name}': '${this.getSelectorString()}' is not a valid selector.`); + } + break; + } + if (!parent2) { + switch (pseudo.name) { + case "first-child": + case "last-child": + case "only-child": + case "first-of-type": + case "last-of-type": + case "only-of-type": + case "nth-child": + case "nth-of-type": + case "nth-last-child": + case "nth-last-of-type": + return null; + } + } + const selectorMatch = this.matchPseudoItem(scope, element, parentChildren, pseudo, ignoreErrors); + if (!selectorMatch) { + return null; + } + priorityWeight += selectorMatch.priorityWeight; + } + return { priorityWeight }; + } + /** + * Matches a pseudo selector. + * + * @param scope Scope. + * @param element Element. + * @param parentChildren Parent children. + * @param pseudo Pseudo. + * @param [ignoreErrors] Ignores errors. + */ + matchPseudoItem(scope, element, parentChildren, pseudo, ignoreErrors) { + const root2 = this.getRootElement(scope); + switch (pseudo.name) { + case "first-child": + return parentChildren[0] === element ? { priorityWeight: 10 } : null; + case "last-child": + return parentChildren.length && parentChildren[parentChildren.length - 1] === element ? { priorityWeight: 10 } : null; + case "only-child": + return parentChildren.length === 1 && parentChildren[0] === element ? { priorityWeight: 10 } : null; + case "first-of-type": + for (const child of parentChildren) { + if (child[tagName] === element[tagName]) { + return child === element ? { priorityWeight: 10 } : null; + } + } + return null; + case "last-of-type": + for (let i = parentChildren.length - 1; i >= 0; i--) { + const child = parentChildren[i]; + if (child[tagName] === element[tagName]) { + return child === element ? { priorityWeight: 10 } : null; + } + } + return null; + case "only-of-type": + let isFound = false; + for (const child of parentChildren) { + if (child[tagName] === element[tagName]) { + if (isFound || child !== element) { + return null; + } + isFound = true; + } + } + return isFound ? { priorityWeight: 10 } : null; + case "checked": + return element[tagName] === "INPUT" && element.checked ? { priorityWeight: 10 } : null; + case "disabled": + return "disabled" in element && element.hasAttribute("disabled") ? { priorityWeight: 10 } : null; + case "empty": + return !element[elementArray].length ? { priorityWeight: 10 } : null; + case "root": + return root2 && element === root2 ? { priorityWeight: 10 } : null; + case "not": + for (const selectorItem of pseudo.selectorItems) { + if (selectorItem.match(scope, element)) { + return null; + } + } + return { priorityWeight: 10 }; + case "nth-child": + let nthChildIndex = -1; + if (pseudo.selectorItems?.[0] && !pseudo.selectorItems[0].match(scope, element)) { + return null; + } + for (let i = 0, max = parentChildren.length; i < max; i++) { + if (!pseudo.selectorItems?.[0] || pseudo.selectorItems[0].match(scope, parentChildren[i])) { + nthChildIndex++; + } + if (parentChildren[i] === element) { + return nthChildIndex !== -1 && pseudo.nthFunction(nthChildIndex + 1) ? { priorityWeight: 10 } : null; + } + } + return null; + case "nth-of-type": + let nthOfTypeIndex = -1; + for (let i = 0, max = parentChildren.length; i < max; i++) { + if (parentChildren[i][tagName] === element[tagName]) { + nthOfTypeIndex++; + } + if (parentChildren[i] === element) { + return nthOfTypeIndex !== -1 && pseudo.nthFunction(nthOfTypeIndex + 1) ? { priorityWeight: 10 } : null; + } + } + return null; + case "nth-last-child": + let nthLastChildIndex = -1; + if (pseudo.selectorItems?.[0] && !pseudo.selectorItems[0].match(scope, element)) { + return null; + } + for (let i = parentChildren.length - 1; i >= 0; i--) { + if (!pseudo.selectorItems?.[0] || pseudo.selectorItems[0].match(scope, parentChildren[i])) { + nthLastChildIndex++; + } + if (parentChildren[i] === element) { + return nthLastChildIndex !== -1 && pseudo.nthFunction(nthLastChildIndex + 1) ? { priorityWeight: 10 } : null; + } + } + return null; + case "nth-last-of-type": + let nthLastOfTypeIndex = -1; + for (let i = parentChildren.length - 1; i >= 0; i--) { + if (parentChildren[i][tagName] === element[tagName]) { + nthLastOfTypeIndex++; + } + if (parentChildren[i] === element) { + return nthLastOfTypeIndex !== -1 && pseudo.nthFunction(nthLastOfTypeIndex + 1) ? { priorityWeight: 10 } : null; + } + } + return null; + case "target": + const hash = element[ownerDocument].location.hash; + if (!hash) { + return null; + } + return element.isConnected && element.id === hash.slice(1) ? { priorityWeight: 10 } : null; + case "is": + let priorityWeightForIs = 0; + if (!pseudo.selectorItems) { + return null; + } + for (const selectorItem of pseudo.selectorItems) { + const match = selectorItem.match(scope, element); + if (match && priorityWeightForIs < match.priorityWeight) { + priorityWeightForIs = match.priorityWeight; + } + } + return priorityWeightForIs ? { priorityWeight: priorityWeightForIs } : null; + case "where": + if (!pseudo.selectorItems) { + return null; + } + for (const selectorItem of pseudo.selectorItems) { + if (selectorItem.match(scope, element)) { + return { priorityWeight: 0 }; + } + } + return null; + case "has": + let priorityWeightForHas = 0; + if (pseudo.arguments && pseudo.selectorItems) { + if (pseudo.arguments[0] === "+") { + const nextSibling = element.nextElementSibling; + if (!nextSibling) { + return null; + } + for (const selectorItem of pseudo.selectorItems) { + const match = selectorItem.match(scope, nextSibling); + if (match && priorityWeightForHas < match.priorityWeight) { + priorityWeightForHas = match.priorityWeight; + } + } + } else if (pseudo.arguments[0] === ">") { + for (const selectorItem of pseudo.selectorItems) { + for (const child of element[elementArray]) { + const match = selectorItem.match(scope, child); + if (match && priorityWeightForHas < match.priorityWeight) { + priorityWeightForHas = match.priorityWeight; + break; + } + } + } + } else { + for (const selectorItem of pseudo.selectorItems) { + const match = this.matchChildOfElement(scope, selectorItem, element, ignoreErrors); + if (match && priorityWeightForHas < match.priorityWeight) { + priorityWeightForHas = match.priorityWeight; + } + } + } + } + return priorityWeightForHas ? { priorityWeight: priorityWeightForHas } : null; + case "focus": + case "focus-visible": + return element[ownerDocument].activeElement === element ? { priorityWeight: 10 } : null; + case "scope": + return scope && scope === element ? { priorityWeight: 10 } : null; + default: + return null; + } + } + /** + * Matches attribute. + * + * @param element Element. + * @returns Result. + */ + matchAttributes(element) { + if (!this.attributes) { + return null; + } + let priorityWeight = 0; + for (const attribute of this.attributes) { + const elementAttribute = element[attributes].getNamedItem(attribute.name); + if (!elementAttribute) { + return null; + } + priorityWeight += 10; + if (attribute.value !== null && (elementAttribute[value] === null || attribute.regExp && !attribute.regExp.test(elementAttribute[value]) || !attribute.regExp && attribute.value !== elementAttribute[value])) { + return null; + } + } + return { priorityWeight }; + } + /** + * Matches class. + * + * @param element Element. + * @returns Result. + */ + matchClass(element) { + if (!this.classNames) { + return null; + } + let priorityWeight = 0; + for (const className of this.classNames) { + if (!element.classList.contains(className)) { + return null; + } + priorityWeight += 10; + } + return { priorityWeight }; + } + /** + * Matches a selector item against children of an element. + * + * @param scope Scope. + * @param selectorItem Selector item. + * @param element Element. + * @param [ignoreErrors] Ignores errors. + * @returns Result. + */ + matchChildOfElement(scope, selectorItem, element, ignoreErrors) { + for (const child of element[elementArray]) { + const match = selectorItem.match(scope, child, ignoreErrors); + if (match) { + return match; + } + const childMatch = this.matchChildOfElement(scope, selectorItem, child, ignoreErrors); + if (childMatch) { + return childMatch; + } + } + return null; + } + /** + * Returns the selector string. + * + * @returns Selector string. + */ + getSelectorString() { + return `${this.tagName ? this.tagName.toLowerCase() : ""}${this.id ? `#${this.id}` : ""}${this.classNames ? `.${this.classNames.join(".")}` : ""}${this.attributes ? this.attributes.map((attribute) => `[${attribute.name}${attribute.value ? `${attribute.operator || ""}="${attribute.value}"` : ""}]`).join("") : ""}${this.pseudos ? this.pseudos.map((pseudo) => `:${pseudo.name}${pseudo.arguments ? `(${pseudo.arguments})` : ""}`).join("") : ""}`; + } + /** + * Returns the root element. + * + * @param scope Scope. + * @returns Root element. + */ + getRootElement(scope) { + return scope?.[ownerDocument]?.documentElement || scope?.[window].document?.documentElement || null; + } + }; + } +}); + +// node_modules/happy-dom/lib/query-selector/SelectorParser.js +var SELECTOR_GROUP_REGEXP, SELECTOR_REGEXP, SELECTOR_PSEUDO_REGEXP, ESCAPED_CHARACTER_REGEXP, CSS_UNESCAPE_REGEXP, ATTRIBUTE_ESCAPE_REGEXP, NTH_FUNCTION, SPACE_REGEXP, SelectorParser; +var init_SelectorParser = __esm({ + "node_modules/happy-dom/lib/query-selector/SelectorParser.js"() { + init_SelectorItem(); + init_SelectorCombinatorEnum(); + init_NodeTypeEnum(); + init_PropertySymbol(); + SELECTOR_GROUP_REGEXP = /(\s*[\s,+>~]\s*)|([\[\]\(\)"'])/g; + SELECTOR_REGEXP = /(\*)|([a-zA-Z0-9\u00A0-\uFFFF-]+)|#(([a-zA-Z0-9\u00A0-\uFFFF_-]|\\.)+)|\.(([a-zA-Z0-9\u00A0-\uFFFF_-]|\\.)+)|\[(([a-zA-Z0-9-_]|\\.)+)\]|\[(([a-zA-Z0-9-_]|\\.)+)\s*([~|^$*]{0,1})\s*=\s*("([^"]*)"|'([^']*)')\s*(s|i){0,1}\]|\[(([a-zA-Z0-9-_]|\\.)+)\s*([~|^$*]{0,1})\s*=\s*(([a-zA-Z0-9\u00A0-\uFFFF_¤£-]|\\.)+)\]|:([a-zA-Z-]+)\s*\(.+\)|:([a-zA-Z-]+)|::([a-zA-Z-]+)/g; + SELECTOR_PSEUDO_REGEXP = /:([a-zA-Z-]+)|([()])/g; + ESCAPED_CHARACTER_REGEXP = /\\/g; + CSS_UNESCAPE_REGEXP = /\\([0-9a-fA-F]{1,6})\s?|\\(.)/g; + ATTRIBUTE_ESCAPE_REGEXP = /[.*+?^${}()|[\]\\]/g; + NTH_FUNCTION = { + odd: (n) => (n + 1) % 2 === 0, + even: (n) => (n + 1) % 2 !== 0, + alwaysFalse: () => false + }; + SPACE_REGEXP = / /g; + SelectorParser = class _SelectorParser { + window; + scope; + ignoreErrors; + /** + * Constructor. + * + * @param options + * @param options.window + * @param options.scope + * @param options.ignoreErrors + */ + constructor(options2) { + this.window = options2.window; + this.scope = options2.scope; + this.ignoreErrors = options2.ignoreErrors ?? false; + } + /** + * Parses a selector string and returns an instance of SelectorItem. + * + * @param selector Selector. + * @returns Selector item. + */ + getSelectorItem(selector) { + return this.getSelectorGroups(selector)[0][0]; + } + /** + * Parses a selector string and returns instances of SelectorItem. + * + * @param selector Selector. + * @returns Selector groups. + */ + getSelectorGroups(selector) { + selector = selector.trim(); + const cached = this.window[querySelectorCache].get(selector); + if (cached) { + return cached; + } + const groups = this.getSelectorGroupsUncached(selector); + this.window[querySelectorCache].set(selector, groups); + return groups; + } + /** + * Returns an error for an invalid selector. + * + * Constructed lazily, as creating a DOMException captures the current stack trace, which is + * expensive on hot paths such as Element.matches() and getComputedStyle() during rendering. + * + * @param selector Selector. + * @returns Error. + */ + getInvalidSelectorError(selector) { + const name2 = this.scope.nodeType === NodeTypeEnum_default.documentNode ? "Document" : "Element"; + return new this.window.DOMException(`Failed to execute 'querySelectorAll' on '${name2}': '${selector}' is not a valid selector.`); + } + /** + * Parses a selector string and returns instances of SelectorItem without using cache. + * + * @param selector Selector. + * @returns Selector groups. + */ + getSelectorGroupsUncached(selector) { + let currentGroup = []; + const groups = [currentGroup]; + const regExp = new RegExp(SELECTOR_GROUP_REGEXP); + const depth = { + parentheses: 0, + brackets: 0, + doubleApostrophe: 0, + singleApostrophe: 0 + }; + let match = null; + let lastIndex = 0; + let selectorItem = null; + let combinator = SelectorCombinatorEnum_default.none; + while (match = regExp.exec(selector)) { + if (match[1]) { + if (depth.parentheses === 0 && depth.brackets === 0 && depth.singleApostrophe === 0 && depth.doubleApostrophe === 0) { + const childSelector = selector.substring(lastIndex, match.index).trim(); + switch (match[1].trim()) { + case ",": + selectorItem = this.getSelectorGroupItem(childSelector, combinator); + if (!selectorItem) { + if (this.ignoreErrors) { + return []; + } + throw this.getInvalidSelectorError(selector); + } + currentGroup.push(selectorItem); + currentGroup = []; + groups.push(currentGroup); + combinator = SelectorCombinatorEnum_default.none; + break; + case ">": + selectorItem = this.getSelectorGroupItem(childSelector, combinator); + if (!selectorItem) { + if (this.ignoreErrors) { + return []; + } + throw this.getInvalidSelectorError(selector); + } + currentGroup.push(selectorItem); + combinator = SelectorCombinatorEnum_default.child; + break; + case "+": + selectorItem = this.getSelectorGroupItem(childSelector, combinator); + if (!selectorItem) { + if (this.ignoreErrors) { + return []; + } + throw this.getInvalidSelectorError(selector); + } + currentGroup.push(selectorItem); + combinator = SelectorCombinatorEnum_default.adjacentSibling; + break; + case "~": + selectorItem = this.getSelectorGroupItem(childSelector, combinator); + if (!selectorItem) { + if (this.ignoreErrors) { + return []; + } + throw this.getInvalidSelectorError(selector); + } + currentGroup.push(selectorItem); + combinator = SelectorCombinatorEnum_default.subsequentSibling; + break; + case "": + selectorItem = this.getSelectorGroupItem(childSelector, combinator); + if (!selectorItem) { + if (this.ignoreErrors) { + return []; + } + throw this.getInvalidSelectorError(selector); + } + currentGroup.push(selectorItem); + combinator = SelectorCombinatorEnum_default.descendant; + break; + } + lastIndex = regExp.lastIndex; + } + } else { + switch (match[2]) { + case "(": + if (depth.singleApostrophe === 0 && depth.doubleApostrophe === 0) { + depth.parentheses++; + } + break; + case ")": + if (depth.singleApostrophe === 0 && depth.doubleApostrophe === 0) { + depth.parentheses--; + } + break; + case "[": + if (depth.singleApostrophe === 0 && depth.doubleApostrophe === 0) { + depth.brackets++; + } + break; + case "]": + if (depth.singleApostrophe === 0 && depth.doubleApostrophe === 0) { + depth.brackets--; + } + break; + case '"': + if (depth.singleApostrophe === 0) { + depth.doubleApostrophe = depth.doubleApostrophe === 1 ? 0 : 1; + } + break; + case "'": + if (depth.doubleApostrophe === 0) { + depth.singleApostrophe = depth.singleApostrophe === 1 ? 0 : 1; + } + break; + } + } + } + selectorItem = this.getSelectorGroupItem(selector.substring(lastIndex), combinator); + if (!selectorItem || depth.parentheses !== 0 || depth.brackets !== 0 || depth.singleApostrophe !== 0 || depth.doubleApostrophe !== 0) { + if (this.ignoreErrors) { + return []; + } + throw this.getInvalidSelectorError(selector); + } + if (combinator === SelectorCombinatorEnum_default.none && currentGroup.length > 0) { + groups.push([selectorItem]); + } else { + currentGroup.push(selectorItem); + } + return groups; + } + /** + * Parses a selector string and returns an SelectorItem. + * + * @param selector Selector. + * @param combinator Combinator. + * @returns Selector item. + */ + getSelectorGroupItem(selector, combinator) { + selector = selector.trim(); + if (!selector) { + return null; + } + if (selector === "*") { + return new SelectorItem({ tagName: "*", combinator }); + } + const regexp = new RegExp(SELECTOR_REGEXP); + const selectorItem = new SelectorItem({ + combinator + }); + let match; + let lastIndex = 0; + while (match = regexp.exec(selector)) { + if (selector.substring(lastIndex, match.index).trim() !== "") { + return null; + } + if (match[1]) { + selectorItem.tagName = "*"; + } else if (match[2]) { + selectorItem.tagName = match[2].toUpperCase(); + } else if (match[3]) { + selectorItem.id = match[3].replace(ESCAPED_CHARACTER_REGEXP, ""); + } else if (match[5]) { + selectorItem.classNames = selectorItem.classNames || []; + selectorItem.classNames.push(match[5].replace(ESCAPED_CHARACTER_REGEXP, "")); + } else if (match[7]) { + selectorItem.attributes = selectorItem.attributes || []; + selectorItem.attributes.push({ + name: match[7].replace(ESCAPED_CHARACTER_REGEXP, ""), + operator: null, + value: null, + modifier: null, + regExp: null + }); + } else if (match[9] && (match[13] !== void 0 || match[14] !== void 0)) { + const value2 = match[13] ?? match[14]; + const unescapedValue = _SelectorParser.cssUnescape(value2); + selectorItem.attributes = selectorItem.attributes || []; + selectorItem.attributes.push({ + name: match[9].replace(ESCAPED_CHARACTER_REGEXP, ""), + operator: match[11] || null, + value: unescapedValue, + modifier: match[15] || null, + regExp: this.getAttributeRegExp({ + operator: match[11], + value: unescapedValue, + modifier: match[15] + }) + }); + } else if (match[16] && match[19] !== void 0) { + const unescapedValue = _SelectorParser.cssUnescape(match[19]); + selectorItem.attributes = selectorItem.attributes || []; + selectorItem.attributes.push({ + name: match[16].replace(ESCAPED_CHARACTER_REGEXP, ""), + operator: match[18] || null, + value: unescapedValue, + modifier: null, + regExp: this.getAttributeRegExp({ operator: match[18], value: unescapedValue }) + }); + } else if (match[21]) { + const pseudoRegExp = new RegExp(SELECTOR_PSEUDO_REGEXP); + let pseudoMatch = null; + let name2 = null; + let depth = 0; + let pseudoStartIndex = -1; + while (pseudoMatch = pseudoRegExp.exec(match[0])) { + if (pseudoMatch[1]) { + if (depth === 0) { + name2 = pseudoMatch[1]; + } + } else if (pseudoMatch[2]) { + if (pseudoMatch[2] === "(") { + if (depth === 0) { + pseudoStartIndex = pseudoRegExp.lastIndex; + } + depth++; + } else if (pseudoMatch[2] === ")") { + depth--; + if (depth < 0) { + return null; + } + if (depth === 0) { + if (pseudoStartIndex === -1 || !name2) { + return null; + } + selectorItem.pseudos = selectorItem.pseudos || []; + selectorItem.pseudos.push(this.getPseudo(name2, match[0].substring(pseudoStartIndex, pseudoMatch.index))); + name2 = null; + pseudoStartIndex = -1; + } + } + } + } + } else if (match[22]) { + selectorItem.pseudos = selectorItem.pseudos || []; + selectorItem.pseudos.push(this.getPseudo(match[22], null)); + } else if (match[23]) { + selectorItem.isPseudoElement = true; + } + lastIndex = regexp.lastIndex; + } + if (lastIndex < selector.length) { + return null; + } + return selectorItem; + } + /** + * Returns attribute RegExp. + * + * @param attribute Attribute. + * @param attribute.value Attribute value. + * @param attribute.operator Attribute operator. + * @param attribute.modifier Attribute modifier. + * @returns Attribute RegExp. + */ + getAttributeRegExp(attribute) { + const modifier = attribute.modifier === "i" ? "i" : ""; + if (!attribute.operator || !attribute.value) { + return null; + } + const escapedValue = attribute.value.replace(ATTRIBUTE_ESCAPE_REGEXP, "\\$&"); + switch (attribute.operator) { + // [attribute~="value"] - Contains a specified word. + case "~": + return new RegExp(`(^|\\s)${escapedValue}(\\s|$)`, modifier); + // [attribute|="value"] - Starts with the specified word. + case "|": + return new RegExp(`^${escapedValue}[- ]|^${escapedValue}$`, modifier); + // [attribute^="value"] - Begins with a specified value. + case "^": + return new RegExp(`^${escapedValue}`, modifier); + // [attribute$="value"] - Ends with a specified value. + case "$": + return new RegExp(`${escapedValue}$`, modifier); + // [attribute*="value"] - Contains a specified value. + case "*": + return new RegExp(`${escapedValue}`, modifier); + default: + return null; + } + } + /** + * Returns pseudo. + * + * @param name Pseudo name. + * @param args Pseudo arguments. + * @returns Pseudo. + */ + getPseudo(name2, args) { + const lowerName = name2.toLowerCase(); + if (args) { + args = args.trim(); + } + if (!args) { + return { name: lowerName, arguments: null, selectorItems: null, nthFunction: null }; + } + switch (lowerName) { + case "nth-last-child": + case "nth-child": + const nthOfIndex = args.indexOf(" of "); + const nthFunction = nthOfIndex !== -1 ? args.substring(0, nthOfIndex) : args; + const selectorItem = nthOfIndex !== -1 ? this.getSelectorItem(args.substring(nthOfIndex + 4).trim()) : null; + return { + name: lowerName, + arguments: args, + selectorItems: selectorItem ? [selectorItem] : null, + nthFunction: this.getPseudoNthFunction(nthFunction) + }; + case "nth-of-type": + case "nth-last-of-type": + return { + name: lowerName, + arguments: args, + selectorItems: null, + nthFunction: this.getPseudoNthFunction(args) + }; + case "not": + const notSelectorItems = []; + for (const group of this.getSelectorGroups(args)) { + if (group[0]) { + notSelectorItems.push(group[0]); + } + } + return { + name: lowerName, + arguments: args, + selectorItems: notSelectorItems, + nthFunction: null + }; + case "is": + case "where": + const selectorItems = []; + for (const group of this.getSelectorGroups(args)) { + if (group[0]) { + selectorItems.push(group[0]); + } + } + return { + name: lowerName, + arguments: args, + selectorItems, + nthFunction: null + }; + case "has": + const hasSelectorItems = []; + if (!args.includes(":has(")) { + let newArgs = args; + if (args[0] === "+") { + newArgs = args.replace("+", ""); + } else if (args[0] === ">") { + newArgs = args.replace(">", ""); + } + for (const group of this.getSelectorGroups(newArgs)) { + if (group[0]) { + hasSelectorItems.push(group[0]); + } + } + } + return { + name: lowerName, + arguments: args || "", + selectorItems: hasSelectorItems, + nthFunction: null + }; + case "scope": + case "root": + default: + return { name: lowerName, arguments: args, selectorItems: null, nthFunction: null }; + } + } + /** + * Returns pseudo nth function. + * + * Based on: + * https://github.com/dperini/nwsapi/blob/master/src/nwsapi.js + * + * @param args Pseudo arguments. + * @returns Pseudo nth function. + */ + getPseudoNthFunction(args) { + if (!args) { + return null; + } + if (args === "odd") { + return NTH_FUNCTION.odd; + } else if (args === "even") { + return NTH_FUNCTION.even; + } + const parts = args.replace(SPACE_REGEXP, "").split("n"); + let partA = parseInt(parts[0], 10) || 0; + if (parts[0] == "-") { + partA = -1; + } + if (parts.length === 1) { + return (n) => n == partA; + } + let partB = parseInt(parts[1], 10) || 0; + if (parts[0] == "+") { + partB = 1; + } + if (partA >= 1 || partA <= -1) { + if (partA >= 1) { + if (Math.abs(partA) === 1) { + return (n) => n > partB - 1; + } + return (n) => n > partB - 1 && (n + -1 * partB) % partA === 0; + } + if (Math.abs(partA) === 1) { + return (n) => n < partB + 1; + } + return (n) => n < partB + 1 && (n + -1 * partB) % partA === 0; + } + if (parts[0]) { + return (n) => n === partB; + } + return (n) => n > partB - 1; + } + /** + * Unescapes CSS escape sequences in a string value. + * + * Handles hex escapes (e.g. "\30 " → "0", "\0041" → "A") and character escapes (e.g. "\:" → ":"). + * + * @see https://www.w3.org/TR/css-syntax-3/#consume-escaped-code-point + * @param value Escaped CSS value. + * @returns Unescaped value. + */ + static cssUnescape(value2) { + return value2.replace(CSS_UNESCAPE_REGEXP, (_match, hex, char) => { + if (hex) { + return String.fromCodePoint(parseInt(hex, 16)); + } + return char; + }); + } + }; + } +}); + +// node_modules/happy-dom/lib/query-selector/QuerySelector.js +var INVALID_SELECTOR_REGEXP, QuerySelector; +var init_QuerySelector = __esm({ + "node_modules/happy-dom/lib/query-selector/QuerySelector.js"() { + init_PropertySymbol(); + init_NodeList(); + init_NodeTypeEnum(); + init_SelectorCombinatorEnum(); + init_SelectorParser(); + INVALID_SELECTOR_REGEXP = /^[.#\[]?\d|[.#]$/; + QuerySelector = class { + /** + * Finds elements based on a query selector. + * + * @param node Node to search in. + * @param selector Selector. + * @returns HTML elements. + */ + static querySelectorAll(node, selector) { + const window2 = node[window]; + if (selector === "") { + throw new window2.DOMException(`Failed to execute 'querySelectorAll' on '${node.constructor.name}': The provided selector is empty.`); + } + if (typeof selector === "function") { + throw new window2.DOMException(`Failed to execute 'querySelectorAll' on '${node.constructor.name}': '${selector}' is not a valid selector.`); + } + if (typeof selector === "symbol") { + throw new window2.TypeError(`Failed to execute 'querySelectorAll' on '${node.constructor.name}': Cannot convert a Symbol value to a string`); + } + selector = String(selector); + if (INVALID_SELECTOR_REGEXP.test(selector)) { + throw new window2.DOMException(`Failed to execute 'querySelectorAll' on '${node.constructor.name}': '${selector}' is not a valid selector.`); + } + const cache2 = node[cache].querySelectorAll; + const cachedResult = cache2.get(selector); + if (cachedResult) { + if (cachedResult.result !== null) { + const result3 = cachedResult.result.deref(); + if (result3) { + return result3; + } + } + cache2.delete(selector); + } + const scope = node[nodeType] === NodeTypeEnum_default.documentNode ? node.documentElement : node; + const groups = new SelectorParser({ window: window2, scope }).getSelectorGroups(selector); + const items2 = []; + const nodeList = new NodeList_default(illegalConstructor, items2); + const matchesMap = /* @__PURE__ */ new Map(); + const matchedPositions = []; + const cachedItem = { + result: new WeakRef(nodeList) + }; + node[cache].querySelectorAll.set(selector, cachedItem); + if (node[isConnected]) { + (node[ownerDocument] || node)[affectsCache].push(cachedItem); + } + for (const selectorItems of groups) { + const rootElement = node[nodeType] === NodeTypeEnum_default.elementNode ? node : null; + const children2 = node[nodeType] === NodeTypeEnum_default.elementNode ? [node] : node[elementArray]; + const matches = this.findAll({ scope, rootElement, children: children2, selectorItems, cachedItem }); + for (const match of matches) { + if (!matchesMap.has(match.documentPosition)) { + matchesMap.set(match.documentPosition, match.element); + matchedPositions.push(match.documentPosition); + } + } + } + const keys = matchedPositions.sort(); + for (let i = 0, max = keys.length; i < max; i++) { + items2.push(matchesMap.get(keys[i])); + } + return nodeList; + } + /** + * Finds an element based on a query selector. + * + * @param node Node to search in. + * @param selector Selector. + * @returns HTML element. + */ + static querySelector(node, selector) { + const window2 = node[window]; + if (selector === "") { + throw new window2.DOMException(`Failed to execute 'querySelector' on '${node.constructor.name}': The provided selector is empty.`); + } + if (typeof selector === "function") { + throw new window2.DOMException(`Failed to execute 'querySelector' on '${node.constructor.name}': '${selector}' is not a valid selector.`); + } + if (typeof selector === "symbol") { + throw new window2.TypeError(`Failed to execute 'querySelector' on '${node.constructor.name}': Cannot convert a Symbol value to a string`); + } + selector = String(selector); + if (INVALID_SELECTOR_REGEXP.test(selector)) { + throw new window2.DOMException(`Failed to execute 'querySelector' on '${node.constructor.name}': '${selector}' is not a valid selector.`); + } + const cachedResult = node[cache].querySelector.get(selector); + if (cachedResult) { + if (cachedResult.result !== null) { + if (!cachedResult.result.element) { + return null; + } + const result3 = cachedResult.result.element.deref(); + if (result3) { + return result3; + } + } + node[cache].querySelector.delete(selector); + } + const cachedItem = { + result: { element: null } + }; + node[cache].querySelector.set(selector, cachedItem); + if (node[isConnected]) { + (node[ownerDocument] || node)[affectsCache].push(cachedItem); + } + let bestMatch = null; + const matchesMap = /* @__PURE__ */ new Map(); + const scope = node[nodeType] === NodeTypeEnum_default.documentNode ? node.documentElement : node; + for (const selectorItems of new SelectorParser({ window: window2, scope }).getSelectorGroups(selector)) { + const rootElement = node[nodeType] === NodeTypeEnum_default.elementNode ? node : null; + const children2 = node[nodeType] === NodeTypeEnum_default.elementNode ? [node] : node[elementArray]; + const match = this.findFirst({ scope, rootElement, children: children2, selectorItems, cachedItem }); + if (match && !matchesMap.has(match.documentPosition)) { + matchesMap.set(match.documentPosition, true); + if (!bestMatch || match.documentPosition < bestMatch.documentPosition) { + bestMatch = match; + } + } + } + const element = bestMatch?.element || null; + cachedItem.result = { element: element ? new WeakRef(element) : null }; + return element; + } + /** + * Checks if an element matches a selector and returns priority weight. + * + * @param element Element to match. + * @param selector Selector to match with. + * @param [options] Options. + * @param [options.scope] Scope. + * @param [options.ignoreErrors] Ignores errors. + * @returns Result. + */ + static matches(element, selector, options2) { + const ignoreErrors = options2?.ignoreErrors; + const window2 = element[window]; + if (selector === "*") { + return { + priorityWeight: 1 + }; + } + if (selector === "") { + if (ignoreErrors) { + return null; + } + throw new window2.DOMException(`Failed to execute 'matches' on '${element.constructor.name}': The provided selector is empty.`); + } + if (typeof selector === "function") { + if (ignoreErrors) { + return null; + } + throw new window2.DOMException(`Failed to execute 'matches' on '${element.constructor.name}': '${selector}' is not a valid selector.`); + } + if (typeof selector === "symbol") { + if (ignoreErrors) { + return null; + } + throw new window2.TypeError(`Cannot convert a Symbol value to a string`); + } + selector = String(selector); + if (INVALID_SELECTOR_REGEXP.test(selector)) { + if (ignoreErrors) { + return null; + } + throw new window2.DOMException(`Failed to execute 'matches' on '${element.constructor.name}': '${selector}' is not a valid selector.`); + } + const cachedResult = element[cache].matches.get(selector); + if (cachedResult) { + if (cachedResult.result !== null) { + return cachedResult.result.match; + } + element[cache].matches.delete(selector); + } + const cachedItem = { + result: { match: null } + }; + element[cache].matches.set(selector, cachedItem); + if (element[isConnected]) { + (element[ownerDocument] || element)[affectsCache].push(cachedItem); + } + const scopeOrElement = options2?.scope || element; + const scope = scopeOrElement[nodeType] === NodeTypeEnum_default.documentNode ? scopeOrElement.documentElement : scopeOrElement; + for (const items2 of new SelectorParser({ + ignoreErrors: options2?.ignoreErrors, + window: window2, + scope + }).getSelectorGroups(selector)) { + const result3 = this.matchSelector({ + scope, + element, + selectorItems: items2.slice().reverse(), + cachedItem, + ignoreErrors + }); + if (result3) { + cachedItem.result.match = result3; + return result3; + } + } + return null; + } + /** + * Checks if a node matches a selector. + * + * @param options Options. + * @param options.scope Scope. + * @param options.element Target element. + * @param options.currentElement + * @param options.selectorItems Selector items. + * @param options.cachedItem Cached item. + * @param [options.ignoreErrors] Ignores errors. + * @param [previousSelectorItem] Previous selector item. + * @param [priorityWeight] Priority weight. + * @returns Result. + */ + static matchSelector(options2, previousSelectorItem = null, priorityWeight = 0) { + const { scope, element, selectorItems, cachedItem, ignoreErrors } = options2; + const selectorItem = selectorItems[0]; + if (!selectorItem) { + return null; + } + const result3 = selectorItem.match(scope, element, ignoreErrors); + if (result3) { + if (selectorItems.length === 1) { + return { + priorityWeight: priorityWeight + result3.priorityWeight + }; + } + switch (selectorItem.combinator) { + case SelectorCombinatorEnum_default.adjacentSibling: + const previousElementSibling = element.previousElementSibling; + if (previousElementSibling) { + previousElementSibling[affectsCache].push(cachedItem); + const match = this.matchSelector({ + scope, + element: previousElementSibling, + selectorItems: selectorItems.slice(1), + cachedItem, + ignoreErrors + }, selectorItem, priorityWeight + result3.priorityWeight); + if (match) { + return match; + } + } + break; + case SelectorCombinatorEnum_default.none: + case SelectorCombinatorEnum_default.child: + case SelectorCombinatorEnum_default.descendant: + const parentElement = element.parentElement; + if (parentElement) { + parentElement[affectsCache].push(cachedItem); + const match = this.matchSelector({ + scope, + element: parentElement, + selectorItems: selectorItems.slice(1), + cachedItem, + ignoreErrors + }, selectorItem, priorityWeight + result3.priorityWeight); + if (match) { + return match; + } + } + break; + case SelectorCombinatorEnum_default.subsequentSibling: + const siblingParentElement = element.parentElement; + if (siblingParentElement) { + const siblings = siblingParentElement[elementArray]; + const index = siblings.indexOf(element); + siblingParentElement[affectsCache].push(cachedItem); + for (let i = index - 1; i >= 0; i--) { + const sibling = siblings[i]; + sibling[affectsCache].push(cachedItem); + const match = this.matchSelector({ + scope, + element: sibling, + selectorItems: selectorItems.slice(1), + cachedItem, + ignoreErrors + }, selectorItem, priorityWeight + result3.priorityWeight); + if (match) { + return match; + } + } + } + break; + } + } + if (previousSelectorItem?.combinator === SelectorCombinatorEnum_default.none || previousSelectorItem?.combinator === SelectorCombinatorEnum_default.descendant) { + const parentElement = element.parentElement; + if (parentElement) { + return this.matchSelector({ + scope, + element: parentElement, + selectorItems, + cachedItem, + ignoreErrors + }, previousSelectorItem, priorityWeight); + } + } + return null; + } + /** + * Finds elements based on a query selector for a part of a list of selectors separated with comma. + * + * @param options Options. + * @param options.scope Scope. + * @param options.rootElement Root element. + * @param options.children Child elements. + * @param options.selectorItems Selector items. + * @param options.cachedItem Cached item. + * @param [documentPosition] Document position of the element. + * @returns Document position and element map. + */ + static findAll(options2, documentPosition) { + const { scope, rootElement, children: children2, selectorItems, cachedItem } = options2; + const selectorItem = selectorItems[0]; + const nextSelectorItem = selectorItems[1]; + let matched = []; + if (!selectorItem) { + return []; + } + for (let i = 0, max = children2.length; i < max; i++) { + const child = children2[i]; + const childrenOfChild = child[elementArray]; + const position = (documentPosition ? documentPosition + ">" : "") + String.fromCharCode(i); + child[affectsCache].push(cachedItem); + if (selectorItem.match(scope, child)) { + if (!nextSelectorItem) { + if (rootElement !== child) { + matched.push({ + documentPosition: position, + element: child + }); + } + } else { + switch (nextSelectorItem.combinator) { + case SelectorCombinatorEnum_default.adjacentSibling: + const nextElementSibling = child.nextElementSibling; + if (nextElementSibling) { + matched = matched.concat(this.findAll({ + scope, + rootElement, + children: [nextElementSibling], + selectorItems: selectorItems.slice(1), + cachedItem + }, position)); + } + break; + case SelectorCombinatorEnum_default.none: + case SelectorCombinatorEnum_default.descendant: + case SelectorCombinatorEnum_default.child: + matched = matched.concat(this.findAll({ + scope, + rootElement, + children: childrenOfChild, + selectorItems: selectorItems.slice(1), + cachedItem + }, position)); + break; + case SelectorCombinatorEnum_default.subsequentSibling: + const index = children2.indexOf(child); + for (let j = index + 1; j < children2.length; j++) { + const sibling = children2[j]; + matched = matched.concat(this.findAll({ + scope, + rootElement, + children: [sibling], + selectorItems: selectorItems.slice(1), + cachedItem + }, position)); + } + break; + } + } + } + if ((selectorItem.combinator === SelectorCombinatorEnum_default.none || selectorItem.combinator === SelectorCombinatorEnum_default.descendant) && childrenOfChild.length) { + matched = matched.concat(this.findAll({ + scope, + rootElement, + children: childrenOfChild, + selectorItems, + cachedItem + }, position)); + } + } + return matched; + } + /** + * Finds an element based on a query selector for a part of a list of selectors separated with comma. + * + * @param options Options. + * @param options.scope Scope. + * @param options.rootElement Root element. + * @param options.children Child elements. + * @param options.selectorItems Selector items. + * @param options.cachedItem Cached item. + * @param [documentPosition] Document position of the element. + * @returns Document position and element map. + */ + static findFirst(options2, documentPosition) { + const { scope, rootElement, children: children2, selectorItems, cachedItem } = options2; + const selectorItem = selectorItems[0]; + const nextSelectorItem = selectorItems[1]; + if (!selectorItem) { + return null; + } + for (let i = 0, max = children2.length; i < max; i++) { + const child = children2[i]; + const childrenOfChild = child[elementArray]; + const position = (documentPosition ? documentPosition + ">" : "") + String.fromCharCode(i); + child[affectsCache].push(cachedItem); + if (selectorItem.match(scope, child)) { + if (!nextSelectorItem) { + if (rootElement !== child) { + return { documentPosition: position, element: child }; + } + } else { + switch (nextSelectorItem.combinator) { + case SelectorCombinatorEnum_default.adjacentSibling: + const nextElementSibling = child.nextElementSibling; + if (nextElementSibling) { + const match2 = this.findFirst({ + scope, + rootElement, + children: [nextElementSibling], + selectorItems: selectorItems.slice(1), + cachedItem + }, position); + if (match2) { + return match2; + } + } + break; + case SelectorCombinatorEnum_default.none: + case SelectorCombinatorEnum_default.descendant: + case SelectorCombinatorEnum_default.child: + const match = this.findFirst({ + scope, + rootElement, + children: childrenOfChild, + selectorItems: selectorItems.slice(1), + cachedItem + }, position); + if (match) { + return match; + } + break; + case SelectorCombinatorEnum_default.subsequentSibling: + const index = children2.indexOf(child); + for (let i2 = index + 1; i2 < children2.length; i2++) { + const sibling = children2[i2]; + const match2 = this.findFirst({ + scope, + rootElement, + children: [sibling], + selectorItems: selectorItems.slice(1), + cachedItem + }, position); + if (match2) { + return match2; + } + } + break; + } + } + } + if ((selectorItem.combinator === SelectorCombinatorEnum_default.none || selectorItem.combinator === SelectorCombinatorEnum_default.descendant) && childrenOfChild.length) { + const match = this.findFirst({ + scope, + rootElement, + children: childrenOfChild, + selectorItems, + cachedItem + }, position); + if (match) { + return match; + } + } + } + return null; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/measurement-converter/CSSMeasurementConverter.js +var CSSMeasurementConverter; +var init_CSSMeasurementConverter = __esm({ + "node_modules/happy-dom/lib/css/declaration/measurement-converter/CSSMeasurementConverter.js"() { + CSSMeasurementConverter = class { + /** + * Returns measurement in pixels. + * + * @param options Options. + * @param options.window Owner window. + * @param options.value Measurement (e.g. "10px", "10rem" or "10em"). + * @param options.rootFontSize Root font size in pixels. + * @param options.parentFontSize Parent font size in pixels. + * @param [options.parentSize] Parent size in pixels. + * @returns Measurement in pixels. + */ + static toPixels(options2) { + const value2 = parseFloat(options2.value); + const unit = options2.value.replace(value2.toString(), ""); + if (isNaN(value2)) { + return null; + } + switch (unit) { + case "px": + return value2; + case "rem": + return this.round(value2 * parseFloat(options2.rootFontSize)); + case "em": + return this.round(value2 * parseFloat(options2.parentFontSize)); + case "vw": + return this.round(value2 * options2.window.innerWidth / 100); + case "vh": + return this.round(value2 * options2.window.innerHeight / 100); + case "%": + return options2.parentSize !== void 0 && options2.parentSize !== null ? this.round(value2 * parseFloat(options2.parentSize) / 100) : null; + case "vmin": + return this.round(value2 * Math.min(options2.window.innerWidth, options2.window.innerHeight) / 100); + case "vmax": + return value2 * Math.max(options2.window.innerWidth, options2.window.innerHeight) / 100; + case "cm": + return this.round(value2 * 37.7812); + case "mm": + return this.round(value2 * 3.7781); + case "in": + return this.round(value2 * 96); + case "pt": + return this.round(value2 * 1.3281); + case "pc": + return this.round(value2 * 16); + case "Q": + return this.round(value2 * 0.945); + default: + return null; + } + } + /** + * Rounds the number with 4 decimals. + * + * @param value Value. + * @returns Rounded value. + */ + static round(value2) { + return Math.round(value2 * 1e4) / 1e4; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/MediaQueryListEvent.js +var MediaQueryListEvent; +var init_MediaQueryListEvent = __esm({ + "node_modules/happy-dom/lib/event/events/MediaQueryListEvent.js"() { + init_Event(); + MediaQueryListEvent = class extends Event2 { + matches; + media; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.matches = eventInit?.matches ?? false; + this.media = eventInit?.media ?? ""; + } + }; + } +}); + +// node_modules/happy-dom/lib/match-media/MediaQueryTypeEnum.js +var MediaQueryTypeEnum, MediaQueryTypeEnum_default; +var init_MediaQueryTypeEnum = __esm({ + "node_modules/happy-dom/lib/match-media/MediaQueryTypeEnum.js"() { + (function(MediaQueryTypeEnum2) { + MediaQueryTypeEnum2["all"] = "all"; + MediaQueryTypeEnum2["print"] = "print"; + MediaQueryTypeEnum2["screen"] = "screen"; + })(MediaQueryTypeEnum || (MediaQueryTypeEnum = {})); + MediaQueryTypeEnum_default = MediaQueryTypeEnum; + } +}); + +// node_modules/happy-dom/lib/match-media/MediaQueryItem.js +var MediaQueryItem; +var init_MediaQueryItem = __esm({ + "node_modules/happy-dom/lib/match-media/MediaQueryItem.js"() { + init_CSSMeasurementConverter(); + init_WindowBrowserContext(); + init_MediaQueryTypeEnum(); + MediaQueryItem = class { + mediaTypes; + not; + rules; + ranges; + rootFontSize = null; + window; + /** + * Constructor. + * + * @param options Options. + * @param options.window Owner window. + * @param [options.rootFontSize] Root font size. + * @param [options.mediaTypes] Media types. + * @param [options.not] Not. + * @param [options.rules] Rules. + * @param [options.ranges] Ranges. + */ + constructor(options2) { + this.window = options2.window; + this.rootFontSize = options2.rootFontSize || null; + this.mediaTypes = options2.mediaTypes || []; + this.not = options2.not || false; + this.rules = options2.rules || []; + this.ranges = options2.ranges || []; + } + /** + * Returns media string. + */ + toString() { + return `${this.not ? "not " : ""}${this.mediaTypes.join(", ")}${(this.not || this.mediaTypes.length > 0) && !!this.ranges.length ? " and " : ""}${this.ranges.map((range) => `(${range.before ? `${range.before.value} ${range.before.operator} ` : ""}${range.type}${range.after ? ` ${range.after.operator} ${range.after.value}` : ""})`).join(" and ")}${(this.not || this.mediaTypes.length > 0) && !!this.rules.length ? " and " : ""}${this.rules.map((rule) => rule.value ? `(${rule.name}: ${rule.value})` : `(${rule.name})`).join(" and ")}`; + } + /** + * Returns "true" if the item matches. + */ + matches() { + return this.not ? !this.matchesAll() : this.matchesAll(); + } + /** + * Returns "true" if all matches. + * + * @returns "true" if all matches. + */ + matchesAll() { + if (!!this.mediaTypes.length) { + let isMediaTypeMatch = false; + for (const mediaType of this.mediaTypes) { + if (this.matchesMediaType(mediaType)) { + isMediaTypeMatch = true; + break; + } + } + if (!isMediaTypeMatch) { + return false; + } + } + for (const rule of this.rules) { + if (!this.matchesRule(rule)) { + return false; + } + } + for (const range of this.ranges) { + if (!this.matchesRange(range)) { + return false; + } + } + return true; + } + /** + * Returns "true" if the mediaType matches. + * + * @param mediaType Media type. + * @returns "true" if the mediaType matches. + */ + matchesMediaType(mediaType) { + if (mediaType === MediaQueryTypeEnum_default.all) { + return true; + } + return mediaType === new WindowBrowserContext(this.window).getSettings()?.device.mediaType; + } + /** + * Returns "true" if the range matches. + * + * @param range Range. + * @returns "true" if the range matches. + */ + matchesRange(range) { + const windowSize = range.type === "width" ? this.window.innerWidth : this.window.innerHeight; + if (range.before) { + const beforeValue = this.toPixels(range.before.value); + if (beforeValue === null) { + return false; + } + switch (range.before.operator) { + case "<": + if (beforeValue >= windowSize) { + return false; + } + break; + case "<=": + if (beforeValue > windowSize) { + return false; + } + break; + case ">": + if (beforeValue <= windowSize) { + return false; + } + break; + case ">=": + if (beforeValue < windowSize) { + return false; + } + break; + } + } + if (range.after) { + const afterValue = this.toPixels(range.after.value); + if (afterValue === null) { + return false; + } + switch (range.after.operator) { + case "<": + if (windowSize >= afterValue) { + return false; + } + break; + case "<=": + if (windowSize > afterValue) { + return false; + } + break; + case ">": + if (windowSize <= afterValue) { + return false; + } + break; + case ">=": + if (windowSize < afterValue) { + return false; + } + break; + } + } + return true; + } + /** + * Returns "true" if the rule matches. + * + * @param rule Rule. + * @returns "true" if the rule matches. + */ + matchesRule(rule) { + const settings2 = new WindowBrowserContext(this.window).getSettings(); + if (!settings2) { + return false; + } + if (!rule.value) { + switch (rule.name) { + case "min-width": + case "max-width": + case "min-height": + case "max-height": + case "width": + case "height": + case "orientation": + case "prefers-color-scheme": + case "hover": + case "any-hover": + case "any-pointer": + case "pointer": + case "display-mode": + case "min-aspect-ratio": + case "max-aspect-ratio": + case "aspect-ratio": + return true; + case "prefers-reduced-motion": + return settings2.device.prefersReducedMotion === "reduce"; + case "forced-colors": + return settings2.device.forcedColors === "active"; + } + return false; + } + switch (rule.name) { + case "min-width": + const minWidth = this.toPixels(rule.value); + return minWidth !== null && this.window.innerWidth >= minWidth; + case "max-width": + const maxWidth = this.toPixels(rule.value); + return maxWidth !== null && this.window.innerWidth <= maxWidth; + case "min-height": + const minHeight = this.toPixels(rule.value); + return minHeight !== null && this.window.innerHeight >= minHeight; + case "max-height": + const maxHeight = this.toPixels(rule.value); + return maxHeight !== null && this.window.innerHeight <= maxHeight; + case "width": + const width2 = this.toPixels(rule.value); + return width2 !== null && this.window.innerWidth === width2; + case "height": + const height2 = this.toPixels(rule.value); + return height2 !== null && this.window.innerHeight === height2; + case "orientation": + return rule.value === "landscape" ? this.window.innerWidth > this.window.innerHeight : this.window.innerWidth < this.window.innerHeight; + case "prefers-color-scheme": + return rule.value === settings2.device.prefersColorScheme; + case "prefers-reduced-motion": + return rule.value === settings2.device.prefersReducedMotion; + case "forced-colors": + return (rule.value === "none" || rule.value === "active") && rule.value === settings2.device.forcedColors; + case "any-hover": + case "hover": + if (rule.value === "none") { + return this.window.navigator.maxTouchPoints > 0; + } + if (rule.value === "hover") { + return this.window.navigator.maxTouchPoints === 0; + } + return false; + case "any-pointer": + case "pointer": + if (rule.value === "none") { + return false; + } + if (rule.value === "coarse") { + return this.window.navigator.maxTouchPoints > 0; + } + if (rule.value === "fine") { + return this.window.navigator.maxTouchPoints === 0; + } + return false; + case "display-mode": + return rule.value === "browser"; + case "min-aspect-ratio": + case "max-aspect-ratio": + case "aspect-ratio": + const aspectRatio = rule.value.split("/"); + const aspectRatioWidth = parseInt(aspectRatio[0], 10); + const aspectRatioHeight = parseInt(aspectRatio[1], 10); + if (isNaN(aspectRatioWidth) || isNaN(aspectRatioHeight)) { + return false; + } + switch (rule.name) { + case "min-aspect-ratio": + return aspectRatioWidth / aspectRatioHeight <= this.window.innerWidth / this.window.innerHeight; + case "max-aspect-ratio": + return aspectRatioWidth / aspectRatioHeight >= this.window.innerWidth / this.window.innerHeight; + case "aspect-ratio": + return aspectRatioWidth / aspectRatioHeight === this.window.innerWidth / this.window.innerHeight; + } + } + return false; + } + /** + * Convert to pixels. + * + * @param value Value. + * @returns Value in pixels. + */ + toPixels(value2) { + if (!new WindowBrowserContext(this.window).getSettings()?.disableComputedStyleRendering && value2.endsWith("em")) { + this.rootFontSize = this.rootFontSize || parseFloat(this.window.getComputedStyle(this.window.document.documentElement).fontSize); + return CSSMeasurementConverter.toPixels({ + window: this.window, + value: value2, + rootFontSize: this.rootFontSize, + parentFontSize: this.rootFontSize + }); + } + return CSSMeasurementConverter.toPixels({ + window: this.window, + value: value2, + rootFontSize: 16, + parentFontSize: 16 + }); + } + }; + } +}); + +// node_modules/happy-dom/lib/match-media/MediaQueryParser.js +var MEDIA_QUERY_REGEXP, IS_RESOLUTION_REGEXP, RESOLUTION_REGEXP, MediaQueryParser; +var init_MediaQueryParser = __esm({ + "node_modules/happy-dom/lib/match-media/MediaQueryParser.js"() { + init_MediaQueryItem(); + init_MediaQueryTypeEnum(); + MEDIA_QUERY_REGEXP = /(not|only|all|screen|print)|\(([^\)]+)(\)){0,1}|(,)| +(or|and) +/g; + IS_RESOLUTION_REGEXP = /[<>]/; + RESOLUTION_REGEXP = /(?:([0-9]+[a-z]+) *(<|<=|>|>=)){0,1} *(width|height) *(?:(<|<=|>|>=) *([0-9]+[a-z]+)){0,1}/; + MediaQueryParser = class { + /** + * Parses a media query string. + * + * @param options Options. + * @param options.window Owner window. + * @param options.mediaQuery Media query string. + * @param [options.rootFontSize] Root font size. + * @returns Media query items. + */ + static parse(options2) { + let currentMediaQueryItem = new MediaQueryItem({ + window: options2.window, + rootFontSize: options2.rootFontSize + }); + const mediaQueryItems = [currentMediaQueryItem]; + const regexp = new RegExp(MEDIA_QUERY_REGEXP); + let match = null; + while (match = regexp.exec(options2.mediaQuery.toLowerCase())) { + if (match[4] === "," || match[5] === "or") { + currentMediaQueryItem = new MediaQueryItem({ + window: options2.window, + rootFontSize: options2.rootFontSize + }); + mediaQueryItems.push(currentMediaQueryItem); + } else if (match[1] === "all" || match[1] === "screen" || match[1] === "print") { + currentMediaQueryItem.mediaTypes.push(match[1]); + } else if (match[1] === "not") { + currentMediaQueryItem.not = true; + } else if (match[2]) { + const resolutionMatch = IS_RESOLUTION_REGEXP.test(match[2]) ? match[2].match(RESOLUTION_REGEXP) : null; + if (resolutionMatch && (resolutionMatch[1] || resolutionMatch[5])) { + currentMediaQueryItem.ranges.push({ + before: resolutionMatch[1] ? { + value: resolutionMatch[1], + operator: resolutionMatch[2] + } : null, + type: resolutionMatch[3], + after: resolutionMatch[5] ? { + value: resolutionMatch[5], + operator: resolutionMatch[4] + } : null + }); + } else { + const [name2, value2] = match[2].split(":"); + const trimmedValue = value2 ? value2.trim() : null; + if (!trimmedValue && !match[3]) { + return [ + new MediaQueryItem({ + window: options2.window, + rootFontSize: options2.rootFontSize, + not: true, + mediaTypes: [MediaQueryTypeEnum_default.all] + }) + ]; + } + currentMediaQueryItem.rules.push({ + name: name2.trim(), + value: trimmedValue + }); + } + } + } + return mediaQueryItems; + } + }; + } +}); + +// node_modules/happy-dom/lib/match-media/MediaQueryList.js +var MediaQueryList; +var init_MediaQueryList = __esm({ + "node_modules/happy-dom/lib/match-media/MediaQueryList.js"() { + init_EventTarget(); + init_PropertySymbol(); + init_MediaQueryListEvent(); + init_MediaQueryParser(); + MediaQueryList = class extends EventTarget2 { + onchange = null; + #window; + #items = null; + #media; + #rootFontSize = null; + /** + * Constructor. + * + * @param options Options. + * @param options.window Owner window. + * @param options.media Media. + * @param [options.rootFontSize] Root font size. + */ + constructor(options2) { + super(); + this.#window = options2.window; + this.#media = options2.media; + this.#rootFontSize = options2.rootFontSize || null; + } + /** + * Returns media. + * + * @returns Media. + */ + get media() { + this.#items = this.#items || MediaQueryParser.parse({ + window: this.#window, + mediaQuery: this.#media, + rootFontSize: this.#rootFontSize + }); + return this.#items.map((item) => item.toString()).join(", "); + } + /** + * Returns "true" if the document matches. + * + * @returns Matches. + */ + get matches() { + this.#items = this.#items || MediaQueryParser.parse({ + window: this.#window, + mediaQuery: this.#media, + rootFontSize: this.#rootFontSize + }); + for (const item of this.#items) { + if (!item.matches()) { + return false; + } + } + return true; + } + /** + * Adds a listener. + * + * @deprecated + * @param callback Callback. + */ + addListener(callback) { + this.addEventListener("change", callback); + } + /** + * Removes listener. + * + * @deprecated + * @param callback Callback. + */ + removeListener(callback) { + this.removeEventListener("change", callback); + } + /** + * @override + */ + addEventListener(type2, listener) { + super.addEventListener(type2, listener); + if (type2 === "change") { + let matchesState = false; + const resizeListener = () => { + const matches = this.matches; + if (matches !== matchesState) { + matchesState = matches; + this.dispatchEvent(new MediaQueryListEvent("change", { matches, media: this.media })); + } + }; + listener[windowResizeListener] = resizeListener; + this.#window.addEventListener("resize", resizeListener); + } + } + /** + * @override + */ + removeEventListener(type2, listener) { + super.removeEventListener(type2, listener); + if (type2 === "change" && listener[windowResizeListener]) { + this.#window.removeEventListener("resize", listener[windowResizeListener]); + } + } + }; + } +}); + +// node_modules/happy-dom/lib/css/rules/CSSGroupingRule.js +var CSSGroupingRule; +var init_CSSGroupingRule = __esm({ + "node_modules/happy-dom/lib/css/rules/CSSGroupingRule.js"() { + init_CSSRule(); + init_DOMExceptionNameEnum(); + init_PropertySymbol(); + CSSGroupingRule = class extends CSSRule { + [cssRules] = []; + /** + * Returns CSS rules. + * + * @returns CSS rules. + */ + get cssRules() { + return this[cssRules]; + } + /** + * Inserts a new rule. + * + * @param rule Rule. + * @param [index] Index. + * @returns The index of the new rule. + */ + insertRule(rule, index) { + if (arguments.length === 0) { + throw new this[window].TypeError(`Failed to execute 'insertRule' on '${this.constructor.name}': 1 argument required, but only 0 present.`); + } + const rules = this[cssParser].parseFromString(rule); + if (rules.length === 0 || rules.length > 1) { + throw new this[window].DOMException(`Failed to execute 'insertRule' on '${this.constructor.name}': Failed to parse the rule '${rule}'.`, DOMExceptionNameEnum_default.syntaxError); + } + if (index !== void 0) { + index = Number(index); + if (isNaN(index) || index > this.cssRules.length) { + throw new this[window].DOMException(`Failed to execute 'insertRule' on '${this.constructor.name}': The index provided (${index}) is larger than the maximum index (${this.cssRules.length}).`, DOMExceptionNameEnum_default.indexSizeError); + } + this.cssRules.splice(index, 0, rules[0]); + return index; + } + const newIndex = this.cssRules.length; + this.cssRules.unshift(rules[0]); + return newIndex; + } + /** + * Removes a rule. + * + * @param index Index. + */ + deleteRule(index) { + if (arguments.length === 0) { + throw new this[window].TypeError(`Failed to execute 'deleteRule' on '${this.constructor.name}': 1 argument required, but only 0 present.`); + } + index = Number(index); + if (isNaN(index) || index < 0 || index >= this.cssRules.length) { + throw new this[window].DOMException(`Failed to execute 'deleteRule' on '${this.constructor.name}': the index (${index}) is greater than the length of the rule list.`, DOMExceptionNameEnum_default.indexSizeError); + } + this.cssRules.splice(index, 1); + } + }; + } +}); + +// node_modules/happy-dom/lib/css/rules/CSSScopeRule.js +var CSSScopeRule; +var init_CSSScopeRule = __esm({ + "node_modules/happy-dom/lib/css/rules/CSSScopeRule.js"() { + init_PropertySymbol(); + init_CSSRuleTypeEnum(); + init_CSSGroupingRule(); + CSSScopeRule = class extends CSSGroupingRule { + [start] = ""; + [end] = ""; + [rulePrefix] = ""; + /** + * @override + */ + get type() { + return CSSRuleTypeEnum_default.containerRule; + } + /** + * @override + */ + get cssText() { + let cssText2 = ""; + for (const cssRule2 of this[cssRules]) { + cssText2 += "\n " + cssRule2.cssText; + } + cssText2 += "\n"; + return `@${this[rulePrefix]}scope${this[start] ? ` (${this[start]})` : ""}${this[end] ? ` to (${this[end]})` : ""} {${cssText2}}`; + } + /** + * Returns start. + * + * @returns Start. + */ + get start() { + return this[start]; + } + /** + * Returns end. + * + * @returns End. + */ + get end() { + return this[end]; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.js +var CSS_MEASUREMENT_REGEXP, HOST_REGEXP, SINGLE_CSS_VARIABLE_REGEXP, CSS_VARIABLE_REGEXP2, CSSStyleDeclarationComputedStyle; +var init_CSSStyleDeclarationComputedStyle = __esm({ + "node_modules/happy-dom/lib/css/declaration/computed-style/CSSStyleDeclarationComputedStyle.js"() { + init_PropertySymbol(); + init_CSSStyleDeclarationPropertyManager(); + init_NodeTypeEnum(); + init_CSSRuleTypeEnum(); + init_CSSStyleDeclarationElementDefaultCSS(); + init_CSSStyleDeclarationElementInheritedProperties(); + init_CSSStyleDeclarationElementMeasurementProperties(); + init_CSSStyleDeclarationCSSParser(); + init_QuerySelector(); + init_CSSMeasurementConverter(); + init_MediaQueryList(); + init_WindowBrowserContext(); + init_CSSScopeRule(); + CSS_MEASUREMENT_REGEXP = /[0-9.]+(px|rem|em|vw|vh|%|vmin|vmax|cm|mm|in|pt|pc|Q)/g; + HOST_REGEXP = /:host\s*\(([^)]+)\)|:host-context\s*\(([^)]+)\)/; + SINGLE_CSS_VARIABLE_REGEXP = /var\( *(--[^), ]+)\)/; + CSS_VARIABLE_REGEXP2 = /var\( *(--[^), ]+), *([^), ]+)\)/; + CSSStyleDeclarationComputedStyle = class { + element; + /** + * Constructor. + * + * @param element Element. + * @param [computed] Computed. + */ + constructor(element) { + this.element = element; + } + /** + * Returns style sheets. + * + * @param element Element. + * @returns Style sheets. + */ + getComputedStyle() { + const documentElements = []; + const parentElements = []; + let styleAndElement = { + element: this.element, + cssTexts: [] + }; + let shadowRootElements = []; + let customElements = []; + if (!this.element[isConnected]) { + return new CSSStyleDeclarationPropertyManager(); + } + const cacheResult = this.element[cache].computedStyle; + if (cacheResult?.result) { + const result3 = cacheResult.result.deref(); + if (result3) { + return result3; + } + } + while (styleAndElement.element) { + if (styleAndElement.element[nodeType] === NodeTypeEnum_default.elementNode) { + const rootNode2 = styleAndElement.element.getRootNode(); + if (rootNode2[nodeType] === NodeTypeEnum_default.documentNode) { + documentElements.unshift(styleAndElement); + } else { + shadowRootElements.unshift(styleAndElement); + } + if (styleAndElement.element.shadowRoot) { + customElements.push(styleAndElement); + } + parentElements.unshift(styleAndElement); + } + if (styleAndElement.element === this.element[ownerDocument]) { + const styleSheets = this.getStyleSheets(this.element[ownerDocument]); + for (const styleSheet of styleSheets) { + this.parseCSSRules({ + elements: documentElements, + cssRules: styleSheet.cssRules + }); + } + for (const customElement of customElements) { + const styleSheets2 = this.getStyleSheets(customElement.element.shadowRoot); + for (const styleSheet of styleSheets2) { + this.parseCSSRules({ + elements: [], + cssRules: styleSheet.cssRules, + hostElement: customElement + }); + } + } + styleAndElement = { element: null, cssTexts: [] }; + } else if (styleAndElement.element[nodeType] === NodeTypeEnum_default.documentFragmentNode && styleAndElement.element.host) { + const shadowRoot2 = styleAndElement.element; + const styleSheets = this.getStyleSheets(shadowRoot2); + styleAndElement = { + element: shadowRoot2.host, + cssTexts: [] + }; + for (const styleSheet of styleSheets) { + this.parseCSSRules({ + elements: shadowRootElements, + cssRules: styleSheet.cssRules, + hostElement: styleAndElement + }); + } + for (const customElement of customElements) { + const styleSheets2 = this.getStyleSheets(customElement.element.shadowRoot); + for (const styleSheet of styleSheets2) { + this.parseCSSRules({ + elements: [], + cssRules: styleSheet.cssRules, + hostElement: customElement + }); + } + } + customElements = []; + shadowRootElements = []; + } else { + styleAndElement = { + element: styleAndElement.element[parentNode], + cssTexts: [] + }; + } + } + const targetElement = parentElements[parentElements.length - 1]; + const propertyManager = new CSSStyleDeclarationPropertyManager(); + const cssProperties = {}; + let rootFontSize = 16; + let parentFontSize = 16; + for (const parentElement of parentElements) { + parentElement.cssTexts.sort((a, b) => a.priorityWeight - b.priorityWeight); + const defaultCSS = CSSStyleDeclarationElementDefaultCSS_default[parentElement.element[tagName]]; + let elementCSSText = ""; + if (defaultCSS) { + if (typeof defaultCSS === "string") { + elementCSSText += defaultCSS; + } else { + for (const key of Object.keys(defaultCSS)) { + if (key === "default" || !!parentElement.element[key]) { + elementCSSText += defaultCSS[key]; + } + } + } + } + for (const cssText2 of parentElement.cssTexts) { + elementCSSText += cssText2.cssText; + } + const elementStyleAttribute = parentElement.element.getAttribute("style"); + if (elementStyleAttribute) { + elementCSSText += elementStyleAttribute; + } + const rulesAndProperties = CSSStyleDeclarationCSSParser.parse(elementCSSText); + const rules = rulesAndProperties.rules; + Object.assign(cssProperties, rulesAndProperties.properties); + for (const { name: name2, value: value2, important } of rules) { + if (CSSStyleDeclarationElementInheritedProperties_default[name2] || parentElement === targetElement) { + const parsedValue = this.parseCSSVariablesInValue(value2.trim(), cssProperties); + if (parsedValue && (!propertyManager.get(name2)?.important || important)) { + propertyManager.set(name2, parsedValue, important); + if (name2 === "font" || name2 === "font-size") { + const fontSize = propertyManager.properties["font-size"]; + if (fontSize !== null) { + const parsedValue2 = this.parseMeasurementsInValue({ + value: fontSize.value, + rootFontSize, + parentFontSize, + parentSize: parentFontSize + }); + if (parentElement.element[tagName] === "HTML") { + rootFontSize = parsedValue2; + } else if (parentElement !== targetElement) { + parentFontSize = parsedValue2; + } + } + } + } + } + } + } + for (const name2 of CSSStyleDeclarationElementMeasurementProperties_default) { + const property = propertyManager.properties[name2]; + if (property) { + property.value = this.parseMeasurementsInValue({ + value: property.value, + rootFontSize, + parentFontSize, + // TODO: Only "font-size" is supported when using percentage values. Add support for other properties. + parentSize: name2 === "font-size" ? parentFontSize : null + }); + } + } + const cachedResult = { + result: new WeakRef(propertyManager) + }; + this.element[cache].computedStyle = cachedResult; + this.element[ownerDocument][affectsComputedStyleCache].push(cachedResult); + return propertyManager; + } + /** + * Returns style sheets. + * + * @param root Root element. + * @returns Style sheets. + */ + getStyleSheets(root2) { + if (!root2) { + return []; + } + const styleElements = root2.querySelectorAll('style,link[rel="stylesheet"]'); + let styleSheets = []; + for (const styleElement of styleElements) { + const sheet2 = styleElement.sheet; + if (sheet2) { + styleSheets.push(sheet2); + } + } + if (root2.adoptedStyleSheets) { + styleSheets = styleSheets.concat(root2.adoptedStyleSheets); + } + return styleSheets; + } + /** + * Applies CSS text to elements. + * + * @param options Options. + * @param options.elements Elements. + * @param options.cssRules CSS rules. + * @param [options.hostElement] Host element. + * @param [options.scopeElement] Scope element. + */ + parseCSSRules(options2) { + if (!options2.hostElement && !options2.elements.length) { + return; + } + const window2 = this.element[window]; + for (const rule of options2.cssRules) { + if (rule.type === CSSRuleTypeEnum_default.styleRule) { + const selectorText2 = rule.selectorText; + if (selectorText2) { + if (selectorText2[0] === ":" && selectorText2.startsWith(":host")) { + if (options2.hostElement) { + let isTargetHost = true; + if (selectorText2 !== ":host") { + const selectorMatch = selectorText2.match(HOST_REGEXP); + if (selectorMatch) { + const match = QuerySelector.matches(options2.hostElement.element, selectorMatch[1] || selectorMatch[2], { + ignoreErrors: true, + scope: options2.scopeElement?.element + }); + if (match) { + const hostContextSelectorText = selectorText2?.replace(HOST_REGEXP, "").trim(); + if (hostContextSelectorText && hostContextSelectorText[0] !== ":") { + isTargetHost = false; + for (const element of options2.elements) { + const match2 = QuerySelector.matches(element.element, hostContextSelectorText, { + ignoreErrors: true, + scope: options2.scopeElement?.element + }); + if (match2) { + element.cssTexts.push({ + cssText: rule[cssText], + priorityWeight: 10 + match2.priorityWeight + }); + } + } + } + } else { + isTargetHost = false; + } + } + } + if (isTargetHost) { + options2.hostElement.cssTexts.push({ + cssText: rule[cssText], + priorityWeight: 10 + }); + } + } + } else { + for (const element of options2.elements) { + const match = QuerySelector.matches(element.element, selectorText2, { + ignoreErrors: true, + scope: options2.scopeElement?.element + }); + if (match) { + element.cssTexts.push({ + cssText: rule[cssText], + priorityWeight: match.priorityWeight + }); + } + } + } + } + } else if (rule.type === CSSRuleTypeEnum_default.mediaRule && // TODO: We need to send in a predefined root font size as it will otherwise be calculated using Window.getComputedStyle(), which will cause a never ending loop. Is there another solution? + new MediaQueryList({ + window: window2, + media: rule.conditionText, + rootFontSize: this.element[tagName] === "HTML" ? 16 : null + }).matches) { + this.parseCSSRules({ + elements: options2.elements, + cssRules: rule.cssRules, + hostElement: options2.hostElement, + scopeElement: options2.scopeElement + }); + } else if (rule.type === CSSRuleTypeEnum_default.supportsRule) { + if (window2.CSS.supports(rule.conditionText)) { + this.parseCSSRules({ + elements: options2.elements, + cssRules: rule.cssRules, + hostElement: options2.hostElement, + scopeElement: options2.scopeElement + }); + } + } else if (rule.type === CSSRuleTypeEnum_default.containerRule) { + if (rule instanceof CSSScopeRule) { + const scopedElements = []; + let scope = null; + for (const element of options2.elements) { + if (scope) { + if (rule[end]) { + const match = QuerySelector.matches(element.element, rule[end], { + ignoreErrors: true, + scope: scope.element + }); + if (match) { + break; + } + } + scopedElements.push(element); + } else { + const match = QuerySelector.matches(element.element, rule[start] || ":root", { + ignoreErrors: true + }); + if (match) { + scope = element; + scopedElements.push(element); + } + } + } + if (scopedElements.length) { + this.parseCSSRules({ + elements: scopedElements, + cssRules: rule.cssRules, + hostElement: options2.hostElement, + scopeElement: scope + }); + } + } + } + } + } + /** + * Parses CSS variables in a value. + * + * @param value Value. + * @param cssVariables CSS variables. + * @returns CSS value. + */ + parseCSSVariablesInValue(value2, cssVariables) { + let newValue = value2; + let match; + while ((match = newValue.match(SINGLE_CSS_VARIABLE_REGEXP)) != null) { + newValue = newValue.replace(match[0], cssVariables[match[1]] || ""); + } + while ((match = newValue.match(CSS_VARIABLE_REGEXP2)) !== null) { + newValue = newValue.replace(match[0], cssVariables[match[1]] || match[2]); + } + return newValue; + } + /** + * Parses measurements in a value. + * + * @param options Options. + * @param options.value Value. + * @param options.rootFontSize Root font size. + * @param options.parentFontSize Parent font size. + * @param [options.parentSize] Parent width. + * @returns CSS value. + */ + parseMeasurementsInValue(options2) { + if (new WindowBrowserContext(this.element[window]).getSettings()?.disableComputedStyleRendering) { + return options2.value; + } + const regexp = new RegExp(CSS_MEASUREMENT_REGEXP); + let newValue = options2.value; + let match; + while ((match = regexp.exec(options2.value)) !== null) { + if (match[1] !== "px") { + const valueInPixels = CSSMeasurementConverter.toPixels({ + window: this.element[window], + value: match[0], + rootFontSize: options2.rootFontSize, + parentFontSize: options2.parentFontSize, + parentSize: options2.parentSize + }); + if (valueInPixels !== null) { + newValue = newValue.replace(match[0], valueInPixels + "px"); + } + } + } + return newValue; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/declaration/CSSStyleDeclaration.js +var CSSStyleDeclaration; +var init_CSSStyleDeclaration = __esm({ + "node_modules/happy-dom/lib/css/declaration/CSSStyleDeclaration.js"() { + init_DOMExceptionNameEnum(); + init_CSSStyleDeclarationPropertyManager(); + init_PropertySymbol(); + init_CSSStyleDeclarationComputedStyle(); + CSSStyleDeclaration = class { + // Public properties + parentRule = null; + // Internal properties + [window]; + // Private properties + #element; + #computed; + #cache = { + attributeValue: null, + propertyManager: null + }; + /** + * Constructor. + * + * @param illegalConstructorSymbol Illegal constructor symbol. + * @param window Window. + * @param [options] Options. + * @param [options.element] Element. + * @param [options.computed] Computed. + */ + constructor(illegalConstructorSymbol, window2, options2) { + if (illegalConstructorSymbol !== illegalConstructor) { + throw new TypeError("Illegal constructor"); + } + this[window] = window2; + this.#element = options2?.element || null; + this.#computed = options2?.element ? !!options2?.computed : false; + } + /** + * Index properties + */ + /* eslint-disable jsdoc/require-jsdoc */ + get 0() { + return this.item(0) || void 0; + } + get 1() { + return this.item(1) || void 0; + } + get 2() { + return this.item(2) || void 0; + } + get 3() { + return this.item(3) || void 0; + } + get 4() { + return this.item(4) || void 0; + } + get 5() { + return this.item(5) || void 0; + } + get 6() { + return this.item(6) || void 0; + } + get 7() { + return this.item(7) || void 0; + } + get 8() { + return this.item(8) || void 0; + } + get 9() { + return this.item(9) || void 0; + } + get 10() { + return this.item(10) || void 0; + } + get 11() { + return this.item(11) || void 0; + } + get 12() { + return this.item(12) || void 0; + } + get 13() { + return this.item(13) || void 0; + } + get 14() { + return this.item(14) || void 0; + } + get 15() { + return this.item(15) || void 0; + } + get 16() { + return this.item(16) || void 0; + } + get 17() { + return this.item(17) || void 0; + } + get 18() { + return this.item(18) || void 0; + } + get 19() { + return this.item(19) || void 0; + } + get 20() { + return this.item(20) || void 0; + } + get 21() { + return this.item(21) || void 0; + } + get 22() { + return this.item(22) || void 0; + } + get 23() { + return this.item(23) || void 0; + } + get 24() { + return this.item(24) || void 0; + } + get 25() { + return this.item(25) || void 0; + } + get 26() { + return this.item(26) || void 0; + } + get 27() { + return this.item(27) || void 0; + } + get 28() { + return this.item(28) || void 0; + } + get 29() { + return this.item(29) || void 0; + } + get 30() { + return this.item(30) || void 0; + } + get 31() { + return this.item(31) || void 0; + } + get 32() { + return this.item(32) || void 0; + } + get 33() { + return this.item(33) || void 0; + } + get 34() { + return this.item(34) || void 0; + } + get 35() { + return this.item(35) || void 0; + } + get 36() { + return this.item(36) || void 0; + } + get 37() { + return this.item(37) || void 0; + } + get 38() { + return this.item(38) || void 0; + } + get 39() { + return this.item(39) || void 0; + } + get 40() { + return this.item(40) || void 0; + } + get 41() { + return this.item(41) || void 0; + } + get 42() { + return this.item(42) || void 0; + } + get 43() { + return this.item(43) || void 0; + } + get 44() { + return this.item(44) || void 0; + } + get 45() { + return this.item(45) || void 0; + } + get 46() { + return this.item(46) || void 0; + } + get 47() { + return this.item(47) || void 0; + } + get 48() { + return this.item(48) || void 0; + } + get 49() { + return this.item(49) || void 0; + } + get 50() { + return this.item(50) || void 0; + } + get 51() { + return this.item(51) || void 0; + } + get 52() { + return this.item(52) || void 0; + } + get 53() { + return this.item(53) || void 0; + } + get 54() { + return this.item(54) || void 0; + } + get 55() { + return this.item(55) || void 0; + } + get 56() { + return this.item(56) || void 0; + } + get 57() { + return this.item(57) || void 0; + } + get 58() { + return this.item(58) || void 0; + } + get 59() { + return this.item(59) || void 0; + } + get 60() { + return this.item(60) || void 0; + } + get 61() { + return this.item(61) || void 0; + } + get 62() { + return this.item(62) || void 0; + } + get 63() { + return this.item(63) || void 0; + } + get 64() { + return this.item(64) || void 0; + } + get 65() { + return this.item(65) || void 0; + } + get 66() { + return this.item(66) || void 0; + } + get 67() { + return this.item(67) || void 0; + } + get 68() { + return this.item(68) || void 0; + } + get 69() { + return this.item(69) || void 0; + } + get 70() { + return this.item(70) || void 0; + } + get 71() { + return this.item(71) || void 0; + } + get 72() { + return this.item(72) || void 0; + } + get 73() { + return this.item(73) || void 0; + } + get 74() { + return this.item(74) || void 0; + } + get 75() { + return this.item(75) || void 0; + } + get 76() { + return this.item(76) || void 0; + } + get 77() { + return this.item(77) || void 0; + } + get 78() { + return this.item(78) || void 0; + } + get 79() { + return this.item(79) || void 0; + } + get 80() { + return this.item(80) || void 0; + } + get 81() { + return this.item(81) || void 0; + } + get 82() { + return this.item(82) || void 0; + } + get 83() { + return this.item(83) || void 0; + } + get 84() { + return this.item(84) || void 0; + } + get 85() { + return this.item(85) || void 0; + } + get 86() { + return this.item(86) || void 0; + } + get 87() { + return this.item(87) || void 0; + } + get 88() { + return this.item(88) || void 0; + } + get 89() { + return this.item(89) || void 0; + } + get 90() { + return this.item(90) || void 0; + } + get 91() { + return this.item(91) || void 0; + } + get 92() { + return this.item(92) || void 0; + } + get 93() { + return this.item(93) || void 0; + } + get 94() { + return this.item(94) || void 0; + } + get 95() { + return this.item(95) || void 0; + } + get 96() { + return this.item(96) || void 0; + } + get 97() { + return this.item(97) || void 0; + } + get 98() { + return this.item(98) || void 0; + } + get 99() { + return this.item(99) || void 0; + } + get 100() { + return this.item(100) || void 0; + } + get 101() { + return this.item(101) || void 0; + } + get 102() { + return this.item(102) || void 0; + } + get 103() { + return this.item(103) || void 0; + } + get 104() { + return this.item(104) || void 0; + } + get 105() { + return this.item(105) || void 0; + } + get 106() { + return this.item(106) || void 0; + } + get 107() { + return this.item(107) || void 0; + } + get 108() { + return this.item(108) || void 0; + } + get 109() { + return this.item(109) || void 0; + } + get 110() { + return this.item(110) || void 0; + } + get 111() { + return this.item(111) || void 0; + } + get 112() { + return this.item(112) || void 0; + } + get 113() { + return this.item(113) || void 0; + } + get 114() { + return this.item(114) || void 0; + } + get 115() { + return this.item(115) || void 0; + } + get 116() { + return this.item(116) || void 0; + } + get 117() { + return this.item(117) || void 0; + } + get 118() { + return this.item(118) || void 0; + } + get 119() { + return this.item(119) || void 0; + } + get 120() { + return this.item(120) || void 0; + } + get 121() { + return this.item(121) || void 0; + } + get 122() { + return this.item(122) || void 0; + } + get 123() { + return this.item(123) || void 0; + } + get 124() { + return this.item(124) || void 0; + } + get 125() { + return this.item(125) || void 0; + } + get 126() { + return this.item(126) || void 0; + } + get 127() { + return this.item(127) || void 0; + } + get 128() { + return this.item(128) || void 0; + } + get 129() { + return this.item(129) || void 0; + } + get 130() { + return this.item(130) || void 0; + } + get 131() { + return this.item(131) || void 0; + } + get 132() { + return this.item(132) || void 0; + } + get 133() { + return this.item(133) || void 0; + } + get 134() { + return this.item(134) || void 0; + } + get 135() { + return this.item(135) || void 0; + } + get 136() { + return this.item(136) || void 0; + } + get 137() { + return this.item(137) || void 0; + } + get 138() { + return this.item(138) || void 0; + } + get 139() { + return this.item(139) || void 0; + } + get 140() { + return this.item(140) || void 0; + } + get 141() { + return this.item(141) || void 0; + } + get 142() { + return this.item(142) || void 0; + } + get 143() { + return this.item(143) || void 0; + } + get 144() { + return this.item(144) || void 0; + } + get 145() { + return this.item(145) || void 0; + } + get 146() { + return this.item(146) || void 0; + } + get 147() { + return this.item(147) || void 0; + } + get 148() { + return this.item(148) || void 0; + } + get 149() { + return this.item(149) || void 0; + } + get 150() { + return this.item(150) || void 0; + } + get 151() { + return this.item(151) || void 0; + } + get 152() { + return this.item(152) || void 0; + } + get 153() { + return this.item(153) || void 0; + } + get 154() { + return this.item(154) || void 0; + } + get 155() { + return this.item(155) || void 0; + } + get 156() { + return this.item(156) || void 0; + } + get 157() { + return this.item(157) || void 0; + } + get 158() { + return this.item(158) || void 0; + } + get 159() { + return this.item(159) || void 0; + } + get 160() { + return this.item(160) || void 0; + } + get 161() { + return this.item(161) || void 0; + } + get 162() { + return this.item(162) || void 0; + } + get 163() { + return this.item(163) || void 0; + } + get 164() { + return this.item(164) || void 0; + } + get 165() { + return this.item(165) || void 0; + } + get 166() { + return this.item(166) || void 0; + } + get 167() { + return this.item(167) || void 0; + } + get 168() { + return this.item(168) || void 0; + } + get 169() { + return this.item(169) || void 0; + } + get 170() { + return this.item(170) || void 0; + } + get 171() { + return this.item(171) || void 0; + } + get 172() { + return this.item(172) || void 0; + } + get 173() { + return this.item(173) || void 0; + } + get 174() { + return this.item(174) || void 0; + } + get 175() { + return this.item(175) || void 0; + } + get 176() { + return this.item(176) || void 0; + } + get 177() { + return this.item(177) || void 0; + } + get 178() { + return this.item(178) || void 0; + } + get 179() { + return this.item(179) || void 0; + } + get 180() { + return this.item(180) || void 0; + } + get 181() { + return this.item(181) || void 0; + } + get 182() { + return this.item(182) || void 0; + } + get 183() { + return this.item(183) || void 0; + } + get 184() { + return this.item(184) || void 0; + } + get 185() { + return this.item(185) || void 0; + } + get 186() { + return this.item(186) || void 0; + } + get 187() { + return this.item(187) || void 0; + } + get 188() { + return this.item(188) || void 0; + } + get 189() { + return this.item(189) || void 0; + } + get 190() { + return this.item(190) || void 0; + } + get 191() { + return this.item(191) || void 0; + } + get 192() { + return this.item(192) || void 0; + } + get 193() { + return this.item(193) || void 0; + } + get 194() { + return this.item(194) || void 0; + } + get 195() { + return this.item(195) || void 0; + } + get 196() { + return this.item(196) || void 0; + } + get 197() { + return this.item(197) || void 0; + } + get 198() { + return this.item(198) || void 0; + } + get 199() { + return this.item(199) || void 0; + } + get 200() { + return this.item(200) || void 0; + } + get 201() { + return this.item(201) || void 0; + } + get 202() { + return this.item(202) || void 0; + } + get 203() { + return this.item(203) || void 0; + } + get 204() { + return this.item(204) || void 0; + } + get 205() { + return this.item(205) || void 0; + } + get 206() { + return this.item(206) || void 0; + } + get 207() { + return this.item(207) || void 0; + } + get 208() { + return this.item(208) || void 0; + } + get 209() { + return this.item(209) || void 0; + } + get 210() { + return this.item(210) || void 0; + } + get 211() { + return this.item(211) || void 0; + } + get 212() { + return this.item(212) || void 0; + } + get 213() { + return this.item(213) || void 0; + } + get 214() { + return this.item(214) || void 0; + } + get 215() { + return this.item(215) || void 0; + } + get 216() { + return this.item(216) || void 0; + } + get 217() { + return this.item(217) || void 0; + } + get 218() { + return this.item(218) || void 0; + } + get 219() { + return this.item(219) || void 0; + } + get 220() { + return this.item(220) || void 0; + } + get 221() { + return this.item(221) || void 0; + } + get 222() { + return this.item(222) || void 0; + } + get 223() { + return this.item(223) || void 0; + } + get 224() { + return this.item(224) || void 0; + } + get 225() { + return this.item(225) || void 0; + } + get 226() { + return this.item(226) || void 0; + } + get 227() { + return this.item(227) || void 0; + } + get 228() { + return this.item(228) || void 0; + } + get 229() { + return this.item(229) || void 0; + } + get 230() { + return this.item(230) || void 0; + } + get 231() { + return this.item(231) || void 0; + } + get 232() { + return this.item(232) || void 0; + } + get 233() { + return this.item(233) || void 0; + } + get 234() { + return this.item(234) || void 0; + } + get 235() { + return this.item(235) || void 0; + } + get 236() { + return this.item(236) || void 0; + } + get 237() { + return this.item(237) || void 0; + } + get 238() { + return this.item(238) || void 0; + } + get 239() { + return this.item(239) || void 0; + } + get 240() { + return this.item(240) || void 0; + } + get 241() { + return this.item(241) || void 0; + } + get 242() { + return this.item(242) || void 0; + } + get 243() { + return this.item(243) || void 0; + } + get 244() { + return this.item(244) || void 0; + } + get 245() { + return this.item(245) || void 0; + } + get 246() { + return this.item(246) || void 0; + } + get 247() { + return this.item(247) || void 0; + } + get 248() { + return this.item(248) || void 0; + } + get 249() { + return this.item(249) || void 0; + } + get 250() { + return this.item(250) || void 0; + } + get 251() { + return this.item(251) || void 0; + } + get 252() { + return this.item(252) || void 0; + } + get 253() { + return this.item(253) || void 0; + } + get 254() { + return this.item(254) || void 0; + } + get 255() { + return this.item(255) || void 0; + } + get 256() { + return this.item(256) || void 0; + } + get 257() { + return this.item(257) || void 0; + } + get 258() { + return this.item(258) || void 0; + } + get 259() { + return this.item(259) || void 0; + } + get 260() { + return this.item(260) || void 0; + } + get 261() { + return this.item(261) || void 0; + } + get 262() { + return this.item(262) || void 0; + } + get 263() { + return this.item(263) || void 0; + } + get 264() { + return this.item(264) || void 0; + } + get 265() { + return this.item(265) || void 0; + } + get 266() { + return this.item(266) || void 0; + } + get 267() { + return this.item(267) || void 0; + } + get 268() { + return this.item(268) || void 0; + } + get 269() { + return this.item(269) || void 0; + } + get 270() { + return this.item(270) || void 0; + } + get 271() { + return this.item(271) || void 0; + } + get 272() { + return this.item(272) || void 0; + } + get 273() { + return this.item(273) || void 0; + } + get 274() { + return this.item(274) || void 0; + } + get 275() { + return this.item(275) || void 0; + } + get 276() { + return this.item(276) || void 0; + } + get 277() { + return this.item(277) || void 0; + } + get 278() { + return this.item(278) || void 0; + } + get 279() { + return this.item(279) || void 0; + } + get 280() { + return this.item(280) || void 0; + } + get 281() { + return this.item(281) || void 0; + } + get 282() { + return this.item(282) || void 0; + } + get 283() { + return this.item(283) || void 0; + } + get 284() { + return this.item(284) || void 0; + } + get 285() { + return this.item(285) || void 0; + } + get 286() { + return this.item(286) || void 0; + } + get 287() { + return this.item(287) || void 0; + } + get 288() { + return this.item(288) || void 0; + } + get 289() { + return this.item(289) || void 0; + } + get 290() { + return this.item(290) || void 0; + } + get 291() { + return this.item(291) || void 0; + } + get 292() { + return this.item(292) || void 0; + } + get 293() { + return this.item(293) || void 0; + } + get 294() { + return this.item(294) || void 0; + } + get 295() { + return this.item(295) || void 0; + } + get 296() { + return this.item(296) || void 0; + } + get 297() { + return this.item(297) || void 0; + } + get 298() { + return this.item(298) || void 0; + } + get 299() { + return this.item(299) || void 0; + } + get 300() { + return this.item(300) || void 0; + } + get 301() { + return this.item(301) || void 0; + } + get 302() { + return this.item(302) || void 0; + } + get 303() { + return this.item(303) || void 0; + } + get 304() { + return this.item(304) || void 0; + } + get 305() { + return this.item(305) || void 0; + } + get 306() { + return this.item(306) || void 0; + } + get 307() { + return this.item(307) || void 0; + } + get 308() { + return this.item(308) || void 0; + } + get 309() { + return this.item(309) || void 0; + } + get 310() { + return this.item(310) || void 0; + } + get 311() { + return this.item(311) || void 0; + } + get 312() { + return this.item(312) || void 0; + } + get 313() { + return this.item(313) || void 0; + } + get 314() { + return this.item(314) || void 0; + } + get 315() { + return this.item(315) || void 0; + } + get 316() { + return this.item(316) || void 0; + } + get 317() { + return this.item(317) || void 0; + } + get 318() { + return this.item(318) || void 0; + } + get 319() { + return this.item(319) || void 0; + } + get 320() { + return this.item(320) || void 0; + } + get 321() { + return this.item(321) || void 0; + } + get 322() { + return this.item(322) || void 0; + } + get 323() { + return this.item(323) || void 0; + } + get 324() { + return this.item(324) || void 0; + } + get 325() { + return this.item(325) || void 0; + } + get 326() { + return this.item(326) || void 0; + } + get 327() { + return this.item(327) || void 0; + } + get 328() { + return this.item(328) || void 0; + } + get 329() { + return this.item(329) || void 0; + } + get 330() { + return this.item(330) || void 0; + } + get 331() { + return this.item(331) || void 0; + } + get 332() { + return this.item(332) || void 0; + } + get 333() { + return this.item(333) || void 0; + } + get 334() { + return this.item(334) || void 0; + } + get 335() { + return this.item(335) || void 0; + } + get 336() { + return this.item(336) || void 0; + } + get 337() { + return this.item(337) || void 0; + } + get 338() { + return this.item(338) || void 0; + } + get 339() { + return this.item(339) || void 0; + } + get 340() { + return this.item(340) || void 0; + } + get 341() { + return this.item(341) || void 0; + } + get 342() { + return this.item(342) || void 0; + } + get 343() { + return this.item(343) || void 0; + } + get 344() { + return this.item(344) || void 0; + } + get 345() { + return this.item(345) || void 0; + } + get 346() { + return this.item(346) || void 0; + } + get 347() { + return this.item(347) || void 0; + } + get 348() { + return this.item(348) || void 0; + } + get 349() { + return this.item(349) || void 0; + } + get 350() { + return this.item(350) || void 0; + } + get 351() { + return this.item(351) || void 0; + } + get 352() { + return this.item(352) || void 0; + } + get 353() { + return this.item(353) || void 0; + } + get 354() { + return this.item(354) || void 0; + } + get 355() { + return this.item(355) || void 0; + } + get 356() { + return this.item(356) || void 0; + } + get 357() { + return this.item(357) || void 0; + } + get 358() { + return this.item(358) || void 0; + } + get 359() { + return this.item(359) || void 0; + } + get 360() { + return this.item(360) || void 0; + } + get 361() { + return this.item(361) || void 0; + } + get 362() { + return this.item(362) || void 0; + } + get 363() { + return this.item(363) || void 0; + } + get 364() { + return this.item(364) || void 0; + } + get 365() { + return this.item(365) || void 0; + } + get 366() { + return this.item(366) || void 0; + } + get 367() { + return this.item(367) || void 0; + } + get 368() { + return this.item(368) || void 0; + } + get 369() { + return this.item(369) || void 0; + } + get 370() { + return this.item(370) || void 0; + } + get 371() { + return this.item(371) || void 0; + } + get 372() { + return this.item(372) || void 0; + } + get 373() { + return this.item(373) || void 0; + } + get 374() { + return this.item(374) || void 0; + } + get 375() { + return this.item(375) || void 0; + } + get 376() { + return this.item(376) || void 0; + } + get 377() { + return this.item(377) || void 0; + } + get 378() { + return this.item(378) || void 0; + } + get 379() { + return this.item(379) || void 0; + } + get 380() { + return this.item(380) || void 0; + } + get 381() { + return this.item(381) || void 0; + } + get 382() { + return this.item(382) || void 0; + } + get 383() { + return this.item(383) || void 0; + } + get 384() { + return this.item(384) || void 0; + } + get 385() { + return this.item(385) || void 0; + } + get 386() { + return this.item(386) || void 0; + } + get 387() { + return this.item(387) || void 0; + } + get 388() { + return this.item(388) || void 0; + } + get 389() { + return this.item(389) || void 0; + } + get 390() { + return this.item(390) || void 0; + } + get 391() { + return this.item(391) || void 0; + } + get 392() { + return this.item(392) || void 0; + } + get 393() { + return this.item(393) || void 0; + } + /** + * CSS properties + */ + get accentColor() { + return this.getPropertyValue("accent-color"); + } + set accentColor(value2) { + this.setProperty("accent-color", value2); + } + get appRegion() { + return this.getPropertyValue("app-region"); + } + set appRegion(value2) { + this.setProperty("app-region", value2); + } + get alignContent() { + return this.getPropertyValue("align-content"); + } + set alignContent(value2) { + this.setProperty("align-content", value2); + } + get alignItems() { + return this.getPropertyValue("align-items"); + } + set alignItems(value2) { + this.setProperty("align-items", value2); + } + get alignSelf() { + return this.getPropertyValue("align-self"); + } + set alignSelf(value2) { + this.setProperty("align-self", value2); + } + get alignmentBaseline() { + return this.getPropertyValue("alignment-baseline"); + } + set alignmentBaseline(value2) { + this.setProperty("alignment-baseline", value2); + } + get all() { + return this.getPropertyValue("all"); + } + set all(value2) { + this.setProperty("all", value2); + } + get animation() { + return this.getPropertyValue("animation"); + } + set animation(value2) { + this.setProperty("animation", value2); + } + get animationDelay() { + return this.getPropertyValue("animation-delay"); + } + set animationDelay(value2) { + this.setProperty("animation-delay", value2); + } + get animationDirection() { + return this.getPropertyValue("animation-direction"); + } + set animationDirection(value2) { + this.setProperty("animation-direction", value2); + } + get animationDuration() { + return this.getPropertyValue("animation-duration"); + } + set animationDuration(value2) { + this.setProperty("animation-duration", value2); + } + get animationFillMode() { + return this.getPropertyValue("animation-fill-mode"); + } + set animationFillMode(value2) { + this.setProperty("animation-fill-mode", value2); + } + get animationIterationCount() { + return this.getPropertyValue("animation-iteration-count"); + } + set animationIterationCount(value2) { + this.setProperty("animation-iteration-count", value2); + } + get animationName() { + return this.getPropertyValue("animation-name"); + } + set animationName(value2) { + this.setProperty("animation-name", value2); + } + get animationPlayState() { + return this.getPropertyValue("animation-play-state"); + } + set animationPlayState(value2) { + this.setProperty("animation-play-state", value2); + } + get animationTimingFunction() { + return this.getPropertyValue("animation-timing-function"); + } + set animationTimingFunction(value2) { + this.setProperty("animation-timing-function", value2); + } + get appearance() { + return this.getPropertyValue("appearance"); + } + set appearance(value2) { + this.setProperty("appearance", value2); + } + get backdropFilter() { + return this.getPropertyValue("backdrop-filter"); + } + set backdropFilter(value2) { + this.setProperty("backdrop-filter", value2); + } + get backfaceVisibility() { + return this.getPropertyValue("backface-visibility"); + } + set backfaceVisibility(value2) { + this.setProperty("backface-visibility", value2); + } + get background() { + return this.getPropertyValue("background"); + } + set background(value2) { + this.setProperty("background", value2); + } + get backgroundAttachment() { + return this.getPropertyValue("background-attachment"); + } + set backgroundAttachment(value2) { + this.setProperty("background-attachment", value2); + } + get backgroundBlendMode() { + return this.getPropertyValue("background-blend-mode"); + } + set backgroundBlendMode(value2) { + this.setProperty("background-blend-mode", value2); + } + get backgroundClip() { + return this.getPropertyValue("background-clip"); + } + set backgroundClip(value2) { + this.setProperty("background-clip", value2); + } + get backgroundColor() { + return this.getPropertyValue("background-color"); + } + set backgroundColor(value2) { + this.setProperty("background-color", value2); + } + get backgroundImage() { + return this.getPropertyValue("background-image"); + } + set backgroundImage(value2) { + this.setProperty("background-image", value2); + } + get backgroundOrigin() { + return this.getPropertyValue("background-origin"); + } + set backgroundOrigin(value2) { + this.setProperty("background-origin", value2); + } + get backgroundPosition() { + return this.getPropertyValue("background-position"); + } + set backgroundPosition(value2) { + this.setProperty("background-position", value2); + } + get backgroundPositionX() { + return this.getPropertyValue("background-position-x"); + } + set backgroundPositionX(value2) { + this.setProperty("background-position-x", value2); + } + get backgroundPositionY() { + return this.getPropertyValue("background-position-y"); + } + set backgroundPositionY(value2) { + this.setProperty("background-position-y", value2); + } + get backgroundRepeat() { + return this.getPropertyValue("background-repeat"); + } + set backgroundRepeat(value2) { + this.setProperty("background-repeat", value2); + } + get backgroundRepeatX() { + return this.getPropertyValue("background-repeat-x"); + } + set backgroundRepeatX(value2) { + this.setProperty("background-repeat-x", value2); + } + get backgroundRepeatY() { + return this.getPropertyValue("background-repeat-y"); + } + set backgroundRepeatY(value2) { + this.setProperty("background-repeat-y", value2); + } + get backgroundSize() { + return this.getPropertyValue("background-size"); + } + set backgroundSize(value2) { + this.setProperty("background-size", value2); + } + get baselineShift() { + return this.getPropertyValue("baseline-shift"); + } + set baselineShift(value2) { + this.setProperty("baseline-shift", value2); + } + get blockSize() { + return this.getPropertyValue("block-size"); + } + set blockSize(value2) { + this.setProperty("block-size", value2); + } + get border() { + return this.getPropertyValue("border"); + } + set border(value2) { + this.setProperty("border", value2); + } + get borderBlockEnd() { + return this.getPropertyValue("border-block-end"); + } + set borderBlockEnd(value2) { + this.setProperty("border-block-end", value2); + } + get borderBlockEndColor() { + return this.getPropertyValue("border-block-end-color"); + } + set borderBlockEndColor(value2) { + this.setProperty("border-block-end-color", value2); + } + get borderBlockEndStyle() { + return this.getPropertyValue("border-block-end-style"); + } + set borderBlockEndStyle(value2) { + this.setProperty("border-block-end-style", value2); + } + get borderBlockEndWidth() { + return this.getPropertyValue("border-block-end-width"); + } + set borderBlockEndWidth(value2) { + this.setProperty("border-block-end-width", value2); + } + get borderBlockStart() { + return this.getPropertyValue("border-block-start"); + } + set borderBlockStart(value2) { + this.setProperty("border-block-start", value2); + } + get borderBlockStartColor() { + return this.getPropertyValue("border-block-start-color"); + } + set borderBlockStartColor(value2) { + this.setProperty("border-block-start-color", value2); + } + get borderBlockStartStyle() { + return this.getPropertyValue("border-block-start-style"); + } + set borderBlockStartStyle(value2) { + this.setProperty("border-block-start-style", value2); + } + get borderBlockStartWidth() { + return this.getPropertyValue("border-block-start-width"); + } + set borderBlockStartWidth(value2) { + this.setProperty("border-block-start-width", value2); + } + get borderBottom() { + return this.getPropertyValue("border-bottom"); + } + set borderBottom(value2) { + this.setProperty("border-bottom", value2); + } + get borderBottomColor() { + return this.getPropertyValue("border-bottom-color"); + } + set borderBottomColor(value2) { + this.setProperty("border-bottom-color", value2); + } + get borderBottomLeftRadius() { + return this.getPropertyValue("border-bottom-left-radius"); + } + set borderBottomLeftRadius(value2) { + this.setProperty("border-bottom-left-radius", value2); + } + get borderBottomRightRadius() { + return this.getPropertyValue("border-bottom-right-radius"); + } + set borderBottomRightRadius(value2) { + this.setProperty("border-bottom-right-radius", value2); + } + get borderBottomStyle() { + return this.getPropertyValue("border-bottom-style"); + } + set borderBottomStyle(value2) { + this.setProperty("border-bottom-style", value2); + } + get borderBottomWidth() { + return this.getPropertyValue("border-bottom-width"); + } + set borderBottomWidth(value2) { + this.setProperty("border-bottom-width", value2); + } + get borderCollapse() { + return this.getPropertyValue("border-collapse"); + } + set borderCollapse(value2) { + this.setProperty("border-collapse", value2); + } + get borderColor() { + return this.getPropertyValue("border-color"); + } + set borderColor(value2) { + this.setProperty("border-color", value2); + } + get borderImage() { + return this.getPropertyValue("border-image"); + } + set borderImage(value2) { + this.setProperty("border-image", value2); + } + get borderImageOutset() { + return this.getPropertyValue("border-image-outset"); + } + set borderImageOutset(value2) { + this.setProperty("border-image-outset", value2); + } + get borderImageRepeat() { + return this.getPropertyValue("border-image-repeat"); + } + set borderImageRepeat(value2) { + this.setProperty("border-image-repeat", value2); + } + get borderImageSlice() { + return this.getPropertyValue("border-image-slice"); + } + set borderImageSlice(value2) { + this.setProperty("border-image-slice", value2); + } + get borderImageSource() { + return this.getPropertyValue("border-image-source"); + } + set borderImageSource(value2) { + this.setProperty("border-image-source", value2); + } + get borderImageWidth() { + return this.getPropertyValue("border-image-width"); + } + set borderImageWidth(value2) { + this.setProperty("border-image-width", value2); + } + get borderInlineEnd() { + return this.getPropertyValue("border-inline-end"); + } + set borderInlineEnd(value2) { + this.setProperty("border-inline-end", value2); + } + get borderInlineEndColor() { + return this.getPropertyValue("border-inline-end-color"); + } + set borderInlineEndColor(value2) { + this.setProperty("border-inline-end-color", value2); + } + get borderInlineEndStyle() { + return this.getPropertyValue("border-inline-end-style"); + } + set borderInlineEndStyle(value2) { + this.setProperty("border-inline-end-style", value2); + } + get borderInlineEndWidth() { + return this.getPropertyValue("border-inline-end-width"); + } + set borderInlineEndWidth(value2) { + this.setProperty("border-inline-end-width", value2); + } + get borderInlineStart() { + return this.getPropertyValue("border-inline-start"); + } + set borderInlineStart(value2) { + this.setProperty("border-inline-start", value2); + } + get borderInlineStartColor() { + return this.getPropertyValue("border-inline-start-color"); + } + set borderInlineStartColor(value2) { + this.setProperty("border-inline-start-color", value2); + } + get borderInlineStartStyle() { + return this.getPropertyValue("border-inline-start-style"); + } + set borderInlineStartStyle(value2) { + this.setProperty("border-inline-start-style", value2); + } + get borderInlineStartWidth() { + return this.getPropertyValue("border-inline-start-width"); + } + set borderInlineStartWidth(value2) { + this.setProperty("border-inline-start-width", value2); + } + get borderLeft() { + return this.getPropertyValue("border-left"); + } + set borderLeft(value2) { + this.setProperty("border-left", value2); + } + get borderLeftColor() { + return this.getPropertyValue("border-left-color"); + } + set borderLeftColor(value2) { + this.setProperty("border-left-color", value2); + } + get borderLeftStyle() { + return this.getPropertyValue("border-left-style"); + } + set borderLeftStyle(value2) { + this.setProperty("border-left-style", value2); + } + get borderLeftWidth() { + return this.getPropertyValue("border-left-width"); + } + set borderLeftWidth(value2) { + this.setProperty("border-left-width", value2); + } + get borderRadius() { + return this.getPropertyValue("border-radius"); + } + set borderRadius(value2) { + this.setProperty("border-radius", value2); + } + get borderRight() { + return this.getPropertyValue("border-right"); + } + set borderRight(value2) { + this.setProperty("border-right", value2); + } + get borderRightColor() { + return this.getPropertyValue("border-right-color"); + } + set borderRightColor(value2) { + this.setProperty("border-right-color", value2); + } + get borderRightStyle() { + return this.getPropertyValue("border-right-style"); + } + set borderRightStyle(value2) { + this.setProperty("border-right-style", value2); + } + get borderRightWidth() { + return this.getPropertyValue("border-right-width"); + } + set borderRightWidth(value2) { + this.setProperty("border-right-width", value2); + } + get borderSpacing() { + return this.getPropertyValue("border-spacing"); + } + set borderSpacing(value2) { + this.setProperty("border-spacing", value2); + } + get borderStyle() { + return this.getPropertyValue("border-style"); + } + set borderStyle(value2) { + this.setProperty("border-style", value2); + } + get borderTop() { + return this.getPropertyValue("border-top"); + } + set borderTop(value2) { + this.setProperty("border-top", value2); + } + get borderTopColor() { + return this.getPropertyValue("border-top-color"); + } + set borderTopColor(value2) { + this.setProperty("border-top-color", value2); + } + get borderTopLeftRadius() { + return this.getPropertyValue("border-top-left-radius"); + } + set borderTopLeftRadius(value2) { + this.setProperty("border-top-left-radius", value2); + } + get borderTopRightRadius() { + return this.getPropertyValue("border-top-right-radius"); + } + set borderTopRightRadius(value2) { + this.setProperty("border-top-right-radius", value2); + } + get borderTopStyle() { + return this.getPropertyValue("border-top-style"); + } + set borderTopStyle(value2) { + this.setProperty("border-top-style", value2); + } + get borderTopWidth() { + return this.getPropertyValue("border-top-width"); + } + set borderTopWidth(value2) { + this.setProperty("border-top-width", value2); + } + get borderWidth() { + return this.getPropertyValue("border-width"); + } + set borderWidth(value2) { + this.setProperty("border-width", value2); + } + get borderEndEndRadius() { + return this.getPropertyValue("border-end-end-radius"); + } + set borderEndEndRadius(value2) { + this.setProperty("border-end-end-radius", value2); + } + get borderEndStartRadius() { + return this.getPropertyValue("border-end-start-radius"); + } + set borderEndStartRadius(value2) { + this.setProperty("border-end-start-radius", value2); + } + get borderStartEndRadius() { + return this.getPropertyValue("border-start-end-radius"); + } + set borderStartEndRadius(value2) { + this.setProperty("border-start-end-radius", value2); + } + get borderStartStartRadius() { + return this.getPropertyValue("border-start-start-radius"); + } + set borderStartStartRadius(value2) { + this.setProperty("border-start-start-radius", value2); + } + get bottom() { + return this.getPropertyValue("bottom"); + } + set bottom(value2) { + this.setProperty("bottom", value2); + } + get boxShadow() { + return this.getPropertyValue("box-shadow"); + } + set boxShadow(value2) { + this.setProperty("box-shadow", value2); + } + get boxSizing() { + return this.getPropertyValue("box-sizing"); + } + set boxSizing(value2) { + this.setProperty("box-sizing", value2); + } + get breakAfter() { + return this.getPropertyValue("break-after"); + } + set breakAfter(value2) { + this.setProperty("break-after", value2); + } + get breakBefore() { + return this.getPropertyValue("break-before"); + } + set breakBefore(value2) { + this.setProperty("break-before", value2); + } + get breakInside() { + return this.getPropertyValue("break-inside"); + } + set breakInside(value2) { + this.setProperty("break-inside", value2); + } + get bufferedRendering() { + return this.getPropertyValue("buffered-rendering"); + } + set bufferedRendering(value2) { + this.setProperty("buffered-rendering", value2); + } + get captionSide() { + return this.getPropertyValue("caption-side"); + } + set captionSide(value2) { + this.setProperty("caption-side", value2); + } + get caretColor() { + return this.getPropertyValue("caret-color"); + } + set caretColor(value2) { + this.setProperty("caret-color", value2); + } + get clear() { + return this.getPropertyValue("clear"); + } + set clear(value2) { + this.setProperty("clear", value2); + } + get clip() { + return this.getPropertyValue("clip"); + } + set clip(value2) { + this.setProperty("clip", value2); + } + get clipPath() { + return this.getPropertyValue("clip-path"); + } + set clipPath(value2) { + this.setProperty("clip-path", value2); + } + get clipRule() { + return this.getPropertyValue("clip-rule"); + } + set clipRule(value2) { + this.setProperty("clip-rule", value2); + } + get color() { + return this.getPropertyValue("color"); + } + set color(value2) { + this.setProperty("color", value2); + } + get colorInterpolation() { + return this.getPropertyValue("color-interpolation"); + } + set colorInterpolation(value2) { + this.setProperty("color-interpolation", value2); + } + get colorInterpolationFilters() { + return this.getPropertyValue("color-interpolation-filters"); + } + set colorInterpolationFilters(value2) { + this.setProperty("color-interpolation-filters", value2); + } + get colorRendering() { + return this.getPropertyValue("color-rendering"); + } + set colorRendering(value2) { + this.setProperty("color-rendering", value2); + } + get colorScheme() { + return this.getPropertyValue("color-scheme"); + } + set colorScheme(value2) { + this.setProperty("color-scheme", value2); + } + get columnCount() { + return this.getPropertyValue("column-count"); + } + set columnCount(value2) { + this.setProperty("column-count", value2); + } + get columnFill() { + return this.getPropertyValue("column-fill"); + } + set columnFill(value2) { + this.setProperty("column-fill", value2); + } + get columnGap() { + return this.getPropertyValue("column-gap"); + } + set columnGap(value2) { + this.setProperty("column-gap", value2); + } + get columnRule() { + return this.getPropertyValue("column-rule"); + } + set columnRule(value2) { + this.setProperty("column-rule", value2); + } + get columnRuleColor() { + return this.getPropertyValue("column-rule-color"); + } + set columnRuleColor(value2) { + this.setProperty("column-rule-color", value2); + } + get columnRuleStyle() { + return this.getPropertyValue("column-rule-style"); + } + set columnRuleStyle(value2) { + this.setProperty("column-rule-style", value2); + } + get columnRuleWidth() { + return this.getPropertyValue("column-rule-width"); + } + set columnRuleWidth(value2) { + this.setProperty("column-rule-width", value2); + } + get columnSpan() { + return this.getPropertyValue("column-span"); + } + set columnSpan(value2) { + this.setProperty("column-span", value2); + } + get columnWidth() { + return this.getPropertyValue("column-width"); + } + set columnWidth(value2) { + this.setProperty("column-width", value2); + } + get columns() { + return this.getPropertyValue("columns"); + } + set columns(value2) { + this.setProperty("columns", value2); + } + get contain() { + return this.getPropertyValue("contain"); + } + set contain(value2) { + this.setProperty("contain", value2); + } + get containIntrinsicSize() { + return this.getPropertyValue("contain-intrinsic-size"); + } + set containIntrinsicSize(value2) { + this.setProperty("contain-intrinsic-size", value2); + } + get content() { + return this.getPropertyValue("content"); + } + set content(value2) { + this.setProperty("content", value2); + } + get contentVisibility() { + return this.getPropertyValue("content-visibility"); + } + set contentVisibility(value2) { + this.setProperty("content-visibility", value2); + } + get counterIncrement() { + return this.getPropertyValue("counter-increment"); + } + set counterIncrement(value2) { + this.setProperty("counter-increment", value2); + } + get counterReset() { + return this.getPropertyValue("counter-reset"); + } + set counterReset(value2) { + this.setProperty("counter-reset", value2); + } + get counterSet() { + return this.getPropertyValue("counter-set"); + } + set counterSet(value2) { + this.setProperty("counter-set", value2); + } + get containIntrinsicBlockSize() { + return this.getPropertyValue("contain-intrinsic-block-size"); + } + set containIntrinsicBlockSize(value2) { + this.setProperty("contain-intrinsic-block-size", value2); + } + get containIntrinsicHeight() { + return this.getPropertyValue("contain-intrinsic-height"); + } + set containIntrinsicHeight(value2) { + this.setProperty("contain-intrinsic-height", value2); + } + get containIntrinsicInlineSize() { + return this.getPropertyValue("contain-intrinsic-inline-size"); + } + set containIntrinsicInlineSize(value2) { + this.setProperty("contain-intrinsic-inline-size", value2); + } + get containIntrinsicWidth() { + return this.getPropertyValue("contain-intrinsic-width"); + } + set containIntrinsicWidth(value2) { + this.setProperty("contain-intrinsic-width", value2); + } + get cssFloat() { + return this.getPropertyValue("css-float"); + } + set cssFloat(value2) { + this.setProperty("css-float", value2); + } + get cursor() { + return this.getPropertyValue("cursor"); + } + set cursor(value2) { + this.setProperty("cursor", value2); + } + get cx() { + return this.getPropertyValue("cx"); + } + set cx(value2) { + this.setProperty("cx", value2); + } + get cy() { + return this.getPropertyValue("cy"); + } + set cy(value2) { + this.setProperty("cy", value2); + } + get d() { + return this.getPropertyValue("d"); + } + set d(value2) { + this.setProperty("d", value2); + } + get direction() { + return this.getPropertyValue("direction"); + } + set direction(value2) { + this.setProperty("direction", value2); + } + get display() { + return this.getPropertyValue("display"); + } + set display(value2) { + this.setProperty("display", value2); + } + get dominantBaseline() { + return this.getPropertyValue("dominant-baseline"); + } + set dominantBaseline(value2) { + this.setProperty("dominant-baseline", value2); + } + get emptyCells() { + return this.getPropertyValue("empty-cells"); + } + set emptyCells(value2) { + this.setProperty("empty-cells", value2); + } + get fill() { + return this.getPropertyValue("fill"); + } + set fill(value2) { + this.setProperty("fill", value2); + } + get fillOpacity() { + return this.getPropertyValue("fill-opacity"); + } + set fillOpacity(value2) { + this.setProperty("fill-opacity", value2); + } + get fillRule() { + return this.getPropertyValue("fill-rule"); + } + set fillRule(value2) { + this.setProperty("fill-rule", value2); + } + get filter() { + return this.getPropertyValue("filter"); + } + set filter(value2) { + this.setProperty("filter", value2); + } + get flex() { + return this.getPropertyValue("flex"); + } + set flex(value2) { + this.setProperty("flex", value2); + } + get flexBasis() { + return this.getPropertyValue("flex-basis"); + } + set flexBasis(value2) { + this.setProperty("flex-basis", value2); + } + get flexDirection() { + return this.getPropertyValue("flex-direction"); + } + set flexDirection(value2) { + this.setProperty("flex-direction", value2); + } + get flexFlow() { + return this.getPropertyValue("flex-flow"); + } + set flexFlow(value2) { + this.setProperty("flex-flow", value2); + } + get flexGrow() { + return this.getPropertyValue("flex-grow"); + } + set flexGrow(value2) { + this.setProperty("flex-grow", value2); + } + get flexShrink() { + return this.getPropertyValue("flex-shrink"); + } + set flexShrink(value2) { + this.setProperty("flex-shrink", value2); + } + get flexWrap() { + return this.getPropertyValue("flex-wrap"); + } + set flexWrap(value2) { + this.setProperty("flex-wrap", value2); + } + get float() { + return this.getPropertyValue("float"); + } + set float(value2) { + this.setProperty("float", value2); + } + get floodColor() { + return this.getPropertyValue("flood-color"); + } + set floodColor(value2) { + this.setProperty("flood-color", value2); + } + get floodOpacity() { + return this.getPropertyValue("flood-opacity"); + } + set floodOpacity(value2) { + this.setProperty("flood-opacity", value2); + } + get font() { + return this.getPropertyValue("font"); + } + set font(value2) { + this.setProperty("font", value2); + } + get fontDisplay() { + return this.getPropertyValue("font-display"); + } + set fontDisplay(value2) { + this.setProperty("font-display", value2); + } + get fontFamily() { + return this.getPropertyValue("font-family"); + } + set fontFamily(value2) { + this.setProperty("font-family", value2); + } + get fontFeatureSettings() { + return this.getPropertyValue("font-feature-settings"); + } + set fontFeatureSettings(value2) { + this.setProperty("font-feature-settings", value2); + } + get fontKerning() { + return this.getPropertyValue("font-kerning"); + } + set fontKerning(value2) { + this.setProperty("font-kerning", value2); + } + get fontOpticalSizing() { + return this.getPropertyValue("font-optical-sizing"); + } + set fontOpticalSizing(value2) { + this.setProperty("font-optical-sizing", value2); + } + get fontSize() { + return this.getPropertyValue("font-size"); + } + set fontSize(value2) { + this.setProperty("font-size", value2); + } + get fontStretch() { + return this.getPropertyValue("font-stretch"); + } + set fontStretch(value2) { + this.setProperty("font-stretch", value2); + } + get fontStyle() { + return this.getPropertyValue("font-style"); + } + set fontStyle(value2) { + this.setProperty("font-style", value2); + } + get fontVariant() { + return this.getPropertyValue("font-variant"); + } + set fontVariant(value2) { + this.setProperty("font-variant", value2); + } + get fontVariantCaps() { + return this.getPropertyValue("font-variant-caps"); + } + set fontVariantCaps(value2) { + this.setProperty("font-variant-caps", value2); + } + get fontVariantEastAsian() { + return this.getPropertyValue("font-variant-east-asian"); + } + set fontVariantEastAsian(value2) { + this.setProperty("font-variant-east-asian", value2); + } + get fontVariantLigatures() { + return this.getPropertyValue("font-variant-ligatures"); + } + set fontVariantLigatures(value2) { + this.setProperty("font-variant-ligatures", value2); + } + get fontVariantNumeric() { + return this.getPropertyValue("font-variant-numeric"); + } + set fontVariantNumeric(value2) { + this.setProperty("font-variant-numeric", value2); + } + get fontVariationSettings() { + return this.getPropertyValue("font-variation-settings"); + } + set fontVariationSettings(value2) { + this.setProperty("font-variation-settings", value2); + } + get fontPalette() { + return this.getPropertyValue("font-palette"); + } + set fontPalette(value2) { + this.setProperty("font-palette", value2); + } + get fontSynthesisSmallCaps() { + return this.getPropertyValue("font-synthesis-small-caps"); + } + set fontSynthesisSmallCaps(value2) { + this.setProperty("font-synthesis-small-caps", value2); + } + get fontSynthesisStyle() { + return this.getPropertyValue("font-synthesis-style"); + } + set fontSynthesisStyle(value2) { + this.setProperty("font-synthesis-style", value2); + } + get fontSynthesisWeight() { + return this.getPropertyValue("font-synthesis-weight"); + } + set fontSynthesisWeight(value2) { + this.setProperty("font-synthesis-weight", value2); + } + get fontWeight() { + return this.getPropertyValue("font-weight"); + } + set fontWeight(value2) { + this.setProperty("font-weight", value2); + } + get gap() { + return this.getPropertyValue("gap"); + } + set gap(value2) { + this.setProperty("gap", value2); + } + get grid() { + return this.getPropertyValue("grid"); + } + set grid(value2) { + this.setProperty("grid", value2); + } + get gridArea() { + return this.getPropertyValue("grid-area"); + } + set gridArea(value2) { + this.setProperty("grid-area", value2); + } + get gridAutoColumns() { + return this.getPropertyValue("grid-auto-columns"); + } + set gridAutoColumns(value2) { + this.setProperty("grid-auto-columns", value2); + } + get gridAutoFlow() { + return this.getPropertyValue("grid-auto-flow"); + } + set gridAutoFlow(value2) { + this.setProperty("grid-auto-flow", value2); + } + get gridAutoRows() { + return this.getPropertyValue("grid-auto-rows"); + } + set gridAutoRows(value2) { + this.setProperty("grid-auto-rows", value2); + } + get gridColumn() { + return this.getPropertyValue("grid-column"); + } + set gridColumn(value2) { + this.setProperty("grid-column", value2); + } + get gridColumnEnd() { + return this.getPropertyValue("grid-column-end"); + } + set gridColumnEnd(value2) { + this.setProperty("grid-column-end", value2); + } + get gridColumnGap() { + return this.getPropertyValue("grid-column-gap"); + } + set gridColumnGap(value2) { + this.setProperty("grid-column-gap", value2); + } + get gridColumnStart() { + return this.getPropertyValue("grid-column-start"); + } + set gridColumnStart(value2) { + this.setProperty("grid-column-start", value2); + } + get gridGap() { + return this.getPropertyValue("grid-gap"); + } + set gridGap(value2) { + this.setProperty("grid-gap", value2); + } + get gridRow() { + return this.getPropertyValue("grid-row"); + } + set gridRow(value2) { + this.setProperty("grid-row", value2); + } + get gridRowEnd() { + return this.getPropertyValue("grid-row-end"); + } + set gridRowEnd(value2) { + this.setProperty("grid-row-end", value2); + } + get gridRowGap() { + return this.getPropertyValue("grid-row-gap"); + } + set gridRowGap(value2) { + this.setProperty("grid-row-gap", value2); + } + get gridRowStart() { + return this.getPropertyValue("grid-row-start"); + } + set gridRowStart(value2) { + this.setProperty("grid-row-start", value2); + } + get gridTemplate() { + return this.getPropertyValue("grid-template"); + } + set gridTemplate(value2) { + this.setProperty("grid-template", value2); + } + get gridTemplateAreas() { + return this.getPropertyValue("grid-template-areas"); + } + set gridTemplateAreas(value2) { + this.setProperty("grid-template-areas", value2); + } + get gridTemplateColumns() { + return this.getPropertyValue("grid-template-columns"); + } + set gridTemplateColumns(value2) { + this.setProperty("grid-template-columns", value2); + } + get gridTemplateRows() { + return this.getPropertyValue("grid-template-rows"); + } + set gridTemplateRows(value2) { + this.setProperty("grid-template-rows", value2); + } + get height() { + return this.getPropertyValue("height"); + } + set height(value2) { + this.setProperty("height", value2); + } + get hyphens() { + return this.getPropertyValue("hyphens"); + } + set hyphens(value2) { + this.setProperty("hyphens", value2); + } + get imageOrientation() { + return this.getPropertyValue("image-orientation"); + } + set imageOrientation(value2) { + this.setProperty("image-orientation", value2); + } + get imageRendering() { + return this.getPropertyValue("image-rendering"); + } + set imageRendering(value2) { + this.setProperty("image-rendering", value2); + } + get inherits() { + return this.getPropertyValue("inherits"); + } + set inherits(value2) { + this.setProperty("inherits", value2); + } + get initialValue() { + return this.getPropertyValue("initial-value"); + } + set initialValue(value2) { + this.setProperty("initial-value", value2); + } + get inlineSize() { + return this.getPropertyValue("inline-size"); + } + set inlineSize(value2) { + this.setProperty("inline-size", value2); + } + get isolation() { + return this.getPropertyValue("isolation"); + } + set isolation(value2) { + this.setProperty("isolation", value2); + } + get insetBlockEnd() { + return this.getPropertyValue("inset-block-end"); + } + set insetBlockEnd(value2) { + this.setProperty("inset-block-end", value2); + } + get insetBlockStart() { + return this.getPropertyValue("inset-block-start"); + } + set insetBlockStart(value2) { + this.setProperty("inset-block-start", value2); + } + get insetInlineEnd() { + return this.getPropertyValue("inset-inline-end"); + } + set insetInlineEnd(value2) { + this.setProperty("inset-inline-end", value2); + } + get insetInlineStart() { + return this.getPropertyValue("inset-inline-start"); + } + set insetInlineStart(value2) { + this.setProperty("inset-inline-start", value2); + } + get justifyContent() { + return this.getPropertyValue("justify-content"); + } + set justifyContent(value2) { + this.setProperty("justify-content", value2); + } + get justifyItems() { + return this.getPropertyValue("justify-items"); + } + set justifyItems(value2) { + this.setProperty("justify-items", value2); + } + get justifySelf() { + return this.getPropertyValue("justify-self"); + } + set justifySelf(value2) { + this.setProperty("justify-self", value2); + } + get left() { + return this.getPropertyValue("left"); + } + set left(value2) { + this.setProperty("left", value2); + } + get letterSpacing() { + return this.getPropertyValue("letter-spacing"); + } + set letterSpacing(value2) { + this.setProperty("letter-spacing", value2); + } + get lightingColor() { + return this.getPropertyValue("lighting-color"); + } + set lightingColor(value2) { + this.setProperty("lighting-color", value2); + } + get lineBreak() { + return this.getPropertyValue("line-break"); + } + set lineBreak(value2) { + this.setProperty("line-break", value2); + } + get lineHeight() { + return this.getPropertyValue("line-height"); + } + set lineHeight(value2) { + this.setProperty("line-height", value2); + } + get listStyle() { + return this.getPropertyValue("list-style"); + } + set listStyle(value2) { + this.setProperty("list-style", value2); + } + get listStyleImage() { + return this.getPropertyValue("list-style-image"); + } + set listStyleImage(value2) { + this.setProperty("list-style-image", value2); + } + get listStylePosition() { + return this.getPropertyValue("list-style-position"); + } + set listStylePosition(value2) { + this.setProperty("list-style-position", value2); + } + get listStyleType() { + return this.getPropertyValue("list-style-type"); + } + set listStyleType(value2) { + this.setProperty("list-style-type", value2); + } + get margin() { + return this.getPropertyValue("margin"); + } + set margin(value2) { + this.setProperty("margin", value2); + } + get marginBlockEnd() { + return this.getPropertyValue("margin-block-end"); + } + set marginBlockEnd(value2) { + this.setProperty("margin-block-end", value2); + } + get marginBlockStart() { + return this.getPropertyValue("margin-block-start"); + } + set marginBlockStart(value2) { + this.setProperty("margin-block-start", value2); + } + get marginBottom() { + return this.getPropertyValue("margin-bottom"); + } + set marginBottom(value2) { + this.setProperty("margin-bottom", value2); + } + get marginInlineEnd() { + return this.getPropertyValue("margin-inline-end"); + } + set marginInlineEnd(value2) { + this.setProperty("margin-inline-end", value2); + } + get marginInlineStart() { + return this.getPropertyValue("margin-inline-start"); + } + set marginInlineStart(value2) { + this.setProperty("margin-inline-start", value2); + } + get marginLeft() { + return this.getPropertyValue("margin-left"); + } + set marginLeft(value2) { + this.setProperty("margin-left", value2); + } + get marginRight() { + return this.getPropertyValue("margin-right"); + } + set marginRight(value2) { + this.setProperty("margin-right", value2); + } + get marginTop() { + return this.getPropertyValue("margin-top"); + } + set marginTop(value2) { + this.setProperty("margin-top", value2); + } + get marker() { + return this.getPropertyValue("marker"); + } + set marker(value2) { + this.setProperty("marker", value2); + } + get markerEnd() { + return this.getPropertyValue("marker-end"); + } + set markerEnd(value2) { + this.setProperty("marker-end", value2); + } + get markerMid() { + return this.getPropertyValue("marker-mid"); + } + set markerMid(value2) { + this.setProperty("marker-mid", value2); + } + get markerStart() { + return this.getPropertyValue("marker-start"); + } + set markerStart(value2) { + this.setProperty("marker-start", value2); + } + get mask() { + return this.getPropertyValue("mask"); + } + set mask(value2) { + this.setProperty("mask", value2); + } + get maskType() { + return this.getPropertyValue("mask-type"); + } + set maskType(value2) { + this.setProperty("mask-type", value2); + } + get maxBlockSize() { + return this.getPropertyValue("max-block-size"); + } + set maxBlockSize(value2) { + this.setProperty("max-block-size", value2); + } + get maxHeight() { + return this.getPropertyValue("max-height"); + } + set maxHeight(value2) { + this.setProperty("max-height", value2); + } + get maxInlineSize() { + return this.getPropertyValue("max-inline-size"); + } + set maxInlineSize(value2) { + this.setProperty("max-inline-size", value2); + } + get maxWidth() { + return this.getPropertyValue("max-width"); + } + set maxWidth(value2) { + this.setProperty("max-width", value2); + } + get maxZoom() { + return this.getPropertyValue("max-zoom"); + } + set maxZoom(value2) { + this.setProperty("max-zoom", value2); + } + get minBlockSize() { + return this.getPropertyValue("min-block-size"); + } + set minBlockSize(value2) { + this.setProperty("min-block-size", value2); + } + get minHeight() { + return this.getPropertyValue("min-height"); + } + set minHeight(value2) { + this.setProperty("min-height", value2); + } + get minInlineSize() { + return this.getPropertyValue("min-inline-size"); + } + set minInlineSize(value2) { + this.setProperty("min-inline-size", value2); + } + get minWidth() { + return this.getPropertyValue("min-width"); + } + set minWidth(value2) { + this.setProperty("min-width", value2); + } + get minZoom() { + return this.getPropertyValue("min-zoom"); + } + set minZoom(value2) { + this.setProperty("min-zoom", value2); + } + get mixBlendMode() { + return this.getPropertyValue("mix-blend-mode"); + } + set mixBlendMode(value2) { + this.setProperty("mix-blend-mode", value2); + } + get objectFit() { + return this.getPropertyValue("object-fit"); + } + set objectFit(value2) { + this.setProperty("object-fit", value2); + } + get objectPosition() { + return this.getPropertyValue("object-position"); + } + set objectPosition(value2) { + this.setProperty("object-position", value2); + } + get offset() { + return this.getPropertyValue("offset"); + } + set offset(value2) { + this.setProperty("offset", value2); + } + get offsetDistance() { + return this.getPropertyValue("offset-distance"); + } + set offsetDistance(value2) { + this.setProperty("offset-distance", value2); + } + get offsetPath() { + return this.getPropertyValue("offset-path"); + } + set offsetPath(value2) { + this.setProperty("offset-path", value2); + } + get offsetRotate() { + return this.getPropertyValue("offset-rotate"); + } + set offsetRotate(value2) { + this.setProperty("offset-rotate", value2); + } + get opacity() { + return this.getPropertyValue("opacity"); + } + set opacity(value2) { + this.setProperty("opacity", value2); + } + get order() { + return this.getPropertyValue("order"); + } + set order(value2) { + this.setProperty("order", value2); + } + get orientation() { + return this.getPropertyValue("orientation"); + } + set orientation(value2) { + this.setProperty("orientation", value2); + } + get orphans() { + return this.getPropertyValue("orphans"); + } + set orphans(value2) { + this.setProperty("orphans", value2); + } + get outline() { + return this.getPropertyValue("outline"); + } + set outline(value2) { + this.setProperty("outline", value2); + } + get outlineColor() { + return this.getPropertyValue("outline-color"); + } + set outlineColor(value2) { + this.setProperty("outline-color", value2); + } + get outlineOffset() { + return this.getPropertyValue("outline-offset"); + } + set outlineOffset(value2) { + this.setProperty("outline-offset", value2); + } + get outlineStyle() { + return this.getPropertyValue("outline-style"); + } + set outlineStyle(value2) { + this.setProperty("outline-style", value2); + } + get outlineWidth() { + return this.getPropertyValue("outline-width"); + } + set outlineWidth(value2) { + this.setProperty("outline-width", value2); + } + get overflow() { + return this.getPropertyValue("overflow"); + } + set overflow(value2) { + this.setProperty("overflow", value2); + } + get overflowAnchor() { + return this.getPropertyValue("overflow-anchor"); + } + set overflowAnchor(value2) { + this.setProperty("overflow-anchor", value2); + } + get overflowWrap() { + return this.getPropertyValue("overflow-wrap"); + } + set overflowWrap(value2) { + this.setProperty("overflow-wrap", value2); + } + get overflowX() { + return this.getPropertyValue("overflow-x"); + } + set overflowX(value2) { + this.setProperty("overflow-x", value2); + } + get overflowY() { + return this.getPropertyValue("overflow-y"); + } + set overflowY(value2) { + this.setProperty("overflow-y", value2); + } + get overscrollBehavior() { + return this.getPropertyValue("overscroll-behavior"); + } + set overscrollBehavior(value2) { + this.setProperty("overscroll-behavior", value2); + } + get overscrollBehaviorBlock() { + return this.getPropertyValue("overscroll-behavior-block"); + } + set overscrollBehaviorBlock(value2) { + this.setProperty("overscroll-behavior-block", value2); + } + get overscrollBehaviorInline() { + return this.getPropertyValue("overscroll-behavior-inline"); + } + set overscrollBehaviorInline(value2) { + this.setProperty("overscroll-behavior-inline", value2); + } + get overscrollBehaviorX() { + return this.getPropertyValue("overscroll-behavior-x"); + } + set overscrollBehaviorX(value2) { + this.setProperty("overscroll-behavior-x", value2); + } + get overscrollBehaviorY() { + return this.getPropertyValue("overscroll-behavior-y"); + } + set overscrollBehaviorY(value2) { + this.setProperty("overscroll-behavior-y", value2); + } + get overflowClipMargin() { + return this.getPropertyValue("overflow-clip-margin"); + } + set overflowClipMargin(value2) { + this.setProperty("overflow-clip-margin", value2); + } + get padding() { + return this.getPropertyValue("padding"); + } + set padding(value2) { + this.setProperty("padding", value2); + } + get paddingBlockEnd() { + return this.getPropertyValue("padding-block-end"); + } + set paddingBlockEnd(value2) { + this.setProperty("padding-block-end", value2); + } + get paddingBlockStart() { + return this.getPropertyValue("padding-block-start"); + } + set paddingBlockStart(value2) { + this.setProperty("padding-block-start", value2); + } + get paddingBottom() { + return this.getPropertyValue("padding-bottom"); + } + set paddingBottom(value2) { + this.setProperty("padding-bottom", value2); + } + get paddingInlineEnd() { + return this.getPropertyValue("padding-inline-end"); + } + set paddingInlineEnd(value2) { + this.setProperty("padding-inline-end", value2); + } + get paddingInlineStart() { + return this.getPropertyValue("padding-inline-start"); + } + set paddingInlineStart(value2) { + this.setProperty("padding-inline-start", value2); + } + get paddingLeft() { + return this.getPropertyValue("padding-left"); + } + set paddingLeft(value2) { + this.setProperty("padding-left", value2); + } + get paddingRight() { + return this.getPropertyValue("padding-right"); + } + set paddingRight(value2) { + this.setProperty("padding-right", value2); + } + get paddingTop() { + return this.getPropertyValue("padding-top"); + } + set paddingTop(value2) { + this.setProperty("padding-top", value2); + } + get page() { + return this.getPropertyValue("page"); + } + set page(value2) { + this.setProperty("page", value2); + } + get pageBreakAfter() { + return this.getPropertyValue("page-break-after"); + } + set pageBreakAfter(value2) { + this.setProperty("page-break-after", value2); + } + get pageBreakBefore() { + return this.getPropertyValue("page-break-before"); + } + set pageBreakBefore(value2) { + this.setProperty("page-break-before", value2); + } + get pageBreakInside() { + return this.getPropertyValue("page-break-inside"); + } + set pageBreakInside(value2) { + this.setProperty("page-break-inside", value2); + } + get pageOrientation() { + return this.getPropertyValue("page-orientation"); + } + set pageOrientation(value2) { + this.setProperty("page-orientation", value2); + } + get paintOrder() { + return this.getPropertyValue("paint-order"); + } + set paintOrder(value2) { + this.setProperty("paint-order", value2); + } + get perspective() { + return this.getPropertyValue("perspective"); + } + set perspective(value2) { + this.setProperty("perspective", value2); + } + get perspectiveOrigin() { + return this.getPropertyValue("perspective-origin"); + } + set perspectiveOrigin(value2) { + this.setProperty("perspective-origin", value2); + } + get placeContent() { + return this.getPropertyValue("place-content"); + } + set placeContent(value2) { + this.setProperty("place-content", value2); + } + get placeItems() { + return this.getPropertyValue("place-items"); + } + set placeItems(value2) { + this.setProperty("place-items", value2); + } + get placeSelf() { + return this.getPropertyValue("place-self"); + } + set placeSelf(value2) { + this.setProperty("place-self", value2); + } + get pointerEvents() { + return this.getPropertyValue("pointer-events"); + } + set pointerEvents(value2) { + this.setProperty("pointer-events", value2); + } + get position() { + return this.getPropertyValue("position"); + } + set position(value2) { + this.setProperty("position", value2); + } + get quotes() { + return this.getPropertyValue("quotes"); + } + set quotes(value2) { + this.setProperty("quotes", value2); + } + get r() { + return this.getPropertyValue("r"); + } + set r(value2) { + this.setProperty("r", value2); + } + get resize() { + return this.getPropertyValue("resize"); + } + set resize(value2) { + this.setProperty("resize", value2); + } + get right() { + return this.getPropertyValue("right"); + } + set right(value2) { + this.setProperty("right", value2); + } + get rowGap() { + return this.getPropertyValue("row-gap"); + } + set rowGap(value2) { + this.setProperty("row-gap", value2); + } + get rubyPosition() { + return this.getPropertyValue("ruby-position"); + } + set rubyPosition(value2) { + this.setProperty("ruby-position", value2); + } + get rx() { + return this.getPropertyValue("rx"); + } + set rx(value2) { + this.setProperty("rx", value2); + } + get ry() { + return this.getPropertyValue("ry"); + } + set ry(value2) { + this.setProperty("ry", value2); + } + get scrollBehavior() { + return this.getPropertyValue("scroll-behavior"); + } + set scrollBehavior(value2) { + this.setProperty("scroll-behavior", value2); + } + get scrollMargin() { + return this.getPropertyValue("scroll-margin"); + } + set scrollMargin(value2) { + this.setProperty("scroll-margin", value2); + } + get scrollMarginBlock() { + return this.getPropertyValue("scroll-margin-block"); + } + set scrollMarginBlock(value2) { + this.setProperty("scroll-margin-block", value2); + } + get scrollMarginBlockEnd() { + return this.getPropertyValue("scroll-margin-block-end"); + } + set scrollMarginBlockEnd(value2) { + this.setProperty("scroll-margin-block-end", value2); + } + get scrollMarginBlockStart() { + return this.getPropertyValue("scroll-margin-block-start"); + } + set scrollMarginBlockStart(value2) { + this.setProperty("scroll-margin-block-start", value2); + } + get scrollMarginBottom() { + return this.getPropertyValue("scroll-margin-bottom"); + } + set scrollMarginBottom(value2) { + this.setProperty("scroll-margin-bottom", value2); + } + get scrollMarginInline() { + return this.getPropertyValue("scroll-margin-inline"); + } + set scrollMarginInline(value2) { + this.setProperty("scroll-margin-inline", value2); + } + get scrollMarginInlineEnd() { + return this.getPropertyValue("scroll-margin-inline-end"); + } + set scrollMarginInlineEnd(value2) { + this.setProperty("scroll-margin-inline-end", value2); + } + get scrollMarginInlineStart() { + return this.getPropertyValue("scroll-margin-inline-start"); + } + set scrollMarginInlineStart(value2) { + this.setProperty("scroll-margin-inline-start", value2); + } + get scrollMarginLeft() { + return this.getPropertyValue("scroll-margin-left"); + } + set scrollMarginLeft(value2) { + this.setProperty("scroll-margin-left", value2); + } + get scrollMarginRight() { + return this.getPropertyValue("scroll-margin-right"); + } + set scrollMarginRight(value2) { + this.setProperty("scroll-margin-right", value2); + } + get scrollMarginTop() { + return this.getPropertyValue("scroll-margin-top"); + } + set scrollMarginTop(value2) { + this.setProperty("scroll-margin-top", value2); + } + get scrollPadding() { + return this.getPropertyValue("scroll-padding"); + } + set scrollPadding(value2) { + this.setProperty("scroll-padding", value2); + } + get scrollPaddingBlock() { + return this.getPropertyValue("scroll-padding-block"); + } + set scrollPaddingBlock(value2) { + this.setProperty("scroll-padding-block", value2); + } + get scrollPaddingBlockEnd() { + return this.getPropertyValue("scroll-padding-block-end"); + } + set scrollPaddingBlockEnd(value2) { + this.setProperty("scroll-padding-block-end", value2); + } + get scrollPaddingBlockStart() { + return this.getPropertyValue("scroll-padding-block-start"); + } + set scrollPaddingBlockStart(value2) { + this.setProperty("scroll-padding-block-start", value2); + } + get scrollPaddingBottom() { + return this.getPropertyValue("scroll-padding-bottom"); + } + set scrollPaddingBottom(value2) { + this.setProperty("scroll-padding-bottom", value2); + } + get scrollPaddingInline() { + return this.getPropertyValue("scroll-padding-inline"); + } + set scrollPaddingInline(value2) { + this.setProperty("scroll-padding-inline", value2); + } + get scrollPaddingInlineEnd() { + return this.getPropertyValue("scroll-padding-inline-end"); + } + set scrollPaddingInlineEnd(value2) { + this.setProperty("scroll-padding-inline-end", value2); + } + get scrollPaddingInlineStart() { + return this.getPropertyValue("scroll-padding-inline-start"); + } + set scrollPaddingInlineStart(value2) { + this.setProperty("scroll-padding-inline-start", value2); + } + get scrollPaddingLeft() { + return this.getPropertyValue("scroll-padding-left"); + } + set scrollPaddingLeft(value2) { + this.setProperty("scroll-padding-left", value2); + } + get scrollPaddingRight() { + return this.getPropertyValue("scroll-padding-right"); + } + set scrollPaddingRight(value2) { + this.setProperty("scroll-padding-right", value2); + } + get scrollPaddingTop() { + return this.getPropertyValue("scroll-padding-top"); + } + set scrollPaddingTop(value2) { + this.setProperty("scroll-padding-top", value2); + } + get scrollSnapAlign() { + return this.getPropertyValue("scroll-snap-align"); + } + set scrollSnapAlign(value2) { + this.setProperty("scroll-snap-align", value2); + } + get scrollSnapStop() { + return this.getPropertyValue("scroll-snap-stop"); + } + set scrollSnapStop(value2) { + this.setProperty("scroll-snap-stop", value2); + } + get scrollSnapType() { + return this.getPropertyValue("scroll-snap-type"); + } + set scrollSnapType(value2) { + this.setProperty("scroll-snap-type", value2); + } + get shapeImageThreshold() { + return this.getPropertyValue("shape-image-threshold"); + } + set shapeImageThreshold(value2) { + this.setProperty("shape-image-threshold", value2); + } + get shapeMargin() { + return this.getPropertyValue("shape-margin"); + } + set shapeMargin(value2) { + this.setProperty("shape-margin", value2); + } + get shapeOutside() { + return this.getPropertyValue("shape-outside"); + } + set shapeOutside(value2) { + this.setProperty("shape-outside", value2); + } + get shapeRendering() { + return this.getPropertyValue("shape-rendering"); + } + set shapeRendering(value2) { + this.setProperty("shape-rendering", value2); + } + get size() { + return this.getPropertyValue("size"); + } + set size(value2) { + this.setProperty("size", value2); + } + get speak() { + return this.getPropertyValue("speak"); + } + set speak(value2) { + this.setProperty("speak", value2); + } + get src() { + return this.getPropertyValue("src"); + } + set src(value2) { + this.setProperty("src", value2); + } + get stopColor() { + return this.getPropertyValue("stop-color"); + } + set stopColor(value2) { + this.setProperty("stop-color", value2); + } + get stopOpacity() { + return this.getPropertyValue("stop-opacity"); + } + set stopOpacity(value2) { + this.setProperty("stop-opacity", value2); + } + get stroke() { + return this.getPropertyValue("stroke"); + } + set stroke(value2) { + this.setProperty("stroke", value2); + } + get strokeDasharray() { + return this.getPropertyValue("stroke-dasharray"); + } + set strokeDasharray(value2) { + this.setProperty("stroke-dasharray", value2); + } + get strokeDashoffset() { + return this.getPropertyValue("stroke-dashoffset"); + } + set strokeDashoffset(value2) { + this.setProperty("stroke-dashoffset", value2); + } + get strokeLinecap() { + return this.getPropertyValue("stroke-linecap"); + } + set strokeLinecap(value2) { + this.setProperty("stroke-linecap", value2); + } + get strokeLinejoin() { + return this.getPropertyValue("stroke-linejoin"); + } + set strokeLinejoin(value2) { + this.setProperty("stroke-linejoin", value2); + } + get strokeMiterlimit() { + return this.getPropertyValue("stroke-miterlimit"); + } + set strokeMiterlimit(value2) { + this.setProperty("stroke-miterlimit", value2); + } + get strokeOpacity() { + return this.getPropertyValue("stroke-opacity"); + } + set strokeOpacity(value2) { + this.setProperty("stroke-opacity", value2); + } + get strokeWidth() { + return this.getPropertyValue("stroke-width"); + } + set strokeWidth(value2) { + this.setProperty("stroke-width", value2); + } + get syntax() { + return this.getPropertyValue("syntax"); + } + set syntax(value2) { + this.setProperty("syntax", value2); + } + get scrollbarGutter() { + return this.getPropertyValue("scrollbar-gutter"); + } + set scrollbarGutter(value2) { + this.setProperty("scrollbar-gutter", value2); + } + get tabSize() { + return this.getPropertyValue("tab-size"); + } + set tabSize(value2) { + this.setProperty("tab-size", value2); + } + get tableLayout() { + return this.getPropertyValue("table-layout"); + } + set tableLayout(value2) { + this.setProperty("table-layout", value2); + } + get textAlign() { + return this.getPropertyValue("text-align"); + } + set textAlign(value2) { + this.setProperty("text-align", value2); + } + get textAlignLast() { + return this.getPropertyValue("text-align-last"); + } + set textAlignLast(value2) { + this.setProperty("text-align-last", value2); + } + get textAnchor() { + return this.getPropertyValue("text-anchor"); + } + set textAnchor(value2) { + this.setProperty("text-anchor", value2); + } + get textCombineUpright() { + return this.getPropertyValue("text-combine-upright"); + } + set textCombineUpright(value2) { + this.setProperty("text-combine-upright", value2); + } + get textDecoration() { + return this.getPropertyValue("text-decoration"); + } + set textDecoration(value2) { + this.setProperty("text-decoration", value2); + } + get textDecorationColor() { + return this.getPropertyValue("text-decoration-color"); + } + set textDecorationColor(value2) { + this.setProperty("text-decoration-color", value2); + } + get textDecorationLine() { + return this.getPropertyValue("text-decoration-line"); + } + set textDecorationLine(value2) { + this.setProperty("text-decoration-line", value2); + } + get textDecorationSkipInk() { + return this.getPropertyValue("text-decoration-skip-ink"); + } + set textDecorationSkipInk(value2) { + this.setProperty("text-decoration-skip-ink", value2); + } + get textDecorationStyle() { + return this.getPropertyValue("text-decoration-style"); + } + set textDecorationStyle(value2) { + this.setProperty("text-decoration-style", value2); + } + get textIndent() { + return this.getPropertyValue("text-indent"); + } + set textIndent(value2) { + this.setProperty("text-indent", value2); + } + get textOrientation() { + return this.getPropertyValue("text-orientation"); + } + set textOrientation(value2) { + this.setProperty("text-orientation", value2); + } + get textOverflow() { + return this.getPropertyValue("text-overflow"); + } + set textOverflow(value2) { + this.setProperty("text-overflow", value2); + } + get textRendering() { + return this.getPropertyValue("text-rendering"); + } + set textRendering(value2) { + this.setProperty("text-rendering", value2); + } + get textShadow() { + return this.getPropertyValue("text-shadow"); + } + set textShadow(value2) { + this.setProperty("text-shadow", value2); + } + get textSizeAdjust() { + return this.getPropertyValue("text-size-adjust"); + } + set textSizeAdjust(value2) { + this.setProperty("text-size-adjust", value2); + } + get textTransform() { + return this.getPropertyValue("text-transform"); + } + set textTransform(value2) { + this.setProperty("text-transform", value2); + } + get textUnderlinePosition() { + return this.getPropertyValue("text-underline-position"); + } + set textUnderlinePosition(value2) { + this.setProperty("text-underline-position", value2); + } + get top() { + return this.getPropertyValue("top"); + } + set top(value2) { + this.setProperty("top", value2); + } + get touchAction() { + return this.getPropertyValue("touch-action"); + } + set touchAction(value2) { + this.setProperty("touch-action", value2); + } + get transform() { + return this.getPropertyValue("transform"); + } + set transform(value2) { + this.setProperty("transform", value2); + } + get transformBox() { + return this.getPropertyValue("transform-box"); + } + set transformBox(value2) { + this.setProperty("transform-box", value2); + } + get transformOrigin() { + return this.getPropertyValue("transform-origin"); + } + set transformOrigin(value2) { + this.setProperty("transform-origin", value2); + } + get transformStyle() { + return this.getPropertyValue("transform-style"); + } + set transformStyle(value2) { + this.setProperty("transform-style", value2); + } + get transition() { + return this.getPropertyValue("transition"); + } + set transition(value2) { + this.setProperty("transition", value2); + } + get transitionDelay() { + return this.getPropertyValue("transition-delay"); + } + set transitionDelay(value2) { + this.setProperty("transition-delay", value2); + } + get transitionDuration() { + return this.getPropertyValue("transition-duration"); + } + set transitionDuration(value2) { + this.setProperty("transition-duration", value2); + } + get transitionProperty() { + return this.getPropertyValue("transition-property"); + } + set transitionProperty(value2) { + this.setProperty("transition-property", value2); + } + get transitionTimingFunction() { + return this.getPropertyValue("transition-timing-function"); + } + set transitionTimingFunction(value2) { + this.setProperty("transition-timing-function", value2); + } + get textEmphasisColor() { + return this.getPropertyValue("text-emphasis-color"); + } + set textEmphasisColor(value2) { + this.setProperty("text-emphasis-color", value2); + } + get textEmphasisPosition() { + return this.getPropertyValue("text-emphasis-position"); + } + set textEmphasisPosition(value2) { + this.setProperty("text-emphasis-position", value2); + } + get textEmphasisStyle() { + return this.getPropertyValue("text-emphasis-style"); + } + set textEmphasisStyle(value2) { + this.setProperty("text-emphasis-style", value2); + } + get unicodeBidi() { + return this.getPropertyValue("unicode-bidi"); + } + set unicodeBidi(value2) { + this.setProperty("unicode-bidi", value2); + } + get unicodeRange() { + return this.getPropertyValue("unicode-range"); + } + set unicodeRange(value2) { + this.setProperty("unicode-range", value2); + } + get userSelect() { + return this.getPropertyValue("user-select"); + } + set userSelect(value2) { + this.setProperty("user-select", value2); + } + get userZoom() { + return this.getPropertyValue("user-zoom"); + } + set userZoom(value2) { + this.setProperty("user-zoom", value2); + } + get vectorEffect() { + return this.getPropertyValue("vector-effect"); + } + set vectorEffect(value2) { + this.setProperty("vector-effect", value2); + } + get verticalAlign() { + return this.getPropertyValue("vertical-align"); + } + set verticalAlign(value2) { + this.setProperty("vertical-align", value2); + } + get visibility() { + return this.getPropertyValue("visibility"); + } + set visibility(value2) { + this.setProperty("visibility", value2); + } + get whiteSpace() { + return this.getPropertyValue("white-space"); + } + set whiteSpace(value2) { + this.setProperty("white-space", value2); + } + get widows() { + return this.getPropertyValue("widows"); + } + set widows(value2) { + this.setProperty("widows", value2); + } + get width() { + return this.getPropertyValue("width"); + } + set width(value2) { + this.setProperty("width", value2); + } + get willChange() { + return this.getPropertyValue("will-change"); + } + set willChange(value2) { + this.setProperty("will-change", value2); + } + get wordBreak() { + return this.getPropertyValue("word-break"); + } + set wordBreak(value2) { + this.setProperty("word-break", value2); + } + get wordSpacing() { + return this.getPropertyValue("word-spacing"); + } + set wordSpacing(value2) { + this.setProperty("word-spacing", value2); + } + get wordWrap() { + return this.getPropertyValue("word-wrap"); + } + set wordWrap(value2) { + this.setProperty("word-wrap", value2); + } + get writingMode() { + return this.getPropertyValue("writing-mode"); + } + set writingMode(value2) { + this.setProperty("writing-mode", value2); + } + get x() { + return this.getPropertyValue("x"); + } + set x(value2) { + this.setProperty("x", value2); + } + get y() { + return this.getPropertyValue("y"); + } + set y(value2) { + this.setProperty("y", value2); + } + get zIndex() { + return this.getPropertyValue("z-index"); + } + set zIndex(value2) { + this.setProperty("z-index", value2); + } + get zoom() { + return this.getPropertyValue("zoom"); + } + set zoom(value2) { + this.setProperty("zoom", value2); + } + get containerType() { + return this.getPropertyValue("container-type"); + } + set containerType(value2) { + this.setProperty("container-type", value2); + } + get containerName() { + return this.getPropertyValue("container-name"); + } + set containerName(value2) { + this.setProperty("container-name", value2); + } + get aspectRatio() { + return this.getPropertyValue("aspect-ratio"); + } + set aspectRatio(value2) { + this.setProperty("aspect-ratio", value2); + } + /* eslint-enable jsdoc/require-jsdoc */ + /** + * Returns length. + * + * @returns Length. + */ + get length() { + return this.#getPropertyManager().size(); + } + /** + * Returns the style decleration as a CSS text. + * + * @returns CSS text. + */ + get cssText() { + if (this.#element && this.#computed) { + return ""; + } + return this.#getPropertyManager().toString(); + } + /** + * Sets CSS text. + * + * @param cssText CSS text. + */ + set cssText(cssText2) { + if (this.#computed) { + throw new this[window].DOMException(`Failed to execute 'cssText' on 'CSSStyleDeclaration': These styles are computed, and the properties are therefore read-only.`, DOMExceptionNameEnum_default.domException); + } + if (this.#element) { + this.#cache.propertyManager = new CSSStyleDeclarationPropertyManager({ cssText: cssText2 }); + this.#cache.attributeValue = cssText2; + this.#element.setAttribute("style", this.#cache.propertyManager.toString()); + } else { + this.#cache.propertyManager = new CSSStyleDeclarationPropertyManager({ cssText: cssText2 }); + } + } + /** + * Returns item. + * + * @param index Index. + * @returns Item. + */ + item(index) { + return this.#getPropertyManager().item(index); + } + /** + * Set a property. + * + * @param name Property name. + * @param value Value. Must not contain "!important" as that should be set using the priority parameter. + * @param [priority] Can be "important", or an empty string. + */ + setProperty(name2, value2, priority) { + if (this.#computed) { + throw new this[window].DOMException(`Failed to execute 'setProperty' on 'CSSStyleDeclaration': These styles are computed, and therefore the '${name2}' property is read-only.`, DOMExceptionNameEnum_default.domException); + } + if (priority !== "" && priority !== void 0 && priority !== "important") { + return; + } + const stringValue = String(value2).trim(); + const propertyManager = this.#getPropertyManager(); + if (stringValue) { + propertyManager.set(name2, stringValue, !!priority); + } else { + propertyManager.remove(name2); + } + if (this.#element) { + this.#cache.attributeValue = propertyManager.toString(); + if (this.#cache.attributeValue) { + this.#element.setAttribute("style", this.#cache.attributeValue); + } else { + this.#element.removeAttribute("style"); + } + } + } + /** + * Removes a property. + * + * @param name Property name in kebab case. + * @param value Value. Must not contain "!important" as that should be set using the priority parameter. + * @param [priority] Can be "important", or an empty string. + */ + removeProperty(name2) { + if (this.#computed) { + throw new this[window].DOMException(`Failed to execute 'removeProperty' on 'CSSStyleDeclaration': These styles are computed, and therefore the '${name2}' property is read-only.`, DOMExceptionNameEnum_default.domException); + } + const propertyManager = this.#getPropertyManager(); + propertyManager.remove(name2); + if (this.#element) { + this.#cache.attributeValue = propertyManager.toString(); + if (this.#cache.attributeValue) { + this.#element.setAttribute("style", this.#cache.attributeValue); + } else { + this.#element.removeAttribute("style"); + } + } + } + /** + * Returns a property. + * + * @param name Property name in kebab case. + * @returns Property value. + */ + getPropertyValue(name2) { + return this.#getPropertyManager().get(name2)?.value || ""; + } + /** + * Returns a property. + * + * @param name Property name in kebab case. + * @returns "important" if set to be important. + */ + getPropertyPriority(name2) { + return this.#getPropertyManager().get(name2)?.important ? "important" : ""; + } + /** + * Returns property manager. + * + * @returns Property manager. + */ + #getPropertyManager() { + const element = this.#element; + const cache2 = this.#cache; + if (!element) { + if (!cache2.propertyManager) { + cache2.propertyManager = new CSSStyleDeclarationPropertyManager(); + } + return cache2.propertyManager; + } + if (this.#computed) { + return new CSSStyleDeclarationComputedStyle(element).getComputedStyle(); + } + const attributeValue2 = element.getAttribute("style") || ""; + if (cache2.attributeValue !== attributeValue2) { + cache2.propertyManager = new CSSStyleDeclarationPropertyManager({ cssText: attributeValue2 }); + } + return cache2.propertyManager; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/rules/CSSConditionRule.js +var CSSConditionRule; +var init_CSSConditionRule = __esm({ + "node_modules/happy-dom/lib/css/rules/CSSConditionRule.js"() { + init_PropertySymbol(); + init_CSSGroupingRule(); + CSSConditionRule = class extends CSSGroupingRule { + [conditionText] = ""; + /** + * Returns condition text. + * + * @returns Condition text. + */ + get conditionText() { + return this[conditionText]; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/rules/CSSContainerRule.js +var CSSContainerRule; +var init_CSSContainerRule = __esm({ + "node_modules/happy-dom/lib/css/rules/CSSContainerRule.js"() { + init_CSSRuleTypeEnum(); + init_CSSConditionRule(); + init_PropertySymbol(); + CSSContainerRule = class extends CSSConditionRule { + [type] = CSSRuleTypeEnum_default.containerRule; + [rulePrefix] = ""; + /** + * @override + */ + get type() { + return CSSRuleTypeEnum_default.containerRule; + } + /** + * @override + */ + get cssText() { + let cssText2 = ""; + for (const cssRule2 of this[cssRules]) { + cssText2 += "\n " + cssRule2.cssText; + } + cssText2 += "\n"; + return `@${this[rulePrefix]}container ${this[conditionText]} {${cssText2}}`; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/rules/CSSFontFaceRule.js +var CSSFontFaceRule; +var init_CSSFontFaceRule = __esm({ + "node_modules/happy-dom/lib/css/rules/CSSFontFaceRule.js"() { + init_CSSRule(); + init_PropertySymbol(); + init_CSSStyleDeclaration(); + init_CSSRuleTypeEnum(); + CSSFontFaceRule = class extends CSSRule { + [cssText] = ""; + #style = null; + /** + * @override + */ + get type() { + return CSSRuleTypeEnum_default.fontFaceRule; + } + /** + * @override + */ + get cssText() { + return `@font-face { ${this.style.cssText} }`; + } + /** + * Returns style. + * + * @returns Style. + */ + get style() { + if (!this.#style) { + this.#style = new CSSStyleDeclaration(illegalConstructor, this[window]); + this.#style.parentRule = this; + this.#style.cssText = this[cssText]; + } + return this.#style; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/rules/CSSKeyframeRule.js +var CSSKeyframeRule; +var init_CSSKeyframeRule = __esm({ + "node_modules/happy-dom/lib/css/rules/CSSKeyframeRule.js"() { + init_CSSRule(); + init_PropertySymbol(); + init_CSSStyleDeclaration(); + init_CSSRuleTypeEnum(); + CSSKeyframeRule = class extends CSSRule { + [keyText] = ""; + [cssText] = ""; + #style = null; + /** + * @override + */ + get type() { + return CSSRuleTypeEnum_default.keyframeRule; + } + /** + * @override + */ + get cssText() { + return `${this[keyText]} { ${this.style.cssText} }`; + } + /** + * Returns style. + * + * @returns Style. + */ + get style() { + if (!this.#style) { + this.#style = new CSSStyleDeclaration(illegalConstructor, this[window]); + this.#style.parentRule = this; + this.#style.cssText = this[cssText]; + } + return this.#style; + } + /** + * Returns key text. + * + * @returns Key text. + */ + get keyText() { + return this[keyText]; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/rules/CSSKeyframesRule.js +var CSS_RULE_REGEXP, CSSKeyframesRule; +var init_CSSKeyframesRule = __esm({ + "node_modules/happy-dom/lib/css/rules/CSSKeyframesRule.js"() { + init_CSSRule(); + init_CSSKeyframeRule(); + init_PropertySymbol(); + init_CSSRuleTypeEnum(); + init_DOMExceptionNameEnum(); + CSS_RULE_REGEXP = /^(from|to|[0-9]{1,3}%)\s*{([^}]*)}$/; + CSSKeyframesRule = class extends CSSRule { + [cssRules] = []; + [name] = ""; + [rulePrefix] = ""; + /** + * @override + */ + get type() { + return CSSRuleTypeEnum_default.keyframesRule; + } + /** + * @override + */ + get cssText() { + let cssText2 = ""; + for (const cssRule2 of this[cssRules]) { + cssText2 += "\n " + cssRule2.cssText; + } + cssText2 += "\n"; + return `@${this[rulePrefix]}keyframes ${this[name]} { ${cssText2}}`; + } + /** + * Returns CSS rules. + * + * @returns CSS rules. + */ + get cssRules() { + return this[cssRules]; + } + /** + * Returns name. + * + * @returns Name. + */ + get name() { + return this[name]; + } + /** + * Returns length. + * + * @returns Length. + */ + get length() { + return this[cssRules].length; + } + /** + * Appends a rule. + * + * @param rule Rule. E.g. "0% { transform: rotate(360deg); }". + */ + appendRule(rule) { + if (arguments.length === 0) { + throw new this[window].TypeError(`Failed to execute 'appendRule' on 'CSSKeyframesRule': 1 argument required, but only 0 present.`); + } + const match = String(rule).trim().match(CSS_RULE_REGEXP); + if (!match) { + throw new this[window].DOMException(`Invalid or unexpected token`, DOMExceptionNameEnum_default.syntaxError); + } + const cssRule2 = new CSSKeyframeRule(illegalConstructor, this[window], this[cssParser]); + let keyText2 = match[1].trim(); + if (keyText2 === "from") { + keyText2 = "0%"; + } else if (keyText2 === "to") { + keyText2 = "100%"; + } + cssRule2[parentRule] = this; + cssRule2[keyText] = keyText2; + cssRule2[cssText] = match[2].trim(); + this[cssRules].push(cssRule2); + } + /** + * Removes a rule. + * + * @param rule Rule. E.g. "0%". + */ + deleteRule(rule) { + if (arguments.length === 0) { + throw new this[window].TypeError(`Failed to execute 'deleteRule' on 'CSSKeyframesRule': 1 argument required, but only 0 present.`); + } + for (let i = 0, max = this[cssRules].length; i < max; i++) { + if (this[cssRules][i][keyText] === rule) { + this[cssRules].splice(i, 1); + return; + } + } + } + /** + * Finds a rule. + * + * @param rule Rule. E.g. "0%". + * @returns Rule. + */ + findRule(rule) { + if (arguments.length === 0) { + throw new this[window].TypeError(`Failed to execute 'findRule' on 'CSSKeyframesRule': 1 argument required, but only 0 present.`); + } + for (let i = 0, max = this[cssRules].length; i < max; i++) { + if (this[cssRules][i][keyText] === rule) { + return this[cssRules][i]; + } + } + return null; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/MediaList.js +var MEDIUM_REGEXP, MediaList; +var init_MediaList = __esm({ + "node_modules/happy-dom/lib/css/MediaList.js"() { + init_PropertySymbol(); + init_ClassMethodBinder(); + MEDIUM_REGEXP = /\s*,\s*/; + MediaList = class _MediaList { + [cssRule]; + /** + * + * @param illegalConstructorSymbol + * @param cssRule + */ + constructor(illegalConstructorSymbol, cssRule2) { + if (illegalConstructorSymbol !== illegalConstructor) { + throw new TypeError("Illegal constructor"); + } + this[cssRule] = cssRule2; + const methodBinder = new ClassMethodBinder(this, [_MediaList]); + return new Proxy(this, { + get: (target2, property) => { + if (property in target2 || typeof property === "symbol") { + methodBinder.bind(property); + return target2[property]; + } + const index = Number(property); + if (!isNaN(index)) { + return target2[getItemList]()[index]; + } + }, + set(target2, property, newValue) { + methodBinder.bind(property); + if (property in target2 || typeof property === "symbol") { + target2[property] = newValue; + return true; + } + return true; + }, + deleteProperty(target2, property) { + if (property in target2 || typeof property === "symbol") { + delete target2[property]; + return true; + } + return true; + }, + ownKeys(target2) { + return Object.keys(target2[getItemList]()); + }, + has(target2, property) { + if (typeof property === "symbol") { + return false; + } + if (property in target2) { + return true; + } + const index = Number(property); + return !isNaN(index) && index >= 0 && index < target2[getItemList]().length; + }, + defineProperty(target2, property, descriptor) { + methodBinder.preventBinding(property); + if (property in target2) { + Object.defineProperty(target2, property, descriptor); + return true; + } + return false; + }, + getOwnPropertyDescriptor(target2, property) { + if (property in target2 || typeof property === "symbol") { + return; + } + const index = Number(property); + const items2 = target2[getItemList](); + if (!isNaN(index) && items2[index]) { + return { + value: items2[index], + writable: false, + enumerable: true, + configurable: true + }; + } + } + }); + } + /** + * Returns length. + * + * @returns Length. + */ + get length() { + return this[getItemList]().length; + } + /** + * Returns media text. + * + * @returns Media text. + */ + get mediaText() { + return this[cssRule][conditionText]; + } + /** + * Sets media text. + * + * @param mediaText Media text. + */ + set mediaText(mediaText) { + this[cssRule][conditionText] = mediaText === null ? "" : String(mediaText).split(MEDIUM_REGEXP).join(", "); + } + /** + * Returns item. + * + * @param index Index. + * @returns Item. + */ + item(index) { + const items2 = this[getItemList](); + return items2[Number(index)] || null; + } + /** + * Appends a medium. + * + * @param medium Medium. + */ + appendMedium(medium) { + const items2 = this[getItemList](); + if (items2.indexOf(medium) === -1) { + items2.push(medium); + this[cssRule][conditionText] = items2.join(", "); + } + } + /** + * Deletes a medium. + * + * @param medium Medium. + */ + deleteMedium(medium) { + const items2 = this[getItemList](); + const index = items2.indexOf(medium); + if (index !== -1) { + items2.splice(index, 1); + this[cssRule][conditionText] = items2.join(", "); + } + } + /** + * Returns item list. + * + * @returns Item list. + */ + [getItemList]() { + const text = this[cssRule][conditionText].trim(); + const media2 = text ? this[cssRule][conditionText].split(MEDIUM_REGEXP) : []; + return media2; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/rules/CSSMediaRule.js +var CSSMediaRule; +var init_CSSMediaRule = __esm({ + "node_modules/happy-dom/lib/css/rules/CSSMediaRule.js"() { + init_CSSRuleTypeEnum(); + init_MediaList(); + init_CSSConditionRule(); + init_PropertySymbol(); + CSSMediaRule = class extends CSSConditionRule { + [media] = new MediaList(illegalConstructor, this); + /** + * @override + */ + get type() { + return CSSRuleTypeEnum_default.mediaRule; + } + /** + * @override + */ + get cssText() { + let cssText2 = ""; + for (const cssRule2 of this[cssRules]) { + cssText2 += "\n " + cssRule2.cssText; + } + cssText2 += cssText2 ? "\n" : " "; + return `@media ${this.conditionText} {${cssText2}}`; + } + /** + * Returns media. + * + * @returns Media. + */ + get media() { + return this[media]; + } + /** + * Returns conditional text. + * + * @returns Conditional text. + */ + get conditionText() { + return this.media.mediaText; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/style-property-map/CSSKeywordValue.js +var CSSKeywordValue; +var init_CSSKeywordValue = __esm({ + "node_modules/happy-dom/lib/css/style-property-map/CSSKeywordValue.js"() { + CSSKeywordValue = class { + #value; + /** + * Constructor. + * + * @param value Value.. + */ + constructor(value2) { + this.#value = value2; + } + /** + * Returns value. + * + * @returns Value. + */ + get value() { + return this.#value; + } + /** + * Sets value. + * + * @param value Value. + */ + set value(value2) { + this.#value = value2; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/style-property-map/CSSStyleValue.js +var CSSStyleValue; +var init_CSSStyleValue = __esm({ + "node_modules/happy-dom/lib/css/style-property-map/CSSStyleValue.js"() { + init_PropertySymbol(); + CSSStyleValue = class { + #style; + #property; + /** + * Constructor. + * + * @param illegalConstructorSymbol + * @param style Style. + * @param property Property. + */ + constructor(illegalConstructorSymbol, style2, property) { + if (illegalConstructorSymbol !== illegalConstructor) { + throw new TypeError("Illegal constructor"); + } + this.#style = style2; + this.#property = property; + } + /** + * Returns value as string. + * + * @returns Value. + */ + toString() { + return this.#style.getPropertyValue(this.#property); + } + }; + } +}); + +// node_modules/happy-dom/lib/css/style-property-map/StylePropertyMapReadOnly.js +var StylePropertyMapReadOnly; +var init_StylePropertyMapReadOnly = __esm({ + "node_modules/happy-dom/lib/css/style-property-map/StylePropertyMapReadOnly.js"() { + init_CSSKeywordValue(); + init_CSSStyleValue(); + init_PropertySymbol(); + StylePropertyMapReadOnly = class { + [style]; + /** + * Constructor. + * + * @param illegalConstructorSymbol Illegal constructor symbol. + * @param style Style. + */ + constructor(illegalConstructorSymbol, style2) { + if (illegalConstructorSymbol !== illegalConstructor) { + throw new TypeError("Illegal constructor"); + } + this[style] = style2; + } + /** + * Returns size. + * + * @returns Size. + */ + get size() { + return this[style].length; + } + /** + * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. + * + * @returns Iterator. + */ + [Symbol.iterator]() { + return this.entries(); + } + /** + * Returns an iterator, allowing you to go through all key/value pairs contained in this object. + * + * @returns Entries. + */ + entries() { + const length2 = this[style].length; + const array = new Array(length2); + for (let i = 0; i < length2; i++) { + const property = this[style][i]; + array[i] = [ + property, + [new CSSKeywordValue(this[style].getPropertyValue(property))] + ]; + } + return array.values(); + } + /** + * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. + * + * @returns Values. + */ + values() { + const length2 = this[style].length; + const array = new Array(length2); + for (let i = 0; i < length2; i++) { + const property = this[style][i]; + array[i] = [new CSSKeywordValue(this[style].getPropertyValue(property))]; + } + return array.values(); + } + /** + * Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object. + * + * @returns Keys. + */ + keys() { + const length2 = this[style].length; + const array = new Array(length2); + for (let i = 0; i < length2; i++) { + array[i] = this[style][i]; + } + return array.values(); + } + /** + * Returns a property value. + * + * @param property Property. + * @returns Value. + */ + get(property) { + return new CSSStyleValue(illegalConstructor, this[style], property); + } + /** + * Returns array of property values. + * + * @param property Property. + * @returns Values. + */ + getAll(property) { + return [ + new CSSStyleValue(illegalConstructor, this[style], property) + ]; + } + /** + * Checks if a property is present. + * + * @param property Property. + * @returns True if the property is present. + */ + has(property) { + return !!this[style].getPropertyValue(property); + } + }; + } +}); + +// node_modules/happy-dom/lib/css/style-property-map/StylePropertyMap.js +var StylePropertyMap; +var init_StylePropertyMap = __esm({ + "node_modules/happy-dom/lib/css/style-property-map/StylePropertyMap.js"() { + init_StylePropertyMapReadOnly(); + init_PropertySymbol(); + StylePropertyMap = class extends StylePropertyMapReadOnly { + /** + * Appends a property. + * + * @param property Property. + * @param value Value. + */ + append(property, value2) { + this[style].setProperty(property, value2); + } + /** + * Clears all properties. + */ + clear() { + this[style].cssText = ""; + } + /** + * Deletes a property. + * + * @param property Property. + */ + delete(property) { + this[style].removeProperty(property); + } + /** + * Sets a property. + * + * @param property Property. + * @param value Value. + */ + set(property, value2) { + this[style].setProperty(property, value2); + } + }; + } +}); + +// node_modules/happy-dom/lib/css/rules/CSSStyleRule.js +var CSSStyleRule; +var init_CSSStyleRule = __esm({ + "node_modules/happy-dom/lib/css/rules/CSSStyleRule.js"() { + init_PropertySymbol(); + init_CSSStyleDeclaration(); + init_CSSRuleTypeEnum(); + init_CSSGroupingRule(); + init_StylePropertyMap(); + CSSStyleRule = class extends CSSGroupingRule { + [styleMap] = null; + [selectorText] = ""; + [cssText] = ""; + #style = null; + /** + * @override + */ + get type() { + return CSSRuleTypeEnum_default.styleRule; + } + /** + * @override + */ + get cssText() { + return `${this[selectorText]} { ${this.style.cssText} }`; + } + /** + * Returns style map. + * + * @returns Style map. + */ + get styleMap() { + if (!this[styleMap]) { + this[styleMap] = new StylePropertyMap(illegalConstructor, this.style); + } + return this[styleMap]; + } + /** + * Returns selector text. + * + * @returns Selector text. + */ + get selectorText() { + return this[selectorText]; + } + /** + * Returns style. + * + * @returns Style. + */ + get style() { + if (!this.#style) { + this.#style = new CSSStyleDeclaration(illegalConstructor, this[window]); + this.#style.parentRule = this; + this.#style.cssText = this[cssText]; + } + return this.#style; + } + }; + } +}); + +// node_modules/happy-dom/lib/css/rules/CSSSupportsRule.js +var CSSSupportsRule; +var init_CSSSupportsRule = __esm({ + "node_modules/happy-dom/lib/css/rules/CSSSupportsRule.js"() { + init_CSSRuleTypeEnum(); + init_CSSConditionRule(); + init_PropertySymbol(); + CSSSupportsRule = class extends CSSConditionRule { + [type] = CSSRuleTypeEnum_default.supportsRule; + [rulePrefix] = ""; + /** + * @override + */ + get type() { + return CSSRuleTypeEnum_default.supportsRule; + } + /** + * @override + */ + get cssText() { + let cssText2 = ""; + for (const cssRule2 of this[cssRules]) { + cssText2 += "\n " + cssRule2.cssText; + } + cssText2 += "\n"; + return `@${this[rulePrefix]}supports ${this.conditionText} {${cssText2}}`; + } + }; + } +}); + +// node_modules/happy-dom/lib/config/NamespaceURI.js +var NamespaceURI_default; +var init_NamespaceURI = __esm({ + "node_modules/happy-dom/lib/config/NamespaceURI.js"() { + NamespaceURI_default = { + html: "http://www.w3.org/1999/xhtml", + svg: "http://www.w3.org/2000/svg", + mathML: "http://www.w3.org/1998/Math/MathML", + xml: "http://www.w3.org/XML/1998/namespace", + xlink: "http://www.w3.org/1999/xlink", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + } +}); + +// node_modules/happy-dom/lib/utilities/StringUtility.js +var ASCII_LOWER_CASE_CACHE, ASCII_UPPER_CASE_CACHE, ASCII_UPPER_CASE_REGEXP, ASCII_LOWER_CASE_REGEXP, StringUtility; +var init_StringUtility = __esm({ + "node_modules/happy-dom/lib/utilities/StringUtility.js"() { + ASCII_LOWER_CASE_CACHE = /* @__PURE__ */ new Map(); + ASCII_UPPER_CASE_CACHE = /* @__PURE__ */ new Map(); + ASCII_UPPER_CASE_REGEXP = /[A-Z]/g; + ASCII_LOWER_CASE_REGEXP = /[a-z]/g; + StringUtility = class { + /** + * ASCII lowercase. + * + * @see https://infra.spec.whatwg.org/#ascii-lowercase + * @param text Text. + * @returns Lowercase text. + */ + static asciiLowerCase(text) { + const cached = ASCII_LOWER_CASE_CACHE.get(text); + if (cached) { + return cached; + } + const newText = text.replace(ASCII_UPPER_CASE_REGEXP, (char) => String.fromCharCode(char.charCodeAt(0) + 32)); + ASCII_LOWER_CASE_CACHE.set(text, newText); + return newText; + } + /** + * ASCII uppercase. + * + * @see https://infra.spec.whatwg.org/#ascii-uppercase + * @param text Text. + * @returns Uppercase text. + */ + static asciiUpperCase(text) { + const cached = ASCII_UPPER_CASE_CACHE.get(text); + if (cached) { + return cached; + } + const newText = text.replace(ASCII_LOWER_CASE_REGEXP, (char) => String.fromCharCode(char.charCodeAt(0) - 32)); + ASCII_UPPER_CASE_CACHE.set(text, newText); + return newText; + } + }; + } +}); + +// node_modules/happy-dom/lib/custom-element/CustomElementUtility.js +var PCEN_CHAR, PCEN_REGEXP, RESERVED_NAMES, CustomElementUtility; +var init_CustomElementUtility = __esm({ + "node_modules/happy-dom/lib/custom-element/CustomElementUtility.js"() { + PCEN_CHAR = "[-_.]|[0-9]|[a-z]|\xB7|[\xC0-\xD6]|[\xD8-\xF6]|[\xF8-\u037D]|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u203F-\u2040]|[\u2070-\u218F]|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]|[\uFDF0-\uFFFD]|[\u{10000}-\u{EFFFF}]"; + PCEN_REGEXP = new RegExp(`^[a-z](${PCEN_CHAR})*-(${PCEN_CHAR})*$`, "u"); + RESERVED_NAMES = [ + "annotation-xml", + "color-profile", + "font-face", + "font-face-src", + "font-face-uri", + "font-face-format", + "font-face-name", + "missing-glyph" + ]; + CustomElementUtility = class { + /** + * Returns true if the tag name is a valid custom element name. + * + * @see https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name + * @param name Tag name. + * @returns True if valid. + */ + static isValidCustomElementName(name2) { + return PCEN_REGEXP.test(name2) && !RESERVED_NAMES.includes(name2); + } + }; + } +}); + +// node_modules/happy-dom/lib/custom-element/CustomElementRegistry.js +var CustomElementRegistry; +var init_CustomElementRegistry = __esm({ + "node_modules/happy-dom/lib/custom-element/CustomElementRegistry.js"() { + init_PropertySymbol(); + init_NamespaceURI(); + init_StringUtility(); + init_CustomElementUtility(); + CustomElementRegistry = class { + [registry] = /* @__PURE__ */ new Map(); + [classRegistry] = /* @__PURE__ */ new Map(); + [callbacks] = /* @__PURE__ */ new Map(); + [destroyed] = false; + #window; + /** + * Constructor. + * + * @param window Window. + */ + constructor(window2) { + if (!window2) { + throw new TypeError("Illegal constructor"); + } + this.#window = window2; + } + /** + * Defines a custom element class. + * + * @param name Tag name of element. + * @param elementClass Element class. + * @param [options] Options. + * @param [options.extends] Extends tag name. + */ + define(name2, elementClass, options2) { + if (this[destroyed]) { + return; + } + if (!CustomElementUtility.isValidCustomElementName(name2)) { + throw new this.#window.DOMException(`Failed to execute 'define' on 'CustomElementRegistry': "${name2}" is not a valid custom element name`); + } + if (this[registry].has(name2)) { + throw new this.#window.DOMException(`Failed to execute 'define' on 'CustomElementRegistry': the name "${name2}" has already been used with this registry`); + } + if (this[classRegistry].has(elementClass)) { + throw new this.#window.DOMException("Failed to execute 'define' on 'CustomElementRegistry': this constructor has already been used with this registry"); + } + const tagName2 = StringUtility.asciiUpperCase(name2); + elementClass.prototype[window] = this.#window; + elementClass.prototype[ownerDocument] = this.#window.document; + elementClass.prototype[tagName] = tagName2; + elementClass.prototype[localName] = name2; + elementClass.prototype[namespaceURI] = NamespaceURI_default.html; + const observedAttributes = /* @__PURE__ */ new Set(); + const elementObservervedAttributes = elementClass.observedAttributes; + if (Array.isArray(elementObservervedAttributes)) { + for (const attribute of elementObservervedAttributes) { + observedAttributes.add(String(attribute).toLowerCase()); + } + } + this[registry].set(name2, { + elementClass, + extends: options2 && options2.extends ? options2.extends.toLowerCase() : null, + observedAttributes, + lifecycleCallbacks: { + connectedCallback: elementClass.prototype.connectedCallback, + disconnectedCallback: elementClass.prototype.disconnectedCallback, + attributeChangedCallback: elementClass.prototype.attributeChangedCallback + } + }); + this[classRegistry].set(elementClass, name2); + const callbacks2 = this[callbacks].get(name2); + if (callbacks2) { + this[callbacks].delete(name2); + for (const callback of callbacks2) { + callback(); + } + } + } + /** + * Returns a defined element class. + * + * @param name Tag name of element. + * @returns HTMLElement Class defined or undefined. + */ + get(name2) { + return this[registry].get(name2)?.elementClass; + } + /** + * Upgrades a custom element directly, even before it is connected to its shadow root. + * + * Not implemented yet. + * + * @param _root Root node. + */ + upgrade(_root) { + } + /** + * When defined. + * + * @param name Tag name of element. + */ + whenDefined(name2) { + if (this[destroyed]) { + return Promise.reject(new this.#window.DOMException(`Failed to execute 'whenDefined' on 'CustomElementRegistry': The custom element registry has been destroyed.`)); + } + if (!CustomElementUtility.isValidCustomElementName(name2)) { + return Promise.reject(new this.#window.DOMException(`Failed to execute 'whenDefined' on 'CustomElementRegistry': Invalid custom element name: "${name2}"`)); + } + if (this.get(name2)) { + return Promise.resolve(); + } + return new Promise((resolve) => { + const callbacks2 = this[callbacks].get(name2); + if (callbacks2) { + callbacks2.push(resolve); + } else { + this[callbacks].set(name2, [resolve]); + } + }); + } + /** + * Reverse lookup searching for name by given element class. + * + * @param elementClass Class constructor. + * @returns Found tag name or `null`. + */ + getName(elementClass) { + return this[classRegistry].get(elementClass) || null; + } + /** + * Destroys the registry. + */ + [destroy]() { + this[destroyed] = true; + for (const definition of this[registry].values()) { + definition.elementClass.prototype[window] = null; + definition.elementClass.prototype[ownerDocument] = null; + definition.elementClass.prototype[tagName] = null; + definition.elementClass.prototype[localName] = null; + definition.elementClass.prototype[namespaceURI] = null; + } + this[registry] = /* @__PURE__ */ new Map(); + this[classRegistry] = /* @__PURE__ */ new Map(); + this[callbacks] = /* @__PURE__ */ new Map(); + } + }; + } +}); + +// node_modules/happy-dom/lib/event/DataTransferItem.js +var DataTransferItem; +var init_DataTransferItem = __esm({ + "node_modules/happy-dom/lib/event/DataTransferItem.js"() { + DataTransferItem = class { + kind; + type; + #item = null; + /** + * Constructor. + * + * @param item Item. + * @param type Type. + */ + constructor(item, type2 = "") { + this.kind = typeof item === "string" ? "string" : "file"; + this.type = this.kind === "string" ? type2 : item.type; + this.#item = item; + } + /** + * Returns file. + */ + getAsFile() { + if (this.kind === "string") { + return null; + } + return this.#item; + } + /** + * Returns string. + * + * @param callback Callback. + */ + getAsString(callback) { + if (this.kind === "file") { + callback(""); + } + callback(this.#item); + } + }; + } +}); + +// node_modules/happy-dom/lib/file/File.js +var File2; +var init_File = __esm({ + "node_modules/happy-dom/lib/file/File.js"() { + init_Blob(); + File2 = class extends Blob2 { + lastModified; + name; + /** + * Constructor. + * + * @param bits File bits. + * @param name File name. + * @param [options] Options. + * @param [options.type] MIME type. + * @param [options.lastModifier] Last modified. Defaults to Date.now(). + * @param options.lastModified + */ + constructor(bits, name2, options2) { + if (arguments.length < 2) { + throw new TypeError("Failed to construct 'File': 2 arguments required, but only " + arguments.length + " present."); + } + super(bits, options2); + this.name = name2; + this.lastModified = options2 && options2.lastModified ? options2.lastModified : Date.now(); + } + }; + } +}); + +// node_modules/happy-dom/lib/event/DataTransferItemList.js +var DataTransferItemList; +var init_DataTransferItemList = __esm({ + "node_modules/happy-dom/lib/event/DataTransferItemList.js"() { + init_File(); + init_DataTransferItem(); + DataTransferItemList = class extends Array { + /** + * Adds an item. + * + * @param item Item. + * @param type Type. + */ + add(item, type2) { + if (item instanceof File2) { + this.push(new DataTransferItem(item)); + return; + } + if (!type2) { + throw new TypeError(`Failed to execute 'add' on 'DataTransferItemList': parameter 1 is not of type 'File'.`); + } + this.push(new DataTransferItem(item, type2)); + } + /** + * Removes an item. + * + * @param index Index. + */ + remove(index) { + this.splice(index, 1); + } + /** + * Clears list. + */ + clear() { + while (this.length) { + this.pop(); + } + } + }; + } +}); + +// node_modules/happy-dom/lib/event/DataTransfer.js +var DataTransfer; +var init_DataTransfer = __esm({ + "node_modules/happy-dom/lib/event/DataTransfer.js"() { + init_DataTransferItem(); + init_DataTransferItemList(); + DataTransfer = class { + dropEffect = "none"; + effectAllowed = "none"; + items = new DataTransferItemList(); + /** + * Returns files. + * + * @returns Files. + */ + get files() { + const files2 = []; + for (const item of this.items) { + if (item.kind === "file") { + const file = item.getAsFile(); + if (file) { + files2.push(file); + } + } + } + return files2; + } + /** + * Returns types. + * + * @returns Types. + */ + get types() { + return this.items.map((item) => item.type); + } + /** + * Clears the data. + */ + clearData() { + this.items.clear(); + } + /** + * Sets the data. + * + * @param format Format. + * @param data Data. + */ + setData(format, data2) { + for (let i = 0, max = this.items.length; i < max; i++) { + if (this.items[i].type === format) { + this.items[i] = new DataTransferItem(data2, format); + return; + } + } + this.items.add(data2, format); + } + /** + * Gets the data. + * + * @param format Format. + * @returns Data. + */ + getData(format) { + const normalizedFormat = this.#normalizeFormat(format); + for (let i = 0, max = this.items.length; i < max; i++) { + const itemFormat = this.#normalizeFormat(this.items[i].type); + if (itemFormat === normalizedFormat) { + let data2 = ""; + this.items[i].getAsString((s) => data2 = s); + return data2; + } + } + return ""; + } + /** + * Normalizes the format according to the HTML spec. + * + * @param format Format to normalize. + * @returns Normalized format. + */ + #normalizeFormat(format) { + const lowercaseFormat = format.toLowerCase(); + if (lowercaseFormat === "text") { + return "text/plain"; + } + if (lowercaseFormat === "url") { + return "text/uri-list"; + } + return lowercaseFormat; + } + /** + * Sets drag image. + * + * TODO: Implement. + */ + setDragImage() { + throw new Error("Not implemented."); + } + }; + } +}); + +// node_modules/happy-dom/lib/event/Touch.js +var Touch; +var init_Touch = __esm({ + "node_modules/happy-dom/lib/event/Touch.js"() { + Touch = class { + identifier; + target; + clientX; + clientY; + screenX; + screenY; + pageX; + pageY; + radiusX; + radiusY; + rotationAngle; + force; + /** + * Constructor. + * + * @param [touchInit] Touch init. + */ + constructor(touchInit) { + this.identifier = touchInit.identifier; + this.target = touchInit.target; + this.clientX = touchInit.clientX ?? 0; + this.clientY = touchInit.clientY ?? 0; + this.screenX = touchInit.screenX ?? 0; + this.screenY = touchInit.screenY ?? 0; + this.pageX = touchInit.pageX ?? 0; + this.pageY = touchInit.pageY ?? 0; + this.radiusX = touchInit.radiusX ?? 0; + this.radiusY = touchInit.radiusY ?? 0; + this.rotationAngle = touchInit.rotationAngle ?? 0; + this.force = touchInit.force ?? 0; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/UIEvent.js +var UIEvent; +var init_UIEvent = __esm({ + "node_modules/happy-dom/lib/event/UIEvent.js"() { + init_Event(); + UIEvent = class extends Event2 { + static NONE = 0; + static CAPTURING_PHASE = 1; + static AT_TARGET = 2; + static BUBBLING_PHASE = 3; + detail; + layerX = 0; + layerY = 0; + pageX = 0; + pageY = 0; + view; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.detail = eventInit?.detail ?? 0; + this.view = eventInit?.view ?? null; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/AnimationEvent.js +var AnimationEvent; +var init_AnimationEvent = __esm({ + "node_modules/happy-dom/lib/event/events/AnimationEvent.js"() { + init_Event(); + AnimationEvent = class extends Event2 { + animationName; + elapsedTime; + pseudoElement; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.animationName = eventInit?.animationName ?? ""; + this.elapsedTime = eventInit?.elapsedTime ?? 0; + this.pseudoElement = eventInit?.pseudoElement ?? ""; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/ClipboardEvent.js +var ClipboardEvent; +var init_ClipboardEvent = __esm({ + "node_modules/happy-dom/lib/event/events/ClipboardEvent.js"() { + init_Event(); + ClipboardEvent = class extends Event2 { + clipboardData; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.clipboardData = eventInit?.clipboardData ?? null; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/CustomEvent.js +var CustomEvent; +var init_CustomEvent = __esm({ + "node_modules/happy-dom/lib/event/events/CustomEvent.js"() { + init_Event(); + init_PropertySymbol(); + CustomEvent = class extends Event2 { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [detail]; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this[detail] = eventInit?.detail ?? null; + } + /** + * Returns detail. + * + * @returns Detail. + */ + get detail() { + return this[detail]; + } + /** + * Init event. + * + * @deprecated + * @param type Type. + * @param [bubbles=false] "true" if it bubbles. + * @param [cancelable=false] "true" if it cancelable. + * @param [detail=null] Custom event detail. + */ + initCustomEvent(type2, bubbles2 = false, cancelable2 = false, detail2 = null) { + this[type] = type2; + this[bubbles] = bubbles2; + this[cancelable] = cancelable2; + this[detail] = detail2; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/ErrorEvent.js +var ErrorEvent; +var init_ErrorEvent = __esm({ + "node_modules/happy-dom/lib/event/events/ErrorEvent.js"() { + init_UIEvent(); + ErrorEvent = class extends UIEvent { + message; + filename; + lineno; + colno; + error; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.message = eventInit?.message ?? ""; + this.filename = eventInit?.filename ?? ""; + this.lineno = eventInit?.lineno ?? 0; + this.colno = eventInit?.colno ?? 0; + this.error = eventInit?.error ?? null; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/FocusEvent.js +var FocusEvent; +var init_FocusEvent = __esm({ + "node_modules/happy-dom/lib/event/events/FocusEvent.js"() { + init_UIEvent(); + FocusEvent = class extends UIEvent { + relatedTarget; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.relatedTarget = eventInit?.relatedTarget ?? null; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/HashChangeEvent.js +var HashChangeEvent; +var init_HashChangeEvent = __esm({ + "node_modules/happy-dom/lib/event/events/HashChangeEvent.js"() { + init_Event(); + HashChangeEvent = class extends Event2 { + newURL; + oldURL; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.newURL = eventInit?.newURL ?? ""; + this.oldURL = eventInit?.oldURL ?? ""; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/InputEvent.js +var InputEvent; +var init_InputEvent = __esm({ + "node_modules/happy-dom/lib/event/events/InputEvent.js"() { + init_UIEvent(); + InputEvent = class extends UIEvent { + data; + dataTransfer; + inputType; + isComposing; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.data = eventInit?.data ?? ""; + this.dataTransfer = eventInit?.dataTransfer ?? null; + this.inputType = eventInit?.inputType ?? ""; + this.isComposing = eventInit?.isComposing ?? false; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/KeyboardEvent.js +var KeyboardEvent; +var init_KeyboardEvent = __esm({ + "node_modules/happy-dom/lib/event/events/KeyboardEvent.js"() { + init_UIEvent(); + KeyboardEvent = class extends UIEvent { + static DOM_KEY_LOCATION_STANDARD = 0; + static DOM_KEY_LOCATION_LEFT = 1; + static DOM_KEY_LOCATION_RIGHT = 2; + static DOM_KEY_LOCATION_NUMPAD = 3; + altKey; + code; + ctrlKey; + isComposing; + key; + location; + metaKey; + repeat; + shiftKey; + /** + * @deprecated + */ + keyCode; + /** + * @deprecated + */ + which; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.altKey = eventInit?.altKey ?? false; + this.code = eventInit?.code ?? ""; + this.ctrlKey = eventInit?.ctrlKey ?? false; + this.isComposing = eventInit?.isComposing ?? false; + this.key = eventInit?.key ?? ""; + this.location = eventInit?.location ?? 0; + this.metaKey = eventInit?.metaKey ?? false; + this.repeat = eventInit?.repeat ?? false; + this.shiftKey = eventInit?.shiftKey ?? false; + this.keyCode = eventInit?.keyCode ?? 0; + this.which = eventInit?.which ?? eventInit?.keyCode ?? 0; + } + /** + * Returns the state of a modifier key. + * + * @param key A modifier key value. + * @returns True if it's pressed, false otherwise. + */ + getModifierState(key) { + if (arguments.length < 1) { + throw new TypeError("Failed to execute 'getModifierState' on 'KeyboardEvent': 1 argument required, but only 0 present."); + } + switch (String(key).toLowerCase()) { + case "alt": + case "altgraph": + return this.altKey; + case "control": + return this.ctrlKey; + case "meta": + return this.metaKey; + case "shift": + return this.shiftKey; + default: + return false; + } + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/MessageEvent.js +var MessageEvent; +var init_MessageEvent = __esm({ + "node_modules/happy-dom/lib/event/events/MessageEvent.js"() { + init_Event(); + MessageEvent = class extends Event2 { + data; + origin; + lastEventId; + source; + ports; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.data = eventInit?.data ?? null; + this.origin = eventInit?.origin ?? ""; + this.lastEventId = eventInit?.lastEventId ?? ""; + this.source = eventInit?.source ?? null; + this.ports = eventInit?.ports ?? []; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/MouseEvent.js +var MouseEvent; +var init_MouseEvent = __esm({ + "node_modules/happy-dom/lib/event/events/MouseEvent.js"() { + init_UIEvent(); + MouseEvent = class extends UIEvent { + altKey; + button; + buttons; + clientX; + clientY; + ctrlKey; + metaKey; + movementX; + movementY; + offsetX; + offsetY; + region; + relatedTarget; + screenX; + screenY; + shiftKey; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.altKey = eventInit?.altKey ?? false; + this.button = eventInit?.button ?? 0; + this.buttons = eventInit?.buttons ?? 0; + this.clientX = eventInit?.clientX ?? 0; + this.clientY = eventInit?.clientY ?? 0; + this.ctrlKey = eventInit?.ctrlKey ?? false; + this.metaKey = eventInit?.metaKey ?? false; + this.movementX = eventInit?.movementX ?? 0; + this.movementY = eventInit?.movementY ?? 0; + this.offsetX = eventInit?.offsetX ?? 0; + this.offsetY = eventInit?.offsetY ?? 0; + this.region = eventInit?.region ?? ""; + this.relatedTarget = eventInit?.relatedTarget ?? null; + this.screenX = eventInit?.screenX ?? 0; + this.screenY = eventInit?.screenY ?? 0; + this.shiftKey = eventInit?.shiftKey ?? false; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/PointerEvent.js +var PointerEvent; +var init_PointerEvent = __esm({ + "node_modules/happy-dom/lib/event/events/PointerEvent.js"() { + init_MouseEvent(); + PointerEvent = class extends MouseEvent { + pointerId; + width; + height; + pressure; + tangentialPressure; + tiltX; + tiltY; + twist; + altitudeAngle; + azimuthAngle; + pointerType; + isPrimary; + coalescedEvents; + predictedEvents; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.pointerId = eventInit?.pointerId ?? 0; + this.width = eventInit?.width ?? 1; + this.height = eventInit?.height ?? 1; + this.pressure = eventInit?.pressure ?? 0; + this.tangentialPressure = eventInit?.tangentialPressure ?? 0; + this.tiltX = eventInit?.tiltX ?? 0; + this.tiltY = eventInit?.tiltY ?? 0; + this.twist = eventInit?.twist ?? 0; + this.altitudeAngle = eventInit?.altitudeAngle ?? 0; + this.azimuthAngle = eventInit?.azimuthAngle ?? 0; + this.pointerType = eventInit?.pointerType ?? ""; + this.isPrimary = eventInit?.isPrimary ?? false; + this.coalescedEvents = eventInit?.coalescedEvents ?? []; + this.predictedEvents = eventInit?.predictedEvents ?? []; + } + getCoalescedEvents = () => this.coalescedEvents; + getPredictedEvents = () => this.predictedEvents; + }; + } +}); + +// node_modules/happy-dom/lib/event/events/ProgressEvent.js +var ProgressEvent; +var init_ProgressEvent = __esm({ + "node_modules/happy-dom/lib/event/events/ProgressEvent.js"() { + init_Event(); + ProgressEvent = class extends Event2 { + lengthComputable; + loaded; + total; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2); + this.lengthComputable = eventInit?.lengthComputable ?? false; + this.loaded = eventInit?.loaded ?? 0; + this.total = eventInit?.total ?? 0; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/StorageEvent.js +var StorageEvent; +var init_StorageEvent = __esm({ + "node_modules/happy-dom/lib/event/events/StorageEvent.js"() { + init_Event(); + StorageEvent = class extends Event2 { + key; + oldValue; + newValue; + url; + storageArea; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2); + this.key = eventInit?.key ?? null; + this.oldValue = eventInit?.oldValue ?? null; + this.newValue = eventInit?.newValue ?? null; + this.url = eventInit?.url ?? ""; + this.storageArea = eventInit?.storageArea ?? null; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/SubmitEvent.js +var SubmitEvent; +var init_SubmitEvent = __esm({ + "node_modules/happy-dom/lib/event/events/SubmitEvent.js"() { + init_Event(); + SubmitEvent = class extends Event2 { + submitter; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.submitter = eventInit?.submitter ?? null; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/TouchEvent.js +var TouchEvent; +var init_TouchEvent = __esm({ + "node_modules/happy-dom/lib/event/events/TouchEvent.js"() { + init_UIEvent(); + TouchEvent = class extends UIEvent { + altKey; + changedTouches; + ctrlKey; + metaKey; + shiftKey; + targetTouches; + touches; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.altKey = eventInit?.altKey ?? false; + this.changedTouches = eventInit?.changedTouches ?? []; + this.ctrlKey = eventInit?.ctrlKey ?? false; + this.metaKey = eventInit?.metaKey ?? false; + this.shiftKey = eventInit?.shiftKey ?? false; + this.targetTouches = eventInit?.targetTouches ?? []; + this.touches = eventInit?.touches ?? []; + } + }; + } +}); + +// node_modules/happy-dom/lib/event/events/WheelEvent.js +var WheelEvent; +var init_WheelEvent = __esm({ + "node_modules/happy-dom/lib/event/events/WheelEvent.js"() { + init_UIEvent(); + WheelEvent = class extends UIEvent { + static DOM_DELTA_PIXEL = 0; + static DOM_DELTA_LINE = 1; + static DOM_DELTA_PAGE = 2; + deltaX; + deltaY; + deltaZ; + deltaMode; + /** + * Constructor. + * + * @param type Event type. + * @param [eventInit] Event init. + */ + constructor(type2, eventInit = null) { + super(type2, eventInit); + this.deltaX = eventInit?.deltaX ?? 0; + this.deltaY = eventInit?.deltaY ?? 0; + this.deltaZ = eventInit?.deltaZ ?? 0; + this.deltaMode = eventInit?.deltaMode ?? 0; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/utilities/FetchRequestReferrerUtility.js +var import_net, REQUEST_REFERRER_UNSUPPORTED_PROTOCOL_REGEXP, REFERRER_POLICIES, FetchRequestReferrerUtility; +var init_FetchRequestReferrerUtility = __esm({ + "node_modules/happy-dom/lib/fetch/utilities/FetchRequestReferrerUtility.js"() { + init_URL(); + init_PropertySymbol(); + import_net = require("net"); + REQUEST_REFERRER_UNSUPPORTED_PROTOCOL_REGEXP = /^(about|blob|data):$/; + REFERRER_POLICIES = [ + "", + "no-referrer", + "no-referrer-when-downgrade", + "same-origin", + "origin", + "strict-origin", + "origin-when-cross-origin", + "strict-origin-when-cross-origin", + "unsafe-url" + ]; + FetchRequestReferrerUtility = class { + /** + * Prepares the request before being sent. + * + * @param originURL Origin URL. + * @param request Request. + */ + static prepareRequest(originURL, request) { + if (!request.referrerPolicy) { + request[referrerPolicy] = "strict-origin-when-cross-origin"; + } + if (request.referrer && request.referrer !== "no-referrer") { + request[referrer] = this.getSentReferrer(originURL, request); + } else { + request[referrer] = "no-referrer"; + } + } + /** + * Returns initial referrer. + * + * @param window Window. + * @param referrer Referrer. + * @returns Initial referrer. + */ + static getInitialReferrer(window2, referrer2) { + if (referrer2 === "" || referrer2 === "no-referrer" || referrer2 === "client") { + return referrer2; + } else if (referrer2) { + const referrerURL = referrer2 instanceof URL2 ? referrer2 : new URL2(referrer2, window2.location.href); + return referrerURL.origin === window2.location.origin ? referrerURL : "client"; + } + return "client"; + } + /** + * Returns referrer policy from header. + * + * @see https://w3c.github.io/webappsec-referrer-policy/#parse-referrer-policy-from-header + * @param headers Response headers + * @returns Policy. + */ + static getReferrerPolicyFromHeader(headers2) { + const referrerPolicyHeader = headers2.get("Referrer-Policy"); + if (!referrerPolicyHeader) { + return ""; + } + const policyTokens = referrerPolicyHeader.split(/[,\s]+/); + let policy = ""; + for (const token of policyTokens) { + if (token && REFERRER_POLICIES.includes(token)) { + policy = token; + } + } + return policy; + } + /** + * Returns the request referrer to be used as the value for the "Referer" header. + * + * Based on: + * https://github.com/node-fetch/node-fetch/blob/main/src/utils/referrer.js (MIT) + * + * @see https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer + * @param originURL Origin URL. + * @param request Request. + * @returns Request referrer. + */ + static getSentReferrer(originURL, request) { + if (request.referrer === "about:client" && originURL.origin === "null") { + return "no-referrer"; + } + const requestURL = new URL2(request.url); + const referrerURL = request.referrer === "about:client" ? new URL2(originURL.href) : new URL2(request.referrer); + if (REQUEST_REFERRER_UNSUPPORTED_PROTOCOL_REGEXP.test(referrerURL.protocol)) { + return "no-referrer"; + } + referrerURL.username = ""; + referrerURL.password = ""; + referrerURL.hash = ""; + switch (request.referrerPolicy) { + case "no-referrer": + return "no-referrer"; + case "origin": + return new URL2(referrerURL.origin); + case "unsafe-url": + return referrerURL; + case "strict-origin": + if (this.isURLPotentiallyTrustWorthy(referrerURL) && !this.isURLPotentiallyTrustWorthy(requestURL)) { + return "no-referrer"; + } + return new URL2(referrerURL.origin); + case "strict-origin-when-cross-origin": + if (referrerURL.origin === requestURL.origin) { + return referrerURL; + } + if (this.isURLPotentiallyTrustWorthy(referrerURL) && !this.isURLPotentiallyTrustWorthy(requestURL)) { + return "no-referrer"; + } + return new URL2(referrerURL.origin); + case "same-origin": + if (referrerURL.origin === requestURL.origin) { + return referrerURL; + } + return "no-referrer"; + case "origin-when-cross-origin": + if (referrerURL.origin === requestURL.origin) { + return referrerURL; + } + return new URL2(referrerURL.origin); + case "no-referrer-when-downgrade": + if (this.isURLPotentiallyTrustWorthy(referrerURL) && !this.isURLPotentiallyTrustWorthy(requestURL)) { + return "no-referrer"; + } + return referrerURL; + } + return "no-referrer"; + } + /** + * Returns "true" if the request's referrer is potentially trustworthy. + * + * @see https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy + * @param url URL. + * @returns "true" if the request's referrer is potentially trustworthy. + */ + static isURLPotentiallyTrustWorthy(url2) { + if (/^about:(blank|srcdoc)$/.test(url2.href)) { + return true; + } + if (url2.protocol === "data:") { + return true; + } + if (/^(blob|filesystem):$/.test(url2.protocol)) { + return true; + } + return this.isOriginPotentiallyTrustWorthy(url2); + } + /** + * Returns "true" if the request's referrer origin is potentially trustworthy. + * + * @see https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy + * @param url URL. + * @returns "true" if the request's referrer origin is potentially trustworthy. + */ + static isOriginPotentiallyTrustWorthy(url2) { + if (/^(http|ws)s:$/.test(url2.protocol)) { + return true; + } + const hostIp = url2.host.replace(/(^\[)|(]$)/g, ""); + const hostIPVersion = (0, import_net.isIP)(hostIp); + if (hostIPVersion === 4 && /^127\./.test(hostIp)) { + return true; + } + if (hostIPVersion === 6 && /^(((0+:){7})|(::(0+:){0,6}))0*1$/.test(hostIp)) { + return true; + } + if (url2.host === "localhost" || url2.host.endsWith(".localhost")) { + return false; + } + if (url2.protocol === "file:") { + return true; + } + return false; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/data-uri/DataURIParser.js +var DataURIParser; +var init_DataURIParser = __esm({ + "node_modules/happy-dom/lib/fetch/data-uri/DataURIParser.js"() { + DataURIParser = class { + /** + * Returns a Buffer instance from the given data URI `uri`. + * + * @param uri Data URI. + * @returns Buffer. + */ + static parse(uri) { + if (!/^data:/i.test(uri)) { + throw new TypeError('`uri` does not appear to be a Data URI (must begin with "data:")'); + } + uri = uri.replace(/\r?\n/g, ""); + const firstComma = uri.indexOf(","); + if (firstComma === -1 || firstComma <= 4) { + throw new TypeError("malformed data: URI"); + } + const meta = uri.substring(5, firstComma).split(";"); + let charset = ""; + let base64 = false; + let type2 = meta[0] || "text/plain"; + for (let i = 1; i < meta.length; i++) { + if (meta[i] === "base64") { + base64 = true; + } else if (meta[i]) { + type2 += `;${meta[i]}`; + if (meta[i].indexOf("charset=") === 0) { + charset = meta[i].substring(8); + } + } + } + if (!meta[0] && !charset.length) { + type2 += ";charset=US-ASCII"; + charset = "US-ASCII"; + } + const encoding = base64 ? "base64" : "ascii"; + const data2 = unescape(uri.substring(firstComma + 1)); + const buffer2 = Buffer.from(data2, encoding); + return { + type: type2, + charset, + buffer: buffer2 + }; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/utilities/FetchCORSUtility.js +var import_url2, FetchCORSUtility; +var init_FetchCORSUtility = __esm({ + "node_modules/happy-dom/lib/fetch/utilities/FetchCORSUtility.js"() { + import_url2 = require("url"); + FetchCORSUtility = class { + /** + * Validates request headers. + * + * @param originURL Origin URL. + * @param targetURL Target URL. + */ + static isCORS(originURL, targetURL) { + originURL = typeof originURL === "string" ? new import_url2.URL(originURL) : originURL; + targetURL = typeof targetURL === "string" ? new import_url2.URL(targetURL) : targetURL; + if (targetURL.protocol === "about:" || targetURL.protocol === "javascript:") { + return false; + } + return originURL.origin !== targetURL.origin; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/multipart/MultipartReader.js +var MultipartParserStateEnum, CHARACTER_CODE, MultipartReader; +var init_MultipartReader = __esm({ + "node_modules/happy-dom/lib/fetch/multipart/MultipartReader.js"() { + init_File(); + (function(MultipartParserStateEnum2) { + MultipartParserStateEnum2[MultipartParserStateEnum2["boundary"] = 0] = "boundary"; + MultipartParserStateEnum2[MultipartParserStateEnum2["headerStart"] = 2] = "headerStart"; + MultipartParserStateEnum2[MultipartParserStateEnum2["header"] = 3] = "header"; + MultipartParserStateEnum2[MultipartParserStateEnum2["data"] = 5] = "data"; + })(MultipartParserStateEnum || (MultipartParserStateEnum = {})); + CHARACTER_CODE = { + lf: 10, + cr: 13 + }; + MultipartReader = class { + formData; + boundary; + boundaryIndex = 0; + state = MultipartParserStateEnum.boundary; + data = { + contentDisposition: null, + value: [], + contentType: null, + header: "" + }; + /** + * Constructor. + * + * @param window Window. + * @param formData Form data. + * @param boundary Boundary. + */ + constructor(window2, boundary) { + const boundaryHeader = `--${boundary}`; + this.boundary = new Uint8Array(boundaryHeader.length); + this.formData = new window2.FormData(); + for (let i = 0, max = boundaryHeader.length; i < max; i++) { + this.boundary[i] = boundaryHeader.charCodeAt(i); + } + } + /** + * Appends data. + * + * @param data Data. + */ + write(data2) { + let char; + let nextChar; + for (let i = 0, max = data2.length; i < max; i++) { + char = data2[i]; + nextChar = data2[i + 1]; + switch (this.state) { + case MultipartParserStateEnum.boundary: + if (char === this.boundary[this.boundaryIndex]) { + this.boundaryIndex++; + } else { + this.boundaryIndex = 0; + } + if (this.boundaryIndex === this.boundary.length) { + this.state = MultipartParserStateEnum.headerStart; + this.boundaryIndex = 0; + } + break; + case MultipartParserStateEnum.headerStart: + if (nextChar !== CHARACTER_CODE.cr && nextChar !== CHARACTER_CODE.lf) { + this.data.header = ""; + this.state = data2[i - 2] === CHARACTER_CODE.lf ? MultipartParserStateEnum.data : MultipartParserStateEnum.header; + } + break; + case MultipartParserStateEnum.header: + if (char === CHARACTER_CODE.cr) { + if (this.data.header) { + const headerParts = this.data.header.split(":"); + if (headerParts.length > 1) { + const headerName = headerParts[0].toLowerCase(); + const headerValue = headerParts[1].trim(); + switch (headerName) { + case "content-disposition": + this.data.contentDisposition = this.getContentDisposition(headerValue); + break; + case "content-type": + this.data.contentType = headerValue; + break; + } + } + } + this.state = MultipartParserStateEnum.headerStart; + } else { + this.data.header += String.fromCharCode(char); + } + break; + case MultipartParserStateEnum.data: + if (char === this.boundary[this.boundaryIndex]) { + this.boundaryIndex++; + } else { + this.boundaryIndex = 0; + } + if (this.boundaryIndex === this.boundary.length) { + this.state = MultipartParserStateEnum.headerStart; + if (this.data.value.length) { + this.appendFormData(this.data.contentDisposition.name, Buffer.from(this.data.value.slice(0, -(this.boundary.length + 1))), this.data.contentDisposition.filename, this.data.contentType); + this.data.value = []; + this.data.contentDisposition = null; + this.data.contentType = null; + } + this.boundaryIndex = 0; + } else { + this.data.value.push(char); + } + break; + } + } + } + /** + * Ends the stream. + * + * @returns Form data. + */ + end() { + if (this.data.contentDisposition && this.data.value.length) { + this.appendFormData(this.data.contentDisposition.name, Buffer.from(this.data.value.slice(0, -2)), this.data.contentDisposition.filename, this.data.contentType); + } + return this.formData; + } + /** + * Appends data. + * + * @param key Key. + * @param value value. + * @param filename Filename. + * @param type Type. + */ + appendFormData(key, value2, filename, type2) { + if (!value2.length) { + return; + } + if (filename) { + this.formData.append(key, new File2([value2], filename, { + type: type2 + })); + } else { + this.formData.append(key, value2.toString()); + } + } + /** + * Returns content disposition. + * + * @param headerValue Header value. + * @returns Content disposition. + */ + getContentDisposition(headerValue) { + const regex = /([a-z]+) *= *"([^"]+)"/g; + const contentDisposition = {}; + let match; + while (match = regex.exec(headerValue)) { + contentDisposition[match[1]] = match[2]; + } + return contentDisposition; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/ReadableStreamWrapper.js +var ReadableStreamWrapper; +var init_ReadableStreamWrapper = __esm({ + "node_modules/happy-dom/lib/fetch/ReadableStreamWrapper.js"() { + ReadableStreamWrapper = class { + #read; + #readableStream = null; + /** + * Constructor. + * + * @param read Function that returns a ReadableStream when called. + */ + constructor(read) { + this.#read = read; + } + /** + * Returns the ReadableStream. If the stream has already been created, it returns the existing instance. + * + * @returns ReadableStream instance + */ + get readableStream() { + if (!this.#readableStream) { + this.#readableStream = this.#read(); + } + return this.#readableStream; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/multipart/MultipartFormDataParser.js +var import_web2, import_buffer3, MultipartFormDataParser; +var init_MultipartFormDataParser = __esm({ + "node_modules/happy-dom/lib/fetch/multipart/MultipartFormDataParser.js"() { + import_web2 = require("stream/web"); + init_PropertySymbol(); + init_MultipartReader(); + init_DOMExceptionNameEnum(); + import_buffer3 = require("buffer"); + init_ReadableStreamWrapper(); + MultipartFormDataParser = class { + /** + * Returns form data. + * + * @param window Window. + * @param response Response object containing a body stream. + * @param response.body Body stream. + * @param requestOrResponse + * @param requestOrResponse.body + * @param contentType Content type header value. + * @returns Form data. + */ + static async streamToFormData(window2, requestOrResponse, contentType2) { + if (!/multipart/i.test(contentType2)) { + throw new window2.DOMException(`Failed to build FormData object: The "content-type" header isn't of type "multipart/form-data".`, DOMExceptionNameEnum_default.invalidStateError); + } + const body2 = requestOrResponse.body; + if (!body2) { + throw new window2.DOMException("Failed to build FormData object: The response body is null.", DOMExceptionNameEnum_default.invalidStateError); + } + const match = contentType2.match(/boundary=(?:"([^"]+)"|([^;]+))/i); + if (!match) { + throw new window2.DOMException(`Failed to build FormData object: The "content-type" header doesn't contain any multipart boundary.`, DOMExceptionNameEnum_default.invalidStateError); + } + const bodyReader = body2.getReader(); + const reader = new MultipartReader(window2, match[1] || match[2]); + const chunks = []; + let buffer2; + const bytes = 0; + let readResult = await bodyReader.read(); + while (!readResult.done) { + if (requestOrResponse[error]) { + throw requestOrResponse[error]; + } + if (requestOrResponse[aborted]) { + throw new window2.DOMException("Failed to read response body: The stream was aborted.", DOMExceptionNameEnum_default.abortError); + } + reader.write(readResult.value); + readResult = await bodyReader.read(); + } + try { + buffer2 = typeof chunks[0] === "string" ? import_buffer3.Buffer.from(chunks.join("")) : import_buffer3.Buffer.concat(chunks, bytes); + } catch (error2) { + throw new window2.DOMException(`Could not create Buffer from response body. Error: ${error2.message}.`, DOMExceptionNameEnum_default.invalidStateError); + } + return { + formData: reader.end(), + buffer: buffer2 + }; + } + /** + * Converts a FormData object to a ReadableStream. + * + * @param formData FormData. + * @returns Stream and type. + */ + static formDataToStream(formData) { + const boundary = "----HappyDOMFormDataBoundary" + Math.random().toString(36); + const chunks = []; + const prefix2 = `--${boundary}\r +Content-Disposition: form-data; name="`; + for (const [name2, value2] of formData) { + if (typeof value2 === "string") { + chunks.push(import_buffer3.Buffer.from(`${prefix2}${this.escapeName(name2)}"\r +\r +${value2.replace(/\r(?!\n)|(? new import_web2.ReadableStream({ + start(controller) { + controller.enqueue(buffer2); + controller.close(); + } + })) + }; + } + /** + * Escapes a form data entry name. + * + * @param name Name. + * @param filename Whether it is a filename. + * @returns Escaped name. + */ + static escapeName(name2, filename = false) { + return (filename ? name2 : name2.replace(/\r?\n|\r/g, "\r\n")).replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22"); + } + }; + } +}); + +// node_modules/happy-dom/lib/form-data/FormData.js +var FormData; +var init_FormData = __esm({ + "node_modules/happy-dom/lib/form-data/FormData.js"() { + init_Blob(); + init_PropertySymbol(); + init_File(); + init_DOMExceptionNameEnum(); + FormData = class { + #entries = []; + /** + * Constructor. + * + * @param [form] Form. + * @param [submitter] The element that triggered the submission if this came from a form submit. + */ + constructor(form, submitter) { + if (!form) { + return; + } + if (submitter) { + const formProxy = form[proxy] ? form[proxy] : form; + if (submitter.form !== formProxy) { + throw new this[window].DOMException("The specified element is not owned by this form element", DOMExceptionNameEnum_default.notFoundError); + } + const isSubmitButton = submitter[tagName] === "INPUT" && (submitter.type === "submit" || submitter.type === "image") || submitter[tagName] === "BUTTON" && submitter.type === "submit"; + if (!isSubmitButton) { + throw new this[window].TypeError("The specified element is not a submit button"); + } + } + const items2 = form[getFormControlItems](); + for (const item of items2) { + const name2 = item.name; + if (name2) { + switch (item[tagName]) { + case "INPUT": + if (item.disabled) { + break; + } + switch (item.type) { + case "file": + if (item[files].length === 0) { + this.append(name2, new File2([], "", { type: "application/octet-stream" })); + } else { + for (const file of item[files]) { + this.append(name2, file); + } + } + break; + case "checkbox": + case "radio": + if (item.checked) { + this.append(name2, item.value); + } + break; + case "submit": + case "reset": + case "button": + if (item === submitter && item.value) { + this.append(name2, item.value); + } + break; + default: + this.append(name2, item.value); + break; + } + break; + case "BUTTON": + if (item === submitter && item.value) { + this.append(name2, item.value); + } + break; + case "TEXTAREA": + case "SELECT": + this.append(name2, item.value); + break; + } + } + } + } + /** + * For each. + * + * @param callback Callback. + * @param thisArg thisArg. + */ + forEach(callback, thisArg) { + for (const entry of this.#entries) { + callback.call(thisArg, entry.value, entry.name, this); + } + } + /** + * Appends a new value onto an existing key. + * + * @param name Name. + * @param value Value. + * @param [filename] Filename. + */ + append(name2, value2, filename) { + if (filename && !(value2 instanceof Blob2)) { + throw new this[window].TypeError('Failed to execute "append" on "FormData": parameter 2 is not of type "Blob".'); + } + this.#entries.push({ + name: name2, + value: this.#parseValue(value2, filename) + }); + } + /** + * Removes a value. + * + * @param name Name. + */ + delete(name2) { + const newEntries = []; + for (const entry of this.#entries) { + if (entry.name !== name2) { + newEntries.push(entry); + } + } + this.#entries = newEntries; + } + /** + * Returns value. + * + * @param name Name. + * @returns Value. + */ + get(name2) { + for (const entry of this.#entries) { + if (entry.name === name2) { + return entry.value; + } + } + return null; + } + /** + * Returns all values associated with the given name. + * + * @param name Name. + * @returns Values. + */ + getAll(name2) { + const values2 = []; + for (const entry of this.#entries) { + if (entry.name === name2) { + values2.push(entry.value); + } + } + return values2; + } + /** + * Returns whether a FormData object contains a certain key. + * + * @param name Name. + * @returns "true" if the FormData object contains the key. + */ + has(name2) { + for (const entry of this.#entries) { + if (entry.name === name2) { + return true; + } + } + return false; + } + /** + * Sets a new value for an existing key inside a FormData object, or adds the key/value if it does not already exist. + * + * @param name Name. + * @param value Value. + * @param [filename] Filename. + */ + set(name2, value2, filename) { + for (const entry of this.#entries) { + if (entry.name === name2) { + entry.value = this.#parseValue(value2, filename); + return; + } + } + this.append(name2, value2); + } + /** + * Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object. + * + * @returns Iterator. + */ + *keys() { + for (const entry of this.#entries) { + yield entry.name; + } + } + /** + * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. + * + * @returns Iterator. + */ + *values() { + for (const entry of this.#entries) { + yield entry.value; + } + } + /** + * Returns an iterator, allowing you to go through all key/value pairs contained in this object. + * + * @returns Iterator. + */ + *entries() { + for (const entry of this.#entries) { + yield [entry.name, entry.value]; + } + } + /** + * Iterator. + * + * @returns Iterator. + */ + *[Symbol.iterator]() { + for (const entry of this.#entries) { + yield [entry.name, entry.value]; + } + } + /** + * Parses a value. + * + * @param value Value. + * @param [filename] Filename. + * @returns Parsed value. + */ + #parseValue(value2, filename) { + if (value2 instanceof File2) { + if (filename) { + const file = new File2([], filename, { type: value2.type, lastModified: value2.lastModified }); + file[buffer] = value2[buffer]; + return file; + } + return value2; + } + if (value2 instanceof Blob2) { + const file = new File2([], "blob", { type: value2.type }); + file[buffer] = value2[buffer]; + return file; + } + return String(value2); + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/utilities/FetchBodyUtility.js +var import_web3, import_url3, import_buffer4, import_stream, FetchBodyUtility; +var init_FetchBodyUtility = __esm({ + "node_modules/happy-dom/lib/fetch/utilities/FetchBodyUtility.js"() { + init_MultipartFormDataParser(); + import_web3 = require("stream/web"); + init_PropertySymbol(); + import_url3 = require("url"); + init_FormData(); + init_Blob(); + init_DOMException(); + init_DOMExceptionNameEnum(); + import_buffer4 = require("buffer"); + import_stream = __toESM(require("stream"), 1); + init_ReadableStreamWrapper(); + FetchBodyUtility = class { + /** + * Parses body and returns stream and type. + * + * Based on: + * https://github.com/node-fetch/node-fetch/blob/main/src/body.js (MIT) + * + * @param body Body. + * @returns Stream and type. + */ + static getBodyStream(body2) { + if (body2 === null || body2 === void 0) { + return { stream: null, buffer: null, contentType: null, contentLength: null }; + } else if (body2 instanceof import_url3.URLSearchParams) { + const buffer3 = import_buffer4.Buffer.from(body2.toString()); + return { + buffer: buffer3, + stream: this.getReadableStream(buffer3), + contentType: "application/x-www-form-urlencoded;charset=UTF-8", + contentLength: buffer3.length + }; + } else if (body2 instanceof Blob2) { + const buffer3 = body2[buffer]; + return { + buffer: buffer3, + stream: this.getReadableStream(buffer3), + contentType: body2.type, + contentLength: body2.size + }; + } else if (import_buffer4.Buffer.isBuffer(body2)) { + return { + buffer: body2, + stream: this.getReadableStream(body2), + contentType: null, + contentLength: body2.length + }; + } else if (body2 instanceof ArrayBuffer) { + const buffer3 = import_buffer4.Buffer.from(body2); + return { + buffer: buffer3, + stream: this.getReadableStream(buffer3), + contentType: null, + contentLength: body2.byteLength + }; + } else if (ArrayBuffer.isView(body2)) { + const buffer3 = import_buffer4.Buffer.from(body2.buffer, body2.byteOffset, body2.byteLength); + return { + buffer: buffer3, + stream: this.getReadableStream(buffer3), + contentType: null, + contentLength: body2.byteLength + }; + } else if (body2 instanceof import_web3.ReadableStream) { + return { + buffer: null, + stream: new ReadableStreamWrapper(() => body2), + contentType: null, + contentLength: null + }; + } else if (body2 instanceof FormData) { + return MultipartFormDataParser.formDataToStream(body2); + } + const buffer2 = import_buffer4.Buffer.from(String(body2)); + return { + buffer: buffer2, + stream: this.getReadableStream(buffer2), + contentType: "text/plain;charset=UTF-8", + contentLength: buffer2.length + }; + } + /** + * Clones a request or body body stream. + * + * It is actually not cloning the stream. + * It creates a pass through stream and pipes the original stream to it. + * + * @param window Window. + * @param requestOrResponse Request or Response. + * @param requestOrResponse.body Body. + * @param requestOrResponse.bodyUsed Body used. + * @returns New stream. + */ + static cloneBodyStream(window2, requestOrResponse) { + if (requestOrResponse.bodyUsed) { + throw new window2.DOMException(`Failed to clone body stream of request: Request body is already used.`, DOMExceptionNameEnum_default.invalidStateError); + } + if (requestOrResponse.body === null || requestOrResponse.body === void 0) { + return null; + } + if (requestOrResponse[buffer]) { + return this.getReadableStream(requestOrResponse[buffer]).readableStream; + } + if (requestOrResponse.body[nodeStream]) { + const stream12 = new import_stream.default.PassThrough(); + const stream22 = new import_stream.default.PassThrough(); + requestOrResponse.body[nodeStream].pipe(stream12); + requestOrResponse.body[nodeStream].pipe(stream22); + requestOrResponse[body] = new ReadableStreamWrapper(() => this.nodeToWebStream(stream12)); + return this.nodeToWebStream(stream22); + } + const [stream1, stream2] = requestOrResponse.body.tee(); + requestOrResponse[body] = new ReadableStreamWrapper(() => stream1); + return stream2; + } + /** + * Consume and convert an entire Body to a Buffer. + * + * Based on: + * https://github.com/node-fetch/node-fetch/blob/main/src/body.js (MIT) + * + * @see https://fetch.spec.whatwg.org/#concept-body-consume-body + * @param window Window. + * @param requestOrResponse + * @param requestOrResponse.body + * @param body Body stream. + * @returns Promise. + */ + static async consumeBodyStream(window2, requestOrResponse) { + const body2 = requestOrResponse.body; + if (body2 === null || !(body2 instanceof import_web3.ReadableStream)) { + return import_buffer4.Buffer.alloc(0); + } + if (requestOrResponse[error]) { + throw requestOrResponse[error]; + } + const reader = body2.getReader(); + const chunks = []; + let bytes = 0; + try { + let readResult = await reader.read(); + while (!readResult.done) { + if (requestOrResponse[error]) { + throw requestOrResponse[error]; + } + if (requestOrResponse[aborted]) { + throw new window2.DOMException("Failed to read response body: The stream was aborted.", DOMExceptionNameEnum_default.abortError); + } + const chunk = readResult.value; + bytes += chunk.length; + chunks.push(chunk); + readResult = await reader.read(); + } + } catch (error2) { + if (error2 instanceof DOMException2) { + throw error2; + } + throw new window2.DOMException(`Failed to read response body. Error: ${error2.message}.`, DOMExceptionNameEnum_default.encodingError); + } + try { + if (typeof chunks[0] === "string") { + return import_buffer4.Buffer.from(chunks.join("")); + } + return import_buffer4.Buffer.concat(chunks, bytes); + } catch (error2) { + throw new window2.DOMException(`Could not create Buffer from response body. Error: ${error2.message}.`, DOMExceptionNameEnum_default.invalidStateError); + } + } + /** + * Wraps a Node.js stream into a browser-compatible ReadableStream. + * + * Enables the use of Node.js streams where browser ReadableStreams are required. + * Handles 'data', 'end', and 'error' events from the Node.js stream. + * + * @param nodeStream The Node.js stream to be converted. + * @returns ReadableStream + */ + static nodeToWebStream(nodeStream2) { + const readableStream = new import_web3.ReadableStream({ + start(controller) { + nodeStream2.on("data", (chunk) => { + controller.enqueue(chunk); + }); + nodeStream2.on("end", () => { + controller.close(); + }); + nodeStream2.on("error", (err) => { + controller.error(err); + }); + } + }); + readableStream[nodeStream] = nodeStream2; + return readableStream; + } + /** + * Wraps a given value in a browser ReadableStream. + * + * This method creates a ReadableStream and immediately enqueues and closes it + * with the provided value, useful for stream API compatibility. + * + * @param value The value to be wrapped in a ReadableStream. + * @returns ReadableStream + */ + static getReadableStream(value2) { + return new ReadableStreamWrapper(() => new import_web3.ReadableStream({ + start(controller) { + controller.enqueue(value2); + controller.close(); + } + })); + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/utilities/FetchRequestValidationUtility.js +var VALID_REFERRER_POLICIES, VALID_REDIRECTS, SUPPORTED_SCHEMAS, FORBIDDEN_REQUEST_METHODS, REQUEST_METHOD_REGEXP, FetchRequestValidationUtility; +var init_FetchRequestValidationUtility = __esm({ + "node_modules/happy-dom/lib/fetch/utilities/FetchRequestValidationUtility.js"() { + init_DOMException(); + init_PropertySymbol(); + init_DOMExceptionNameEnum(); + VALID_REFERRER_POLICIES = [ + "", + "no-referrer", + "no-referrer-when-downgrade", + "same-origin", + "origin", + "strict-origin", + "origin-when-cross-origin", + "strict-origin-when-cross-origin", + "unsafe-url" + ]; + VALID_REDIRECTS = ["error", "manual", "follow"]; + SUPPORTED_SCHEMAS = ["data:", "http:", "https:"]; + FORBIDDEN_REQUEST_METHODS = ["TRACE", "TRACK", "CONNECT"]; + REQUEST_METHOD_REGEXP = /^[A-Z]+$/; + FetchRequestValidationUtility = class { + /** + * Validates request method. + * + * @throws DOMException + * @param request Request. + */ + static validateMethod(request) { + if (!request.method || FORBIDDEN_REQUEST_METHODS.includes(request.method)) { + throw new DOMException2(`'${request.method || ""}' is not a valid HTTP method.`, DOMExceptionNameEnum_default.invalidStateError); + } + if (!REQUEST_METHOD_REGEXP.test(request.method)) { + throw new DOMException2(`'${request.method}' HTTP method is unsupported.`, DOMExceptionNameEnum_default.invalidStateError); + } + } + /** + * Validates request body. + * + * @throws DOMException + * @param request Request. + */ + static validateBody(request) { + if (request.body && (request.method === "GET" || request.method === "HEAD")) { + throw new DOMException2(`Request with GET/HEAD method cannot have body.`, DOMExceptionNameEnum_default.invalidStateError); + } + } + /** + * Validates request URL. + * + * @throws DOMException + * @param url URL. + */ + static validateURL(url2) { + if (url2.username !== "" || url2.password !== "") { + throw new DOMException2(`${url2} is an url with embedded credentials.`, DOMExceptionNameEnum_default.notSupportedError); + } + } + /** + * Validates request referrer policy. + * + * @throws DOMException + * @param referrerPolicy Referrer policy. + */ + static validateReferrerPolicy(referrerPolicy2) { + if (!VALID_REFERRER_POLICIES.includes(referrerPolicy2)) { + throw new DOMException2(`Invalid referrer policy "${referrerPolicy2}".`, DOMExceptionNameEnum_default.syntaxError); + } + } + /** + * Validates request redirect. + * + * @throws DOMException + * @param redirect Redirect. + */ + static validateRedirect(redirect2) { + if (!VALID_REDIRECTS.includes(redirect2)) { + throw new DOMException2(`Invalid redirect "${redirect2}".`, DOMExceptionNameEnum_default.syntaxError); + } + } + /** + * Validates request redirect. + * + * @throws DOMException + * @param request + * @param redirect Redirect. + */ + static validateSchema(request) { + if (!SUPPORTED_SCHEMAS.includes(request[url].protocol)) { + throw new DOMException2(`Failed to fetch from "${request.url}": URL scheme "${request[url].protocol.replace(/:$/, "")}" is not supported.`, DOMExceptionNameEnum_default.notSupportedError); + } + } + }; + } +}); + +// node_modules/happy-dom/lib/cookie/urilities/CookieStringUtility.js +var CookieStringUtility; +var init_CookieStringUtility = __esm({ + "node_modules/happy-dom/lib/cookie/urilities/CookieStringUtility.js"() { + init_CookieSameSiteEnum(); + init_DefaultCookie(); + CookieStringUtility = class { + /** + * Returns cookie. + * + * @param originURL Origin URL. + * @param cookieString Cookie string. + * @returns Cookie. + */ + static stringToCookie(originURL, cookieString) { + const parts = cookieString.split(";"); + const part = parts.shift(); + if (!part) { + return null; + } + const index = part.indexOf("="); + const key = index !== -1 ? part.slice(0, index).trim() : part.trim(); + const value2 = index !== -1 ? part.slice(index + 1).trim() : null; + const cookie = Object.assign({}, DefaultCookie_default, { + // Required + key, + value: value2, + originURL + }); + if (!cookie.key) { + return null; + } + for (const part2 of parts) { + const index2 = part2.indexOf("="); + const key2 = index2 !== -1 ? part2.slice(0, index2).trim().toLowerCase() : part2.trim().toLowerCase(); + const value3 = index2 !== -1 ? part2.slice(index2 + 1).trim() : ""; + switch (key2) { + case "expires": + cookie.expires = new Date(value3); + break; + case "max-age": + cookie.expires = new Date(parseInt(value3, 10) * 1e3 + Date.now()); + break; + case "domain": + cookie.domain = value3; + break; + case "path": + cookie.path = value3[0] === "/" ? value3 : `/${value3}`; + break; + case "httponly": + cookie.httpOnly = true; + break; + case "secure": + cookie.secure = true; + break; + case "samesite": + switch (value3.toLowerCase()) { + case "strict": + cookie.sameSite = CookieSameSiteEnum_default.strict; + break; + case "lax": + cookie.sameSite = CookieSameSiteEnum_default.lax; + break; + case "none": + cookie.sameSite = CookieSameSiteEnum_default.none; + } + break; + } + } + const lowerKey = cookie.key.toLowerCase(); + if (lowerKey.startsWith("__secure-") && !cookie.secure) { + return null; + } + if (lowerKey.startsWith("__host-") && (!cookie.secure || cookie.path !== "/" || cookie.domain)) { + return null; + } + return cookie; + } + /** + * Returns cookie string with key and value. + * + * @param cookies Cookies. + * @returns Cookie string. + */ + static cookiesToString(cookies) { + const cookieString = []; + for (const cookie of cookies) { + if (cookie.value !== null) { + cookieString.push(`${cookie.key}=${cookie.value}`); + } else { + cookieString.push(cookie.key); + } + } + return cookieString.join("; "); + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/utilities/FetchRequestHeaderUtility.js +var import_url4, FORBIDDEN_HEADER_NAMES, FetchRequestHeaderUtility; +var init_FetchRequestHeaderUtility = __esm({ + "node_modules/happy-dom/lib/fetch/utilities/FetchRequestHeaderUtility.js"() { + init_PropertySymbol(); + init_CookieStringUtility(); + init_FetchCORSUtility(); + import_url4 = require("url"); + FORBIDDEN_HEADER_NAMES = [ + "accept-charset", + "accept-encoding", + "access-control-request-headers", + "access-control-request-method", + "connection", + "content-length", + "content-transfer-encoding", + "cookie", + "cookie2", + "date", + "dnt", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "via" + ]; + FetchRequestHeaderUtility = class { + /** + * Validates request headers. + * + * @param headers Headers. + */ + static removeForbiddenHeaders(headers2) { + for (const key of Object.keys(headers2[entries])) { + if (FORBIDDEN_HEADER_NAMES.includes(key) || key.startsWith("proxy-") || key.startsWith("sec-")) { + delete headers2[entries][key]; + } + } + } + /** + * Returns "true" if the header is forbidden. + * + * @param name Header name. + * @returns "true" if the header is forbidden. + */ + static isHeaderForbidden(name2) { + return FORBIDDEN_HEADER_NAMES.includes(name2.toLowerCase()); + } + /** + * Returns request headers. + * + * @param options Options. + * @param options.browserFrame Browser frame. + * @param options.window Window. + * @param options.request Request. + * @param [options.baseHeaders] Any base headers (may be overwritten by browser/window headers). + * @returns Headers. + */ + static getRequestHeaders(options2) { + const headers2 = new options2.window.Headers(options2.baseHeaders); + options2.request.headers.forEach((value2, key) => { + headers2.set(key, value2); + }); + const originURL = new import_url4.URL(options2.window.location.href); + const isCORS = FetchCORSUtility.isCORS(originURL, options2.request[url]); + headers2.set("Accept-Encoding", "gzip, deflate, br"); + headers2.set("Connection", "close"); + if (!headers2.has("User-Agent")) { + headers2.set("User-Agent", options2.window.navigator.userAgent); + } + if (options2.request[referrer] instanceof import_url4.URL) { + headers2.set("Referer", options2.request[referrer].href); + } + if (options2.request.credentials === "include" || options2.request.credentials === "same-origin" && !isCORS) { + const cookies = options2.browserFrame.page.context.cookieContainer.getCookies(options2.request[url], false); + if (cookies.length > 0) { + headers2.set("Cookie", CookieStringUtility.cookiesToString(cookies)); + } + } else { + headers2.delete("Cookie"); + headers2.delete("Cookie2"); + } + if (!headers2.has("Accept")) { + headers2.set("Accept", "*/*"); + } + if (!headers2.has("Content-Length") && options2.request[contentLength] !== null) { + headers2.set("Content-Length", String(options2.request[contentLength])); + } + if (!headers2.has("Content-Type") && options2.request[contentType]) { + headers2.set("Content-Type", options2.request[contentType]); + } + if (isCORS) { + headers2.set("Origin", originURL.origin); + } + const httpRequestHeaders = {}; + for (const header of Object.values(headers2[entries])) { + httpRequestHeaders[header.name] = header.value.join(", "); + } + return httpRequestHeaders; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/Request.js +var import_url5, Request2; +var init_Request = __esm({ + "node_modules/happy-dom/lib/fetch/Request.js"() { + init_PropertySymbol(); + import_url5 = require("url"); + init_DOMExceptionNameEnum(); + init_FetchBodyUtility(); + init_Blob(); + init_FetchRequestValidationUtility(); + init_FetchRequestReferrerUtility(); + init_FetchRequestHeaderUtility(); + init_MultipartFormDataParser(); + init_WindowBrowserContext(); + Request2 = class _Request { + // Public properties + [method]; + [body]; + [mode] = "cors"; + [headers]; + [redirect]; + [referrerPolicy]; + [signal]; + [bodyUsed] = false; + [credentials]; + // Internal properties + [aborted] = false; + [error] = null; + [contentLength] = null; + [contentType] = null; + [referrer] = "client"; + [url]; + [bodyBuffer]; + /** + * Constructor. + * + * @param input Input. + * @param [init] Init. + */ + constructor(input, init) { + const window2 = this[window]; + if (!window2) { + throw new TypeError(`Failed to construct 'Request': 'Request' was constructed outside a Window context.`); + } + if (typeof input !== `string` && !input) { + throw new window2.TypeError(`Failed to construct 'Request': 1 argument required, only 0 present.`); + } + this[method] = (init?.method || input.method || "GET").toUpperCase(); + if (init?.mode) { + switch (init.mode) { + case "navigate": + case "websocket": + throw new window2.DOMException(`Failed to construct 'Request': Cannot construct a Request with a RequestInit whose mode member is set as '${init.mode}'.`, DOMExceptionNameEnum_default.securityError); + case "same-origin": + case "no-cors": + case "cors": + this[mode] = init.mode; + break; + default: + throw new window2.DOMException(`Failed to construct 'Request': The provided value '${init.mode}' is not a valid enum value of type RequestMode.`, DOMExceptionNameEnum_default.syntaxError); + } + } else if (input instanceof _Request) { + this[mode] = input.mode; + } + const { stream, buffer: buffer2, contentType: contentType2, contentLength: contentLength2 } = FetchBodyUtility.getBodyStream(input instanceof _Request && (input[bodyBuffer] || input.body) ? input[bodyBuffer] || FetchBodyUtility.cloneBodyStream(window2, input) : init?.body ?? null); + this[bodyBuffer] = buffer2; + this[body] = stream; + this[credentials] = init?.credentials || input.credentials || "same-origin"; + this[headers] = new this[window].Headers(init?.headers || input.headers || {}); + FetchRequestHeaderUtility.removeForbiddenHeaders(this.headers); + if (contentLength2) { + this[contentLength] = contentLength2; + } else if (!this.body && (this.method === "POST" || this.method === "PUT")) { + this[contentLength] = 0; + } + if (contentType2) { + if (!this.headers.has("Content-Type")) { + this.headers.set("Content-Type", contentType2); + } + this[contentType] = contentType2; + } else if (input instanceof _Request && input[contentType]) { + this[contentType] = input[contentType]; + } + this[redirect] = init?.redirect || input.redirect || "follow"; + this[referrerPolicy] = (init?.referrerPolicy || input.referrerPolicy || "").toLowerCase(); + this[signal] = init?.signal || input.signal || new window2.AbortSignal(); + this[referrer] = FetchRequestReferrerUtility.getInitialReferrer(window2, init?.referrer !== null && init?.referrer !== void 0 ? init?.referrer : input.referrer); + if (input instanceof import_url5.URL) { + this[url] = input; + } else { + try { + if (input instanceof _Request && input.url) { + this[url] = new import_url5.URL(input.url, window2.location.href); + } else { + this[url] = new import_url5.URL(input, window2.location.href); + } + } catch (error2) { + throw new window2.DOMException(`Failed to construct 'Request': Invalid URL "${input}" on document location '${window2.location}'.${window2.location.origin === "null" ? " Relative URLs are not permitted on current document location." : ""}`, DOMExceptionNameEnum_default.notSupportedError); + } + } + FetchRequestValidationUtility.validateMethod(this); + FetchRequestValidationUtility.validateBody(this); + FetchRequestValidationUtility.validateURL(this[url]); + FetchRequestValidationUtility.validateReferrerPolicy(this.referrerPolicy); + FetchRequestValidationUtility.validateRedirect(this.redirect); + } + /** + * Returns method. + * + * @returns Method. + */ + get method() { + return this[method]; + } + /** + * Returns body. + * + * @returns Body. + */ + get body() { + return this[body]?.readableStream || null; + } + /** + * Returns mode. + * + * @returns Mode. + */ + get mode() { + return this[mode]; + } + /** + * Returns headers. + * + * @returns Headers. + */ + get headers() { + return this[headers]; + } + /** + * Returns redirect. + * + * @returns Redirect. + */ + get redirect() { + return this[redirect]; + } + /** + * Returns referrer policy. + * + * @returns Referrer policy. + */ + get referrerPolicy() { + return this[referrerPolicy]; + } + /** + * Returns signal. + * + * @returns Signal. + */ + get signal() { + return this[signal]; + } + /** + * Returns body used. + * + * @returns Body used. + */ + get bodyUsed() { + return this[bodyUsed]; + } + /** + * Returns credentials. + * + * @returns Credentials. + */ + get credentials() { + return this[credentials]; + } + /** + * Returns referrer. + * + * @returns Referrer. + */ + get referrer() { + if (!this[referrer] || this[referrer] === "no-referrer") { + return ""; + } + if (this[referrer] === "client") { + return "about:client"; + } + return this[referrer].toString(); + } + /** + * Returns URL. + * + * @returns URL. + */ + get url() { + return this[url].href; + } + /** + * Returns string tag. + * + * @returns String tag. + */ + get [Symbol.toStringTag]() { + return "Request"; + } + /** + * Returns array buffer. + * + * @returns Array buffer. + */ + async arrayBuffer() { + const window2 = this[window]; + if (this[bodyUsed]) { + throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); + } + const asyncTaskManager2 = new WindowBrowserContext(window2).getAsyncTaskManager(); + this[bodyUsed] = true; + const taskID = asyncTaskManager2.startTask(() => { + this[aborted] = true; + this.signal[abort](); + }); + let buffer2; + try { + buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); + } catch (error2) { + asyncTaskManager2.endTask(taskID); + throw error2; + } + asyncTaskManager2.endTask(taskID); + return buffer2.buffer.slice(buffer2.byteOffset, buffer2.byteOffset + buffer2.byteLength); + } + /** + * Returns blob. + * + * @returns Blob. + */ + async blob() { + const type2 = this.headers.get("Content-Type") || ""; + const buffer2 = await this.arrayBuffer(); + return new Blob2([buffer2], { type: type2 }); + } + /** + * Returns buffer. + * + * @returns Buffer. + */ + async buffer() { + const window2 = this[window]; + if (this[bodyUsed]) { + throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); + } + const asyncTaskManager2 = new WindowBrowserContext(window2).getAsyncTaskManager(); + this[bodyUsed] = true; + const taskID = asyncTaskManager2.startTask(() => { + this[aborted] = true; + this.signal[abort](); + }); + let buffer2; + try { + buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); + } catch (error2) { + asyncTaskManager2.endTask(taskID); + throw error2; + } + asyncTaskManager2.endTask(taskID); + return buffer2; + } + /** + * Returns text. + * + * @returns Text. + */ + async text() { + const window2 = this[window]; + if (this[bodyUsed]) { + throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); + } + const asyncTaskManager2 = new WindowBrowserContext(window2).getAsyncTaskManager(); + this[bodyUsed] = true; + const taskID = asyncTaskManager2.startTask(() => { + this[aborted] = true; + this.signal[abort](); + }); + let buffer2; + try { + buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); + } catch (error2) { + asyncTaskManager2.endTask(taskID); + throw error2; + } + asyncTaskManager2.endTask(taskID); + return new TextDecoder().decode(buffer2); + } + /** + * Returns json. + * + * @returns JSON. + */ + async json() { + const text = await this.text(); + return JSON.parse(text); + } + /** + * Returns FormData. + * + * @returns FormData. + */ + async formData() { + const window2 = this[window]; + const asyncTaskManager2 = new WindowBrowserContext(window2).getAsyncTaskManager(); + const contentType2 = this.headers.get("Content-Type") ?? this[contentType]; + if (this.body && contentType2 && /multipart/i.test(contentType2)) { + if (this[bodyUsed]) { + throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); + } + this[bodyUsed] = true; + const taskID = asyncTaskManager2.startTask(() => { + this[aborted] = true; + this.signal[abort](); + }); + let formData; + try { + const result3 = await MultipartFormDataParser.streamToFormData(window2, this, contentType2); + formData = result3.formData; + } catch (error2) { + asyncTaskManager2.endTask(taskID); + throw error2; + } + asyncTaskManager2.endTask(taskID); + return formData; + } + if (contentType2?.startsWith("application/x-www-form-urlencoded")) { + const parameters = new URLSearchParams(await this.text()); + const formData = new window2.FormData(); + for (const [key, value2] of parameters) { + formData.append(key, value2); + } + return formData; + } + throw new window2.DOMException(`Failed to construct FormData object: The "content-type" header is neither "application/x-www-form-urlencoded" nor "multipart/form-data".`, DOMExceptionNameEnum_default.invalidStateError); + } + /** + * Clones request. + * + * @returns Clone. + */ + clone() { + return new this[window].Request(this); + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/Response.js +var import_url6, import_buffer5, REDIRECT_STATUS_CODES, Response2; +var init_Response = __esm({ + "node_modules/happy-dom/lib/fetch/Response.js"() { + init_PropertySymbol(); + init_Blob(); + import_url6 = require("url"); + init_URL(); + init_FetchBodyUtility(); + init_DOMExceptionNameEnum(); + init_MultipartFormDataParser(); + import_buffer5 = require("buffer"); + init_WindowBrowserContext(); + REDIRECT_STATUS_CODES = [301, 302, 303, 307, 308]; + Response2 = class { + // Public properties + bodyUsed = false; + redirected = false; + type = "basic"; + url = ""; + status; + statusText; + ok; + headers; + [cachedResponse] = null; + [buffer] = null; + [virtualServerFile] = null; + [aborted] = false; + [error] = null; + [body] = null; + /** + * Constructor. + * + * @param body Body. + * @param [init] Init. + */ + constructor(body2, init) { + if (!this[window]) { + throw new TypeError(`Failed to construct '${this.constructor.name}': '${this.constructor.name}' was constructed outside a Window context.`); + } + this.status = init?.status !== void 0 ? init.status : 200; + this.statusText = init?.statusText || ""; + this.ok = this.status >= 200 && this.status < 300; + this.headers = new this[window].Headers(init?.headers); + this.headers.delete("Set-Cookie"); + this.headers.delete("Set-Cookie2"); + if (body2) { + const { stream, buffer: buffer2, contentType: contentType2 } = FetchBodyUtility.getBodyStream(body2); + this[body] = stream; + if (buffer2) { + this[buffer] = buffer2; + } + if (contentType2 && !this.headers.has("Content-Type")) { + this.headers.set("Content-Type", contentType2); + } + } + } + /** + * Returns string tag. + * + * @returns String tag. + */ + get [Symbol.toStringTag]() { + return "Response"; + } + /** + * Returns body stream. + * + * @returns Body stream. + */ + get body() { + return this[body]?.readableStream || null; + } + /** + * Returns array buffer. + * + * @returns Array buffer. + */ + async arrayBuffer() { + const window2 = this[window]; + if (this.bodyUsed) { + throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); + } + const browserFrame = new WindowBrowserContext(window2).getBrowserFrame(); + if (!browserFrame) { + return new ArrayBuffer(0); + } + const asyncTaskManager2 = browserFrame[asyncTaskManager]; + this.bodyUsed = true; + let buffer2 = this[buffer]; + if (!buffer2) { + const taskID = asyncTaskManager2.startTask(() => { + this[aborted] = true; + }); + try { + buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); + } catch (error2) { + asyncTaskManager2.endTask(taskID); + throw error2; + } + asyncTaskManager2.endTask(taskID); + } + this.#storeBodyInCache(buffer2); + return buffer2.buffer.slice(buffer2.byteOffset, buffer2.byteOffset + buffer2.byteLength); + } + /** + * Returns blob. + * + * @returns Blob. + */ + async blob() { + const type2 = this.headers.get("Content-Type") || ""; + const buffer2 = await this.arrayBuffer(); + return new Blob2([buffer2], { type: type2 }); + } + /** + * Returns buffer. + * + * @returns Buffer. + */ + async buffer() { + const window2 = this[window]; + if (this.bodyUsed) { + throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); + } + const browserFrame = new WindowBrowserContext(window2).getBrowserFrame(); + if (!browserFrame) { + return import_buffer5.Buffer.alloc(0); + } + const asyncTaskManager2 = browserFrame[asyncTaskManager]; + this.bodyUsed = true; + let buffer2 = this[buffer]; + if (!buffer2) { + const taskID = asyncTaskManager2.startTask(() => { + this[aborted] = true; + }); + try { + buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); + } catch (error2) { + asyncTaskManager2.endTask(taskID); + throw error2; + } + asyncTaskManager2.endTask(taskID); + } + this.#storeBodyInCache(buffer2); + return buffer2; + } + /** + * Returns text. + * + * @returns Text. + */ + async text() { + const window2 = this[window]; + if (this.bodyUsed) { + throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); + } + const browserFrame = new WindowBrowserContext(window2).getBrowserFrame(); + if (!browserFrame) { + return ""; + } + const asyncTaskManager2 = browserFrame[asyncTaskManager]; + this.bodyUsed = true; + let buffer2 = this[buffer]; + if (!buffer2) { + const taskID = asyncTaskManager2.startTask(() => { + this[aborted] = true; + }); + try { + buffer2 = await FetchBodyUtility.consumeBodyStream(window2, this); + } catch (error2) { + asyncTaskManager2.endTask(taskID); + throw error2; + } + asyncTaskManager2.endTask(taskID); + } + this.#storeBodyInCache(buffer2); + return new TextDecoder().decode(buffer2); + } + /** + * Returns json. + * + * @returns JSON. + */ + async json() { + const text = await this.text(); + return JSON.parse(text); + } + /** + * Returns form data. + * + * @returns Form data. + */ + async formData() { + const window2 = this[window]; + const browserFrame = new WindowBrowserContext(window2).getBrowserFrame(); + if (!browserFrame) { + return new window2.FormData(); + } + const asyncTaskManager2 = browserFrame[asyncTaskManager]; + const contentType2 = this.headers.get("Content-Type"); + if (contentType2 && this.body && /multipart/i.test(contentType2)) { + if (this.bodyUsed) { + throw new window2.DOMException(`Body has already been used for "${this.url}".`, DOMExceptionNameEnum_default.invalidStateError); + } + this.bodyUsed = true; + const taskID = browserFrame[asyncTaskManager].startTask(() => { + this[aborted] = true; + }); + let formData; + let buffer2; + try { + const result3 = await MultipartFormDataParser.streamToFormData(window2, this, contentType2); + formData = result3.formData; + buffer2 = result3.buffer; + } catch (error2) { + asyncTaskManager2.endTask(taskID); + throw error2; + } + this.#storeBodyInCache(buffer2); + asyncTaskManager2.endTask(taskID); + return formData; + } + if (contentType2?.startsWith("application/x-www-form-urlencoded")) { + const parameters = new import_url6.URLSearchParams(await this.text()); + const formData = new window2.FormData(); + for (const [key, value2] of parameters) { + formData.append(key, value2); + } + return formData; + } + throw new window2.DOMException(`Failed to build FormData object: The "content-type" header is neither "application/x-www-form-urlencoded" nor "multipart/form-data".`, DOMExceptionNameEnum_default.invalidStateError); + } + /** + * Clones request. + * + * @returns Clone. + */ + clone() { + const window2 = this[window]; + const body2 = FetchBodyUtility.cloneBodyStream(window2, this); + const response = new window2.Response(body2, { + status: this.status, + statusText: this.statusText, + headers: this.headers + }); + response[cachedResponse] = this[cachedResponse]; + response[buffer] = this[buffer]; + response.ok = this.ok; + response.redirected = this.redirected; + response.type = this.type; + response.url = this.url; + return response; + } + /** + * Stores body in cache. + * + * @param buffer Buffer. + */ + #storeBodyInCache(buffer2) { + this[buffer] = buffer2; + if (this[cachedResponse]?.response?.waitingForBody) { + this[cachedResponse].response.body = buffer2; + this[cachedResponse].response.waitingForBody = false; + } + } + /** + * Returns a redirect response. + * + * @param url URL. + * @param status Status code. + * @returns Response. + */ + static redirect(url2, status = 302) { + const window2 = this[window]; + if (!REDIRECT_STATUS_CODES.includes(status)) { + throw new window2.DOMException("Failed to create redirect response: Invalid redirect status code.", DOMExceptionNameEnum_default.invalidStateError); + } + return new window2.Response(null, { + headers: { + location: new URL2(url2).toString() + }, + status + }); + } + /** + * Returns an error response. + * + * @param url URL. + * @param status Status code. + * @returns Response. + */ + static error() { + const response = new this[window].Response(null, { status: 0, statusText: "" }); + response.type = "error"; + return response; + } + /** + * Returns an JSON response. + * + * @param injected Injected properties. + * @param data Data. + * @param [init] Init. + * @returns Response. + */ + static json(data2, init) { + const window2 = this[window]; + const body2 = JSON.stringify(data2); + if (body2 === void 0) { + throw new window2.TypeError("data is not JSON serializable"); + } + const headers2 = new window2.Headers(init && init.headers); + if (!headers2.has("Content-Type")) { + headers2.set("Content-Type", "application/json"); + } + return new window2.Response(body2, { + status: 200, + ...init, + headers: headers2 + }); + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/utilities/FetchResponseRedirectUtility.js +var REDIRECT_STATUS_CODES2, MAX_REDIRECT_COUNT, FetchResponseRedirectUtility; +var init_FetchResponseRedirectUtility = __esm({ + "node_modules/happy-dom/lib/fetch/utilities/FetchResponseRedirectUtility.js"() { + REDIRECT_STATUS_CODES2 = [301, 302, 303, 307, 308]; + MAX_REDIRECT_COUNT = 20; + FetchResponseRedirectUtility = class { + /** + * Returns "true" if redirect. + * + * @param statusCode Status code. + * @returns "true" if redirect. + */ + static isRedirect(statusCode) { + return REDIRECT_STATUS_CODES2.includes(statusCode); + } + /** + * Returns "true" if max redirects is reached. + * + * @param redirectCount Redirect count. + * @returns "true" if max redirects is reached. + */ + static isMaxRedirectsReached(redirectCount) { + return redirectCount >= MAX_REDIRECT_COUNT; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/utilities/FetchResponseHeaderUtility.js +var FetchResponseHeaderUtility; +var init_FetchResponseHeaderUtility = __esm({ + "node_modules/happy-dom/lib/fetch/utilities/FetchResponseHeaderUtility.js"() { + init_CookieStringUtility(); + FetchResponseHeaderUtility = class { + /** + * Appends headers to response. + * + * @param nodeResponse HTTP request. + * @param options + * @param options.browserFrame + * @param options.requestURL + * @param options.rawHeaders + * @returns Headers. + */ + static parseResponseHeaders(options2) { + const headers2 = new options2.browserFrame.window.Headers(); + let key = null; + for (const header of options2.rawHeaders) { + if (!key) { + key = header; + } else { + const lowerName = key.toLowerCase(); + if (lowerName === "set-cookie" || lowerName === "set-cookie2") { + const cookie = CookieStringUtility.stringToCookie(options2.requestURL, header); + if (cookie) { + options2.browserFrame.page.context.cookieContainer.addCookies([cookie]); + } + } else { + headers2.append(key, header); + } + key = null; + } + } + return headers2; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/certificate/FetchHTTPSCertificate.js +var FetchHTTPSCertificate_default; +var init_FetchHTTPSCertificate = __esm({ + "node_modules/happy-dom/lib/fetch/certificate/FetchHTTPSCertificate.js"() { + FetchHTTPSCertificate_default = { + cert: `-----BEGIN CERTIFICATE----- +MIIDYzCCAkugAwIBAgIUJRKB/H66hpet1VfUlm0CiXqePA4wDQYJKoZIhvcNAQEL +BQAwQTELMAkGA1UEBhMCU0UxDjAMBgNVBAgMBVNrYW5lMQ4wDAYDVQQHDAVNYWxt +bzESMBAGA1UECgwJSGFwcHkgRE9NMB4XDTIyMTAxMTIyMDM0OVoXDTMyMTAwODIy +MDM0OVowQTELMAkGA1UEBhMCU0UxDjAMBgNVBAgMBVNrYW5lMQ4wDAYDVQQHDAVN +YWxtbzESMBAGA1UECgwJSGFwcHkgRE9NMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAqerQSQEg/SxVxRiwlItithr5e5EMZo1nsqt/xOxagbmpW3IEmt0j +bpbH7iEF4DDEo7KAOwUCOwVWeFxRoag8lG2ax48wrgjlCna45XDn0Xeg1ARajL04 +gs46HZ0VrzIloVGfln0zgt/Vum5BNqs9Oc5fQoBmoP3cAn3dn4ZVcP0AKthtcyPl +q2DuNRN0PV0D2RtMSiAy9l1Ko6N5x+sAeClDyOL+sTDLngZBVeZyOKt9Id15S8Zt +XtA6VMgHnnF3jChn7pag77rsd/y5iANAVNZYqRl+Eg7xaDcsvbgH46UBOrBcB39Q +tTh5Mtjoxep5e3ZDFG+kQ1HUE+iz5O5n0wIDAQABo1MwUTAdBgNVHQ4EFgQU69s9 +YSobG/m2SN4L/7zTaF7iDbwwHwYDVR0jBBgwFoAU69s9YSobG/m2SN4L/7zTaF7i +DbwwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAi/WUXx2oal8L +YnPlIuKfh49n/K18wXSYG//oFYwxfVxqpYH8hUiXVm/GUcXCxS++hUkaKLqXmH9q +MKJiCrZr3vS+2nsBKopkICu/TLdROl0sAI9lByfnEbfSAzjxe1IWJdK8NdY0y5m5 +9pEr/URVIAp/CxrneyASb4q0Jg5To3FR7vYc+2X6wZn0MundKMg6Dp9/A37jiF3l +Tt/EJp299YZcsUzh+LnRuggRjnoOVu1aLcLFlaUiwZfy9m8mLG6B/mdW/qNzNMh9 +Oqvg1zfGdpz/4D/2UUUBn6pq1vbsoAaF3OesoA3mfDcegDf/H9woJlpT0Wql+e68 +Y3FblSokcA== +-----END CERTIFICATE-----`, + key: `-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCp6tBJASD9LFXF +GLCUi2K2Gvl7kQxmjWeyq3/E7FqBualbcgSa3SNulsfuIQXgMMSjsoA7BQI7BVZ4 +XFGhqDyUbZrHjzCuCOUKdrjlcOfRd6DUBFqMvTiCzjodnRWvMiWhUZ+WfTOC39W6 +bkE2qz05zl9CgGag/dwCfd2fhlVw/QAq2G1zI+WrYO41E3Q9XQPZG0xKIDL2XUqj +o3nH6wB4KUPI4v6xMMueBkFV5nI4q30h3XlLxm1e0DpUyAeecXeMKGfulqDvuux3 +/LmIA0BU1lipGX4SDvFoNyy9uAfjpQE6sFwHf1C1OHky2OjF6nl7dkMUb6RDUdQT +6LPk7mfTAgMBAAECggEAKkwTkTjAt4UjzK56tl+EMQTB+ep/hb/JgoaChci4Nva6 +m9LkJpDJ0yuhlTuPNOGu8XjrxsVWas7HWarRf0Zb3i7yip6wZYI9Ub+AA015x4DZ +/i0fRU2NFbK0cM67qSL4jxG8gj+kZP3HPGNZxHwX/53JxMolwgmvjMc8NgvAlSFd +NnV9h4xtbhUh1NGS5zmP3iU2rwnE8JrIEzwy6axLom7nekAgkdcbAr0UoBs8gcgH +aYNhU4Gz3tGcZZ0IXAfT/bJIH1Ko8AGv4pssWc3BXcmmNdm/+kzvHIxEIV7Qegmo +XG1ZyZCyD/0b4/3e8ySDBEDqwR+HeyTW2isWG2agAQKBgQDp44aTwr3dkIXY30xv +FPfUOipg/B49dWnffYJ9MWc1FT9ijNPAngWSk0EIiEQIazICcUBI4Yji6/KeyqLJ +GdLpDi1CkKqtyh73mjELinYp3EUQgEa77aQogGa2+nMOVfu+O5CtloUrv/A18jX3 ++VEyaEASK0fWmnSI0OdlxQHIAQKBgQC5+xOls2F3MlKASvWRLlnW1wHqlDTtVoYg +5Nh8syZH4Ci2UH8tON3A5/7SWNM0t1cgV6Cw4zW8Z2spgIT/W0iYYrQ4hHL1xdCu ++CxL1km4Gy8Uwpsd+KdFahFqF/XTmLzW0HXLxWSK0fTwmdV0SFrKF3MXfTCU2AeZ +jJoMFb6P0wKBgQC3Odw6s0vkYAzLGhuZxfZkVvDOK5RRF0NKpttr0iEFL9EJFkPo +2KKK8jr3QTDy229BBJGUxsJi6u6VwS8HlehpVQbV59kd7oKV/EBBx0XMg1fDlopT +PNbmN7i/zbIG4AsoOyebJZjL7kBzMn1e9vzKHWtcEHXlw/hZGja8vjooAQKBgAeg +xK2HLfg1mCyq5meN/yFQsENu0LzrT5UJzddPgcJw7zqLEqxIKNBAs7Ls8by3yFsL +PQwERa/0jfCl1M6kb9XQNpQa2pw6ANUsWKTDpUJn2wZ+9N3F1RaDwzMWyH5lRVmK +M0qoTfdjpSg5Jwgd75taWt4bxGJWeflSSv8z5R0BAoGAWL8c527AbeBvx2tOYKkD +2TFranvANNcoMrbeviZSkkGvMNDP3p8b6juJwXOIeWNr8q4vFgCzLmq6d1/9gYm2 +3XJwwyD0LKlqzkBrrKU47qrnmMosUrIRlrAzd3HbShOptxc6Iz2apSaUDKGKXkaw +gl5OpEjeliU7Mus0BVS858g= +-----END PRIVATE KEY-----` + }; + } +}); + +// node_modules/happy-dom/lib/fetch/utilities/VirtualServerUtility.js +var import_path2, NOT_FOUND_HTML, VirtualServerUtility; +var init_VirtualServerUtility = __esm({ + "node_modules/happy-dom/lib/fetch/utilities/VirtualServerUtility.js"() { + init_WindowBrowserContext(); + import_path2 = __toESM(require("path"), 1); + init_PropertySymbol(); + NOT_FOUND_HTML = "Happy DOM Virtual Server - 404 Not Found

Happy DOM Virtual Server - 404 Not Found

"; + VirtualServerUtility = class { + /** + * Returns the filesystem path for a request URL if it matches a virtual server. + * + * @param window Window. + * @param requestURL Request URL. + */ + static getFilepath(window2, requestURL) { + const browserSettings = new WindowBrowserContext(window2).getSettings(); + if (!browserSettings || !browserSettings.fetch.virtualServers && !browserSettings.module.resolveNodeModules) { + return null; + } + if (browserSettings.fetch.virtualServers) { + for (const virtualServer of browserSettings.fetch.virtualServers) { + let baseURL = null; + if (typeof virtualServer.url === "string") { + const url2 = new URL(virtualServer.url[virtualServer.url.length - 1] === "/" ? virtualServer.url.slice(0, -1) : virtualServer.url, window2.location.origin !== "null" ? window2.location.origin : void 0); + if (requestURL.startsWith(url2.href)) { + baseURL = url2; + } + } else if (virtualServer.url instanceof RegExp) { + const match = requestURL.match(virtualServer.url); + if (match) { + baseURL = new URL(match[0][match[0].length - 1] === "/" ? match[0].slice(0, -1) : match[0], window2.location.origin); + } + } + if (baseURL) { + const path2 = requestURL.slice(baseURL.href.length).split("?")[0].split("#")[0]; + return import_path2.default.join(import_path2.default.resolve(virtualServer.directory), path2.replaceAll("/", import_path2.default.sep)); + } + } + } + if (browserSettings.module.resolveNodeModules) { + const moduleUrl = browserSettings.module.resolveNodeModules.url; + const url2 = new URL(moduleUrl[moduleUrl.length - 1] === "/" ? moduleUrl.slice(0, -1) : moduleUrl, window2.location.origin); + if (requestURL.startsWith(url2.href)) { + const path2 = requestURL.slice(url2.href.length).split("?")[0].split("#")[0]; + return import_path2.default.join(import_path2.default.resolve(browserSettings.module.resolveNodeModules.directory), path2.replaceAll("/", import_path2.default.sep)); + } + } + return null; + } + /** + * Returns a 404 response. + * + * @param window Window. + * @returns 404 response. + */ + static getNotFoundResponse(window2) { + return new window2.Response(NOT_FOUND_HTML, { + status: 404, + statusText: "Not Found", + headers: { + "Content-Type": "text/html" + } + }); + } + /** + * Returns a 404 response. + * + * @param window Window. + * @param requestURL Request URL. + * @returns 404 response. + */ + static getNotFoundSyncResponse(window2, requestURL) { + return { + status: 404, + statusText: "Not Found", + ok: false, + url: requestURL, + redirected: false, + headers: new window2.Headers({ + "Content-Type": "text/html" + }), + body: Buffer.from(NOT_FOUND_HTML), + [virtualServerFile]: null + }; + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/preload/PreloadUtility.js +var PreloadUtility; +var init_PreloadUtility = __esm({ + "node_modules/happy-dom/lib/fetch/preload/PreloadUtility.js"() { + PreloadUtility = class { + /** + * Returns a key for a preload entry. + * + * @param options Options. + * @param options.url URL. + * @param options.destination Destination. + * @param options.mode Mode. + * @param options.credentialsMode Credentials mode. + * @returns Key. + */ + static getKey(options2) { + return JSON.stringify({ + url: options2.url, + destination: options2.destination, + mode: options2.mode, + credentialsMode: options2.credentialsMode + }); + } + }; + } +}); + +// node_modules/happy-dom/lib/fetch/Fetch.js +var import_http, import_https, import_zlib, import_url7, import_fs2, import_path3, import_stream2, import_buffer6, LAST_CHUNK, Fetch; +var init_Fetch = __esm({ + "node_modules/happy-dom/lib/fetch/Fetch.js"() { + init_PropertySymbol(); + init_FetchRequestReferrerUtility(); + init_DOMExceptionNameEnum(); + import_http = __toESM(require("http"), 1); + import_https = __toESM(require("https"), 1); + import_zlib = __toESM(require("zlib"), 1); + import_url7 = require("url"); + import_fs2 = __toESM(require("fs"), 1); + import_path3 = __toESM(require("path"), 1); + import_stream2 = __toESM(require("stream"), 1); + init_DataURIParser(); + init_FetchCORSUtility(); + init_Request(); + init_Response(); + init_CachedResponseStateEnum(); + init_FetchRequestHeaderUtility(); + init_FetchRequestValidationUtility(); + init_FetchResponseRedirectUtility(); + init_FetchResponseHeaderUtility(); + init_FetchHTTPSCertificate(); + import_buffer6 = require("buffer"); + init_FetchBodyUtility(); + init_VirtualServerUtility(); + init_PreloadUtility(); + LAST_CHUNK = import_buffer6.Buffer.from("0\r\n\r\n"); + Fetch = class _Fetch { + reject = null; + resolve = null; + listeners = { + onSignalAbort: this.onSignalAbort.bind(this) + }; + isChunkedTransfer = false; + isProperLastChunkReceived = false; + previousChunk = null; + nodeRequest = null; + nodeResponse = null; + response = null; + responseHeaders = null; + interceptor; + requestHeaders; + request; + redirectCount = 0; + disableCache; + disableSameOriginPolicy; + disablePreload; + #browserFrame; + #window; + #unfilteredHeaders = null; + /** + * Constructor. + * + * @param options Options. + * @param options.browserFrame Browser frame. + * @param options.window Window. + * @param options.url URL. + * @param [options.init] Init. + * @param [options.redirectCount] Redirect count. + * @param [options.contentType] Content Type. + * @param [options.disableCache] Disables the use of cached responses. It will still store the response in the cache. + * @param [options.disableSameOriginPolicy] Disables the Same-Origin policy. + * @param [options.unfilteredHeaders] Unfiltered headers - necessary for preflight requests. + * @param [options.disablePreload] Disables the use of preloaded responses. + */ + constructor(options2) { + this.#browserFrame = options2.browserFrame; + this.#window = options2.window; + this.#unfilteredHeaders = options2.unfilteredHeaders ?? null; + this.request = typeof options2.url === "string" || options2.url instanceof import_url7.URL ? new options2.window.Request(options2.url, options2.init) : options2.url; + if (options2.contentType) { + this.request[contentType] = options2.contentType; + } + this.redirectCount = options2.redirectCount ?? 0; + this.disableCache = options2.disableCache ?? false; + this.disableSameOriginPolicy = options2.disableSameOriginPolicy ?? this.#browserFrame.page.context.browser.settings.fetch.disableSameOriginPolicy ?? false; + this.interceptor = this.#browserFrame.page.context.browser.settings.fetch.interceptor; + this.requestHeaders = this.#browserFrame.page.context.browser.settings.fetch.requestHeaders; + this.disablePreload = options2.disablePreload ?? false; + } + /** + * Sends request. + * + * @returns Response. + */ + async send() { + if (!(this.request instanceof Request2) || !(this.request[url] instanceof import_url7.URL)) { + throw new this.#window.DOMException("Unknown request object. Request object must be an instance of Request.", DOMExceptionNameEnum_default.invalidStateError); + } + FetchRequestReferrerUtility.prepareRequest(new import_url7.URL(this.#window.location.href), this.request); + if (this.requestHeaders) { + for (const header of this.requestHeaders) { + if (!header.url || (typeof header.url === "string" ? header.url.startsWith(this.request.url) : this.request.url.match(header.url))) { + for (const [key, value2] of Object.entries(header.headers)) { + this.request.headers.set(key, value2); + } + } + } + } + if (this.interceptor?.beforeAsyncRequest) { + const taskID = this.#browserFrame[asyncTaskManager].startTask(); + const response = await this.interceptor.beforeAsyncRequest({ + request: this.request, + window: this.#window + }); + this.#browserFrame[asyncTaskManager].endTask(taskID); + if (response instanceof Response2) { + return response; + } + } + FetchRequestValidationUtility.validateSchema(this.request); + if (this.request.signal[aborted]) { + if (this.request.signal[reason] !== void 0) { + throw this.request.signal[reason]; + } + throw new this.#window.DOMException("signal is aborted without reason", DOMExceptionNameEnum_default.abortError); + } + if (this.request[url].protocol === "data:") { + const result3 = DataURIParser.parse(this.request.url); + this.response = new this.#window.Response(result3.buffer, { + headers: { "Content-Type": result3.type } + }); + const interceptedResponse = this.interceptor?.afterAsyncResponse ? await this.interceptor.afterAsyncResponse({ + window: this.#window, + response: this.response, + request: this.request + }) : void 0; + return interceptedResponse instanceof Response2 ? interceptedResponse : this.response; + } + if (this.request[url].protocol === "http:" && this.#window.location.protocol === "https:") { + throw new this.#window.DOMException(`Mixed Content: The page at '${this.#window.location.href}' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint '${this.request.url}'. This request has been blocked; the content must be served over HTTPS.`, DOMExceptionNameEnum_default.securityError); + } + if (!this.disableCache) { + const cachedResponse2 = await this.getCachedResponse(); + if (cachedResponse2) { + return cachedResponse2; + } + } + if (!this.disablePreload) { + const preloadKey = PreloadUtility.getKey({ + url: this.request.url, + destination: "fetch", + mode: this.request.mode, + credentialsMode: this.request.credentials + }); + const preloadEntry = this.#window.document[preloads].get(preloadKey); + if (preloadEntry) { + this.#window.document[preloads].delete(preloadKey); + if (preloadEntry.response) { + return preloadEntry.response; + } + const taskID = this.#browserFrame[asyncTaskManager].startTask(); + const response = await preloadEntry.onResponseAvailable(); + this.#browserFrame[asyncTaskManager].endTask(taskID); + return response; + } + } + const virtualServerResponse = await this.getVirtualServerResponse(); + if (virtualServerResponse) { + return virtualServerResponse; + } + if (!this.disableSameOriginPolicy) { + const compliesWithCrossOriginPolicy = await this.compliesWithCrossOriginPolicy(); + if (!compliesWithCrossOriginPolicy) { + this.#browserFrame.page.console.warn(`Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at "${this.request.url}".`); + throw new this.#window.DOMException(`Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at "${this.request.url}".`, DOMExceptionNameEnum_default.networkError); + } + } + return await this.sendRequest(); + } + /** + * Returns cached response. + * + * @returns Response. + */ + async getCachedResponse() { + if (this.disableCache) { + return null; + } + let cachedResponse2 = this.#browserFrame.page.context.responseCache.get(this.request); + if (!cachedResponse2 || cachedResponse2.response.waitingForBody) { + return null; + } + if (cachedResponse2.state === CachedResponseStateEnum_default.stale) { + const headers2 = new this.#window.Headers(cachedResponse2.request.headers); + if (cachedResponse2.etag) { + headers2.set("If-None-Match", cachedResponse2.etag); + } else { + if (!cachedResponse2.lastModified) { + return null; + } + headers2.set("If-Modified-Since", new Date(cachedResponse2.lastModified).toUTCString()); + } + const fetch2 = new _Fetch({ + browserFrame: this.#browserFrame, + window: this.#window, + url: this.request.url, + init: { headers: headers2, method: cachedResponse2.request.method }, + disableCache: true, + disableSameOriginPolicy: true + }); + if (cachedResponse2.etag || !cachedResponse2.staleWhileRevalidate) { + const validateResponse = await fetch2.send(); + const body2 = validateResponse.status !== 304 ? await validateResponse.buffer() : null; + cachedResponse2 = this.#browserFrame.page.context.responseCache.add(this.request, { + ...validateResponse, + body: body2, + waitingForBody: false + }); + if (validateResponse.status !== 304) { + const response2 = new this.#window.Response(body2, { + status: validateResponse.status, + statusText: validateResponse.statusText, + headers: validateResponse.headers + }); + response2.url = validateResponse.url; + response2[cachedResponse] = cachedResponse2; + return response2; + } + } else { + fetch2.send().then((response2) => { + response2.buffer().then((body2) => { + this.#browserFrame.page.context.responseCache.add(this.request, { + ...response2, + body: body2, + waitingForBody: false + }); + }); + }); + } + } + if (!cachedResponse2 || cachedResponse2.response.waitingForBody) { + return null; + } + const response = new this.#window.Response(cachedResponse2.response.body, { + status: cachedResponse2.response.status, + statusText: cachedResponse2.response.statusText, + headers: cachedResponse2.response.headers + }); + response.url = cachedResponse2.response.url; + response[cachedResponse] = cachedResponse2; + return response; + } + /** + * Returns virtual server response. + * + * @returns Response. + */ + async getVirtualServerResponse() { + let filePath = VirtualServerUtility.getFilepath(this.#window, this.request.url); + if (!filePath) { + return null; + } + const taskID = this.#browserFrame[asyncTaskManager].startTask(); + if (this.request.method !== "GET") { + this.#browserFrame.page.console.error(`${this.request.method} ${this.request.url} 404 (Not Found)`); + const response2 = VirtualServerUtility.getNotFoundResponse(this.#window); + const interceptedResponse2 = this.interceptor?.afterAsyncResponse ? await this.interceptor.afterAsyncResponse({ + window: this.#window, + response: await response2, + request: this.request + }) : void 0; + this.#browserFrame[asyncTaskManager].endTask(taskID); + return interceptedResponse2 instanceof Response2 ? interceptedResponse2 : response2; + } + let buffer2; + try { + const stat = await import_fs2.default.promises.stat(filePath); + filePath = stat.isDirectory() ? import_path3.default.join(filePath, "index.html") : filePath; + buffer2 = await import_fs2.default.promises.readFile(filePath); + } catch (error2) { + this.#browserFrame.page.console.error(`${this.request.method} ${this.request.url} 404 (Not Found)`); + const response2 = VirtualServerUtility.getNotFoundResponse(this.#window); + const interceptedResponse2 = this.interceptor?.afterAsyncResponse ? await this.interceptor.afterAsyncResponse({ + window: this.#window, + response: await response2, + request: this.request + }) : void 0; + this.#browserFrame[asyncTaskManager].endTask(taskID); + return interceptedResponse2 instanceof Response2 ? interceptedResponse2 : response2; + } + const body2 = new this.#window.ReadableStream({ + start: (controller) => { + this.#window.queueMicrotask(() => { + controller.enqueue(buffer2); + controller.close(); + }); + } + }); + const response = new this.#window.Response(body2); + response[buffer] = buffer2; + response[virtualServerFile] = filePath; + response.url = this.request.url; + const interceptedResponse = this.interceptor?.afterAsyncResponse ? await this.interceptor.afterAsyncResponse({ + window: this.#window, + response: await response, + request: this.request + }) : void 0; + this.#browserFrame[asyncTaskManager].endTask(taskID); + const returnResponse = interceptedResponse instanceof Response2 ? interceptedResponse : response; + const cacheableResponse = { + ...returnResponse, + body: buffer2, + waitingForBody: false, + virtual: true + }; + response[cachedResponse] = this.#browserFrame.page.context.responseCache.add(this.request, cacheableResponse); + return returnResponse; + } + /** + * Checks if the request complies with the Cross-Origin policy. + * + * @returns True if it complies with the policy. + */ + async compliesWithCrossOriginPolicy() { + if (this.disableSameOriginPolicy || !FetchCORSUtility.isCORS(this.#window.location.href, this.request[url])) { + return true; + } + const cachedPreflightResponse = this.#browserFrame.page.context.preflightResponseCache.get(this.request); + if (cachedPreflightResponse) { + if (cachedPreflightResponse.allowOrigin !== "*" && cachedPreflightResponse.allowOrigin !== this.#window.location.origin) { + return false; + } + if (cachedPreflightResponse.allowMethods.length !== 0 && !cachedPreflightResponse.allowMethods.includes(this.request.method)) { + return false; + } + return true; + } + const requestHeaders = []; + for (const [header] of this.request.headers) { + requestHeaders.push(header.toLowerCase()); + } + const corsHeaders2 = new this.#window.Headers({ + "Access-Control-Request-Method": this.request.method, + Origin: this.#window.location.origin + }); + if (requestHeaders.length > 0) { + corsHeaders2.set("Access-Control-Request-Headers", requestHeaders.slice().sort().join(",")); + } + const fetch2 = new _Fetch({ + browserFrame: this.#browserFrame, + window: this.#window, + url: this.request.url, + init: { method: "OPTIONS" }, + disableCache: true, + disableSameOriginPolicy: true, + unfilteredHeaders: corsHeaders2 + }); + const response = await fetch2.send(); + if (!response.ok) { + return false; + } + const allowOrigin = response.headers.get("Access-Control-Allow-Origin"); + if (!allowOrigin) { + return false; + } + if (allowOrigin !== "*" && allowOrigin !== this.#window.location.origin) { + return false; + } + const allowMethods = []; + if (response.headers.has("Access-Control-Allow-Methods")) { + const allowMethodsHeader = response.headers.get("Access-Control-Allow-Methods"); + if (allowMethodsHeader !== "*") { + for (const method2 of allowMethodsHeader.split(",")) { + allowMethods.push(method2.trim().toUpperCase()); + } + } + } + if (allowMethods.length !== 0 && !allowMethods.includes(this.request.method)) { + return false; + } + return true; + } + /** + * Sends request. + * + * @returns Response. + */ + sendRequest() { + return new Promise((resolve, reject) => { + const taskID = this.#browserFrame[asyncTaskManager].startTask(() => this.onAsyncTaskManagerAbort()); + if (this.resolve) { + throw new this.#window.Error("Fetch already sent."); + } + this.resolve = async (response) => { + if (!this.disableCache && response instanceof Response2 && this.#browserFrame.page && this.#browserFrame.page.context) { + response[cachedResponse] = this.#browserFrame.page.context.responseCache.add(this.request, { + ...response, + headers: this.responseHeaders, + body: response[buffer], + waitingForBody: !response[buffer] && !!response.body + }); + } + const interceptedResponse = this.interceptor?.afterAsyncResponse ? await this.interceptor.afterAsyncResponse({ + window: this.#window, + response: await response, + request: this.request + }) : void 0; + this.#browserFrame[asyncTaskManager].endTask(taskID); + const returnResponse = interceptedResponse instanceof Response2 ? interceptedResponse : response; + if (returnResponse instanceof Response2 && !returnResponse.ok) { + this.#browserFrame.page.console.error(`${this.request.method} ${this.request.url} ${returnResponse.status} (${returnResponse.statusText})`); + } + resolve(returnResponse); + }; + this.reject = (error2) => { + this.#browserFrame[asyncTaskManager].endTask(taskID); + reject(error2); + }; + this.request.signal.addEventListener("abort", this.listeners.onSignalAbort); + const send = (this.request[url].protocol === "https:" ? import_https.default : import_http.default).request; + this.nodeRequest = send(this.request[url].href, { + method: this.request.method, + headers: FetchRequestHeaderUtility.getRequestHeaders({ + browserFrame: this.#browserFrame, + window: this.#window, + request: this.request, + baseHeaders: this.#unfilteredHeaders + }), + agent: false, + rejectUnauthorized: !this.#browserFrame.page.context.browser.settings.fetch.disableStrictSSL, + key: this.request[url].protocol === "https:" ? FetchHTTPSCertificate_default.key : void 0, + cert: this.request[url].protocol === "https:" ? FetchHTTPSCertificate_default.cert : void 0 + }); + this.nodeRequest.on("error", this.onError.bind(this)); + this.nodeRequest.on("socket", this.onSocket.bind(this)); + this.nodeRequest.on("response", this.onResponse.bind(this)); + if (this.request.body === null) { + this.nodeRequest.end(); + } else { + import_stream2.default.pipeline(this.request.body, this.nodeRequest, (error2) => { + if (error2) { + this.onError(error2); + } + }); + } + }); + } + /** + * Event listener for "socket" event. + * + * @param socket Socket. + */ + onSocket(socket) { + const onSocketClose = () => { + if (this.isChunkedTransfer && !this.isProperLastChunkReceived) { + const error2 = new this.#window.DOMException("Premature close.", DOMExceptionNameEnum_default.networkError); + this.request[error] = error2; + if (this.response) { + this.response[error] = error2; + if (this.response.body && !this.response.body.locked) { + this.response.body.cancel(error2); + } + } + } + }; + const onData = (buffer2) => { + this.isProperLastChunkReceived = import_buffer6.Buffer.compare(buffer2.slice(-5), LAST_CHUNK) === 0; + if (!this.isProperLastChunkReceived && this.previousChunk) { + this.isProperLastChunkReceived = import_buffer6.Buffer.compare(this.previousChunk.slice(-3), LAST_CHUNK.slice(0, 3)) === 0 && import_buffer6.Buffer.compare(buffer2.slice(-2), LAST_CHUNK.slice(3)) === 0; + } + this.previousChunk = buffer2; + }; + socket.prependListener("close", onSocketClose); + socket.on("data", onData); + this.nodeRequest.on("close", () => { + socket.removeListener("close", onSocketClose); + socket.removeListener("data", onData); + }); + } + /** + * Event listener for signal "abort" event. + * + * @param event Event. + */ + onSignalAbort(event) { + this.finalizeRequest(); + this.abort(event.target?.reason); + } + /** + * Event listener for request "error" event. + * + * @param error Error. + */ + onError(error2) { + this.finalizeRequest(); + this.#browserFrame.page.console.error(error2); + this.reject(new this.#window.DOMException(`Failed to execute "fetch()" on "Window" with URL "${this.request.url}": ${error2.message}`, DOMExceptionNameEnum_default.networkError)); + } + /** + * Triggered when the async task manager aborts. + */ + onAsyncTaskManagerAbort() { + const error2 = new this.#window.DOMException("The operation was aborted.", DOMExceptionNameEnum_default.abortError); + this.request[aborted] = true; + this.request[error] = error2; + if (this.response) { + this.response[aborted] = true; + this.response[error] = error2; + } + if (this.listeners.onSignalAbort) { + this.request.signal.removeEventListener("abort", this.listeners.onSignalAbort); + } + if (this.nodeRequest && !this.nodeRequest.destroyed) { + this.nodeRequest.destroy(error2); + } + if (this.nodeResponse && !this.nodeResponse.destroyed) { + this.nodeResponse.destroy(error2); + } + if (this.response && this.response.body) { + if (!this.response.body.locked) { + this.response.body.cancel(error2); + } + } + } + /** + * Event listener for request "response" event. + * + * @param nodeResponse Node response. + */ + onResponse(nodeResponse) { + this.isChunkedTransfer = nodeResponse.headers["transfer-encoding"] === "chunked" && !nodeResponse.headers["content-length"]; + this.nodeRequest.setTimeout(0); + this.responseHeaders = FetchResponseHeaderUtility.parseResponseHeaders({ + browserFrame: this.#browserFrame, + requestURL: this.request[url], + rawHeaders: nodeResponse.rawHeaders + }); + if (this.handleRedirectResponse(nodeResponse, this.responseHeaders)) { + return; + } + nodeResponse.once("end", () => this.request.signal.removeEventListener("abort", this.listeners.onSignalAbort)); + let body2 = import_stream2.default.pipeline(nodeResponse, new import_stream2.default.PassThrough(), (error2) => { + if (error2) { + } + }); + const responseOptions = { + status: nodeResponse.statusCode, + statusText: nodeResponse.statusMessage, + headers: this.responseHeaders + }; + const contentEncodingHeader = this.responseHeaders.get("Content-Encoding"); + if (this.request.method === "HEAD" || contentEncodingHeader === null || nodeResponse.statusCode === 204 || nodeResponse.statusCode === 304) { + this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); + this.response.redirected = this.redirectCount > 0; + this.response.url = this.request.url; + this.resolve(this.response); + return; + } + if (contentEncodingHeader === "gzip" || contentEncodingHeader === "x-gzip") { + const zlibOptions = { + flush: import_zlib.default.constants.Z_SYNC_FLUSH, + finishFlush: import_zlib.default.constants.Z_SYNC_FLUSH + }; + body2 = import_stream2.default.pipeline(body2, import_zlib.default.createGunzip(zlibOptions), (error2) => { + if (error2) { + } + }); + this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); + this.response.redirected = this.redirectCount > 0; + this.response.url = this.request.url; + this.resolve(this.response); + return; + } + if (contentEncodingHeader === "deflate" || contentEncodingHeader === "x-deflate") { + const raw = import_stream2.default.pipeline(nodeResponse, new import_stream2.default.PassThrough(), (error2) => { + if (error2) { + } + }); + raw.on("data", (chunk) => { + if ((chunk[0] & 15) === 8) { + body2 = import_stream2.default.pipeline(body2, import_zlib.default.createInflate(), (error2) => { + if (error2) { + } + }); + } else { + body2 = import_stream2.default.pipeline(body2, import_zlib.default.createInflateRaw(), (error2) => { + if (error2) { + } + }); + } + this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); + this.response.redirected = this.redirectCount > 0; + this.response.url = this.request.url; + this.resolve(this.response); + }); + raw.on("end", () => { + if (!this.response) { + this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); + this.response.redirected = this.redirectCount > 0; + this.response.url = this.request.url; + this.resolve(this.response); + } + }); + return; + } + if (contentEncodingHeader === "br") { + body2 = import_stream2.default.pipeline(body2, import_zlib.default.createBrotliDecompress(), (error2) => { + if (error2) { + } + }); + this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); + this.response.redirected = this.redirectCount > 0; + this.response.url = this.request.url; + this.resolve(this.response); + return; + } + this.response = new this.#window.Response(FetchBodyUtility.nodeToWebStream(body2), responseOptions); + this.response.redirected = this.redirectCount > 0; + this.response.url = this.request.url; + this.resolve(this.response); + } + /** + * Handles redirect response. + * + * @param nodeResponse Node response. + * @param responseHeaders Headers. + * @returns True if redirect response was handled, false otherwise. + */ + handleRedirectResponse(nodeResponse, responseHeaders) { + if (!FetchResponseRedirectUtility.isRedirect(nodeResponse.statusCode)) { + return false; + } + switch (this.request.redirect) { + case "error": + this.finalizeRequest(); + this.reject(new this.#window.DOMException(`URI requested responds with a redirect, redirect mode is set to "error": ${this.request.url}`, DOMExceptionNameEnum_default.abortError)); + return true; + case "manual": + return false; + case "follow": + const locationHeader = responseHeaders.get("Location"); + const shouldBecomeGetRequest = nodeResponse.statusCode === 303 || (nodeResponse.statusCode === 301 || nodeResponse.statusCode === 302) && this.request.method === "POST"; + let locationURL = null; + if (locationHeader !== null) { + try { + locationURL = new import_url7.URL(locationHeader, this.request.url); + } catch { + this.finalizeRequest(); + this.reject(new this.#window.DOMException(`URI requested responds with an invalid redirect URL: ${locationHeader}`, DOMExceptionNameEnum_default.uriMismatchError)); + return true; + } + } + if (locationURL === null) { + return false; + } + if (FetchResponseRedirectUtility.isMaxRedirectsReached(this.redirectCount)) { + this.finalizeRequest(); + this.reject(new this.#window.DOMException(`Maximum redirects reached at: ${this.request.url}`, DOMExceptionNameEnum_default.networkError)); + return true; + } + const headers2 = new this.#window.Headers(this.request.headers); + const requestInit = { + method: this.request.method, + signal: this.request.signal, + referrer: this.request.referrer, + referrerPolicy: this.request.referrerPolicy, + credentials: this.request.credentials, + headers: headers2, + body: this.request[bodyBuffer] + }; + if (this.request.credentials === "omit" || this.request.credentials === "same-origin" && FetchCORSUtility.isCORS(this.#window.location.href, locationURL)) { + headers2.delete("cookie"); + headers2.delete("cookie2"); + } + if (this.request.signal[aborted]) { + this.abort(this.request.signal[reason]); + return true; + } + if (shouldBecomeGetRequest) { + requestInit.method = "GET"; + requestInit.body = void 0; + headers2.delete("Content-Length"); + headers2.delete("Content-Type"); + } + const responseReferrerPolicy = FetchRequestReferrerUtility.getReferrerPolicyFromHeader(headers2); + if (responseReferrerPolicy) { + requestInit.referrerPolicy = responseReferrerPolicy; + } + const fetch2 = new _Fetch({ + browserFrame: this.#browserFrame, + window: this.#window, + url: locationURL, + init: requestInit, + redirectCount: this.redirectCount + 1, + disableSameOriginPolicy: this.disableSameOriginPolicy, + contentType: !shouldBecomeGetRequest ? this.request[contentType] : null + }); + this.finalizeRequest(); + fetch2.send().then((response) => this.resolve(response)).catch((error2) => this.reject(error2)); + return true; + default: + this.finalizeRequest(); + this.reject(new this.#window.DOMException(`Redirect option '${this.request.redirect}' is not a valid value of TRequestRedirect`)); + return true; + } + } + /** + * Finalizes the request. + */ + finalizeRequest() { + this.request.signal.removeEventListener("abort", this.listeners.onSignalAbort); + this.nodeRequest?.destroy(); + } + /** + * Aborts the request. + * + * @param reason Reason. + */ + abort(reason2) { + const error2 = new this.#window.DOMException("The operation was aborted." + (reason2 ? " " + reason2.toString() : ""), DOMExceptionNameEnum_default.abortError); + this.request[aborted] = true; + this.request[error] = error2; + if (this.response) { + this.response[aborted] = true; + this.response[error] = error2; + } + if (this.nodeRequest && !this.nodeRequest.destroyed) { + this.nodeRequest.destroy(error2); + } + if (this.nodeResponse && !this.nodeResponse.destroyed) { + this.nodeResponse.destroy(error2); + } + if (this.response && this.response.body) { + if (!this.response.body.locked) { + this.response.body.cancel(error2); + } + } + if (this.reject) { + this.reject(reason2 !== void 0 ? reason2 : error2); + } + } + }; + } +}); + +// node_modules/happy-dom/lib/history/HistoryScrollRestorationEnum.js +var HistoryScrollRestorationEnum, HistoryScrollRestorationEnum_default; +var init_HistoryScrollRestorationEnum = __esm({ + "node_modules/happy-dom/lib/history/HistoryScrollRestorationEnum.js"() { + (function(HistoryScrollRestorationEnum2) { + HistoryScrollRestorationEnum2["auto"] = "auto"; + HistoryScrollRestorationEnum2["manual"] = "manual"; + })(HistoryScrollRestorationEnum || (HistoryScrollRestorationEnum = {})); + HistoryScrollRestorationEnum_default = HistoryScrollRestorationEnum; + } +}); + +// node_modules/happy-dom/lib/browser/utilities/BrowserFrameURL.js +var import_url8, BrowserFrameURL; +var init_BrowserFrameURL = __esm({ + "node_modules/happy-dom/lib/browser/utilities/BrowserFrameURL.js"() { + import_url8 = require("url"); + init_PropertySymbol(); + BrowserFrameURL = class { + /** + * Returns relative URL. + * + * @param frame Frame. + * @param url URL. + * @returns Relative URL. + */ + static getRelativeURL(frame, url2) { + url2 = url2 ? String(url2) : "about:blank"; + if (url2.startsWith("about:") || url2.startsWith("javascript:")) { + return new import_url8.URL(url2); + } + try { + return new import_url8.URL(url2, frame.window[location].href); + } catch (e) { + return new import_url8.URL("about:blank"); + } + } + }; + } +}); + +// node_modules/happy-dom/lib/history/History.js +var History; +var init_History = __esm({ + "node_modules/happy-dom/lib/history/History.js"() { + init_HistoryScrollRestorationEnum(); + init_PropertySymbol(); + init_BrowserFrameURL(); + init_DOMExceptionNameEnum(); + History = class { + #browserFrame; + #window; + /** + * Constructor. + * + * @param browserFrame Browser frame. + * @param window Owner window. + */ + constructor(browserFrame, window2) { + if (!browserFrame) { + throw new TypeError("Illegal constructor"); + } + this.#browserFrame = browserFrame; + this.#window = window2; + } + /** + * Returns the history length. + * + * @returns History length. + */ + get length() { + return this.#browserFrame?.[history].items.length || 0; + } + /** + * Returns an any value representing the state at the top of the history stack. This is a way to look at the state without having to wait for a popstate event. + * + * @returns State. + */ + get state() { + return this.#browserFrame?.[history].currentItem.state || null; + } + /** + * Returns scroll restoration. + * + * @returns Sroll restoration. + */ + get scrollRestoration() { + return this.#browserFrame?.[history].currentItem.scrollRestoration || HistoryScrollRestorationEnum_default.auto; + } + /** + * Sets scroll restoration. + * + * @param scrollRestoration Sroll restoration. + */ + set scrollRestoration(scrollRestoration) { + switch (scrollRestoration) { + case HistoryScrollRestorationEnum_default.auto: + case HistoryScrollRestorationEnum_default.manual: + const currentItem = this.#browserFrame?.[history].currentItem; + if (currentItem) { + currentItem.scrollRestoration = scrollRestoration; + } + break; + } + } + /** + * Goes to the previous page in session history. + */ + back() { + if (!this.#window.closed) { + this.#browserFrame?.goBack(); + } + } + /** + * Goes to the next page in session history. + */ + forward() { + if (!this.#window.closed) { + this.#browserFrame?.goForward(); + } + } + /** + * Load a specific page from the session history. + * + * @param delta Delta. + * @param _delta + */ + go(delta) { + if (!this.#window.closed) { + this.#browserFrame?.goSteps(delta); + } + } + /** + * Pushes the given data onto the session history stack. + * + * @param state State. + * @param _unused Unused. + * @param [url] URL. + */ + pushState(state2, _unused, url2) { + if (!this.#browserFrame || this.#window.closed) { + return; + } + const history2 = this.#browserFrame?.[history]; + if (!history2) { + return; + } + if (arguments.length < 2) { + throw new this.#window.TypeError(`Failed to execute 'pushState' on 'History': 2 arguments required, but only ${arguments.length} present.`); + } + const location2 = this.#window[location]; + const newURL = url2 ? BrowserFrameURL.getRelativeURL(this.#browserFrame, url2) : location2; + if (url2 && newURL.origin !== location2.origin) { + throw new this.#window.DOMException(`Failed to execute 'pushState' on 'History': A history state object with URL '${url2.toString()}' cannot be created in a document with origin '${location2.origin}' and URL '${location2.href}'.`, DOMExceptionNameEnum_default.securityError); + } + history2.currentItem.popState = true; + history2.push({ + title: this.#window.document.title, + href: newURL.href, + state: state2, + popState: true, + scrollRestoration: history2.currentItem.scrollRestoration, + method: history2.currentItem.method || "GET", + formData: history2.currentItem.formData || null + }); + location2[setURL](this.#browserFrame, history2.currentItem.href); + } + /** + * This method modifies the current history entry, replacing it with a new state. + * + * @param state State. + * @param _unused Unused. + * @param [url] URL. + */ + replaceState(state2, _unused, url2) { + if (!this.#browserFrame || this.#window.closed) { + return; + } + const history2 = this.#browserFrame?.[history]; + if (!history2) { + return; + } + if (arguments.length < 2) { + throw new this.#window.TypeError(`Failed to execute 'pushState' on 'History': 2 arguments required, but only ${arguments.length} present.`); + } + const location2 = this.#window[location]; + const newURL = url2 ? BrowserFrameURL.getRelativeURL(this.#browserFrame, url2) : location2; + if (url2 && newURL.origin !== location2.origin) { + throw new this.#window.DOMException(`Failed to execute 'pushState' on 'History': A history state object with URL '${url2.toString()}' cannot be created in a document with origin '${location2.origin}' and URL '${location2.href}'.`, DOMExceptionNameEnum_default.securityError); + } + history2.replace({ + title: this.#window.document.title, + href: newURL.href, + state: state2, + popState: history2.currentItem.popState, + scrollRestoration: history2.currentItem.scrollRestoration, + method: history2.currentItem.method, + formData: history2.currentItem.formData + }); + if (url2) { + location2[setURL](this.#browserFrame, history2.currentItem.href); + } + } + /** + * Destroys the history. + * + * This will make sure that the History API can't access page data from the next history item. + */ + [destroy]() { + this.#browserFrame = null; + } + }; + } +}); + +// node_modules/happy-dom/lib/intersection-observer/IntersectionObserver.js +var IntersectionObserver; +var init_IntersectionObserver = __esm({ + "node_modules/happy-dom/lib/intersection-observer/IntersectionObserver.js"() { + IntersectionObserver = class { + // @ts-ignore + #callback; + // @ts-ignore + #options; + /** + * Constructor. + * + * @param callback Callback. + * @param options Options. + */ + constructor(callback, options2) { + this.#callback = callback; + this.#options = options2 || {}; + } + /** + * Starts observing. + * + * @param _target Target. + */ + observe(_target) { + } + /** + * Disconnects. + */ + disconnect() { + } + /** + * Unobserves an element. + * + * @param _target Target. + */ + unobserve(_target) { + } + /** + * Returns an array of IntersectionObserverEntry objects for all observed targets. + * + * @returns Records. + */ + takeRecords() { + return []; + } + }; + } +}); + +// node_modules/happy-dom/lib/intersection-observer/IntersectionObserverEntry.js +var IntersectionObserverEntry; +var init_IntersectionObserverEntry = __esm({ + "node_modules/happy-dom/lib/intersection-observer/IntersectionObserverEntry.js"() { + IntersectionObserverEntry = class { + boundingClientRect = null; + intersectionRatio = 0; + intersectionRect = null; + isIntersecting = false; + rootBounds = null; + target = null; + time = 0; + /** + * Constructor. + * + * @param init Options to initialize the intersection observer entry. + */ + constructor(init) { + Object.assign(this, init); + } + }; + } +}); + +// node_modules/happy-dom/lib/location/Location.js +var Location; +var init_Location = __esm({ + "node_modules/happy-dom/lib/location/Location.js"() { + init_HashChangeEvent(); + init_HistoryScrollRestorationEnum(); + init_PropertySymbol(); + Location = class { + // Public properties + [Symbol.toStringTag] = "Location"; + // Private properties + #browserFrame; + #url; + #hashChangeTimeout = null; + #hashChangeEvents = []; + /** + * Constructor. + * + * @param browserFrame Browser frame. + * @param url URL. + */ + constructor(browserFrame, url2) { + if (!browserFrame) { + throw new TypeError("Illegal constructor"); + } + this.#browserFrame = browserFrame; + this.#url = new URL(url2); + } + /** + * Returns hash. + * + * @returns Hash. + */ + get hash() { + return this.#url.hash; + } + /** + * Sets hash. + * + * @param hash Value. + */ + set hash(hash) { + const history2 = this.#browserFrame?.[history]; + if (!history2 || !this.#browserFrame) { + return; + } + const url2 = new URL(this.#url.href); + const oldHash = this.#url.hash; + url2.hash = hash; + if (url2.hash !== oldHash) { + history2.currentItem.popState = true; + history2.push({ + title: "", + href: url2.href, + state: history2.currentItem.state, + popState: true, + scrollRestoration: HistoryScrollRestorationEnum_default.manual, + method: history2.currentItem.method, + formData: history2.currentItem.formData || null + }); + this[setURL](this.#browserFrame, url2.href); + } + } + /** + * Returns host. + * + * @returns Host. + */ + get host() { + return this.#url.host; + } + /** + * Sets host. + * + * @param host Value. + */ + set host(host2) { + const url2 = new URL(this.#url.href); + url2.host = host2; + this.href = url2.href; + } + /** + * Returns hostname. + * + * @returns Hostname. + */ + get hostname() { + return this.#url.hostname; + } + /** + * Sets hostname. + * + * @param hostname Value. + */ + set hostname(hostname) { + const url2 = new URL(this.#url.href); + url2.hostname = hostname; + this.href = url2.href; + } + /** + * Override set href. + */ + get href() { + return this.#url.href; + } + /** + * Override set href. + */ + set href(url2) { + if (!this.#browserFrame) { + return; + } + this.#browserFrame.goto(url2).catch((error2) => { + if (this.#browserFrame?.page?.console) { + this.#browserFrame.page.console.error(error2); + } else { + throw error2; + } + }); + } + /** + * Returns origin. + * + * @returns Origin. + */ + get origin() { + return this.#url.origin; + } + /** + * Returns pathname + * + * @returns Pathname. + */ + get pathname() { + return this.#url.pathname; + } + /** + * Sets pathname. + * + * @param pathname Value. + */ + set pathname(pathname) { + const url2 = new URL(this.#url.href); + url2.pathname = pathname; + this.href = url2.href; + } + /** + * Returns port. + * + * @returns Port. + */ + get port() { + return this.#url.port; + } + /** + * Sets port. + * + * @param port Value. + */ + set port(port) { + const url2 = new URL(this.#url.href); + url2.port = port; + this.href = url2.href; + } + /** + * Returns protocol. + * + * @returns Protocol. + */ + get protocol() { + return this.#url.protocol; + } + /** + * Sets protocol. + * + * @param protocol Value. + */ + set protocol(protocol) { + const url2 = new URL(this.#url.href); + url2.protocol = protocol; + this.href = url2.href; + } + /** + * Returns search. + * + * @returns Search. + */ + get search() { + return this.#url.search; + } + /** + * Sets search. + * + * @param search Value. + */ + set search(search) { + const url2 = new URL(this.#url.href); + url2.search = search; + this.href = url2.href; + } + /** + * Replaces the current resource with the one at the provided URL. The difference from the assign() method is that after using replace() the current page will not be saved in session History, meaning the user won't be able to use the back button to navigate to it. + * + * @param url URL. + */ + replace(url2) { + this.href = String(url2); + } + /** + * Loads the resource at the URL provided in parameter. + * + * @param url URL. + */ + assign(url2) { + this.href = String(url2); + } + /** + * Reloads the resource from the current URL. + */ + reload() { + if (!this.#browserFrame) { + return; + } + this.#browserFrame.goto(this.href).catch((error2) => { + if (this.#browserFrame?.page.console) { + this.#browserFrame.page.console.error(error2); + } else { + throw error2; + } + }); + } + /** + * Replaces the current URL state with the provided one without navigating to the new URL. + * + * @param browserFrame Browser frame that must match the current one as validation. + * @param url URL. + */ + [setURL](browserFrame, url2) { + if (!this.#browserFrame) { + return; + } + if (this.#browserFrame !== browserFrame) { + throw new Error("Failed to set URL. Browser frame mismatch."); + } + const oldURL = this.#url.href; + const oldHash = this.#url.hash; + this.#url.href = url2; + if (this.#url.hash !== oldHash) { + const newURL = this.#url.href; + this.#hashChangeEvents.push(new HashChangeEvent("hashchange", { oldURL, newURL })); + this.#browserFrame?.window?.document?.[clearCache](); + if (this.#hashChangeTimeout) { + this.#browserFrame.window?.clearTimeout(this.#hashChangeTimeout); + } + this.#hashChangeTimeout = this.#browserFrame.window?.setTimeout(() => { + const hashChangeEvents = this.#hashChangeEvents; + this.#hashChangeEvents = []; + for (const event of hashChangeEvents) { + this.#browserFrame?.window?.dispatchEvent(event); + } + }); + } + } + /** + * Destroys the location. + */ + [destroy]() { + if (this.#hashChangeTimeout) { + this.#browserFrame?.window?.clearTimeout(this.#hashChangeTimeout); + } + this.#browserFrame = null; + } + /** + * Returns the URL as a string. + * + * @returns URL as a string. + */ + toString() { + return this.#url.toString(); + } + }; + } +}); + +// node_modules/happy-dom/lib/mutation-observer/MutationRecord.js +var MutationRecord; +var init_MutationRecord = __esm({ + "node_modules/happy-dom/lib/mutation-observer/MutationRecord.js"() { + MutationRecord = class { + type; + target; + addedNodes; + removedNodes; + previousSibling; + nextSibling; + attributeName; + attributeNamespace; + oldValue; + /** + * Constructor. + * + * @param init Options to initialize the mutation record. + * @param init.type Type. + * @param init.target Target node. + * @param init.addedNodes Nodes added. + * @param init.removedNodes Nodes removed. + * @param init.previousSibling Previous sibling node. + * @param init.nextSibling Next sibling node. + * @param init.attributeName Name of the attribute. + * @param init.attributeNamespace Namespace of the attribute. + * @param init.oldValue Previous value of the attribute. + */ + constructor(init) { + this.type = init.type; + this.target = init.target; + this.addedNodes = init.addedNodes || []; + this.removedNodes = init.removedNodes || []; + this.previousSibling = init.previousSibling || null; + this.nextSibling = init.nextSibling || null; + this.attributeName = init.attributeName || null; + this.attributeNamespace = init.attributeNamespace || null; + this.oldValue = init.oldValue || null; + } + }; + } +}); + +// node_modules/happy-dom/lib/navigator/MimeType.js +var MimeType; +var init_MimeType = __esm({ + "node_modules/happy-dom/lib/navigator/MimeType.js"() { + MimeType = class { + description; + enabledPlugin; + suffixes; + type; + /** + * Constructor. + * + * @param description + * @param enabledPlugin + * @param suffixes + * @param type + */ + constructor(description, enabledPlugin, suffixes, type2) { + this.description = description; + this.enabledPlugin = enabledPlugin; + this.suffixes = suffixes; + this.type = type2; + } + /** + * Returns the object as a string. + * + * @returns String. + */ + toString() { + return "[object MimeType]"; + } + }; + } +}); + +// node_modules/happy-dom/lib/navigator/MimeTypeArray.js +var MimeTypeArray; +var init_MimeTypeArray = __esm({ + "node_modules/happy-dom/lib/navigator/MimeTypeArray.js"() { + MimeTypeArray = class { + length; + /** + * Constructor. + * + * @param mimeTypes + */ + constructor(mimeTypes) { + for (let i = 0, max = mimeTypes.length; i < max; i++) { + this[i] = mimeTypes[i]; + this[mimeTypes[i].type] = mimeTypes[i]; + } + this.length = mimeTypes.length; + } + /** + * @param index + */ + item(index) { + return this[index] || null; + } + /** + * @param name + */ + namedItem(name2) { + return this[name2] || null; + } + /** + * Returns the object as a string. + * + * @returns String. + */ + toString() { + return "[object MimeTypeArray]"; + } + }; + } +}); + +// node_modules/happy-dom/lib/navigator/PluginArray.js +var PluginArray; +var init_PluginArray = __esm({ + "node_modules/happy-dom/lib/navigator/PluginArray.js"() { + PluginArray = class { + length; + /** + * Constructor. + * + * @param plugins Plugins. + */ + constructor(plugins) { + for (let i = 0, max = plugins.length; i < max; i++) { + this[i] = plugins[i]; + this[plugins[i].name] = plugins[i]; + } + this.length = plugins.length; + } + /** + * Returns an item. + * + * @param index Index. + * @returns Plugin. + */ + item(index) { + return this[index] || null; + } + /** + * Returns an item. + * + * @param name Name. + * @returns Plugin. + */ + namedItem(name2) { + return this[name2] || null; + } + /** + * Refreshes the list. + */ + refresh() { + } + /** + * Returns the object as a string. + * + * @returns String. + */ + toString() { + return "[object PluginArray]"; + } + }; + } +}); + +// node_modules/happy-dom/lib/permissions/PermissionNameEnum.js +var PermissionNameEnum, PermissionNameEnum_default; +var init_PermissionNameEnum = __esm({ + "node_modules/happy-dom/lib/permissions/PermissionNameEnum.js"() { + (function(PermissionNameEnum2) { + PermissionNameEnum2["geolocation"] = "geolocation"; + PermissionNameEnum2["notifications"] = "notifications"; + PermissionNameEnum2["push"] = "push"; + PermissionNameEnum2["midi"] = "midi"; + PermissionNameEnum2["camera"] = "camera"; + PermissionNameEnum2["microphone"] = "microphone"; + PermissionNameEnum2["backgroundFetch"] = "background-fetch"; + PermissionNameEnum2["backgroundSync"] = "background-sync"; + PermissionNameEnum2["persistentStorage"] = "persistent-storage"; + PermissionNameEnum2["ambientLightSensor"] = "ambient-light-sensor"; + PermissionNameEnum2["accelerometer"] = "accelerometer"; + PermissionNameEnum2["gyroscope"] = "gyroscope"; + PermissionNameEnum2["magnetometer"] = "magnetometer"; + PermissionNameEnum2["screenWakeLock"] = "screen-wake-lock"; + PermissionNameEnum2["nfc"] = "nfc"; + PermissionNameEnum2["displayCapture"] = "display-capture"; + PermissionNameEnum2["accessibilityEvents"] = "accessibility-events"; + PermissionNameEnum2["clipboardRead"] = "clipboard-read"; + PermissionNameEnum2["clipboardWrite"] = "clipboard-write"; + PermissionNameEnum2["paymentHandler"] = "payment-handler"; + PermissionNameEnum2["idleDetection"] = "idle-detection"; + PermissionNameEnum2["periodicBackgroundSync"] = "periodic-background-sync"; + PermissionNameEnum2["systemWakeLock"] = "system-wake-lock"; + PermissionNameEnum2["storageAccess"] = "storage-access"; + PermissionNameEnum2["windowManagement"] = "window-management"; + PermissionNameEnum2["windowPlacement"] = "window-placement"; + PermissionNameEnum2["localFonts"] = "local-fonts"; + PermissionNameEnum2["topLevelStorageAccess"] = "top-level-storage-access"; + })(PermissionNameEnum || (PermissionNameEnum = {})); + PermissionNameEnum_default = PermissionNameEnum; + } +}); + +// node_modules/happy-dom/lib/permissions/Permissions.js +var Permissions; +var init_Permissions = __esm({ + "node_modules/happy-dom/lib/permissions/Permissions.js"() { + init_PermissionNameEnum(); + Permissions = class { + #permissionStatus = {}; + #window; + /** + * Constructor. + * + * @param window Window. + */ + constructor(window2) { + if (!window2?.document) { + new TypeError("Invalid constructor"); + } + this.#window = window2; + } + /** + * Returns scroll restoration. + * + * @param permissionDescriptor Permission descriptor. + * @param permissionDescriptor.name Permission name. + * @param [permissionDescriptor.userVisibleOnly] User visible only. + * @param [permissionDescriptor.sysex] Sysex. + * @returns Permission status. + */ + async query(permissionDescriptor) { + const name2 = permissionDescriptor?.name; + if (name2 && this.#permissionStatus[name2]) { + return this.#permissionStatus[name2]; + } + if (!Object.values(PermissionNameEnum_default).includes(name2)) { + throw new Error(`Failed to execute 'query' on 'Permissions': Failed to read the 'name' property from 'PermissionDescriptor': The provided value '${name2}' is not a valid enum value of type PermissionName.`); + } + this.#permissionStatus[name2] = new this.#window.PermissionStatus("granted"); + return this.#permissionStatus[name2]; + } + }; + } +}); + +// node_modules/happy-dom/lib/navigator/Navigator.js +var Navigator; +var init_Navigator = __esm({ + "node_modules/happy-dom/lib/navigator/Navigator.js"() { + init_MimeTypeArray(); + init_PluginArray(); + init_Permissions(); + init_Clipboard(); + init_WindowBrowserContext(); + Navigator = class { + #window; + #clipboard; + #permissions; + /** + * Constructor. + * + * @param window Owner window. + */ + constructor(window2) { + if (!window2) { + throw new TypeError("Invalid constructor"); + } + this.#window = window2; + this.#clipboard = new Clipboard(window2); + this.#permissions = new Permissions(window2); + } + /** + * False if setting a cookie will be ignored and true otherwise. + */ + get cookieEnabled() { + return true; + } + /** + * TODO: Not implemented. + */ + get credentials() { + return null; + } + /** + * TODO: Not implemented. + */ + get geolocation() { + return null; + } + /** + * String representing the preferred language of the user, usually the language of the browser UI. + */ + get language() { + return "en-US"; + } + /** + * Array of string representing the user's preferred languages. + */ + get languages() { + return ["en-US", "en"]; + } + /** + * TODO: Not implemented. + */ + get locks() { + return null; + } + /** + * Maximum number of simultaneous touch contact points are supported by the current device. + */ + get maxTouchPoints() { + return new WindowBrowserContext(this.#window).getSettings()?.navigator.maxTouchPoints || 0; + } + /** + * Number of logical processors available to run threads on the user's computer. + */ + get hardwareConcurrency() { + return 8; + } + /** + * Browser app code name. + */ + get appCodeName() { + return "Mozilla"; + } + /** + * Browser app name. + */ + get appName() { + return "Netscape"; + } + /** + * Browser app version. + */ + get appVersion() { + const userAgent = this.userAgent; + const index = userAgent.indexOf("/"); + return index > -1 ? userAgent.substring(index + 1) : ""; + } + /** + * Browser platform. + */ + get platform() { + const userAgent = this.userAgent; + const indexStart = userAgent.indexOf("("); + const indexEnd = userAgent.indexOf(")"); + return indexStart > -1 && indexEnd > -1 ? userAgent.substring(indexStart + 1, indexEnd) : ""; + } + /** + * Browser product. + */ + get product() { + return "Gecko"; + } + /** + * Browser product sub. + */ + get productSub() { + return "20100101"; + } + /** + * Browser vendor. + */ + get vendor() { + return ""; + } + /** + * Browser vendor sub. + */ + get vendorSub() { + return ""; + } + /** + * Browser user agent. + * + * "appCodeName/appVersion number (Platform; Security; OS-or-CPU; Localization; rv: revision-version-number) product/productSub Application-Name Application-Name-version". + */ + get userAgent() { + return new WindowBrowserContext(this.#window).getSettings()?.navigator.userAgent || ""; + } + /** + * Boolean value indicating whether the browser is working online. + */ + get onLine() { + return true; + } + /** + * Returns a Permissions object that can be used to query and update permission status of APIs covered by the Permissions API. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/permissions + * @returns Permissions. + */ + get permissions() { + return this.#permissions; + } + /** + * Returns a Clipboard object providing access to the contents of the system clipboard. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/clipboard + * @returns Clipboard. + */ + get clipboard() { + return this.#clipboard; + } + /** + * Boolean Indicates whether the user agent is controlled by automation. + */ + get webdriver() { + return true; + } + /** + * The user's Do Not Track setting, which indicates whether the user is requesting web sites and advertisers to not track them. + * + * The value of the property reflects that of the DNT HTTP header, i.e. Values of "1", "0", or "unspecified". + */ + get doNotTrack() { + return "unspecified"; + } + /** + * Browser mime-types. + */ + get mimeTypes() { + return new MimeTypeArray([]); + } + /** + * Browser plugins. + */ + get plugins() { + return new PluginArray([]); + } + /** + * Sends an HTTP POST request containing a small amount of data to a web server. + * + * @param url URL. + * @param data Data. + * @returns "true" if the user agent successfully queued the data for transfer. Otherwise, it returns "false". + */ + sendBeacon(url2, data2) { + this.#window.fetch(url2, { + method: "POST", + body: data2 + }); + return true; + } + /** + * Returns the object as a string. + * + * @returns String. + */ + toString() { + return "[object Navigator]"; + } + }; + } +}); + +// node_modules/happy-dom/lib/navigator/Plugin.js +var Plugin; +var init_Plugin = __esm({ + "node_modules/happy-dom/lib/navigator/Plugin.js"() { + Plugin = class { + length = 0; + description; + filename; + name; + /** + * Constructor. + * + * @param mimeTypes Mime types. + * @param description Description. + * @param filename Filename. + * @param name Name. + */ + constructor(mimeTypes, description, filename, name2) { + this.description = description; + this.filename = filename; + this.name = name2; + for (let i = 0, max = mimeTypes.length; i < max; i++) { + this[i] = mimeTypes[i]; + this[mimeTypes[i].type] = mimeTypes[i]; + } + this.length = mimeTypes.length; + } + /** + * Item. + * + * @param index Number. + * @returns IMimeType. + */ + item(index) { + return this[index] || null; + } + /** + * NamedItem. + * + * @param name String. + * @returns IMimeType. + */ + namedItem(name2) { + return this[name2] || null; + } + /** + * Returns the object as a string. + * + * @returns String. + */ + toString() { + return "[object Plugin]"; + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/node/NodeDocumentPositionEnum.js +var NodeDocumentPositionEnum, NodeDocumentPositionEnum_default; +var init_NodeDocumentPositionEnum = __esm({ + "node_modules/happy-dom/lib/nodes/node/NodeDocumentPositionEnum.js"() { + (function(NodeDocumentPositionEnum2) { + NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["disconnect"] = 1] = "disconnect"; + NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["preceding"] = 2] = "preceding"; + NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["following"] = 4] = "following"; + NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["contains"] = 8] = "contains"; + NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["containedBy"] = 16] = "containedBy"; + NodeDocumentPositionEnum2[NodeDocumentPositionEnum2["implementationSpecific"] = 32] = "implementationSpecific"; + })(NodeDocumentPositionEnum || (NodeDocumentPositionEnum = {})); + NodeDocumentPositionEnum_default = NodeDocumentPositionEnum; + } +}); + +// node_modules/happy-dom/lib/nodes/node/NodeUtility.js +var NodeUtility; +var init_NodeUtility = __esm({ + "node_modules/happy-dom/lib/nodes/node/NodeUtility.js"() { + init_PropertySymbol(); + init_NodeTypeEnum(); + NodeUtility = class _NodeUtility { + /** + * Returns whether the passed node is a text node, and narrows its type. + * + * @param node The node to be tested. + * @returns "true" if the node is a text node. + */ + static isTextNode(node) { + return node?.[nodeType] === NodeTypeEnum_default.textNode; + } + /** + * Returns boolean indicating if "ancestorNode" is an inclusive ancestor of "referenceNode". + * + * Based on: + * https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/helpers/node.js + * + * @see https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor + * @param ancestorNode Ancestor node. + * @param referenceNode Reference node. + * @param [includeShadowRoots = false] Include shadow roots. + * @returns "true" if inclusive ancestor. + */ + static isInclusiveAncestor(ancestorNode, referenceNode, includeShadowRoots = false) { + if (ancestorNode === null || referenceNode === null) { + return false; + } + if (ancestorNode === referenceNode) { + return true; + } + if (!ancestorNode[nodeArray].length) { + return false; + } + if (includeShadowRoots && referenceNode[isConnected] !== ancestorNode[isConnected]) { + return false; + } + if (includeShadowRoots && ancestorNode === referenceNode[ownerDocument] && referenceNode[isConnected]) { + return true; + } + let parent2 = referenceNode[parentNode]; + while (parent2) { + if (ancestorNode === parent2) { + return true; + } + if (ancestorNode[parentNode] === parent2[parentNode]) { + return false; + } + parent2 = parent2[parentNode] ? parent2[parentNode] : includeShadowRoots && parent2.host ? parent2.host : null; + } + return false; + } + /** + * Returns boolean indicating if nodeB is following nodeA in the document tree. + * + * Based on: + * https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/helpers/node.js + * + * @see https://dom.spec.whatwg.org/#concept-tree-following + * @param nodeA Node A. + * @param nodeB Node B. + * @returns "true" if following. + */ + static isFollowing(nodeA, nodeB) { + if (nodeA === nodeB) { + return false; + } + let current = nodeB; + while (current) { + current = this.following(current); + if (current === nodeA) { + return true; + } + } + return false; + } + /** + * Node length. + * + * Based on: + * https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/helpers/node.js + * + * @see https://dom.spec.whatwg.org/#concept-node-length + * @param node Node. + * @returns Node length. + */ + static getNodeLength(node) { + switch (node[nodeType]) { + case NodeTypeEnum_default.documentTypeNode: + return 0; + case NodeTypeEnum_default.textNode: + case NodeTypeEnum_default.processingInstructionNode: + case NodeTypeEnum_default.commentNode: + return node.data.length; + default: + return node[nodeArray].length; + } + } + /** + * Returns boolean indicating if nodeB is following nodeA in the document tree. + * + * Based on: + * https://github.com/jsdom/js-symbol-tree/blob/master/lib/SymbolTree.js#L220 + * + * @param node Node. + * @param [root] Root. + * @returns Following node. + */ + static following(node, root2) { + const firstChild = node.firstChild; + if (firstChild) { + return firstChild; + } + let current = node; + while (current) { + if (current === root2) { + return null; + } + const nextSibling = current.nextSibling; + if (nextSibling) { + return nextSibling; + } + current = current[parentNode]; + } + return null; + } + /** + * Returns the next sibling or parents sibling. + * + * @param node Node. + * @returns Next descendant node. + */ + static nextDescendantNode(node) { + while (node && !node.nextSibling) { + node = node[parentNode]; + } + if (!node) { + return null; + } + return node.nextSibling; + } + /** + * Needed by https://dom.spec.whatwg.org/#concept-node-equals + * + * @param elementA + * @param elementB + */ + static attributeListsEqual(elementA, elementB) { + const attributesA = Array.from(elementA[attributes][items].values()); + const attributesB = Array.from(elementB[attributes][items].values()); + for (const attributeA of attributesA) { + let found = false; + for (const attributeB of attributesB) { + if (attributeA[namespaceURI] === attributeB[namespaceURI] && attributeA.localName === attributeB.localName && attributeA[value] === attributeB[value]) { + found = true; + break; + } + } + if (!found) { + return false; + } + } + return true; + } + /** + * Check if node nodeA equals node nodeB. + * Reference: https://dom.spec.whatwg.org/#concept-node-equals + * + * @param nodeA Node A. + * @param nodeB Node B. + */ + static isEqualNode(nodeA, nodeB) { + if (nodeA[nodeType] !== nodeB[nodeType]) { + return false; + } + switch (nodeA[nodeType]) { + case NodeTypeEnum_default.documentTypeNode: + const documentTypeA = nodeA; + const documentTypeB = nodeB; + if (documentTypeA.name !== documentTypeB.name || documentTypeA.publicId !== documentTypeB.publicId || documentTypeA.systemId !== documentTypeB.systemId) { + return false; + } + break; + case NodeTypeEnum_default.elementNode: + const elementA = nodeA; + const elementB = nodeB; + if (elementA[namespaceURI] !== elementB[namespaceURI] || elementA[prefix] !== elementB[prefix] || elementA[localName] !== elementB[localName] || elementA[attributes][items].size !== elementB[attributes][items].size) { + return false; + } + break; + case NodeTypeEnum_default.attributeNode: + const attributeA = nodeA; + const attributeB = nodeB; + if (attributeA[namespaceURI] !== attributeB[namespaceURI] || attributeA.localName !== attributeB.localName || attributeA[value] !== attributeB[value]) { + return false; + } + break; + case NodeTypeEnum_default.processingInstructionNode: + const processingInstructionA = nodeA; + const processingInstructionB = nodeB; + if (processingInstructionA.target !== processingInstructionB.target || processingInstructionA.data !== processingInstructionB.data) { + return false; + } + break; + case NodeTypeEnum_default.textNode: + case NodeTypeEnum_default.commentNode: + const textOrCommentA = nodeA; + const textOrCommentB = nodeB; + if (textOrCommentA.data !== textOrCommentB.data) { + return false; + } + break; + } + if (nodeA[nodeType] === NodeTypeEnum_default.elementNode && !_NodeUtility.attributeListsEqual(nodeA, nodeB)) { + return false; + } + if (nodeA[nodeArray].length !== nodeB[nodeArray].length) { + return false; + } + for (let i = 0; i < nodeA[nodeArray].length; i++) { + const childNodeA = nodeA[nodeArray][i]; + const childNodeB = nodeB[nodeArray][i]; + if (!_NodeUtility.isEqualNode(childNodeA, childNodeB)) { + return false; + } + } + return true; + } + }; + } +}); + +// node_modules/happy-dom/lib/mutation-observer/MutationTypeEnum.js +var MutationTypeEnum, MutationTypeEnum_default; +var init_MutationTypeEnum = __esm({ + "node_modules/happy-dom/lib/mutation-observer/MutationTypeEnum.js"() { + (function(MutationTypeEnum2) { + MutationTypeEnum2["attributes"] = "attributes"; + MutationTypeEnum2["characterData"] = "characterData"; + MutationTypeEnum2["childList"] = "childList"; + })(MutationTypeEnum || (MutationTypeEnum = {})); + MutationTypeEnum_default = MutationTypeEnum; + } +}); + +// node_modules/happy-dom/lib/nodes/NodeFactory.js +var NodeFactory; +var init_NodeFactory = __esm({ + "node_modules/happy-dom/lib/nodes/NodeFactory.js"() { + init_PropertySymbol(); + NodeFactory = class { + static ownerDocuments = []; + /** + * Creates a node instance with the given owner document. + * + * @param ownerDocument Owner document. + * @param nodeClass Node class. + * @param [args] Node arguments. + * @returns Node instance. + */ + static createNode(ownerDocument2, nodeClass, ...args) { + if (!nodeClass.prototype[window]) { + this.ownerDocuments.push(ownerDocument2); + } + return new nodeClass(...args); + } + /** + * Pulls an owner document from the queue. + * + * @returns Document. + */ + static pullOwnerDocument() { + return this.ownerDocuments.pop() || null; + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/node/Node.js +var Node; +var init_Node = __esm({ + "node_modules/happy-dom/lib/nodes/node/Node.js"() { + init_EventTarget(); + init_PropertySymbol(); + init_NodeTypeEnum(); + init_NodeDocumentPositionEnum(); + init_NodeUtility(); + init_NodeList(); + init_MutationRecord(); + init_MutationTypeEnum(); + init_DOMExceptionNameEnum(); + init_NodeFactory(); + Node = class _Node extends EventTarget2 { + // Public properties + static ELEMENT_NODE = NodeTypeEnum_default.elementNode; + static ATTRIBUTE_NODE = NodeTypeEnum_default.attributeNode; + static TEXT_NODE = NodeTypeEnum_default.textNode; + static CDATA_SECTION_NODE = NodeTypeEnum_default.cdataSectionNode; + static COMMENT_NODE = NodeTypeEnum_default.commentNode; + static DOCUMENT_NODE = NodeTypeEnum_default.documentNode; + static DOCUMENT_TYPE_NODE = NodeTypeEnum_default.documentTypeNode; + static DOCUMENT_FRAGMENT_NODE = NodeTypeEnum_default.documentFragmentNode; + static PROCESSING_INSTRUCTION_NODE = NodeTypeEnum_default.processingInstructionNode; + static DOCUMENT_POSITION_CONTAINED_BY = NodeDocumentPositionEnum_default.containedBy; + static DOCUMENT_POSITION_CONTAINS = NodeDocumentPositionEnum_default.contains; + static DOCUMENT_POSITION_DISCONNECTED = NodeDocumentPositionEnum_default.disconnect; + static DOCUMENT_POSITION_FOLLOWING = NodeDocumentPositionEnum_default.following; + static DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = NodeDocumentPositionEnum_default.implementationSpecific; + static DOCUMENT_POSITION_PRECEDING = NodeDocumentPositionEnum_default.preceding; + // Internal properties + [isConnected] = false; + [parentNode] = null; + [rootNode] = null; + [styleNode] = null; + [textAreaNode] = null; + [formNode] = null; + [selectNode] = null; + [mutationListeners] = []; + [nodeArray] = []; + [elementArray] = []; + [childNodes] = null; + [assignedToSlot] = null; + [cache] = { + querySelector: /* @__PURE__ */ new Map(), + querySelectorAll: /* @__PURE__ */ new Map(), + matches: /* @__PURE__ */ new Map(), + elementsByTagName: /* @__PURE__ */ new Map(), + elementsByTagNameNS: /* @__PURE__ */ new Map(), + elementByTagName: /* @__PURE__ */ new Map(), + elementById: /* @__PURE__ */ new Map(), + computedStyle: null + }; + [affectsCache] = []; + /** + * Constructor. + */ + constructor() { + super(); + if (this[window]) { + this[ownerDocument] = this[window].document; + } else { + const ownerDocument2 = NodeFactory.pullOwnerDocument(); + if (!ownerDocument2) { + throw new TypeError("Illegal constructor"); + } + this[ownerDocument] = ownerDocument2; + this[window] = ownerDocument2[window]; + } + } + /** + * Returns `Symbol.toStringTag`. + * + * @returns `Symbol.toStringTag`. + */ + get [Symbol.toStringTag]() { + return this.constructor.name; + } + /** + * Returns connected state. + * + * @returns Connected state. + */ + get isConnected() { + return this[isConnected]; + } + /** + * Returns owner document. + * + * @returns Owner document. + */ + get ownerDocument() { + return this[ownerDocument]; + } + /** + * Returns parent node. + * + * @returns Parent node. + */ + get parentNode() { + return this[parentNode]; + } + /** + * Returns node type. + * + * @returns Node type. + */ + get nodeType() { + return this[nodeType]; + } + /** + * Get child nodes. + * + * @returns Child nodes list. + */ + get childNodes() { + if (!this[childNodes]) { + this[childNodes] = new NodeList_default(illegalConstructor, this[nodeArray]); + } + return this[childNodes]; + } + /** + * Get text value of children. + * + * @returns Text content. + */ + get textContent() { + return ""; + } + /** + * Sets text content. + * + * @param _textContent Text content. + */ + set textContent(_textContent) { + } + /** + * Node value. + * + * @returns Node value. + */ + get nodeValue() { + return null; + } + /** + * Sets node value. + */ + set nodeValue(_nodeValue) { + } + /** + * Node name. + * + * @returns Node name. + */ + get nodeName() { + return ""; + } + /** + * Previous sibling. + * + * @returns Node. + */ + get previousSibling() { + if (this[parentNode]) { + const nodeArray2 = this[parentNode][nodeArray]; + const index = nodeArray2.indexOf(this[proxy] || this); + if (index > 0) { + return nodeArray2[index - 1]; + } + } + return null; + } + /** + * Next sibling. + * + * @returns Node. + */ + get nextSibling() { + if (this[parentNode]) { + const nodeArray2 = this[parentNode][nodeArray]; + const index = nodeArray2.indexOf(this[proxy] || this); + if (index > -1 && index + 1 < nodeArray2.length) { + return nodeArray2[index + 1]; + } + } + return null; + } + /** + * First child. + * + * @returns Node. + */ + get firstChild() { + const nodeArray2 = this[nodeArray]; + if (nodeArray2.length > 0) { + return nodeArray2[0]; + } + return null; + } + /** + * Last child. + * + * @returns Node. + */ + get lastChild() { + const nodeArray2 = this[nodeArray]; + if (nodeArray2.length > 0) { + return nodeArray2[nodeArray2.length - 1]; + } + return null; + } + /** + * Returns parent element. + * + * @returns Element. + */ + get parentElement() { + let parent2 = this[parentNode]; + while (parent2 && parent2[nodeType] !== NodeTypeEnum_default.elementNode) { + parent2 = parent2[parentNode]; + } + return parent2; + } + /** + * Returns base URI. + * + * @returns Base URI. + */ + get baseURI() { + const base = this[ownerDocument].querySelector("base"); + if (base) { + return base.href; + } + return this[window].location.href; + } + /** + * Returns "true" if the node has child nodes. + * + * @returns "true" if the node has child nodes. + */ + hasChildNodes() { + return this[nodeArray].length > 0; + } + /** + * Returns "true" if this node contains the other node. + * + * @param otherNode Node to test with. + * @returns "true" if this node contains the other node. + */ + contains(otherNode) { + if (otherNode === void 0) { + return false; + } + const self2 = this[proxy] || this; + return NodeUtility.isInclusiveAncestor(self2, otherNode); + } + /** + * Returns closest root node (Document or ShadowRoot). + * + * @param options Options. + * @param options.composed A Boolean that indicates whether the shadow root should be returned (false, the default), or a root node beyond shadow root (true). + * @returns Node. + */ + getRootNode(options2) { + if (this[isConnected]) { + if (this[rootNode] && !options2?.composed) { + return this[rootNode]; + } + return this[ownerDocument]; + } + let root2 = this; + while (root2[parentNode]) { + root2 = root2[parentNode]; + } + return root2; + } + /** + * Clones a node. + * + * @param [deep=false] "true" to clone deep. + * @returns Cloned node. + */ + cloneNode(deep = false) { + return this[cloneNode](deep); + } + /** + * Append a child node to childNodes. + * + * @param node Node to append. + * @returns Appended node. + */ + appendChild(node) { + if (arguments.length < 1) { + throw new this[window].TypeError(`Failed to execute 'appendChild' on 'Node': 1 argument required, but only 0 present`); + } + return this[appendChild](node); + } + /** + * Remove Child element from childNodes array. + * + * @param node Node to remove. + * @returns Removed node. + */ + removeChild(node) { + if (arguments.length < 1) { + throw new this[window].TypeError(`Failed to execute 'removeChild' on 'Node': 1 argument required, but only 0 present`); + } + return this[removeChild](node); + } + /** + * Inserts a node before another. + * + * @param newNode Node to insert. + * @param referenceNode Node to insert before. + * @returns Inserted node. + */ + insertBefore(newNode, referenceNode) { + if (arguments.length < 2) { + throw new this[window].TypeError(`Failed to execute 'insertBefore' on 'Node': 2 arguments required, but only ${arguments.length} present.`); + } + return this[insertBefore](newNode, referenceNode); + } + /** + * Replaces a node with another. + * + * @param newChild New child. + * @param oldChild Old child. + * @returns Replaced node. + */ + replaceChild(newChild, oldChild) { + if (arguments.length < 2) { + throw new this[window].TypeError(`Failed to execute 'replaceChild' on 'Node': 2 arguments required, but only ${arguments.length} present.`); + } + return this[replaceChild](newChild, oldChild); + } + /** + * Clones a node. + * + * @param [deep=false] "true" to clone deep. + * @returns Cloned node. + */ + [cloneNode](deep = false) { + const clone2 = NodeFactory.createNode(this[ownerDocument], this.constructor); + if (clone2[nodeArray].length) { + const childNodes2 = clone2[nodeArray]; + while (childNodes2.length) { + clone2.removeChild(childNodes2[0]); + } + } + if (deep) { + for (const childNode of this[nodeArray]) { + const childClone = childNode.cloneNode(true); + childClone[parentNode] = clone2; + clone2[nodeArray].push(childClone); + if (childClone[nodeType] === NodeTypeEnum_default.elementNode) { + clone2[elementArray].push(childClone); + } + } + } + return clone2; + } + /** + * Append a child node to childNodes. + * + * @param node Node to append. + * @param [disableValidations=false] "true" to disable validations. + * @returns Appended node. + */ + [appendChild](node, disableValidations = false) { + if (node[proxy]) { + node = node[proxy]; + } + const self2 = this[proxy] || this; + if (!disableValidations) { + if (node === self2) { + throw new this[window].DOMException("Failed to execute 'appendChild' on 'Node': Not possible to append a node as a child of itself."); + } + if (NodeUtility.isInclusiveAncestor(node, self2, true)) { + throw new this[window].DOMException("Failed to execute 'appendChild' on 'Node': The new node is a parent of the node to insert to.", DOMExceptionNameEnum_default.domException); + } + } + if (node[nodeType] === NodeTypeEnum_default.documentFragmentNode) { + const childNodes2 = node[nodeArray]; + while (childNodes2.length) { + this.appendChild(childNodes2[0]); + } + return node; + } + if (node[parentNode]) { + node[parentNode][removeChild](node); + } + node[parentNode] = self2; + node[clearCache](); + this[nodeArray].push(node); + if (node[nodeType] === NodeTypeEnum_default.elementNode) { + this[elementArray].push(node); + } + node[connectedToNode](); + for (const mutationListener of this[mutationListeners]) { + if (mutationListener.options?.subtree && mutationListener.callback.deref()) { + node[observeMutations](mutationListener); + } + } + this[reportMutation](new MutationRecord({ + target: self2, + type: MutationTypeEnum_default.childList, + addedNodes: [node] + })); + return node; + } + /** + * Remove Child element from childNodes array. + * + * @param node Node to remove. + * @returns Removed node. + */ + [removeChild](node) { + if (node[proxy]) { + node = node[proxy]; + } + const index = this[nodeArray].indexOf(node); + if (index === -1) { + throw new this[window].DOMException(`Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.`); + } + const previousSibling = node.previousSibling; + const nextSibling = node.nextSibling; + node[parentNode] = null; + node[clearCache](); + this[nodeArray].splice(index, 1); + if (node[nodeType] === NodeTypeEnum_default.elementNode) { + const index2 = this[elementArray].indexOf(node); + if (index2 !== -1) { + this[elementArray].splice(index2, 1); + } + } + if (node[assignedToSlot]) { + const index2 = node[assignedToSlot][assignedNodes].indexOf(node); + if (index2 !== -1) { + node[assignedToSlot][assignedNodes].splice(index2, 1); + } + node[assignedToSlot] = null; + } + node[disconnectedFromNode](); + for (const mutationListener of this[mutationListeners]) { + if (mutationListener.options?.subtree && mutationListener.callback.deref()) { + node[unobserveMutations](mutationListener); + } + } + this[reportMutation](new MutationRecord({ + target: this[proxy] || this, + type: MutationTypeEnum_default.childList, + removedNodes: [node], + previousSibling, + nextSibling + })); + return node; + } + /** + * Inserts a node before another. + * + * @param newNode Node to insert. + * @param referenceNode Node to insert before. + * @param [disableValidations=false] "true" to disable validations. + * @returns Inserted node. + */ + [insertBefore](newNode, referenceNode, disableValidations = false) { + if (newNode[proxy]) { + newNode = newNode[proxy]; + } + if (referenceNode && referenceNode[proxy]) { + referenceNode = referenceNode[proxy]; + } + if (newNode === referenceNode) { + return newNode; + } + const self2 = this[proxy] || this; + if (!disableValidations) { + if (newNode === self2) { + throw new this[window].DOMException("Failed to execute 'insertBefore' on 'Node': Not possible to insert a node as a child of itself."); + } + if (NodeUtility.isInclusiveAncestor(newNode, self2, true)) { + throw new this[window].DOMException("Failed to execute 'insertBefore' on 'Node': The new node is a parent of the node to insert to.", DOMExceptionNameEnum_default.domException); + } + } + if (newNode[nodeType] === NodeTypeEnum_default.documentFragmentNode) { + const childNodes2 = newNode[nodeArray]; + while (childNodes2.length > 0) { + this[insertBefore](childNodes2[0], referenceNode, true); + } + return newNode; + } + if (!referenceNode) { + this[appendChild](newNode, true); + return newNode; + } + const nodeArray2 = this[nodeArray]; + if (!nodeArray2.includes(referenceNode)) { + throw new this[window].DOMException("Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node."); + } + if (newNode[parentNode]) { + newNode[parentNode][removeChild](newNode); + } + newNode[parentNode] = self2; + newNode[clearCache](); + const index = nodeArray2.indexOf(referenceNode); + if (newNode[nodeType] === NodeTypeEnum_default.elementNode) { + const elementArray2 = this[elementArray]; + if (referenceNode[nodeType] === NodeTypeEnum_default.elementNode) { + elementArray2.splice(elementArray2.indexOf(referenceNode), 0, newNode); + } else { + let isInserted = false; + for (let i = index, max = nodeArray2.length; i < max; i++) { + if (nodeArray2[i][nodeType] === NodeTypeEnum_default.elementNode) { + elementArray2.splice(elementArray2.indexOf(nodeArray2[i]), 0, newNode); + isInserted = true; + break; + } + } + if (!isInserted) { + elementArray2.push(newNode); + } + } + } + nodeArray2.splice(index, 0, newNode); + newNode[connectedToNode](); + for (const mutationListener of this[mutationListeners]) { + if (mutationListener.options?.subtree && mutationListener.callback.deref()) { + newNode[observeMutations](mutationListener); + } + } + this[reportMutation](new MutationRecord({ + target: self2, + type: MutationTypeEnum_default.childList, + addedNodes: [newNode] + })); + return newNode; + } + /** + * Replaces a node with another. + * + * @param newChild New child. + * @param oldChild Old child. + * @returns Replaced node. + */ + [replaceChild](newChild, oldChild) { + this.insertBefore(newChild, oldChild); + this.removeChild(oldChild); + return oldChild; + } + /** + * Compares two nodes. + * Two nodes are equal if they have the same type, defining the same attributes, and so on. + * + * @param node Node to compare. + * @returns boolean - `true` if two nodes are equal. + */ + isEqualNode(node) { + return NodeUtility.isEqualNode(this, node); + } + /** + * Converts the node to a string. + * + * @param listener Listener. + */ + toString() { + return `[object ${this.constructor.name}]`; + } + /** + * Observeres mutations on the node. + * + * Used by MutationObserver and internal logic. + * + * @param listener Listener. + */ + [observeMutations](listener) { + this[mutationListeners].push(listener); + if (listener.options.subtree) { + for (const node of this[nodeArray]) { + node[observeMutations](listener); + } + } + } + /** + * Stops observing mutations on the node. + * + * Used by MutationObserver and internal logic. + * + * @param listener Listener. + */ + [unobserveMutations](listener) { + const index = this[mutationListeners].indexOf(listener); + if (index !== -1) { + this[mutationListeners].splice(index, 1); + } + if (listener.options.subtree) { + for (const node of this[nodeArray]) { + node[unobserveMutations](listener); + } + } + } + /** + * Reports a mutation on the node. + * + * Used by MutationObserver and internal logic. + * + * @param record Mutation record. + */ + [reportMutation](record) { + this[clearCache](); + const mutationListeners2 = this[mutationListeners]; + if (!mutationListeners2.length) { + return; + } + for (let i = 0, max = mutationListeners2.length; i < max; i++) { + const mutationListener = mutationListeners2[i]; + const callback = mutationListener.callback.deref(); + if (callback) { + switch (record.type) { + case MutationTypeEnum_default.childList: + if (mutationListener.options.childList) { + callback(record); + } + break; + case MutationTypeEnum_default.attributes: + if (mutationListener.options.attributes && (!mutationListener.options.attributeFilter || mutationListener.options.attributeFilter.includes(record.attributeName))) { + callback(record); + } + break; + case MutationTypeEnum_default.characterData: + if (mutationListener.options?.characterData) { + callback(record); + } + break; + } + } else { + mutationListeners2.splice(i, 1); + i--; + max--; + } + } + } + /** + * Clears query selector cache. + */ + [clearCache]() { + const cache2 = this[cache]; + if (cache2.querySelector.size) { + for (const item of cache2.querySelector.values()) { + if (item.result) { + item.result = null; + } + } + cache2.querySelector = /* @__PURE__ */ new Map(); + } + if (cache2.querySelectorAll.size) { + for (const item of cache2.querySelectorAll.values()) { + if (item.result) { + item.result = null; + } + } + cache2.querySelectorAll = /* @__PURE__ */ new Map(); + } + if (cache2.matches.size) { + for (const item of cache2.matches.values()) { + if (item.result) { + item.result = null; + } + } + cache2.matches = /* @__PURE__ */ new Map(); + } + if (cache2.elementsByTagName.size) { + for (const item of cache2.elementsByTagName.values()) { + if (item.result) { + item.result = null; + } + } + cache2.elementsByTagName = /* @__PURE__ */ new Map(); + } + if (cache2.elementsByTagNameNS.size) { + for (const item of cache2.elementsByTagNameNS.values()) { + if (item.result) { + item.result = null; + } + } + cache2.elementsByTagNameNS = /* @__PURE__ */ new Map(); + } + if (cache2.elementByTagName.size) { + for (const item of cache2.elementByTagName.values()) { + if (item.result) { + item.result = null; + } + } + cache2.elementByTagName = /* @__PURE__ */ new Map(); + } + if (cache2.elementById.size) { + for (const item of cache2.elementById.values()) { + if (item.result) { + item.result = null; + } + } + cache2.elementById = /* @__PURE__ */ new Map(); + } + const affectsCache2 = this[affectsCache]; + if (affectsCache2.length) { + for (const item of affectsCache2) { + item.result = null; + } + this[affectsCache] = []; + } + const document = this[ownerDocument]; + if (document && document[affectsComputedStyleCache].length) { + for (const item of document[affectsComputedStyleCache]) { + item.result = null; + } + document[affectsComputedStyleCache] = []; + } + } + /** + * Called when connected to a node. + */ + [connectedToNode]() { + const parentNode2 = this[parentNode]; + const parent2 = parentNode2 || this[host]; + let isConnected2 = false; + let isDisconnected = false; + if (!this[isConnected] && parent2[isConnected]) { + this[isConnected] = true; + isConnected2 = true; + } else if (this[isConnected] && !parent2[isConnected]) { + this[isConnected] = false; + isDisconnected = true; + } + this[ownerDocument] = parent2[ownerDocument] || parent2; + this[window] = parent2[window] || parent2[defaultView]; + if (parentNode2) { + if (this[nodeType] !== NodeTypeEnum_default.documentFragmentNode) { + this[rootNode] = parentNode2[rootNode]; + } + const tagName2 = this[tagName]; + if (parentNode2[styleNode] && tagName2 !== "STYLE") { + this[styleNode] = parentNode2[styleNode]; + } + if (parentNode2[textAreaNode] && tagName2 !== "TEXTAREA") { + this[textAreaNode] = parentNode2[textAreaNode]; + } + if (parentNode2[formNode] && tagName2 !== "FORM") { + this[formNode] = parentNode2[formNode]; + } + if (parentNode2[selectNode] && tagName2 !== "SELECT") { + this[selectNode] = parentNode2[selectNode]; + } + } + const childNodes2 = this[nodeArray].slice(); + for (let i = 0, max = childNodes2.length; i < max; i++) { + childNodes2[i][parentNode] = this; + childNodes2[i][connectedToNode](); + } + if (this[shadowRoot]) { + this[shadowRoot][connectedToNode](); + } + if (isConnected2) { + this[connectedToDocument](); + } else if (isDisconnected) { + this[disconnectedFromDocument](); + } + } + /** + * Called when disconnected from a node. + */ + [disconnectedFromNode]() { + if (this[nodeType] !== NodeTypeEnum_default.documentFragmentNode) { + this[rootNode] = null; + } + const tagName2 = this[tagName]; + if (tagName2 !== "STYLE") { + this[styleNode] = null; + } + if (tagName2 !== "TEXTAREA") { + this[textAreaNode] = null; + } + if (tagName2 !== "FORM") { + this[formNode] = null; + } + if (tagName2 !== "SELECT") { + this[selectNode] = null; + } + if (this[isConnected]) { + this[isConnected] = false; + this[disconnectedFromDocument](); + } + const childNodes2 = this[nodeArray].slice(); + for (let i = 0, max = childNodes2.length; i < max; i++) { + childNodes2[i][connectedToNode](); + } + if (this[shadowRoot]) { + this[shadowRoot][disconnectedFromNode](); + } + } + /** + * Called when connected to document. + */ + [connectedToDocument]() { + if (this[shadowRoot]) { + this[shadowRoot][connectedToDocument](); + } + } + /** + * Called when disconnected from document. + */ + [disconnectedFromDocument]() { + if (this[ownerDocument][activeElement] === this) { + this[ownerDocument][clearCache](); + this[ownerDocument][activeElement] = null; + } + if (this[shadowRoot]) { + this[shadowRoot][disconnectedFromDocument](); + } + } + /** + * @override + */ + [destroy]() { + super[destroy](); + this[isConnected] = false; + for (let i = 0, max = this[nodeArray].length; i < max; i++) { + this[nodeArray][i][destroy](); + } + this[mutationListeners] = []; + this[parentNode] = null; + this[rootNode] = null; + this[styleNode] = null; + this[textAreaNode] = null; + this[formNode] = null; + this[selectNode] = null; + this[mutationListeners] = []; + this[nodeArray] = []; + this[elementArray] = []; + this[childNodes] = null; + this[assignedToSlot] = null; + this[clearCache](); + } + /** + * Reports the position of its argument node relative to the node on which it is called. + * + * @see https://dom.spec.whatwg.org/#dom-node-comparedocumentposition + * @param otherNode Other node. + */ + compareDocumentPosition(otherNode) { + if (this === otherNode) { + return 0; + } + let node1 = otherNode; + let node2 = this[proxy] || this; + let attr1 = null; + let attr2 = null; + if (node1[nodeType] === NodeTypeEnum_default.attributeNode) { + attr1 = node1; + node1 = attr1[ownerElement]; + } + if (node2[nodeType] === NodeTypeEnum_default.attributeNode) { + attr2 = node2; + node2 = attr2[ownerElement]; + if (attr1 !== null && node1 !== null && node2 === node1) { + for (const attribute of node2[attributes][items].values()) { + if (NodeUtility.isEqualNode(attribute, attr1)) { + return _Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | _Node.DOCUMENT_POSITION_PRECEDING; + } + if (NodeUtility.isEqualNode(attribute, attr2)) { + return _Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | _Node.DOCUMENT_POSITION_FOLLOWING; + } + } + } + } + const node2Ancestors = []; + let node2Ancestor = node2; + while (node2Ancestor) { + if (node2Ancestor === node1) { + return _Node.DOCUMENT_POSITION_CONTAINS | _Node.DOCUMENT_POSITION_PRECEDING; + } + node2Ancestors.push(node2Ancestor); + node2Ancestor = node2Ancestor[parentNode]; + } + const node1Ancestors = []; + let node1Ancestor = node1; + while (node1Ancestor) { + if (node1Ancestor === node2) { + return _Node.DOCUMENT_POSITION_CONTAINED_BY | _Node.DOCUMENT_POSITION_FOLLOWING; + } + node1Ancestors.push(node1Ancestor); + node1Ancestor = node1Ancestor[parentNode]; + } + const reverseArrayIndex = (array, reverseIndex) => { + return array[array.length - 1 - reverseIndex]; + }; + const root2 = reverseArrayIndex(node2Ancestors, 0); + if (!root2 || root2 !== reverseArrayIndex(node1Ancestors, 0)) { + return _Node.DOCUMENT_POSITION_DISCONNECTED | _Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | _Node.DOCUMENT_POSITION_FOLLOWING; + } + let commonAncestorIndex = 0; + const ancestorsMinLength = Math.min(node2Ancestors.length, node1Ancestors.length); + for (let i = 0; i < ancestorsMinLength; ++i) { + const node2Ancestor2 = reverseArrayIndex(node2Ancestors, i); + const node1Ancestor2 = reverseArrayIndex(node1Ancestors, i); + if (node2Ancestor2 !== node1Ancestor2) { + break; + } + commonAncestorIndex = i; + } + const commonAncestor = reverseArrayIndex(node2Ancestors, commonAncestorIndex); + let indexes = 0; + let node2Index = -1; + let node1Index = -1; + const node2Node = reverseArrayIndex(node2Ancestors, commonAncestorIndex + 1); + const node1Node = reverseArrayIndex(node1Ancestors, commonAncestorIndex + 1); + const computeNodeIndexes = (nodes) => { + for (const childNode of nodes) { + computeNodeIndexes(childNode[nodeArray]); + if (childNode === node2Node) { + node2Index = indexes; + } else if (childNode === node1Node) { + node1Index = indexes; + } + if (node2Index !== -1 && node1Index !== -1) { + break; + } + indexes++; + } + }; + computeNodeIndexes(commonAncestor[nodeArray]); + return node1Index < node2Index ? _Node.DOCUMENT_POSITION_PRECEDING : _Node.DOCUMENT_POSITION_FOLLOWING; + } + /** + * Normalizes the sub-tree of the node, i.e. joins adjacent text nodes, and + * removes all empty text nodes. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/Node/normalize + */ + normalize() { + let child = this.firstChild; + while (child) { + if (NodeUtility.isTextNode(child)) { + while (NodeUtility.isTextNode(child.nextSibling)) { + child.data += child.nextSibling.data; + child.nextSibling.remove(); + } + if (!child.data.length) { + const node = child; + child = child.nextSibling; + node.remove(); + continue; + } + } else { + child.normalize(); + } + child = child.nextSibling; + } + } + /** + * Determines whether the given node is equal to the current node. + * + * @see https://developer.mozilla.org/en-US/docs/Web/API/Node/isSameNode + * @param node Node to check. + * @returns True if the given node is equal to the current node, otherwise false. + */ + isSameNode(node) { + return this === node; + } + }; + Node.prototype.ELEMENT_NODE = NodeTypeEnum_default.elementNode; + Node.prototype.ATTRIBUTE_NODE = NodeTypeEnum_default.attributeNode; + Node.prototype.TEXT_NODE = NodeTypeEnum_default.textNode; + Node.prototype.CDATA_SECTION_NODE = NodeTypeEnum_default.cdataSectionNode; + Node.prototype.COMMENT_NODE = NodeTypeEnum_default.commentNode; + Node.prototype.DOCUMENT_NODE = NodeTypeEnum_default.documentNode; + Node.prototype.DOCUMENT_TYPE_NODE = NodeTypeEnum_default.documentTypeNode; + Node.prototype.DOCUMENT_FRAGMENT_NODE = NodeTypeEnum_default.documentFragmentNode; + Node.prototype.PROCESSING_INSTRUCTION_NODE = NodeTypeEnum_default.processingInstructionNode; + Node.prototype.DOCUMENT_POSITION_CONTAINED_BY = NodeDocumentPositionEnum_default.containedBy; + Node.prototype.DOCUMENT_POSITION_CONTAINS = NodeDocumentPositionEnum_default.contains; + Node.prototype.DOCUMENT_POSITION_DISCONNECTED = NodeDocumentPositionEnum_default.disconnect; + Node.prototype.DOCUMENT_POSITION_FOLLOWING = NodeDocumentPositionEnum_default.following; + Node.prototype.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = NodeDocumentPositionEnum_default.implementationSpecific; + Node.prototype.DOCUMENT_POSITION_PRECEDING = NodeDocumentPositionEnum_default.preceding; + } +}); + +// node_modules/happy-dom/lib/nodes/attr/Attr.js +var Attr; +var init_Attr = __esm({ + "node_modules/happy-dom/lib/nodes/attr/Attr.js"() { + init_Node(); + init_PropertySymbol(); + init_NodeTypeEnum(); + Attr = class extends Node { + [nodeType] = NodeTypeEnum_default.attributeNode; + [namespaceURI] = null; + [name] = null; + [localName] = null; + [prefix] = null; + [value] = null; + [specified] = true; + [ownerElement] = null; + /** + * Returns specified. + * + * @deprecated + * @returns Specified. + */ + get specified() { + return this[specified]; + } + /** + * Returns owner element. + * + * @returns Owner element. + */ + get ownerElement() { + return this[ownerElement]; + } + /** + * Returns value. + * + * @returns Value. + */ + get value() { + return this[value]; + } + /** + * Sets value. + * + * @param value Value. + */ + set value(value2) { + this[value] = value2; + } + /** + * Returns name. + * + * @returns Name. + */ + get name() { + return this[name] || ""; + } + /** + * Returns local name. + * + * @returns Local name. + */ + get localName() { + return this[localName] || ""; + } + /** + * Returns prefix. + * + * @returns Prefix. + */ + get prefix() { + return this[prefix]; + } + /** + * @override + */ + get textContent() { + return this[value] || ""; + } + /** + * Returns namespace URI. + * + * @returns Namespace URI. + */ + get namespaceURI() { + return this[namespaceURI]; + } + /** + * @override + */ + [cloneNode](deep = false) { + const clone2 = super[cloneNode](deep); + clone2[namespaceURI] = this[namespaceURI]; + clone2[name] = this[name]; + clone2[localName] = this[localName]; + clone2[prefix] = this[prefix]; + clone2[value] = this[value]; + clone2[specified] = this[specified]; + return clone2; + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/character-data/CharacterDataUtility.js +var CharacterDataUtility; +var init_CharacterDataUtility = __esm({ + "node_modules/happy-dom/lib/nodes/character-data/CharacterDataUtility.js"() { + CharacterDataUtility = class { + /** + * Appends the given DOMString to the CharacterData.data string; when this method returns, data contains the concatenated DOMString. + * + * @param characterData Character data. + * @param data Data. + */ + static appendData(characterData, data2) { + characterData.data += data2; + } + /** + * Removes the specified amount of characters, starting at the specified offset, from the CharacterData.data string; when this method returns, data contains the shortened DOMString. + * + * @param characterData Character data. + * @param offset Offset. + * @param count Count. + */ + static deleteData(characterData, offset2, count) { + characterData.data = characterData.data.substring(0, offset2) + characterData.data.substring(offset2 + count); + } + /** + * Inserts the specified characters, at the specified offset, in the CharacterData.data string; when this method returns, data contains the modified DOMString. + * + * @param characterData Character data. + * @param offset Offset. + * @param data Data. + */ + static insertData(characterData, offset2, data2) { + characterData.data = characterData.data.substring(0, offset2) + data2 + characterData.data.substring(offset2); + } + /** + * Replaces the specified amount of characters, starting at the specified offset, with the specified DOMString; when this method returns, data contains the modified DOMString. + * + * @param characterData Character data. + * @param offset Offset. + * @param count Count. + * @param data Data. + */ + static replaceData(characterData, offset2, count, data2) { + characterData.data = characterData.data.substring(0, offset2) + data2 + characterData.data.substring(offset2 + count); + } + /** + * Returns a DOMString containing the part of CharacterData.data of the specified length and starting at the specified offset. + * + * @param characterData Character data. + * @param offset Offset. + * @param count Count. + */ + static substringData(characterData, offset2, count) { + return characterData.data.substring(offset2, offset2 + count); + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/child-node/NonDocumentChildNodeUtility.js +var NonDocumentChildNodeUtility; +var init_NonDocumentChildNodeUtility = __esm({ + "node_modules/happy-dom/lib/nodes/child-node/NonDocumentChildNodeUtility.js"() { + init_NodeTypeEnum(); + init_PropertySymbol(); + NonDocumentChildNodeUtility = class { + /** + * Previous element sibling. + * + * @param childNode Child node. + * @returns Element. + */ + static previousElementSibling(childNode) { + let sibling = childNode.previousSibling; + while (sibling && sibling[nodeType] !== NodeTypeEnum_default.elementNode) { + sibling = sibling.previousSibling; + } + return sibling; + } + /** + * Next element sibling. + * + * @param childNode Child node. + * @returns Element. + */ + static nextElementSibling(childNode) { + let sibling = childNode.nextSibling; + while (sibling && sibling[nodeType] !== NodeTypeEnum_default.elementNode) { + sibling = sibling.nextSibling; + } + return sibling; + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/child-node/ChildNodeUtility.js +var ChildNodeUtility; +var init_ChildNodeUtility = __esm({ + "node_modules/happy-dom/lib/nodes/child-node/ChildNodeUtility.js"() { + init_PropertySymbol(); + init_Node(); + ChildNodeUtility = class { + /** + * Removes the node from its parent. + * + * @param childNode Child node. + */ + static remove(childNode) { + if (childNode[parentNode]) { + childNode[parentNode].removeChild(childNode); + } + } + /** + * The Node.replaceWith() method replaces this Node in the children list of its parent with a set of Node or DOMString objects. + * + * @param childNode Child node. + * @param nodes List of Node or DOMString. + */ + static replaceWith(childNode, ...nodes) { + const parent2 = childNode[parentNode]; + if (!parent2) { + return; + } + for (const node of nodes) { + if (node instanceof Node) { + parent2.insertBefore(node, childNode); + } else { + parent2.insertBefore(parent2[ownerDocument].createTextNode(String(node)), childNode); + } + } + parent2.removeChild(childNode); + } + /** + * Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just before this ChildNode. DOMString objects are inserted as equivalent Text nodes. + * + * @param childNode Child node. + * @param nodes List of Node or DOMString. + */ + static before(childNode, ...nodes) { + const parent2 = childNode[parentNode]; + if (!parent2) { + return; + } + for (const node of nodes) { + if (node instanceof Node) { + parent2.insertBefore(node, childNode); + } else { + parent2.insertBefore(parent2[ownerDocument].createTextNode(String(node)), childNode); + } + } + } + /** + * Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just after this ChildNode. DOMString objects are inserted as equivalent Text nodes. + * + * @param childNode Child node. + * @param nodes List of Node or DOMString. + */ + static after(childNode, ...nodes) { + const parent2 = childNode[parentNode]; + if (!parent2) { + return; + } + const nextSibling = childNode.nextSibling; + for (const node of nodes) { + const insertedNode = node instanceof Node ? node : parent2[ownerDocument].createTextNode(String(node)); + if (!nextSibling) { + parent2.appendChild(insertedNode); + } else { + parent2.insertBefore(insertedNode, nextSibling); + } + } + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/character-data/CharacterData.js +var CharacterData; +var init_CharacterData = __esm({ + "node_modules/happy-dom/lib/nodes/character-data/CharacterData.js"() { + init_Node(); + init_PropertySymbol(); + init_CharacterDataUtility(); + init_NonDocumentChildNodeUtility(); + init_ChildNodeUtility(); + init_MutationRecord(); + init_MutationTypeEnum(); + CharacterData = class extends Node { + [data] = ""; + /** + * Constructor. + * + * @param [data] Data. + */ + constructor(data2) { + super(); + this[data] = data2 !== void 0 ? String(data2) : ""; + } + /** + * Returns text content. + * + * @returns Text content. + */ + get length() { + return this[data].length; + } + /** + * Returns text content. + * + * @returns Text content. + */ + get data() { + return this[data]; + } + /** + * Sets text content. + * + * @param textContent Text content. + */ + set data(data2) { + const oldValue = this[data]; + this[data] = String(data2); + this[reportMutation](new MutationRecord({ + target: this, + type: MutationTypeEnum_default.characterData, + oldValue + })); + } + /** + * Returns text content. + * + * @returns Text content. + */ + get textContent() { + return this[data]; + } + /** + * Sets text content. + * + * @param textContent Text content. + */ + set textContent(textContent) { + this.data = textContent; + } + /** + * Returns node value. + * + * @returns Node value. + */ + get nodeValue() { + return this[data]; + } + /** + * Sets node value. + * + * @param nodeValue Node value. + */ + set nodeValue(nodeValue) { + this.textContent = nodeValue; + } + /** + * Previous element sibling. + * + * @returns Element. + */ + get previousElementSibling() { + return NonDocumentChildNodeUtility.previousElementSibling(this); + } + /** + * Next element sibling. + * + * @returns Element. + */ + get nextElementSibling() { + return NonDocumentChildNodeUtility.nextElementSibling(this); + } + /** + * Appends the given DOMString to the CharacterData.data string; when this method returns, data contains the concatenated DOMString. + * + * @param data Data. + */ + appendData(data2) { + CharacterDataUtility.appendData(this, data2); + } + /** + * Removes the specified amount of characters, starting at the specified offset, from the CharacterData.data string; when this method returns, data contains the shortened DOMString. + * + * @param offset Offset. + * @param count Count. + */ + deleteData(offset2, count) { + CharacterDataUtility.deleteData(this, offset2, count); + } + /** + * Inserts the specified characters, at the specified offset, in the CharacterData.data string; when this method returns, data contains the modified DOMString. + * + * @param offset Offset. + * @param data Data. + */ + insertData(offset2, data2) { + CharacterDataUtility.insertData(this, offset2, data2); + } + /** + * Replaces the specified amount of characters, starting at the specified offset, with the specified DOMString; when this method returns, data contains the modified DOMString. + * + * @param offset Offset. + * @param count Count. + * @param data Data. + */ + replaceData(offset2, count, data2) { + CharacterDataUtility.replaceData(this, offset2, count, data2); + } + /** + * Returns a DOMString containing the part of CharacterData.data of the specified length and starting at the specified offset. + * + * @param offset Offset. + * @param count Count. + */ + substringData(offset2, count) { + return CharacterDataUtility.substringData(this, offset2, count); + } + /** + * Removes the object from its parent children list. + */ + remove() { + ChildNodeUtility.remove(this); + } + /** + * The Node.replaceWith() method replaces this Node in the children list of its parent with a set of Node or DOMString objects. + * + * @param nodes List of Node or DOMString. + */ + replaceWith(...nodes) { + ChildNodeUtility.replaceWith(this, ...nodes); + } + /** + * Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just before this ChildNode. DOMString objects are inserted as equivalent Text nodes. + * + * @param nodes List of Node or DOMString. + */ + before(...nodes) { + ChildNodeUtility.before(this, ...nodes); + } + /** + * Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just after this ChildNode. DOMString objects are inserted as equivalent Text nodes. + * + * @param nodes List of Node or DOMString. + */ + after(...nodes) { + ChildNodeUtility.after(this, ...nodes); + } + /** + * @override + */ + [cloneNode](deep = false) { + const clone2 = super[cloneNode](deep); + clone2[data] = this[data]; + return clone2; + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/document-type/DocumentType.js +var DocumentType; +var init_DocumentType = __esm({ + "node_modules/happy-dom/lib/nodes/document-type/DocumentType.js"() { + init_Node(); + init_PropertySymbol(); + init_NodeTypeEnum(); + DocumentType = class extends Node { + [nodeType] = NodeTypeEnum_default.documentTypeNode; + [name] = ""; + [publicId] = ""; + [systemId] = ""; + /** + * Returns name. + * + * @returns Name. + */ + get name() { + return this[name]; + } + /** + * Returns public ID. + * + * @returns Public ID. + */ + get publicId() { + return this[publicId]; + } + /** + * Returns system ID. + * + * @returns System ID. + */ + get systemId() { + return this[systemId]; + } + /** + * Node name. + * + * @returns Node name. + */ + get nodeName() { + return this.name; + } + /** + * Converts to string. + * + * @returns String. + */ + toString() { + return "[object DocumentType]"; + } + /** + * @override + */ + [cloneNode](deep = false) { + const clone2 = super[cloneNode](deep); + clone2[name] = this[name]; + clone2[publicId] = this[publicId]; + clone2[systemId] = this[systemId]; + return clone2; + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/document/DocumentReadyStateEnum.js +var DocumentReadyStateEnum, DocumentReadyStateEnum_default; +var init_DocumentReadyStateEnum = __esm({ + "node_modules/happy-dom/lib/nodes/document/DocumentReadyStateEnum.js"() { + (function(DocumentReadyStateEnum2) { + DocumentReadyStateEnum2["loading"] = "loading"; + DocumentReadyStateEnum2["interactive"] = "interactive"; + DocumentReadyStateEnum2["complete"] = "complete"; + })(DocumentReadyStateEnum || (DocumentReadyStateEnum = {})); + DocumentReadyStateEnum_default = DocumentReadyStateEnum; + } +}); + +// node_modules/happy-dom/lib/nodes/document/DocumentReadyStateManager.js +var DocumentReadyStateManager; +var init_DocumentReadyStateManager = __esm({ + "node_modules/happy-dom/lib/nodes/document/DocumentReadyStateManager.js"() { + init_AsyncTaskManager(); + DocumentReadyStateManager = class { + #asyncTaskManager; + /** + * Constructor. + * + * @param browserFrame Browser frame. + */ + constructor(browserFrame) { + this.#asyncTaskManager = new AsyncTaskManager(browserFrame); + } + /** + * Returns a promise that is fulfilled when ready state is complete. + * + * @returns Promise. + */ + waitUntilComplete() { + return this.#asyncTaskManager.waitUntilComplete(); + } + /** + * Starts a task. + * + * @returns Task ID. + */ + startTask() { + return this.#asyncTaskManager.startTask(); + } + /** + * Ends a task. + * + * @param taskID Task ID. + */ + endTask(taskID) { + this.#asyncTaskManager.endTask(taskID); + } + /** + * Destroys the manager. + */ + destroy() { + return this.#asyncTaskManager.destroy(); + } + }; + } +}); + +// node_modules/happy-dom/lib/dom/DOMRectReadOnly.js +var DOMRectReadOnly; +var init_DOMRectReadOnly = __esm({ + "node_modules/happy-dom/lib/dom/DOMRectReadOnly.js"() { + init_PropertySymbol(); + DOMRectReadOnly = class _DOMRectReadOnly { + [x] = 0; + [y] = 0; + [width] = 0; + [height] = 0; + /** + * Constructor. + * + * @param [x] X position. + * @param [y] Y position. + * @param [width] Width. + * @param [height] Height. + */ + constructor(x3, y3, width2, height2) { + this[x] = x3 !== void 0 && x3 !== null ? Number(x3) : 0; + this[y] = y3 !== void 0 && y3 !== null ? Number(y3) : 0; + this[width] = width2 !== void 0 && width2 !== null ? Number(width2) : 0; + this[height] = height2 !== void 0 && height2 !== null ? Number(height2) : 0; + } + /** + * Returns x. + * + * @returns X. + */ + get x() { + return this[x]; + } + /** + * Returns y. + * + * @returns Y. + */ + get y() { + return this[y]; + } + /** + * Returns width. + * + * @returns Width. + */ + get width() { + return this[width]; + } + /** + * Returns height. + * + * @returns Height. + */ + get height() { + return this[height]; + } + /** + * Returns top. + * + * @returns Top. + */ + get top() { + return Math.min(this[y], this[y] + this[height]); + } + /** + * Returns right. + * + * @returns Right. + */ + get right() { + return Math.max(this[x], this[x] + this[width]); + } + /** + * Returns bottom. + * + * @returns Bottom. + */ + get bottom() { + return Math.max(this[y], this[y] + this[height]); + } + /** + * Returns left. + * + * @returns Left. + */ + get left() { + return Math.min(this[x], this[x] + this[width]); + } + /** + * Returns the JSON representation of the object. + * + * @returns JSON representation. + */ + toJSON() { + return { + x: this.x, + y: this.y, + width: this.width, + height: this.height, + top: this.top, + right: this.right, + bottom: this.bottom, + left: this.left + }; + } + /** + * Returns a new DOMRectReadOnly object. + * + * @param other + * @returns Cloned object. + */ + static fromRect(other) { + return new _DOMRectReadOnly(other.x, other.y, other.width, other.height); + } + }; + } +}); + +// node_modules/happy-dom/lib/dom/DOMRect.js +var DOMRect; +var init_DOMRect = __esm({ + "node_modules/happy-dom/lib/dom/DOMRect.js"() { + init_DOMRectReadOnly(); + init_PropertySymbol(); + DOMRect = class _DOMRect extends DOMRectReadOnly { + /** + * Sets x. + * + * @param value X. + */ + set x(value2) { + this[x] = value2; + } + /** + * Returns x. + * + * @returns X. + */ + get x() { + return this[x]; + } + /** + * Sets y. + * + * @param value Y. + */ + set y(value2) { + this[y] = value2; + } + /** + * Returns y. + * + * @returns Y. + */ + get y() { + return this[y]; + } + /** + * Sets width. + * + * @param value Width. + */ + set width(value2) { + this[width] = value2; + } + /** + * Returns width. + * + * @returns Width. + */ + get width() { + return this[width]; + } + /** + * Sets height. + * + * @param value Height. + */ + set height(value2) { + this[height] = value2; + } + /** + * Returns height. + * + * @returns Height. + */ + get height() { + return this[height]; + } + /** + * Returns a new DOMRect object. + * + * @param other + * @returns Cloned object. + */ + static fromRect(other) { + return new _DOMRect(other.x, other.y, other.width, other.height); + } + }; + } +}); + +// node_modules/happy-dom/lib/dom/DOMTokenList.js +var ATTRIBUTE_SPLIT_REGEXP, DOMTokenList; +var init_DOMTokenList = __esm({ + "node_modules/happy-dom/lib/dom/DOMTokenList.js"() { + init_ClassMethodBinder(); + init_PropertySymbol(); + ATTRIBUTE_SPLIT_REGEXP = /[\t\f\n\r ]+/; + DOMTokenList = class _DOMTokenList { + [ownerElement]; + [attributeName]; + [cache] = { + items: [], + attributeValue: "" + }; + [supports]; + [proxy]; + /** + * Constructor. + * + * @param illegalConstructorSymbol Illegal constructor symbol. + * @param ownerElement Owner element. + * @param attributeName Attribute name. + * @param [supports] Supports. + */ + constructor(illegalConstructorSymbol, ownerElement2, attributeName2, supports2) { + if (illegalConstructorSymbol !== illegalConstructor) { + throw new TypeError("Illegal constructor"); + } + this[ownerElement] = ownerElement2; + this[attributeName] = attributeName2; + this[supports] = supports2 || []; + const methodBinder = new ClassMethodBinder(this, [_DOMTokenList]); + const proxy2 = new Proxy(this, { + get: (target2, property) => { + if (property === "length") { + return target2[getTokenList]().length; + } + if (property in target2 || typeof property === "symbol") { + methodBinder.bind(property); + return target2[property]; + } + const index = Number(property); + if (!isNaN(index)) { + return target2[getTokenList]()[index]; + } + }, + set(target2, property, newValue) { + methodBinder.bind(property); + if (typeof property === "symbol") { + target2[property] = newValue; + return true; + } + const index = Number(property); + if (isNaN(index)) { + target2[property] = newValue; + } + return true; + }, + deleteProperty(target2, property) { + if (typeof property === "symbol") { + delete target2[property]; + return true; + } + const index = Number(property); + if (isNaN(index)) { + delete target2[property]; + } + return true; + }, + ownKeys(target2) { + return Object.keys(target2[getTokenList]()); + }, + has(target2, property) { + if (property in target2) { + return true; + } + if (typeof property === "symbol") { + return false; + } + const index = Number(property); + return !isNaN(index) && index >= 0 && index < target2[getTokenList]().length; + }, + defineProperty(target2, property, descriptor) { + methodBinder.preventBinding(property); + if (property in target2) { + Object.defineProperty(target2, property, descriptor); + return true; + } + return false; + }, + getOwnPropertyDescriptor(target2, property) { + if (property in target2 || typeof property === "symbol") { + return; + } + const index = Number(property); + const items2 = target2[getTokenList](); + if (!isNaN(index) && items2[index]) { + return { + value: items2[index], + writable: false, + enumerable: true, + configurable: true + }; + } + } + }); + this[proxy] = proxy2; + return proxy2; + } + /** + * Returns length. + * + * @returns Length. + */ + get length() { + return this[getTokenList]().length; + } + /** + * Set value. + * + * @param value Value. + */ + set value(value2) { + this[ownerElement].setAttribute(this[attributeName], value2); + } + /** + * Get value. + */ + get value() { + return this[ownerElement].getAttribute(this[attributeName]) || ""; + } + /** + * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. + */ + [Symbol.iterator]() { + return this[getTokenList]().values(); + } + /** + * Get ClassName. + * + * @param index Index. + * */ + item(index) { + const items2 = this[getTokenList](); + if (typeof index === "number") { + return items2[index] ? items2[index] : null; + } + index = Number(index); + index = isNaN(index) ? 0 : index; + return items2[index] ? items2[index] : null; + } + /** + * Replace Token. + * + * @param token Token. + * @param newToken NewToken. + */ + replace(token, newToken) { + const list = this[getTokenList]().slice(); + const index = list.indexOf(token); + if (index === -1) { + return false; + } + list[index] = newToken; + this[ownerElement].setAttribute(this[attributeName], list.join(" ")); + return true; + } + /** + * Supports. + * + * @param token Token. + */ + supports(token) { + return this[supports].includes(token); + } + /** + * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. + */ + values() { + return this[getTokenList]().values(); + } + /** + * Returns an iterator, allowing you to go through all key/value pairs contained in this object. + */ + entries() { + return this[getTokenList]().entries(); + } + /** + * Executes a provided callback function once for each DOMTokenList element. + * + * @param callback + * @param thisArg + */ + forEach(callback, thisArg) { + const thisArgValue = thisArg ?? this[ownerElement][window]; + const items2 = this[getTokenList](); + const proxy2 = this[proxy] ?? this; + for (let i = 0, max = items2.length; i < max; i++) { + callback.call(thisArgValue, items2[i], i, proxy2); + } + } + /** + * Returns an iterator, allowing you to go through all keys of the key/value pairs contained in this object. + * + */ + keys() { + return this[getTokenList]().keys(); + } + /** + * Adds tokens. + * + * @param tokens Tokens. + */ + add(...tokens) { + const list = this[getTokenList]().slice(); + const existingTokens = new Set(list); + for (const token of tokens) { + if (!existingTokens.has(token)) { + existingTokens.add(token); + list.push(token); + } + } + this[ownerElement].setAttribute(this[attributeName], list.join(" ")); + } + /** + * Removes tokens. + * + * @param tokens Tokens. + */ + remove(...tokens) { + const list = this[getTokenList](); + const tokensToRemove = new Set(tokens); + const newList = list.filter((item) => !tokensToRemove.has(item)); + this[ownerElement].setAttribute(this[attributeName], newList.join(" ")); + } + /** + * Check if the list contains a class. + * + * @param className Class name. + * @returns TRUE if it contains. + */ + contains(className) { + return this[getTokenList]().includes(className); + } + /** + * Toggle a class name. + * + * @param token A string representing the class name you want to toggle. + * @param [force] If included, turns the toggle into a one way-only operation. If set to `false`, then class name will only be removed, but not added. If set to `true`, then class name will only be added, but not removed. + * @returns A boolean value, `true` or `false`, indicating whether class name is in the list after the call or not. + */ + toggle(token, force) { + let shouldAdd; + if (force !== void 0) { + shouldAdd = force; + } else { + shouldAdd = !this.contains(token); + } + if (shouldAdd) { + this.add(token); + return true; + } + this.remove(token); + return false; + } + /** + * Returns token list from attribute value. + * + * @see https://infra.spec.whatwg.org/#split-on-ascii-whitespace + */ + [getTokenList]() { + const attributeValue2 = this[ownerElement].getAttribute(this[attributeName]) ?? ""; + const cache2 = this[cache]; + if (cache2.attributeValue === attributeValue2) { + return cache2.items; + } + const items2 = []; + const trimmed = attributeValue2.trim(); + if (trimmed) { + for (const item of trimmed.split(ATTRIBUTE_SPLIT_REGEXP)) { + if (!items2.includes(item)) { + items2.push(item); + } + } + } + cache2.attributeValue = attributeValue2; + cache2.items = items2; + return items2; + } + /** + * Returns DOMTokenList value. + */ + toString() { + return this.value || ""; + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/element/HTMLCollection.js +var HTMLCollection; +var init_HTMLCollection = __esm({ + "node_modules/happy-dom/lib/nodes/element/HTMLCollection.js"() { + init_ClassMethodBinder(); + init_PropertySymbol(); + HTMLCollection = class _HTMLCollection { + [query]; + /** + * Constructor. + * + * @param illegalConstructorSymbol Illegal constructor symbol. + * @param query Query function. + */ + constructor(illegalConstructorSymbol, query2) { + if (illegalConstructorSymbol !== illegalConstructor) { + throw new TypeError("Illegal constructor"); + } + this[query] = query2; + const methodBinder = new ClassMethodBinder(this, this.constructor !== _HTMLCollection ? [this.constructor, _HTMLCollection] : [_HTMLCollection]); + return new Proxy(this, { + get: (target2, property) => { + if (property === "length") { + return query2().length; + } + if (property in target2 || typeof property === "symbol") { + methodBinder.bind(property); + return target2[property]; + } + const index = Number(property); + if (!isNaN(index)) { + return query2()[index]; + } + return target2.namedItem(property) || void 0; + }, + set(target2, property, newValue) { + methodBinder.bind(property); + if (typeof property === "symbol") { + target2[property] = newValue; + return true; + } + const index = Number(property); + if (isNaN(index)) { + target2[property] = newValue; + } + return true; + }, + deleteProperty(target2, property) { + if (typeof property === "symbol") { + delete target2[property]; + return true; + } + const index = Number(property); + if (isNaN(index)) { + delete target2[property]; + } + return true; + }, + ownKeys() { + const keys = []; + const items2 = query2(); + for (let i = 0; i < items2.length; i++) { + const item = items2[i]; + const name2 = item.getAttribute("id") || item.getAttribute("name"); + keys.push(String(i)); + if (name2) { + keys.push(name2); + } + } + return keys; + }, + has(target2, property) { + if (property in target2) { + return true; + } + const items2 = query2(); + const index = Number(property); + if (!isNaN(index) && index >= 0 && index < items2.length) { + return true; + } + property = String(property); + for (let i = 0; i < items2.length; i++) { + const item = items2[i]; + const name2 = item.getAttribute("id") || item.getAttribute("name"); + if (name2 && name2 === property) { + return true; + } + } + return false; + }, + defineProperty(target2, property, descriptor) { + methodBinder.preventBinding(property); + if (property in target2) { + Object.defineProperty(target2, property, descriptor); + return true; + } + return false; + }, + getOwnPropertyDescriptor(target2, property) { + if (property in target2 || typeof property === "symbol") { + return; + } + const items2 = query2(); + const index = Number(property); + if (!isNaN(index) && index >= 0 && index < items2.length) { + return { + value: items2[index], + writable: false, + enumerable: true, + configurable: true + }; + } + for (let i = 0; i < items2.length; i++) { + const item = items2[i]; + const name2 = item.getAttribute("id") || item.getAttribute("name"); + if (name2 && name2 === property) { + return { + value: item, + writable: false, + enumerable: true, + configurable: true + }; + } + } + } + }); + } + /** + * Returns length. + * + * @returns Length. + */ + get length() { + return this[query]().length; + } + /** + * Returns `Symbol.toStringTag`. + * + * @returns `Symbol.toStringTag`. + */ + get [Symbol.toStringTag]() { + return this.constructor.name; + } + /** + * Returns `[object HTMLCollection]`. + * + * @returns `[object HTMLCollection]`. + */ + toLocaleString() { + return `[object ${this.constructor.name}]`; + } + /** + * Returns `[object HTMLCollection]`. + * + * @returns `[object HTMLCollection]`. + */ + toString() { + return `[object ${this.constructor.name}]`; + } + /** + * Returns item by index. + * + * @param index Index. + */ + item(index) { + const items2 = this[query](); + return index >= 0 && items2[index] ? items2[index] : null; + } + /** + * Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object. + * + * @returns Iterator. + */ + [Symbol.iterator]() { + const items2 = this[query](); + return items2[Symbol.iterator](); + } + /** + * Returns named item. + * + * @param name Name. + * @returns Node. + */ + namedItem(name2) { + const items2 = this[query](); + name2 = String(name2); + for (const item of items2) { + if (item.getAttribute("id") === name2 || item.getAttribute("name") === name2) { + return item; + } + } + return null; + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/parent-node/ParentNodeUtility.js +var ParentNodeUtility; +var init_ParentNodeUtility = __esm({ + "node_modules/happy-dom/lib/nodes/parent-node/ParentNodeUtility.js"() { + init_PropertySymbol(); + init_Node(); + init_NamespaceURI(); + init_HTMLCollection(); + init_QuerySelector(); + ParentNodeUtility = class { + /** + * Inserts a set of Node objects or DOMString objects after the last child of the ParentNode. DOMString objects are inserted as equivalent Text nodes. + * + * @param parentNode Parent node. + * @param nodes List of Node or DOMString. + */ + static append(parentNode2, ...nodes) { + for (const node of nodes) { + if (node instanceof Node) { + parentNode2.appendChild(node); + } else { + parentNode2.appendChild(parentNode2[ownerDocument].createTextNode(String(node))); + } + } + } + /** + * Inserts a set of Node objects or DOMString objects before the first child of the ParentNode. DOMString objects are inserted as equivalent Text nodes. + * + * @param parentNode Parent node. + * @param nodes List of Node or DOMString. + */ + static prepend(parentNode2, ...nodes) { + const firstChild = parentNode2.firstChild; + for (const node of nodes) { + if (node instanceof Node) { + parentNode2.insertBefore(node, firstChild); + } else { + parentNode2.insertBefore(parentNode2[ownerDocument].createTextNode(String(node)), firstChild); + } + } + } + /** + * Replaces the existing children of a ParentNode with a specified new set of children. + * + * @param parentNode Parent node. + * @param nodes List of Node or DOMString. + */ + static replaceChildren(parentNode2, ...nodes) { + const childNodes2 = parentNode2[nodeArray]; + while (childNodes2.length) { + parentNode2.removeChild(childNodes2[0]); + } + this.append(parentNode2, ...nodes); + } + /** + * Returns an elements by class name. + * + * @param parentNode Parent node. + * @param className Tag name. + * @returns Matching element. + */ + static getElementsByClassName(parentNode2, className) { + return new HTMLCollection(illegalConstructor, () => QuerySelector.querySelectorAll(parentNode2, `.${className.replace(/\s+/gm, ".")}`)[items]); + } + /** + * Returns an elements by tag name. + * + * @param parentNode Parent node. + * @param tagName Tag name. + * @returns Matching element. + */ + static getElementsByTagName(parentNode2, tagName2) { + const upperTagName = tagName2.toUpperCase(); + const includeAll = tagName2 === "*"; + const find = (parent2, cachedResult) => { + const elements2 = []; + for (const element of parent2[elementArray]) { + if (includeAll || element[tagName].toUpperCase() === upperTagName) { + elements2.push(element); + } + element[affectsCache].push(cachedResult); + for (const foundElement of find(element, cachedResult)) { + elements2.push(foundElement); + } + } + return elements2; + }; + const query2 = () => { + const cache2 = parentNode2[cache].elementsByTagName; + const cachedItems = cache2.get(tagName2); + if (cachedItems?.result) { + const items3 = cachedItems.result.deref(); + if (items3) { + return items3; + } + } + const cachedResult = { result: null }; + const items2 = find(parentNode2, cachedResult); + cachedResult.result = new WeakRef(items2); + cache2.set(tagName2, cachedResult); + return items2; + }; + return new HTMLCollection(illegalConstructor, query2); + } + /** + * Returns an elements by tag name and namespace. + * + * @param parentNode Parent node. + * @param namespaceURI Namespace URI. + * @param tagName Tag name. + * @returns Matching element. + */ + static getElementsByTagNameNS(parentNode2, namespaceURI2, tagName2) { + const formattedTagName = namespaceURI2 === NamespaceURI_default.html && parentNode2[ownerDocument][contentType] === "text/html" ? tagName2.toUpperCase() : tagName2; + const includeAll = tagName2 === "*"; + const find = (parent2, cachedResult) => { + const elements2 = []; + for (const element of parent2[elementArray]) { + if ((includeAll || element[tagName] === formattedTagName) && element[namespaceURI] === namespaceURI2) { + elements2.push(element); + } + element[affectsCache].push(cachedResult); + for (const foundElement of find(element, cachedResult)) { + elements2.push(foundElement); + } + } + return elements2; + }; + const query2 = () => { + const cache2 = parentNode2[cache].elementsByTagNameNS; + const cachedItems = cache2.get(tagName2); + if (cachedItems?.result) { + const items3 = cachedItems.result.deref(); + if (items3) { + return items3; + } + } + const cachedResult = { result: null }; + const items2 = find(parentNode2, cachedResult); + cachedResult.result = new WeakRef(items2); + cache2.set(tagName2, cachedResult); + return items2; + }; + return new HTMLCollection(illegalConstructor, query2); + } + /** + * Returns the first element matching a tag name. + * This is not part of the browser standard and is only used internally (used in Document). + * + * @param parentNode Parent node. + * @param tagName Tag name. + * @returns Matching element. + */ + static getElementByTagName(parentNode2, tagName2) { + const upperTagName = tagName2.toUpperCase(); + const find = (parent2, cachedResult2) => { + for (const element of parent2[elementArray]) { + element[affectsCache].push(cachedResult2); + if (element[tagName] === upperTagName) { + return element; + } + const foundElement = find(element, cachedResult2); + if (foundElement) { + return foundElement; + } + } + return null; + }; + const cache2 = parentNode2[cache].elementByTagName; + const cachedItem = cache2.get(tagName2); + if (cachedItem?.result) { + const item2 = cachedItem.result.deref(); + if (item2) { + return item2; + } + } + const cachedResult = { result: null }; + const item = find(parentNode2, cachedResult); + cachedResult.result = item ? new WeakRef(item) : { deref: () => null }; + cache2.set(tagName2, cachedResult); + return item; + } + /** + * Returns an element by ID. + * + * @param parentNode Parent node. + * @param id ID. + * @returns Matching element. + */ + static getElementById(parentNode2, id2) { + id2 = String(id2); + if (parentNode2[nodeType] === Node.DOCUMENT_NODE) { + const entry = parentNode2[elementIdMap].get(id2); + if (entry && entry.elements.length > 0) { + return entry.elements[0]; + } + return null; + } + const find = (parent2, cachedResult2) => { + for (const element of parent2[elementArray]) { + element[affectsCache].push(cachedResult2); + if (element.getAttribute("id") === id2) { + return element; + } + const foundElement = find(element, cachedResult2); + if (foundElement) { + return foundElement; + } + } + return null; + }; + const cache2 = parentNode2[cache].elementById; + const cachedItem = cache2.get(id2); + if (cachedItem?.result) { + const item2 = cachedItem.result.deref(); + if (item2) { + return item2; + } + } + const cachedResult = { result: null }; + const item = find(parentNode2, cachedResult); + cachedResult.result = item ? new WeakRef(item) : { deref: () => null }; + cache2.set(id2, cachedResult); + return item; + } + }; + } +}); + +// node_modules/happy-dom/lib/dom/DOMRectList.js +var DOMRectList; +var init_DOMRectList = __esm({ + "node_modules/happy-dom/lib/dom/DOMRectList.js"() { + init_PropertySymbol(); + DOMRectList = class extends Array { + /** + * Constructor. + * + * @param illegalConstructorSymbol Illegal constructor symbol. + */ + constructor(illegalConstructorSymbol) { + super(); + if (illegalConstructorSymbol !== 1 && illegalConstructorSymbol !== illegalConstructor) { + throw new TypeError("Illegal constructor"); + } + } + /** + * Returns item by index. + * + * @param index Index. + */ + item(index) { + return this[index] ?? null; + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/element/NamedNodeMap.js +var NamedNodeMap; +var init_NamedNodeMap = __esm({ + "node_modules/happy-dom/lib/nodes/element/NamedNodeMap.js"() { + init_PropertySymbol(); + init_DOMExceptionNameEnum(); + init_NamespaceURI(); + init_StringUtility(); + NamedNodeMap = class { + // Items by attribute namespaceURI + [itemsByNamespaceURI] = /* @__PURE__ */ new Map(); + // Items by attribute name + [itemsByName] = /* @__PURE__ */ new Map(); + // All items + [items] = /* @__PURE__ */ new Map(); + /** + * Constructor. + * + * @param ownerElement Owner element. + */ + constructor(ownerElement2) { + this[ownerElement] = ownerElement2; + } + /** + * Returns length. + * + * @returns Length. + */ + get length() { + return this[items].size; + } + /** + * Returns string. + * + * @returns string. + */ + get [Symbol.toStringTag]() { + return "NamedNodeMap"; + } + /** + * Returns string. + * + * @returns string. + */ + toString() { + return "[object NamedNodeMap]"; + } + /** + * Iterator. + * + * @returns Iterator. + */ + [Symbol.iterator]() { + return this[items].values(); + } + /** + * Returns item by index. + * + * @param index Index. + */ + item(index) { + const items2 = Array.from(this[items].values()); + return index >= 0 && items2[index] ? items2[index] : null; + } + /** + * Returns named item. + * + * @param name Name. + * @returns Item. + */ + getNamedItem(name2) { + name2 = String(name2); + if (this[ownerElement][namespaceURI] === NamespaceURI_default.html && this[ownerElement][ownerDocument][contentType] === "text/html") { + return this[itemsByName].get(StringUtility.asciiLowerCase(name2))?.[0] || null; + } + return this[itemsByName].get(name2)?.[0] || null; + } + /** + * Returns item by name and namespace. + * + * @param namespace Namespace. + * @param localName Local name of the attribute. + * @returns Item. + */ + getNamedItemNS(namespace, localName2) { + const item = this[itemsByNamespaceURI].get(`${namespace || ""}:${localName2}`); + if (item && (!item[prefix] || item[namespaceURI])) { + return item; + } + return null; + } + /** + * Sets named item. + * + * @param item Item. + * @returns Replaced item. + */ + setNamedItem(item) { + return this[setNamedItem](item); + } + /** + * Adds a new namespaced item. + * + * @alias setNamedItem() + * @param item Item. + * @returns Replaced item. + */ + setNamedItemNS(item) { + return this[setNamedItem](item); + } + /** + * Removes an item. + * + * @throws DOMException + * @param name Name of item. + * @returns Removed item. + */ + removeNamedItem(name2) { + const item = this.getNamedItem(name2); + if (!item) { + throw new this[ownerElement][window].DOMException(`Failed to execute 'removeNamedItem' on 'NamedNodeMap': No item with name '${name2}' was found.`, DOMExceptionNameEnum_default.notFoundError); + } + this[removeNamedItem](item); + return item; + } + /** + * Removes a namespaced item. + * + * @param namespace Namespace. + * @param localName Local name of the item. + * @returns Removed item. + */ + removeNamedItemNS(namespace, localName2) { + const item = this.getNamedItemNS(namespace, localName2); + if (!item) { + throw new this[ownerElement][window].DOMException(`Failed to execute 'removeNamedItemNS' on 'NamedNodeMap': No item with name '${localName2}' in namespace '${namespace}' was found.`, DOMExceptionNameEnum_default.notFoundError); + } + this[removeNamedItem](item); + return item; + } + /** + * Sets named item. + * + * @param item Item. + * @param [ignoreListeners] Ignore listeners. + * @returns Replaced item. + */ + [setNamedItem](item, ignoreListeners = false) { + if (item[ownerElement] !== null && item[ownerElement] !== this[ownerElement]) { + throw new this[ownerElement][window].DOMException("The attribute is in use.", DOMExceptionNameEnum_default.inUseAttributeError); + } + item[ownerElement] = this[ownerElement]; + const replacedItem = this.getNamedItemNS(item[namespaceURI], item[localName]) || null; + const itemsByName2 = this[itemsByName].get(item[name]); + if (replacedItem === item) { + return item; + } + this[itemsByNamespaceURI].set(`${item[namespaceURI] || ""}:${item[localName]}`, item); + this[items].set(`${item[namespaceURI] || ""}:${item[name]}`, item); + if (!itemsByName2?.length) { + this[itemsByName].set(item[name], [item]); + } else { + const index = itemsByName2.indexOf(replacedItem); + if (index !== -1) { + itemsByName2.splice(index, 1); + } + itemsByName2.push(item); + } + if (!ignoreListeners) { + this[ownerElement][onSetAttribute](item, replacedItem); + } + return replacedItem; + } + /** + * Removes named item. + * + * @param item Item. + * @param ignoreListeners + */ + [removeNamedItem](item, ignoreListeners = false) { + item[ownerElement] = null; + this[itemsByNamespaceURI].delete(`${item[namespaceURI] || ""}:${item[localName]}`); + this[items].delete(`${item[namespaceURI] || ""}:${item[name]}`); + const itemsByName2 = this[itemsByName].get(item[name]); + if (itemsByName2?.length) { + const index = itemsByName2.indexOf(item); + if (index !== -1) { + itemsByName2.splice(index, 1); + } + if (!itemsByName2.length) { + this[itemsByName].delete(item[name]); + } + } + if (!ignoreListeners) { + this[ownerElement][onRemoveAttribute](item); + } + } + }; + } +}); + +// node_modules/happy-dom/lib/nodes/element/NamedNodeMapProxyFactory.js +var NamedNodeMapProxyFactory; +var init_NamedNodeMapProxyFactory = __esm({ + "node_modules/happy-dom/lib/nodes/element/NamedNodeMapProxyFactory.js"() { + init_ClassMethodBinder(); + init_PropertySymbol(); + init_NamedNodeMap(); + NamedNodeMapProxyFactory = class { + /** + * Constructor. + * + * @param namedNodeMap + */ + static createProxy(namedNodeMap) { + const methodBinder = new ClassMethodBinder(this, [NamedNodeMap]); + return new Proxy(namedNodeMap, { + get: (target2, property) => { + if (property === "length") { + return namedNodeMap[items].size; + } + if (property in target2 || typeof property === "symbol") { + methodBinder.bind(property); + return target2[property]; + } + const index = Number(property); + if (!isNaN(index)) { + return target2.item(index); + } + return target2.getNamedItem(property) || void 0; + }, + set(target2, property, newValue) { + methodBinder.bind(property); + if (typeof property === "symbol") { + target2[property] = newValue; + return true; + } + const index = Number(property); + if (isNaN(index)) { + target2[property] = newValue; + } + return true; + }, + deleteProperty(target2, property) { + if (typeof property === "symbol") { + delete target2[property]; + return true; + } + const index = Number(property); + if (isNaN(index)) { + delete target2[property]; + } + return true; + }, + ownKeys() { + const keys = Array.from(namedNodeMap[items].keys()); + for (let i = 0, max = namedNodeMap[items].size; i < max; i++) { + keys.push(String(i)); + } + return keys; + }, + has(target2, property) { + if (typeof property === "symbol") { + return false; + } + if (property in target2 || namedNodeMap[items].has(property)) { + return true; + } + const index = Number(property); + if (!isNaN(index) && index >= 0 && index < namedNodeMap[items].size) { + return true; + } + return false; + }, + defineProperty(target2, property, descriptor) { + methodBinder.preventBinding(property); + if (property in target2) { + Object.defineProperty(target2, property, descriptor); + return true; + } + return false; + }, + getOwnPropertyDescriptor(target2, property) { + if (property in target2 || typeof property === "symbol") { + return; + } + const index = Number(property); + if (!isNaN(index)) { + if (index >= 0) { + const itemByIndex = target2.item(index); + if (itemByIndex) { + return { + value: itemByIndex, + writable: false, + enumerable: true, + configurable: true + }; + } + } + return; + } + const items2 = namedNodeMap[items].get(property); + if (items2) { + return { + value: items2, + writable: false, + enumerable: true, + configurable: true + }; + } + } + }); + } + }; + } +}); + +// node_modules/happy-dom/lib/config/HTMLElementConfigContentModelEnum.js +var HTMLElementConfigContentModelEnum, HTMLElementConfigContentModelEnum_default; +var init_HTMLElementConfigContentModelEnum = __esm({ + "node_modules/happy-dom/lib/config/HTMLElementConfigContentModelEnum.js"() { + (function(HTMLElementConfigContentModelEnum2) { + HTMLElementConfigContentModelEnum2["rawText"] = "rawText"; + HTMLElementConfigContentModelEnum2["noSelfDescendants"] = "noSelfDescendants"; + HTMLElementConfigContentModelEnum2["noFirstLevelSelfDescendants"] = "noFirstLevelSelfDescendants"; + HTMLElementConfigContentModelEnum2["noForbiddenFirstLevelDescendants"] = "noForbiddenFirstLevelDescendants"; + HTMLElementConfigContentModelEnum2["noDescendants"] = "noDescendants"; + HTMLElementConfigContentModelEnum2["permittedDescendants"] = "permittedDescendants"; + HTMLElementConfigContentModelEnum2["textOrComments"] = "textOrComments"; + HTMLElementConfigContentModelEnum2["anyDescendants"] = "anyDescendants"; + })(HTMLElementConfigContentModelEnum || (HTMLElementConfigContentModelEnum = {})); + HTMLElementConfigContentModelEnum_default = HTMLElementConfigContentModelEnum; + } +}); + +// node_modules/happy-dom/lib/config/HTMLElementConfig.js +var HTMLElementConfig_default; +var init_HTMLElementConfig = __esm({ + "node_modules/happy-dom/lib/config/HTMLElementConfig.js"() { + init_HTMLElementConfigContentModelEnum(); + HTMLElementConfig_default = { + a: { + className: "HTMLAnchorElement", + contentModel: HTMLElementConfigContentModelEnum_default.noSelfDescendants + }, + abbr: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + address: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + area: { + className: "HTMLAreaElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + article: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + aside: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + audio: { + className: "HTMLAudioElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + b: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + base: { + className: "HTMLBaseElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + bdi: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + bdo: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + body: { + className: "HTMLBodyElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + template: { + className: "HTMLTemplateElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + form: { + className: "HTMLFormElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + input: { + className: "HTMLInputElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + textarea: { + className: "HTMLTextAreaElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + script: { + className: "HTMLScriptElement", + contentModel: HTMLElementConfigContentModelEnum_default.rawText + }, + img: { + className: "HTMLImageElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + link: { + className: "HTMLLinkElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + style: { + className: "HTMLStyleElement", + contentModel: HTMLElementConfigContentModelEnum_default.rawText + }, + label: { + className: "HTMLLabelElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + slot: { + className: "HTMLSlotElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + meta: { + className: "HTMLMetaElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + blockquote: { + className: "HTMLQuoteElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + br: { + className: "HTMLBRElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + button: { + className: "HTMLButtonElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + canvas: { + className: "HTMLCanvasElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + caption: { + className: "HTMLTableCaptionElement", + contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, + forbiddenDescendants: ["table", "tbody", "thead", "tfoot", "tr", "td", "th", "col", "colgroup"], + permittedParents: ["table"] + }, + cite: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + code: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + col: { + className: "HTMLTableColElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants, + permittedParents: ["colgroup"] + }, + colgroup: { + className: "HTMLTableColElement", + contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, + permittedDescendants: ["col"] + }, + data: { + className: "HTMLDataElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + datalist: { + className: "HTMLDataListElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + dd: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, + forbiddenDescendants: ["dt", "dd"] + }, + del: { + className: "HTMLModElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + details: { + className: "HTMLDetailsElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + dfn: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + dialog: { + className: "HTMLDialogElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + div: { + className: "HTMLDivElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + dl: { + className: "HTMLDListElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + dt: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, + forbiddenDescendants: ["dt", "dd"] + }, + em: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + embed: { + className: "HTMLEmbedElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + fieldset: { + className: "HTMLFieldSetElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + figcaption: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + figure: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + footer: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + h1: { + className: "HTMLHeadingElement", + contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants + }, + h2: { + className: "HTMLHeadingElement", + contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants + }, + h3: { + className: "HTMLHeadingElement", + contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants + }, + h4: { + className: "HTMLHeadingElement", + contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants + }, + h5: { + className: "HTMLHeadingElement", + contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants + }, + h6: { + className: "HTMLHeadingElement", + contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants + }, + head: { + className: "HTMLHeadElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + header: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + hgroup: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + hr: { + className: "HTMLHRElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + html: { + className: "HTMLHtmlElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + i: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + iframe: { + className: "HTMLIFrameElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + ins: { + className: "HTMLModElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + kbd: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + legend: { + className: "HTMLLegendElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + li: { + className: "HTMLLIElement", + contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants + }, + main: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + map: { + className: "HTMLMapElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + mark: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + menu: { + className: "HTMLMenuElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + meter: { + className: "HTMLMeterElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + nav: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + noscript: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + object: { + className: "HTMLObjectElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + ol: { + className: "HTMLOListElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + optgroup: { + className: "HTMLOptGroupElement", + contentModel: HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants + }, + option: { + className: "HTMLOptionElement", + contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, + forbiddenDescendants: ["option", "optgroup"] + }, + output: { + className: "HTMLOutputElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + p: { + className: "HTMLParagraphElement", + contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, + forbiddenDescendants: [ + "address", + "article", + "aside", + "blockquote", + "details", + "dialog", + "div", + "dl", + "fieldset", + "figcaption", + "figure", + "footer", + "form", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "header", + "hgroup", + "hr", + "main", + "menu", + "nav", + "ol", + "p", + "pre", + "section", + "table", + "ul" + ] + }, + param: { + className: "HTMLParamElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + picture: { + className: "HTMLPictureElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + pre: { + className: "HTMLPreElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + progress: { + className: "HTMLProgressElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + q: { + className: "HTMLQuoteElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + rb: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + rp: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, + forbiddenDescendants: ["rp", "rt"] + }, + rt: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, + forbiddenDescendants: ["rp", "rt"] + }, + rtc: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + ruby: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + s: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + samp: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + section: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + select: { + className: "HTMLSelectElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + small: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + source: { + className: "HTMLSourceElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + span: { + className: "HTMLSpanElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + strong: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + sub: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + summary: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + sup: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + table: { + className: "HTMLTableElement", + contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, + permittedDescendants: ["caption", "colgroup", "thead", "tfoot", "tbody"], + moveForbiddenDescendant: { exclude: [] } + }, + tbody: { + className: "HTMLTableSectionElement", + contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, + permittedDescendants: ["tr"], + permittedParents: ["table"], + moveForbiddenDescendant: { exclude: ["caption", "colgroup", "thead", "tfoot", "tbody"] } + }, + td: { + className: "HTMLTableCellElement", + contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, + forbiddenDescendants: ["td", "th", "tr", "tbody", "tfoot", "thead"], + permittedParents: ["tr"] + }, + tfoot: { + className: "HTMLTableSectionElement", + contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, + permittedDescendants: ["tr"], + permittedParents: ["table"], + moveForbiddenDescendant: { exclude: ["caption", "colgroup", "thead", "tfoot", "tbody"] } + }, + th: { + className: "HTMLTableCellElement", + contentModel: HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants, + forbiddenDescendants: ["td", "th", "tr", "tbody", "tfoot", "thead"], + permittedParents: ["tr"] + }, + thead: { + className: "HTMLTableSectionElement", + contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, + permittedDescendants: ["tr"], + permittedParents: ["table"], + moveForbiddenDescendant: { exclude: ["caption", "colgroup", "thead", "tfoot", "tbody"] } + }, + time: { + className: "HTMLTimeElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + title: { + className: "HTMLTitleElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + tr: { + className: "HTMLTableRowElement", + contentModel: HTMLElementConfigContentModelEnum_default.permittedDescendants, + permittedDescendants: ["td", "th"], + permittedParents: ["tbody", "tfoot", "thead"], + addPermittedParent: "tbody", + moveForbiddenDescendant: { exclude: ["caption", "colgroup", "thead", "tfoot", "tbody", "tr"] } + }, + track: { + className: "HTMLTrackElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + }, + u: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + ul: { + className: "HTMLUListElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + var: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + video: { + className: "HTMLVideoElement", + contentModel: HTMLElementConfigContentModelEnum_default.anyDescendants + }, + wbr: { + className: "HTMLElement", + contentModel: HTMLElementConfigContentModelEnum_default.noDescendants + } + }; + } +}); + +// node_modules/entities/dist/esm/decode-codepoint.js +function replaceCodePoint(codePoint) { + var _a3; + if (codePoint >= 55296 && codePoint <= 57343 || codePoint > 1114111) { + return 65533; + } + return (_a3 = decodeMap.get(codePoint)) !== null && _a3 !== void 0 ? _a3 : codePoint; +} +var _a, decodeMap, fromCodePoint; +var init_decode_codepoint = __esm({ + "node_modules/entities/dist/esm/decode-codepoint.js"() { + decodeMap = /* @__PURE__ */ new Map([ + [0, 65533], + // C1 Unicode control character reference replacements + [128, 8364], + [130, 8218], + [131, 402], + [132, 8222], + [133, 8230], + [134, 8224], + [135, 8225], + [136, 710], + [137, 8240], + [138, 352], + [139, 8249], + [140, 338], + [142, 381], + [145, 8216], + [146, 8217], + [147, 8220], + [148, 8221], + [149, 8226], + [150, 8211], + [151, 8212], + [152, 732], + [153, 8482], + [154, 353], + [155, 8250], + [156, 339], + [158, 382], + [159, 376] + ]); + fromCodePoint = // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, n/no-unsupported-features/es-builtins + (_a = String.fromCodePoint) !== null && _a !== void 0 ? _a : ((codePoint) => { + let output = ""; + if (codePoint > 65535) { + codePoint -= 65536; + output += String.fromCharCode(codePoint >>> 10 & 1023 | 55296); + codePoint = 56320 | codePoint & 1023; + } + output += String.fromCharCode(codePoint); + return output; + }); + } +}); + +// node_modules/entities/dist/esm/internal/decode-shared.js +function decodeBase64(input) { + const binary = ( + // eslint-disable-next-line n/no-unsupported-features/node-builtins + typeof atob === "function" ? ( + // Browser (and Node >=16) + // eslint-disable-next-line n/no-unsupported-features/node-builtins + atob(input) + ) : ( + // Older Node versions (<16) + // eslint-disable-next-line n/no-unsupported-features/node-builtins + typeof Buffer.from === "function" ? ( + // eslint-disable-next-line n/no-unsupported-features/node-builtins + Buffer.from(input, "base64").toString("binary") + ) : ( + // eslint-disable-next-line unicorn/no-new-buffer, n/no-deprecated-api + new Buffer(input, "base64").toString("binary") + ) + ) + ); + const evenLength = binary.length & ~1; + const out = new Uint16Array(evenLength / 2); + for (let index = 0, outIndex = 0; index < evenLength; index += 2) { + const lo = binary.charCodeAt(index); + const hi = binary.charCodeAt(index + 1); + out[outIndex++] = lo | hi << 8; + } + return out; +} +var init_decode_shared = __esm({ + "node_modules/entities/dist/esm/internal/decode-shared.js"() { + } +}); + +// node_modules/entities/dist/esm/generated/decode-data-html.js +var htmlDecodeTree; +var init_decode_data_html = __esm({ + "node_modules/entities/dist/esm/generated/decode-data-html.js"() { + init_decode_shared(); + htmlDecodeTree = /* @__PURE__ */ decodeBase64("QR08ALkAAgH6AYsDNQR2BO0EPgXZBQEGLAbdBxMISQrvCmQLfQurDKQNLw4fD4YPpA+6D/IPAAAAAAAAAAAAAAAAKhBMEY8TmxUWF2EYLBkxGuAa3RsJHDscWR8YIC8jSCSIJcMl6ie3Ku8rEC0CLjoupS7kLgAIRU1hYmNmZ2xtbm9wcnN0dVQAWgBeAGUAaQBzAHcAfgCBAIQAhwCSAJoAoACsALMAbABpAGcAO4DGAMZAUAA7gCYAJkBjAHUAdABlADuAwQDBQHIiZXZlAAJhAAFpeW0AcgByAGMAO4DCAMJAEGRyAADgNdgE3XIAYQB2AGUAO4DAAMBA8CFoYZFj4SFjcgBhZAAAoFMqAAFncIsAjgBvAG4ABGFmAADgNdg43fAlbHlGdW5jdGlvbgCgYSBpAG4AZwA7gMUAxUAAAWNzpACoAHIAAOA12Jzc6SFnbgCgVCJpAGwAZABlADuAwwDDQG0AbAA7gMQAxEAABGFjZWZvcnN1xQDYANoA7QDxAPYA+QD8AAABY3LJAM8AayNzbGFzaAAAoBYidgHTANUAAKDnKmUAZAAAoAYjeQARZIABY3J0AOAA5QDrAGEidXNlAACgNSLuI291bGxpcwCgLCFhAJJjcgAA4DXYBd1wAGYAAOA12Dnd5SF2ZdhiYwDyAOoAbSJwZXEAAKBOIgAHSE9hY2RlZmhpbG9yc3UXARoBHwE6AVIBVQFiAWQBZgGCAakB6QHtAfIBYwB5ACdkUABZADuAqQCpQIABY3B5ACUBKAE1AfUhdGUGYWmg0iJ0KGFsRGlmZmVyZW50aWFsRAAAoEUhbCJleXMAAKAtIQACYWVpb0EBRAFKAU0B8iFvbgxhZABpAGwAO4DHAMdAcgBjAAhhbiJpbnQAAKAwIm8AdAAKYQABZG5ZAV0BaSJsbGEAuGB0I2VyRG90ALdg8gA5AWkAp2NyImNsZQAAAkRNUFRwAXQBeQF9AW8AdAAAoJkiaSJudXMAAKCWIuwhdXMAoJUiaSJtZXMAAKCXIm8AAAFjc4cBlAFrKndpc2VDb250b3VySW50ZWdyYWwAAKAyImUjQ3VybHkAAAFEUZwBpAFvJXVibGVRdW90ZQAAoB0gdSJvdGUAAKAZIAACbG5wdbABtgHNAdgBbwBuAGWgNyIAoHQqgAFnaXQAvAHBAcUB8iJ1ZW50AKBhIm4AdAAAoC8i7yV1ckludGVncmFsAKAuIgABZnLRAdMBAKACIe8iZHVjdACgECJuLnRlckNsb2Nrd2lzZUNvbnRvdXJJbnRlZ3JhbAAAoDMi7yFzcwCgLypjAHIAAOA12J7ccABDoNMiYQBwAACgTSKABURKU1phY2VmaW9zAAsCEgIVAhgCGwIsAjQCOQI9AnMCfwNvoEUh9CJyYWhkAKARKWMAeQACZGMAeQAFZGMAeQAPZIABZ3JzACECJQIoAuchZXIAoCEgcgAAoKEhaAB2AACg5CoAAWF5MAIzAvIhb24OYRRkbAB0oAciYQCUY3IAAOA12AfdAAFhZkECawIAAWNtRQJnAvIjaXRpY2FsAAJBREdUUAJUAl8CYwJjInV0ZQC0YG8AdAFZAloC2WJiJGxlQWN1dGUA3WJyImF2ZQBgYGkibGRlANxi7yFuZACgxCJmJWVyZW50aWFsRAAAoEYhcAR9AgAAAAAAAIECjgIAABoDZgAA4DXYO91EoagAhQKJAm8AdAAAoNwgcSJ1YWwAAKBQIuIhbGUAA0NETFJVVpkCqAK1Au8C/wIRA28AbgB0AG8AdQByAEkAbgB0AGUAZwByAGEA7ADEAW8AdAKvAgAAAACwAqhgbiNBcnJvdwAAoNMhAAFlb7kC0AJmAHQAgAFBUlQAwQLGAs0CciJyb3cAAKDQIekkZ2h0QXJyb3cAoNQhZQDlACsCbgBnAAABTFLWAugC5SFmdAABQVLcAuECciJyb3cAAKD4J+kkZ2h0QXJyb3cAoPon6SRnaHRBcnJvdwCg+SdpImdodAAAAUFU9gL7AnIicm93AACg0iFlAGUAAKCoInAAQQIGAwAAAAALA3Iicm93AACg0SFvJHduQXJyb3cAAKDVIWUlcnRpY2FsQmFyAACgJSJuAAADQUJMUlRhJAM2AzoDWgNxA3oDciJyb3cAAKGTIUJVLAMwA2EAcgAAoBMpcCNBcnJvdwAAoPUhciJldmUAEWPlIWZ00gJDAwAASwMAAFIDaSVnaHRWZWN0b3IAAKBQKWUkZVZlY3RvcgAAoF4p5SJjdG9yQqC9IWEAcgAAoFYpaSJnaHQA1AFiAwAAaQNlJGVWZWN0b3IAAKBfKeUiY3RvckKgwSFhAHIAAKBXKWUAZQBBoKQiciJyb3cAAKCnIXIAcgBvAPcAtAIAAWN0gwOHA3IAAOA12J/c8iFvaxBhAAhOVGFjZGZnbG1vcHFzdHV4owOlA6kDsAO/A8IDxgPNA9ID8gP9AwEEFAQeBCAEJQRHAEphSAA7gNAA0EBjAHUAdABlADuAyQDJQIABYWl5ALYDuQO+A/Ihb24aYXIAYwA7gMoAykAtZG8AdAAWYXIAAOA12AjdcgBhAHYAZQA7gMgAyEDlIm1lbnQAoAgiAAFhcNYD2QNjAHIAEmF0AHkAUwLhAwAAAADpA20lYWxsU3F1YXJlAACg+yVlJ3J5U21hbGxTcXVhcmUAAKCrJQABZ3D2A/kDbwBuABhhZgAA4DXYPN3zImlsb26VY3UAAAFhaQYEDgRsAFSgdSppImxkZQAAoEIi7CNpYnJpdW0AoMwhAAFjaRgEGwRyAACgMCFtAACgcyphAJdjbQBsADuAywDLQAABaXApBC0E8yF0cwCgAyLvJG5lbnRpYWxFAKBHIYACY2Zpb3MAPQQ/BEMEXQRyBHkAJGRyAADgNdgJ3WwibGVkAFMCTAQAAAAAVARtJWFsbFNxdWFyZQAAoPwlZSdyeVNtYWxsU3F1YXJlAACgqiVwA2UEAABpBAAAAABtBGYAAOA12D3dwSFsbACgACLyI2llcnRyZgCgMSFjAPIAcQQABkpUYWJjZGZnb3JzdIgEiwSOBJMElwSkBKcEqwStBLIE5QTqBGMAeQADZDuAPgA+QO0hbWFkoJMD3GNyImV2ZQAeYYABZWl5AJ0EoASjBOQhaWwiYXIAYwAcYRNkbwB0ACBhcgAA4DXYCt0AoNkicABmAADgNdg+3eUiYXRlcgADRUZHTFNUvwTIBM8E1QTZBOAEcSJ1YWwATKBlIuUhc3MAoNsidSRsbEVxdWFsAACgZyJyI2VhdGVyAACgoirlIXNzAKB3IuwkYW50RXF1YWwAoH4qaSJsZGUAAKBzImMAcgAA4DXYotwAoGsiAARBYWNmaW9zdfkE/QQFBQgFCwUTBSIFKwVSIkRjeQAqZAABY3QBBQQFZQBrAMdiXmDpIXJjJGFyAACgDCFsJWJlcnRTcGFjZQAAoAsh8AEYBQAAGwVmAACgDSHpJXpvbnRhbExpbmUAoAAlAAFjdCYFKAXyABIF8iFvayZhbQBwAEQBMQU5BW8AdwBuAEgAdQBtAPAAAAFxInVhbAAAoE8iAAdFSk9hY2RmZ21ub3N0dVMFVgVZBVwFYwVtBXAFcwV6BZAFtgXFBckFzQVjAHkAFWTsIWlnMmFjAHkAAWRjAHUAdABlADuAzQDNQAABaXlnBWwFcgBjADuAzgDOQBhkbwB0ADBhcgAAoBEhcgBhAHYAZQA7gMwAzEAAoREhYXB/BYsFAAFjZ4MFhQVyACphaSNuYXJ5SQAAoEghbABpAGUA8wD6AvQBlQUAAKUFZaAsIgABZ3KaBZ4F8iFhbACgKyLzI2VjdGlvbgCgwiJpI3NpYmxlAAABQ1SsBbEFbyJtbWEAAKBjIGkibWVzAACgYiCAAWdwdAC8Bb8FwwVvAG4ALmFmAADgNdhA3WEAmWNjAHIAAKAQIWkibGRlAChh6wHSBQAA1QVjAHkABmRsADuAzwDPQIACY2Zvc3UA4QXpBe0F8gX9BQABaXnlBegFcgBjADRhGWRyAADgNdgN3XAAZgAA4DXYQd3jAfcFAAD7BXIAAOA12KXc8iFjeQhk6yFjeQRkgANISmFjZm9zAAwGDwYSBhUGHQYhBiYGYwB5ACVkYwB5AAxk8CFwYZpjAAFleRkGHAbkIWlsNmEaZHIAAOA12A7dcABmAADgNdhC3WMAcgAA4DXYptyABUpUYWNlZmxtb3N0AD0GQAZDBl4GawZkB2gHcAd0B80H2gdjAHkACWQ7gDwAPECAAmNtbnByAEwGTwZSBlUGWwb1IXRlOWHiIWRhm2NnAACg6ifsI2FjZXRyZgCgEiFyAACgniGAAWFleQBkBmcGagbyIW9uPWHkIWlsO2EbZAABZnNvBjQHdAAABUFDREZSVFVWYXKABp4GpAbGBssG3AYDByEHwQIqBwABbnKEBowGZyVsZUJyYWNrZXQAAKDoJ/Ihb3cAoZAhQlKTBpcGYQByAACg5CHpJGdodEFycm93AKDGIWUjaWxpbmcAAKAII28A9QGqBgAAsgZiJWxlQnJhY2tldAAAoOYnbgDUAbcGAAC+BmUkZVZlY3RvcgAAoGEp5SJjdG9yQqDDIWEAcgAAoFkpbCJvb3IAAKAKI2kiZ2h0AAABQVbSBtcGciJyb3cAAKCUIeUiY3RvcgCgTikAAWVy4AbwBmUAAKGjIkFW5gbrBnIicm93AACgpCHlImN0b3IAoFopaSNhbmdsZQBCorIi+wYAAAAA/wZhAHIAAKDPKXEidWFsAACgtCJwAIABRFRWAAoHEQcYB+8kd25WZWN0b3IAoFEpZSRlVmVjdG9yAACgYCnlImN0b3JCoL8hYQByAACgWCnlImN0b3JCoLwhYQByAACgUilpAGcAaAB0AGEAcgByAG8A9wDMAnMAAANFRkdMU1Q/B0cHTgdUB1gHXwfxJXVhbEdyZWF0ZXIAoNoidSRsbEVxdWFsAACgZiJyI2VhdGVyAACgdiLlIXNzAKChKuwkYW50RXF1YWwAoH0qaSJsZGUAAKByInIAAOA12A/dZaDYIuYjdGFycm93AKDaIWkiZG90AD9hgAFucHcAege1B7kHZwAAAkxSbHKCB5QHmwerB+UhZnQAAUFSiAeNB3Iicm93AACg9SfpJGdodEFycm93AKD3J+kkZ2h0QXJyb3cAoPYn5SFmdAABYXLcAqEHaQBnAGgAdABhAHIAcgBvAPcA5wJpAGcAaAB0AGEAcgByAG8A9wDuAmYAAOA12EPdZQByAAABTFK/B8YHZSRmdEFycm93AACgmSHpJGdodEFycm93AKCYIYABY2h0ANMH1QfXB/IAWgYAoLAh8iFva0FhAKBqIgAEYWNlZmlvc3XpB+wH7gf/BwMICQgOCBEIcAAAoAUpeQAcZAABZGzyB/kHaSR1bVNwYWNlAACgXyBsI2ludHJmAACgMyFyAADgNdgQ3e4jdXNQbHVzAKATInAAZgAA4DXYRN1jAPIA/gecY4AESmFjZWZvc3R1ACEIJAgoCDUIgQiFCDsKQApHCmMAeQAKZGMidXRlAENhgAFhZXkALggxCDQI8iFvbkdh5CFpbEVhHWSAAWdzdwA7CGEIfQjhInRpdmWAAU1UVgBECEwIWQhlJWRpdW1TcGFjZQAAoAsgaABpAAABY25SCFMIawBTAHAAYQBjAOUASwhlAHIAeQBUAGgAaQDuAFQI9CFlZAABR0xnCHUIcgBlAGEAdABlAHIARwByAGUAYQB0AGUA8gDrBGUAcwBzAEwAZQBzAPMA2wdMImluZQAKYHIAAOA12BHdAAJCbnB0jAiRCJkInAhyImVhawAAoGAgwiZyZWFraW5nU3BhY2WgYGYAAKAVIUOq7CqzCMIIzQgAAOcIGwkAAAAAAAAtCQAAbwkAAIcJAACdCcAJGQoAADQKAAFvdbYIvAjuI2dydWVudACgYiJwIkNhcAAAoG0ibyh1YmxlVmVydGljYWxCYXIAAKAmIoABbHF4ANII1wjhCOUibWVudACgCSL1IWFsVKBgImkibGRlAADgQiI4A2kic3RzAACgBCJyI2VhdGVyAACjbyJFRkdMU1T1CPoIAgkJCQ0JFQlxInVhbAAAoHEidSRsbEVxdWFsAADgZyI4A3IjZWF0ZXIAAOBrIjgD5SFzcwCgeSLsJGFudEVxdWFsAOB+KjgDaSJsZGUAAKB1IvUhbXBEASAJJwnvI3duSHVtcADgTiI4A3EidWFsAADgTyI4A2UAAAFmczEJRgn0JFRyaWFuZ2xlQqLqIj0JAAAAAEIJYQByAADgzyk4A3EidWFsAACg7CJzAICibiJFR0xTVABRCVYJXAlhCWkJcSJ1YWwAAKBwInIjZWF0ZXIAAKB4IuUhc3MA4GoiOAPsJGFudEVxdWFsAOB9KjgDaSJsZGUAAKB0IuUic3RlZAABR0x1CX8J8iZlYXRlckdyZWF0ZXIA4KIqOAPlI3NzTGVzcwDgoSo4A/IjZWNlZGVzAKGAIkVTjwmVCXEidWFsAADgryo4A+wkYW50RXF1YWwAoOAiAAFlaaAJqQl2JmVyc2VFbGVtZW50AACgDCLnJWh0VHJpYW5nbGVCousitgkAAAAAuwlhAHIAAODQKTgDcSJ1YWwAAKDtIgABcXXDCeAJdSNhcmVTdQAAAWJwywnVCfMhZXRF4I8iOANxInVhbAAAoOIi5SJyc2V0ReCQIjgDcSJ1YWwAAKDjIoABYmNwAOYJ8AkNCvMhZXRF4IIi0iBxInVhbAAAoIgi4yJlZWRzgKGBIkVTVAD6CQAKBwpxInVhbAAA4LAqOAPsJGFudEVxdWFsAKDhImkibGRlAADgfyI4A+UicnNldEXggyLSIHEidWFsAACgiSJpImxkZQCAoUEiRUZUACIKJwouCnEidWFsAACgRCJ1JGxsRXF1YWwAAKBHImkibGRlAACgSSJlJXJ0aWNhbEJhcgAAoCQiYwByAADgNdip3GkAbABkAGUAO4DRANFAnWMAB0VhY2RmZ21vcHJzdHV2XgphCmgKcgp2CnoKgQqRCpYKqwqtCrsKyArNCuwhaWdSYWMAdQB0AGUAO4DTANNAAAFpeWwKcQpyAGMAO4DUANRAHmRiImxhYwBQYXIAAOA12BLdcgBhAHYAZQA7gNIA0kCAAWFlaQCHCooKjQpjAHIATGFnAGEAqWNjInJvbgCfY3AAZgAA4DXYRt3lI25DdXJseQABRFGeCqYKbyV1YmxlUXVvdGUAAKAcIHUib3RlAACgGCAAoFQqAAFjbLEKtQpyAADgNdiq3GEAcwBoADuA2ADYQGkAbAHACsUKZABlADuA1QDVQGUAcwAAoDcqbQBsADuA1gDWQGUAcgAAAUJQ0wrmCgABYXLXCtoKcgAAoD4gYQBjAAABZWvgCuIKAKDeI2UAdAAAoLQjYSVyZW50aGVzaXMAAKDcI4AEYWNmaGlsb3JzAP0KAwsFCwkLCwsMCxELIwtaC3IjdGlhbEQAAKACInkAH2RyAADgNdgT3WkApmOgY/Ujc01pbnVzsWAAAWlwFQsgC24AYwBhAHIAZQBwAGwAYQBuAOUACgVmAACgGSGAobsqZWlvACoLRQtJC+MiZWRlc4CheiJFU1QANAs5C0ALcSJ1YWwAAKCvKuwkYW50RXF1YWwAoHwiaSJsZGUAAKB+Im0AZQAAoDMgAAFkcE0LUQv1IWN0AKAPIm8jcnRpb24AYaA3ImwAAKAdIgABY2leC2ILcgAA4DXYq9yoYwACVWZvc2oLbwtzC3cLTwBUADuAIgAiQHIAAOA12BTdcABmAACgGiFjAHIAAOA12KzcAAZCRWFjZWZoaW9yc3WPC5MLlwupC7YL2AvbC90LhQyTDJoMowzhIXJyAKAQKUcAO4CuAK5AgAFjbnIAnQugC6ML9SF0ZVRhZwAAoOsncgB0oKAhbAAAoBYpgAFhZXkArwuyC7UL8iFvblhh5CFpbFZhIGR2oBwhZSJyc2UAAAFFVb8LzwsAAWxxwwvIC+UibWVudACgCyL1JGlsaWJyaXVtAKDLIXAmRXF1aWxpYnJpdW0AAKBvKXIAAKAcIW8AoWPnIWh0AARBQ0RGVFVWYewLCgwQDDIMNwxeDHwM9gIAAW5y8Av4C2clbGVCcmFja2V0AACg6SfyIW93AKGSIUJM/wsDDGEAcgAAoOUhZSRmdEFycm93AACgxCFlI2lsaW5nAACgCSNvAPUBFgwAAB4MYiVsZUJyYWNrZXQAAKDnJ24A1AEjDAAAKgxlJGVWZWN0b3IAAKBdKeUiY3RvckKgwiFhAHIAAKBVKWwib29yAACgCyMAAWVyOwxLDGUAAKGiIkFWQQxGDHIicm93AACgpiHlImN0b3IAoFspaSNhbmdsZQBCorMiVgwAAAAAWgxhAHIAAKDQKXEidWFsAACgtSJwAIABRFRWAGUMbAxzDO8kd25WZWN0b3IAoE8pZSRlVmVjdG9yAACgXCnlImN0b3JCoL4hYQByAACgVCnlImN0b3JCoMAhYQByAACgUykAAXB1iQyMDGYAAKAdIe4kZEltcGxpZXMAoHAp6SRnaHRhcnJvdwCg2yEAAWNongyhDHIAAKAbIQCgsSHsJGVEZWxheWVkAKD0KYAGSE9hY2ZoaW1vcXN0dQC/DMgMzAzQDOIM5gwKDQ0NFA0ZDU8NVA1YDQABQ2PDDMYMyCFjeSlkeQAoZEYiVGN5ACxkYyJ1dGUAWmEAorwqYWVpedgM2wzeDOEM8iFvbmBh5CFpbF5hcgBjAFxhIWRyAADgNdgW3e8hcnQAAkRMUlXvDPYM/QwEDW8kd25BcnJvdwAAoJMhZSRmdEFycm93AACgkCHpJGdodEFycm93AKCSIXAjQXJyb3cAAKCRIechbWGjY+EkbGxDaXJjbGUAoBgicABmAADgNdhK3XICHw0AAAAAIg10AACgGiLhIXJlgKGhJUlTVQAqDTINSg3uJXRlcnNlY3Rpb24AoJMidQAAAWJwNw1ADfMhZXRFoI8icSJ1YWwAAKCRIuUicnNldEWgkCJxInVhbAAAoJIibiJpb24AAKCUImMAcgAA4DXYrtxhAHIAAKDGIgACYmNtcF8Nag2ODZANc6DQImUAdABFoNAicSJ1YWwAAKCGIgABY2huDYkNZSJlZHMAgKF7IkVTVAB4DX0NhA1xInVhbAAAoLAq7CRhbnRFcXVhbACgfSJpImxkZQAAoH8iVABoAGEA9ADHCwCgESIAodEiZXOVDZ8NciJzZXQARaCDInEidWFsAACghyJlAHQAAKDRIoAFSFJTYWNmaGlvcnMAtQ27Db8NyA3ODdsN3w3+DRgOHQ4jDk8AUgBOADuA3gDeQMEhREUAoCIhAAFIY8MNxg1jAHkAC2R5ACZkAAFidcwNzQ0JYKRjgAFhZXkA1A3XDdoN8iFvbmRh5CFpbGJhImRyAADgNdgX3QABZWnjDe4N8gHoDQAA7Q3lImZvcmUAoDQiYQCYYwABY27yDfkNayNTcGFjZQAA4F8gCiDTInBhY2UAoAkg7CFkZYChPCJFRlQABw4MDhMOcSJ1YWwAAKBDInUkbGxFcXVhbAAAoEUiaSJsZGUAAKBIInAAZgAA4DXYS93pI3BsZURvdACg2yAAAWN0Jw4rDnIAAOA12K/c8iFva2Zh4QpFDlYOYA5qDgAAbg5yDgAAAAAAAAAAAAB5DnwOqA6zDgAADg8RDxYPGg8AAWNySA5ODnUAdABlADuA2gDaQHIAb6CfIeMhaXIAoEkpcgDjAVsOAABdDnkADmR2AGUAbGEAAWl5Yw5oDnIAYwA7gNsA20AjZGIibGFjAHBhcgAA4DXYGN1yAGEAdgBlADuA2QDZQOEhY3JqYQABZGl/Dp8OZQByAAABQlCFDpcOAAFhcokOiw5yAF9gYQBjAAABZWuRDpMOAKDfI2UAdAAAoLUjYSVyZW50aGVzaXMAAKDdI28AbgBQoMMi7CF1cwCgjiIAAWdwqw6uDm8AbgByYWYAAOA12EzdAARBREVUYWRwc78O0g7ZDuEOBQPqDvMOBw9yInJvdwDCoZEhyA4AAMwOYQByAACgEilvJHduQXJyb3cAAKDFIW8kd25BcnJvdwAAoJUhcSV1aWxpYnJpdW0AAKBuKWUAZQBBoKUiciJyb3cAAKClIW8AdwBuAGEAcgByAG8A9wAQA2UAcgAAAUxS+Q4AD2UkZnRBcnJvdwAAoJYh6SRnaHRBcnJvdwCglyFpAGyg0gNvAG4ApWPpIW5nbmFjAHIAAOA12LDcaSJsZGUAaGFtAGwAO4DcANxAgAREYmNkZWZvc3YALQ8xDzUPNw89D3IPdg97D4AP4SFzaACgqyJhAHIAAKDrKnkAEmThIXNobKCpIgCg5ioAAWVyQQ9DDwCgwSKAAWJ0eQBJD00Paw9hAHIAAKAWIGmgFiDjIWFsAAJCTFNUWA9cD18PZg9hAHIAAKAjIukhbmV8YGUkcGFyYXRvcgAAoFgnaSJsZGUAAKBAItQkaGluU3BhY2UAoAogcgAA4DXYGd1wAGYAAOA12E3dYwByAADgNdix3GQiYXNoAACgqiKAAmNlZm9zAI4PkQ+VD5kPng/pIXJjdGHkIWdlAKDAInIAAOA12BrdcABmAADgNdhO3WMAcgAA4DXYstwAAmZpb3OqD64Prw+0D3IAAOA12BvdnmNwAGYAAOA12E/dYwByAADgNdiz3IAEQUlVYWNmb3N1AMgPyw/OD9EP2A/gD+QP6Q/uD2MAeQAvZGMAeQAHZGMAeQAuZGMAdQB0AGUAO4DdAN1AAAFpedwP3w9yAGMAdmErZHIAAOA12BzdcABmAADgNdhQ3WMAcgAA4DXYtNxtAGwAeGEABEhhY2RlZm9z/g8BEAUQDRAQEB0QIBAkEGMAeQAWZGMidXRlAHlhAAFheQkQDBDyIW9ufWEXZG8AdAB7YfIBFRAAABwQbwBXAGkAZAB0AOgAVAhhAJZjcgAAoCghcABmAACgJCFjAHIAAOA12LXc4QtCEEkQTRAAAGcQbRByEAAAAAAAAAAAeRCKEJcQ8hD9EAAAGxEhETIROREAAD4RYwB1AHQAZQA7gOEA4UByImV2ZQADYYCiPiJFZGl1eQBWEFkQWxBgEGUQAOA+IjMDAKA/InIAYwA7gOIA4kB0AGUAO4C0ALRAMGRsAGkAZwA7gOYA5kByoGEgAOA12B7dcgBhAHYAZQA7gOAA4EAAAWVwfBCGEAABZnCAEIQQ8yF5bQCgNSHoAIMQaABhALFjAAFhcI0QWwAAAWNskRCTEHIAAWFnAACgPypkApwQAAAAALEQAKInImFkc3ajEKcQqRCuEG4AZAAAoFUqAKBcKmwib3BlAACgWCoAoFoqAKMgImVsbXJzersQvRDAEN0Q5RDtEACgpCllAACgICJzAGQAYaAhImEEzhDQENIQ1BDWENgQ2hDcEACgqCkAoKkpAKCqKQCgqykAoKwpAKCtKQCgrikAoK8pdAB2oB8iYgBkoL4iAKCdKQABcHTpEOwQaAAAoCIixWDhIXJyAKB8IwABZ3D1EPgQbwBuAAVhZgAA4DXYUt0Ao0giRWFlaW9wBxEJEQ0RDxESERQRAKBwKuMhaXIAoG8qAKBKImQAAKBLInMAJ2DyIW94ZaBIIvEADhFpAG4AZwA7gOUA5UCAAWN0eQAmESoRKxFyAADgNdi23CpgbQBwAGWgSCLxAPgBaQBsAGQAZQA7gOMA40BtAGwAO4DkAORAAAFjaUERRxFvAG4AaQBuAPQA6AFuAHQAAKARKgAITmFiY2RlZmlrbG5vcHJzdWQRaBGXEZ8RpxGrEdIR1hErEjASexKKEn0RThNbE3oTbwB0AACg7SoAAWNybBGJEWsAAAJjZXBzdBF4EX0RghHvIW5nAKBMInAjc2lsb24A9mNyImltZQAAoDUgaQBtAGWgPSJxAACgzSJ2AY0RkRFlAGUAAKC9ImUAZABnoAUjZQAAoAUjcgBrAHSgtSPiIXJrAKC2IwABb3mjEaYRbgDnAHcRMWTxIXVvAKAeIIACY21wcnQAtBG5Eb4RwRHFEeEhdXPloDUi5ABwInR5dgAAoLApcwDpAH0RbgBvAPUA6gCAAWFodwDLEcwRzhGyYwCgNiHlIWVuAKBsInIAAOA12B/dZwCAA2Nvc3R1dncA4xHyEQUSEhIhEiYSKRKAAWFpdQDpEesR7xHwAKMFcgBjAACg7yVwAACgwyKAAWRwdAD4EfwRABJvAHQAAKAAKuwhdXMAoAEqaSJtZXMAAKACKnECCxIAAAAADxLjIXVwAKAGKmEAcgAAoAUm8iNpYW5nbGUAAWR1GhIeEu8hd24AoL0lcAAAoLMlcCJsdXMAAKAEKmUA5QBCD+UAkg9hInJvdwAAoA0pgAFha28ANhJoEncSAAFjbjoSZRJrAIABbHN0AEESRxJNEm8jemVuZ2UAAKDrKXEAdQBhAHIA5QBcBPIjaWFuZ2xlgKG0JWRscgBYElwSYBLvIXduAKC+JeUhZnQAoMIlaSJnaHQAAKC4JWsAAKAjJLEBbRIAAHUSsgFxEgAAcxIAoJIlAKCRJTQAAKCTJWMAawAAoIglAAFlb38ShxJx4D0A5SD1IWl2AOBhIuUgdAAAoBAjAAJwdHd4kRKVEpsSnxJmAADgNdhT3XSgpSJvAG0AAKClIvQhaWUAoMgiAAZESFVWYmRobXB0dXayEsES0RLgEvcS+xIKExoTHxMjEygTNxMAAkxSbHK5ErsSvRK/EgCgVyUAoFQlAKBWJQCgUyUAolAlRFVkdckSyxLNEs8SAKBmJQCgaSUAoGQlAKBnJQACTFJsctgS2hLcEt4SAKBdJQCgWiUAoFwlAKBZJQCjUSVITFJobHLrEu0S7xLxEvMS9RIAoGwlAKBjJQCgYCUAoGslAKBiJQCgXyVvAHgAAKDJKQACTFJscgITBBMGEwgTAKBVJQCgUiUAoBAlAKAMJQCiACVEVWR1EhMUExYTGBMAoGUlAKBoJQCgLCUAoDQlaSJudXMAAKCfIuwhdXMAoJ4iaSJtZXMAAKCgIgACTFJsci8TMRMzEzUTAKBbJQCgWCUAoBglAKAUJQCjAiVITFJobHJCE0QTRhNIE0oTTBMAoGolAKBhJQCgXiUAoDwlAKAkJQCgHCUAAWV2UhNVE3YA5QD5AGIAYQByADuApgCmQAACY2Vpb2ITZhNqE24TcgAA4DXYt9xtAGkAAKBPIG0A5aA9IogRbAAAoVwAYmh0E3YTAKDFKfMhdWIAoMgnbAF+E4QTbABloCIgdAAAoCIgcAAAoU4iRWWJE4sTAKCuKvGgTyI8BeEMqRMAAN8TABQDFB8UAAAjFDQUAAAAAIUUAAAAAI0UAAAAANcU4xT3FPsUAACIFQAAlhWAAWNwcgCuE7ET1RP1IXRlB2GAoikiYWJjZHMAuxO/E8QTzhPSE24AZAAAoEQqciJjdXAAAKBJKgABYXXIE8sTcAAAoEsqcAAAoEcqbwB0AACgQCoA4CkiAP4AAWVv2RPcE3QAAKBBIO4ABAUAAmFlaXXlE+8T9RP4E/AB6hMAAO0TcwAAoE0qbwBuAA1hZABpAGwAO4DnAOdAcgBjAAlhcABzAHOgTCptAACgUCpvAHQAC2GAAWRtbgAIFA0UEhRpAGwAO4C4ALhAcCJ0eXYAAKCyKXQAAIGiADtlGBQZFKJAcgBkAG8A9ABiAXIAAOA12CDdgAFjZWkAKBQqFDIUeQBHZGMAawBtoBMn4SFyawCgEyfHY3IAAKPLJUVjZWZtcz8UQRRHFHcUfBSAFACgwykAocYCZWxGFEkUcQAAoFciZQBhAlAUAAAAAGAUciJyb3cAAAFsclYUWhTlIWZ0AKC6IWkiZ2h0AACguyGAAlJTYWNkAGgUaRRrFG8UcxSuYACgyCRzAHQAAKCbIukhcmMAoJoi4SFzaACgnSJuImludAAAoBAqaQBkAACg7yrjIWlyAKDCKfUhYnN1oGMmaQB0AACgYybsApMUmhS2FAAAwxRvAG4AZaA6APGgVCKrAG0CnxQAAAAAoxRhAHSgLABAYAChASJmbKcUqRTuABMNZQAAAW14rhSyFOUhbnQAoAEiZQDzANIB5wG6FAAAwBRkoEUibwB0AACgbSpuAPQAzAGAAWZyeQDIFMsUzhQA4DXYVN1vAOQA1wEAgakAO3MeAdMUcgAAoBchAAFhb9oU3hRyAHIAAKC1IXMAcwAAoBcnAAFjdeYU6hRyAADgNdi43AABYnDuFPIUZaDPKgCg0SploNAqAKDSKuQhb3QAoO8igANkZWxwcnZ3AAYVEBUbFSEVRBVlFYQV4SFycgABbHIMFQ4VAKA4KQCgNSlwAhYVAAAAABkVcgAAoN4iYwAAoN8i4SFycnCgtiEAoD0pgKIqImJjZG9zACsVMBU6FT4VQRVyImNhcAAAoEgqAAFhdTQVNxVwAACgRipwAACgSipvAHQAAKCNInIAAKBFKgDgKiIA/gACYWxydksVURVuFXMVcgByAG2gtyEAoDwpeQCAAWV2dwBYFWUVaRVxAHACXxUAAAAAYxVyAGUA4wAXFXUA4wAZFWUAZQAAoM4iZSJkZ2UAAKDPImUAbgA7gKQApEBlI2Fycm93AAABbHJ7FX8V5SFmdACgtiFpImdodAAAoLchZQDkAG0VAAFjaYsVkRVvAG4AaQBuAPQAkwFuAHQAAKAxImwiY3R5AACgLSOACUFIYWJjZGVmaGlqbG9yc3R1d3oAuBW7Fb8V1RXgFegV+RUKFhUWHxZUFlcWZRbFFtsW7xb7FgUXChdyAPIAtAJhAHIAAKBlKQACZ2xyc8YVyhXOFdAV5yFlcgCgICDlIXRoAKA4IfIA9QxoAHagECAAoKMiawHZFd4VYSJyb3cAAKAPKWEA4wBfAgABYXnkFecV8iFvbg9hNGQAoUYhYW/tFfQVAAFnciEC8RVyAACgyiF0InNlcQAAoHcqgAFnbG0A/xUCFgUWO4CwALBAdABhALRjcCJ0eXYAAKCxKQABaXIOFhIW8yFodACgfykA4DXYId1hAHIAAAFschsWHRYAoMMhAKDCIYACYWVnc3YAKBauAjYWOhY+Fm0AAKHEIm9zLhY0Fm4AZABzoMQi9SFpdACgZiZhIm1tYQDdY2kAbgAAoPIiAKH3AGlvQxZRFmQAZQAAgfcAO29KFksW90BuI3RpbWVzAACgxyJuAPgAUBZjAHkAUmRjAG8CXhYAAAAAYhZyAG4AAKAeI28AcAAAoA0jgAJscHR1dwBuFnEWdRaSFp4W7CFhciRgZgAA4DXYVd0AotkCZW1wc30WhBaJFo0WcQBkoFAibwB0AACgUSJpIm51cwAAoDgi7CF1cwCgFCLxInVhcmUAoKEiYgBsAGUAYgBhAHIAdwBlAGQAZwDlANcAbgCAAWFkaAClFqoWtBZyAHIAbwD3APUMbwB3AG4AYQByAHIAbwB3APMA8xVhI3Jwb29uAAABbHK8FsAWZQBmAPQAHBZpAGcAaAD0AB4WYgHJFs8WawBhAHIAbwD3AJILbwLUFgAAAADYFnIAbgAAoB8jbwBwAACgDCOAAWNvdADhFukW7BYAAXJ55RboFgDgNdi53FVkbAAAoPYp8iFvaxFhAAFkcvMW9xZvAHQAAKDxImkA5qC/JVsSAAFhaP8WAhdyAPIANQNhAPIA1wvhIm5nbGUAoKYpAAFjaQ4XEBd5AF9k5yJyYXJyAKD/JwAJRGFjZGVmZ2xtbm9wcXJzdHV4MRc4F0YXWxcyBF4XaRd5F40XrBe0F78X2RcVGCEYLRg1GEAYAAFEbzUXgRZvAPQA+BUAAWNzPBdCF3UAdABlADuA6QDpQPQhZXIAoG4qAAJhaW95TRdQF1YXWhfyIW9uG2FyAGOgViI7gOoA6kDsIW9uAKBVIk1kbwB0ABdhAAFEcmIXZhdvAHQAAKBSIgDgNdgi3XKhmipuF3QXYQB2AGUAO4DoAOhAZKCWKm8AdAAAoJgqgKGZKmlscwCAF4UXhxfuInRlcnMAoOcjAKATIWSglSpvAHQAAKCXKoABYXBzAJMXlheiF2MAcgATYXQAeQBzogUinxcAAAAAoRdlAHQAAKAFInAAMaADIDMBqRerFwCgBCAAoAUgAAFnc7AXsRdLYXAAAKACIAABZ3C4F7sXbwBuABlhZgAA4DXYVt2AAWFscwDFF8sXzxdyAHOg1SJsAACg4yl1AHMAAKBxKmkAAKG1A2x21RfYF28AbgC1Y/VjAAJjc3V24BfoF/0XEBgAAWlv5BdWF3IAYwAAoFYiaQLuFwAAAADwF+0ADQThIW50AAFnbPUX+Rd0AHIAAKCWKuUhc3MAoJUqgAFhZWkAAxgGGAoYbABzAD1gcwB0AACgXyJ2AESgYSJEAACgeCrwImFyc2wAoOUpAAFEYRkYHRhvAHQAAKBTInIAcgAAoHEpgAFjZGkAJxgqGO0XcgAAoC8hbwD0AIwCAAFhaDEYMhi3YzuA8ADwQAABbXI5GD0YbAA7gOsA60BvAACgrCCAAWNpcABGGEgYSxhsACFgcwD0ACwEAAFlb08YVxhjAHQAYQB0AGkAbwDuABoEbgBlAG4AdABpAGEAbADlADME4Ql1GAAAgRgAAIMYiBgAAAAAoRilGAAAqhgAALsYvhjRGAAA1xgnGWwAbABpAG4AZwBkAG8AdABzAGUA8QBlF3kARGRtImFsZQAAoEAmgAFpbHIAjRiRGJ0Y7CFpZwCgA/tpApcYAAAAAJoYZwAAoAD7aQBnAACgBPsA4DXYI93sIWlnAKAB++whaWcA4GYAagCAAWFsdACvGLIYthh0AACgbSZpAGcAAKAC+24AcwAAoLElbwBmAJJh8AHCGAAAxhhmAADgNdhX3QABYWvJGMwYbADsAGsEdqDUIgCg2SphI3J0aW50AACgDSoAAWFv2hgiGQABY3PeGB8ZsQPnGP0YBRkSGRUZAAAdGbID7xjyGPQY9xj5GAAA+xg7gL0AvUAAoFMhO4C8ALxAAKBVIQCgWSEAoFshswEBGQAAAxkAoFQhAKBWIbQCCxkOGQAAAAAQGTuAvgC+QACgVyEAoFwhNQAAoFghtgEZGQAAGxkAoFohAKBdITgAAKBeIWwAAKBEIHcAbgAAoCIjYwByAADgNdi73IAIRWFiY2RlZmdpamxub3JzdHYARhlKGVoZXhlmGWkZkhmWGZkZnRmgGa0ZxhnLGc8Z4BkjGmygZyIAoIwqgAFjbXAAUBlTGVgZ9SF0ZfVhbQBhAOSgswM6FgCghipyImV2ZQAfYQABaXliGWUZcgBjAB1hM2RvAHQAIWGAoWUibHFzAMYEcBl6GfGhZSLOBAAAdhlsAGEAbgD0AN8EgKF+KmNkbACBGYQZjBljAACgqSpvAHQAb6CAKmyggioAoIQqZeDbIgD+cwAAoJQqcgAA4DXYJN3noGsirATtIWVsAKA3IWMAeQBTZIChdyJFYWoApxmpGasZAKCSKgCgpSoAoKQqAAJFYWVztBm2Gb0ZwhkAoGkicABwoIoq8iFveACgiipxoIgq8aCIKrUZaQBtAACg5yJwAGYAAOA12FjdYQB2AOUAYwIAAWNp0xnWGXIAAKAKIW0AAKFzImVs3BneGQCgjioAoJAqAIM+ADtjZGxxco0E6xn0GfgZ/BkBGgABY2nvGfEZAKCnKnIAAKB6Km8AdAAAoNci0CFhcgCglSl1ImVzdAAAoHwqgAJhZGVscwAKGvQZFhrVBCAa8AEPGgAAFBpwAHIAbwD4AFkZcgAAoHgpcQAAAWxxxAQbGmwAZQBzAPMASRlpAO0A5AQAAWVuJxouGnIjdG5lcXEAAOBpIgD+xQAsGgAFQWFiY2Vma29zeUAaQxpmGmoabRqDGocalhrCGtMacgDyAMwCAAJpbG1yShpOGlAaVBpyAHMA8ABxD2YAvWBpAGwA9AASBQABZHJYGlsaYwB5AEpkAKGUIWN3YBpkGmkAcgAAoEgpAKCtIWEAcgAAoA8h6SFyYyVhgAFhbHIAcxp7Gn8a8iF0c3WgZSZpAHQAAKBlJuwhaXAAoCYg4yFvbgCguSJyAADgNdgl3XMAAAFld4wakRphInJvdwAAoCUpYSJyb3cAAKAmKYACYW1vcHIAnxqjGqcauhq+GnIAcgAAoP8h9CFodACgOyJrAAABbHKsGrMaZSRmdGFycm93AACgqSHpJGdodGFycm93AKCqIWYAAOA12Fnd4iFhcgCgFSCAAWNsdADIGswa0BpyAADgNdi93GEAcwDoAGka8iFvaydhAAFicNca2xr1IWxsAKBDIOghZW4AoBAg4Qr2GgAA/RoAAAgbExsaGwAAIRs7GwAAAAA+G2IbmRuVG6sbAACyG80b0htjAHUAdABlADuA7QDtQAChYyBpeQEbBhtyAGMAO4DuAO5AOGQAAWN4CxsNG3kANWRjAGwAO4ChAKFAAAFmcssCFhsA4DXYJt1yAGEAdgBlADuA7ADsQIChSCFpbm8AJxsyGzYbAAFpbisbLxtuAHQAAKAMKnQAAKAtIuYhaW4AoNwpdABhAACgKSHsIWlnM2GAAWFvcABDG1sbXhuAAWNndABJG0sbWRtyACthgAFlbHAAcQVRG1UbaQBuAOUAyAVhAHIA9AByBWgAMWFmAACgtyJlAGQAtWEAoggiY2ZvdGkbbRt1G3kb4SFyZQCgBSFpAG4AdKAeImkAZQAAoN0pZABvAPQAWxsAoisiY2VscIEbhRuPG5QbYQBsAACguiIAAWdyiRuNG2UAcgDzACMQ4wCCG2EicmhrAACgFyryIW9kAKA8KgACY2dwdJ8boRukG6gbeQBRZG8AbgAvYWYAAOA12FrdYQC5Y3UAZQBzAHQAO4C/AL9AAAFjabUbuRtyAADgNdi+3G4AAKIIIkVkc3bCG8QbyBvQAwCg+SJvAHQAAKD1Inag9CIAoPMiaaBiIOwhZGUpYesB1hsAANkbYwB5AFZkbAA7gO8A70AAA2NmbW9zdeYb7hvyG/Ub+hsFHAABaXnqG+0bcgBjADVhOWRyAADgNdgn3eEhdGg3YnAAZgAA4DXYW93jAf8bAAADHHIAAOA12L/c8iFjeVhk6yFjeVRkAARhY2ZnaGpvcxUcGhwiHCYcKhwtHDAcNRzwIXBhdqC6A/BjAAFleR4cIRzkIWlsN2E6ZHIAAOA12CjdciJlZW4AOGFjAHkARWRjAHkAXGRwAGYAAOA12FzdYwByAADgNdjA3IALQUJFSGFiY2RlZmdoamxtbm9wcnN0dXYAXhxtHHEcdRx5HN8cBx0dHTwd3B3tHfEdAR4EHh0eLB5FHrwewx7hHgkfPR9LH4ABYXJ0AGQcZxxpHHIA8gBvB/IAxQLhIWlsAKAbKeEhcnIAoA4pZ6BmIgCgiyphAHIAAKBiKWMJjRwAAJAcAACVHAAAAAAAAAAAAACZHJwcAACmHKgcrRwAANIc9SF0ZTph7SJwdHl2AKC0KXIAYQDuAFoG4iFkYbtjZwAAoegnZGyhHKMcAKCRKeUAiwYAoIUqdQBvADuAqwCrQHIAgKOQIWJmaGxwc3QAuhy/HMIcxBzHHMoczhxmoOQhcwAAoB8pcwAAoB0p6wCyGnAAAKCrIWwAAKA5KWkAbQAAoHMpbAAAoKIhAKGrKmFl1hzaHGkAbAAAoBkpc6CtKgDgrSoA/oABYWJyAOUc6RztHHIAcgAAoAwpcgBrAACgcicAAWFr8Rz4HGMAAAFla/Yc9xx7YFtgAAFlc/wc/hwAoIspbAAAAWR1Ax0FHQCgjykAoI0pAAJhZXV5Dh0RHRodHB3yIW9uPmEAAWRpFR0YHWkAbAA8YewAowbiAPccO2QAAmNxcnMkHScdLB05HWEAAKA2KXUAbwDyoBwgqhEAAWR1MB00HeghYXIAoGcpcyJoYXIAAKBLKWgAAKCyIQCiZCJmZ3FzRB1FB5Qdnh10AIACYWhscnQATh1WHWUdbB2NHXIicm93AHSgkCFhAOkAzxxhI3Jwb29uAAABZHVeHWId7yF3bgCgvSFwAACgvCHlJGZ0YXJyb3dzAKDHIWkiZ2h0AIABYWhzAHUdex2DHXIicm93APOglCGdBmEAcgBwAG8AbwBuAPMAzgtxAHUAaQBnAGEAcgByAG8A9wBlGugkcmVldGltZXMAoMsi8aFkIk0HAACaHWwAYQBuAPQAXgcAon0qY2Rnc6YdqR2xHbcdYwAAoKgqbwB0AG+gfypyoIEqAKCDKmXg2iIA/nMAAKCTKoACYWRlZ3MAwB3GHcod1h3ZHXAAcAByAG8A+ACmHG8AdAAAoNYicQAAAWdxzx3SHXQA8gBGB2cAdADyAHQcdADyAFMHaQDtAGMHgAFpbHIA4h3mHeod8yFodACgfClvAG8A8gDKBgDgNdgp3UWgdiIAoJEqYQH1Hf4dcgAAAWR1YB35HWygvCEAoGopbABrAACghCVjAHkAWWQAomoiYWNodAweDx4VHhkecgDyAGsdbwByAG4AZQDyAGAW4SFyZACgaylyAGkAAKD6JQABaW8hHiQe5CFvdEBh9SFzdGGgsCPjIWhlAKCwIwACRWFlczMeNR48HkEeAKBoInAAcKCJKvIhb3gAoIkqcaCHKvGghyo0HmkAbQAAoOYiAARhYm5vcHR3elIeXB5fHoUelh6mHqsetB4AAW5yVh5ZHmcAAKDsJ3IAAKD9IXIA6wCwBmcAgAFsbXIAZh52Hnse5SFmdAABYXKIB2weaQBnAGgAdABhAHIAcgBvAPcAkwfhInBzdG8AoPwnaQBnAGgAdABhAHIAcgBvAPcAmgdwI2Fycm93AAABbHKNHpEeZQBmAPQAxhxpImdodAAAoKwhgAFhZmwAnB6fHqIecgAAoIUpAOA12F3ddQBzAACgLSppIm1lcwAAoDQqYQGvHrMecwB0AACgFyLhAIoOZaHKJbkeRhLuIWdlAKDKJWEAcgBsoCgAdAAAoJMpgAJhY2htdADMHs8e1R7bHt0ecgDyAJ0GbwByAG4AZQDyANYWYQByAGSgyyEAoG0pAKAOIHIAaQAAoL8iAANhY2hpcXTrHu8e1QfzHv0eBh/xIXVvAKA5IHIAAOA12MHcbQDloXIi+h4AAPweAKCNKgCgjyoAAWJ19xwBH28AcqAYIACgGiDyIW9rQmEAhDwAO2NkaGlscXJCBhcfxh0gHyQfKB8sHzEfAAFjaRsfHR8AoKYqcgAAoHkqcgBlAOUAkx3tIWVzAKDJIuEhcnIAoHYpdSJlc3QAAKB7KgABUGk1HzkfYQByAACglillocMlAgdfEnIAAAFkdUIfRx9zImhhcgAAoEop6CFhcgCgZikAAWVuTx9WH3IjdG5lcXEAAOBoIgD+xQBUHwAHRGFjZGVmaGlsbm9wc3VuH3Ifoh+rH68ftx+7H74f5h/uH/MfBwj/HwsgxCFvdACgOiIAAmNscHJ5H30fiR+eH3IAO4CvAK9AAAFldIEfgx8AoEImZaAgJ3MAZQAAoCAnc6CmIXQAbwCAoaYhZGx1AJQfmB+cH28AdwDuAHkDZQBmAPQA6gbwAOkO6yFlcgCgriUAAW95ph+qH+0hbWEAoCkqPGThIXNoAKAUIOElc3VyZWRhbmdsZQCgISJyAADgNdgq3W8AAKAnIYABY2RuAMQfyR/bH3IAbwA7gLUAtUBhoiMi0B8AANMf1x9zAPQAKxFpAHIAAKDwKm8AdAA7gLcAt0B1AHMA4qESIh4TAADjH3WgOCIAoCoqYwHqH+0fcAAAoNsq8gB+GnAAbAB1APMACAgAAWRw9x/7H+UhbHMAoKciZgAA4DXYXt0AAWN0AyAHIHIAAOA12MLc8CFvcwCgPiJsobwDECAVIPQiaW1hcACguCJhAPAAEyAADEdMUlZhYmNkZWZnaGlqbG1vcHJzdHV2dzwgRyBmIG0geSCqILgg2iDeIBEhFSEyIUMhTSFQIZwhnyHSIQAiIyKLIrEivyIUIwABZ3RAIEMgAODZIjgD9uBrItIgBwmAAWVsdABNIF8gYiBmAHQAAAFhclMgWCByInJvdwAAoM0h6SRnaHRhcnJvdwCgziEA4NgiOAP24Goi0iBfCekkZ2h0YXJyb3cAoM8hAAFEZHEgdSDhIXNoAKCvIuEhc2gAoK4igAJiY25wdACCIIYgiSCNIKIgbABhAACgByL1IXRlRGFnAADgICLSIACiSSJFaW9wlSCYIJwgniAA4HAqOANkAADgSyI4A3MASWFyAG8A+AAyCnUAcgBhoG4mbADzoG4mmwjzAa8gAACzIHAAO4CgAKBAbQBwAOXgTiI4AyoJgAJhZW91eQDBIMogzSDWINkg8AHGIAAAyCAAoEMqbwBuAEhh5CFpbEZhbgBnAGSgRyJvAHQAAOBtKjgDcAAAoEIqPWThIXNoAKATIACjYCJBYWRxc3jpIO0g+SD+IAIhDCFyAHIAAKDXIXIAAAFocvIg9SBrAACgJClvoJch9wAGD28AdAAA4FAiOAN1AGkA9gC7CAABZWkGIQohYQByAACgKCntAN8I6SFzdPOgBCLlCHIAAOA12CvdAAJFZXN0/wgcISshLiHxoXEiIiEAABMJ8aFxIgAJAAAnIWwAYQBuAPQAEwlpAO0AGQlyoG8iAKBvIoABQWFwADghOyE/IXIA8gBeIHIAcgAAoK4hYQByAACg8ipzogsiSiEAAAAAxwtkoPwiAKD6ImMAeQBaZIADQUVhZGVzdABcIV8hYiFmIWkhkyGWIXIA8gBXIADgZiI4A3IAcgAAoJohcgAAoCUggKFwImZxcwBwIYQhjiF0AAABYXJ1IXohcgByAG8A9wBlIWkAZwBoAHQAYQByAHIAbwD3AD4h8aFwImAhAACKIWwAYQBuAPQAZwlz4H0qOAMAoG4iaQDtAG0JcqBuImkA5aDqIkUJaQDkADoKAAFwdKMhpyFmAADgNdhf3YCBrAA7aW4AriGvIcchrEBuAIChCSJFZHYAtyG6Ib8hAOD5IjgDbwB0AADg9SI4A+EB1gjEIcYhAKD3IgCg9iJpAHagDCLhAagJzyHRIQCg/iIAoP0igAFhb3IA2CHsIfEhcgCAoSYiYXN0AOAh5SHpIWwAbABlAOwAywhsAADg/SrlIADgAiI4A2wiaW50AACgFCrjoYAi9yEAAPohdQDlAJsJY+CvKjgDZaCAIvEAkwkAAkFhaXQHIgoiFyIeInIA8gBsIHIAcgAAoZshY3cRIhQiAOAzKTgDAOCdITgDZyRodGFycm93AACgmyFyAGkA5aDrIr4JgANjaGltcHF1AC8iPCJHIpwhTSJQIloigKGBImNlcgA2Iv0JOSJ1AOUABgoA4DXYw9zvIXJ0bQKdIQAAAABEImEAcgDhAOEhbQBloEEi8aBEIiYKYQDyAMsIcwB1AAABYnBWIlgi5QDUCeUA3wmAAWJjcABgInMieCKAoYQiRWVzAGci7glqIgDgxSo4A2UAdABl4IIi0iBxAPGgiCJoImMAZaCBIvEA/gmAoYUiRWVzAH8iFgqCIgDgxio4A2UAdABl4IMi0iBxAPGgiSKAIgACZ2lscpIilCKaIpwi7AAMCWwAZABlADuA8QDxQOcAWwlpI2FuZ2xlAAABbHKkIqoi5SFmdGWg6iLxAEUJaSJnaHQAZaDrIvEAvgltoL0DAKEjAGVzuCK8InIAbwAAoBYhcAAAoAcggARESGFkZ2lscnMAziLSItYi2iLeIugi7SICIw8j4SFzaACgrSLhIXJyAKAEKXAAAOBNItIg4SFzaACgrCIAAWV04iLlIgDgZSLSIADgPgDSIG4iZmluAACg3imAAUFldADzIvci+iJyAHIAAKACKQDgZCLSIHLgPADSIGkAZQAA4LQi0iAAAUF0BiMKI3IAcgAAoAMp8iFpZQDgtSLSIGkAbQAA4Dwi0iCAAUFhbgAaIx4jKiNyAHIAAKDWIXIAAAFociMjJiNrAACgIylvoJYh9wD/DuUhYXIAoCcpUxJqFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVCMAAF4jaSN/I4IjjSOeI8AUAAAAAKYjwCMAANoj3yMAAO8jHiQvJD8kRCQAAWNzVyNsFHUAdABlADuA8wDzQAABaXlhI2cjcgBjoJoiO4D0APRAPmSAAmFiaW9zAHEjdCN3I3EBeiNzAOgAdhTsIWFjUWF2AACgOCrvIWxkAKC8KewhaWdTYQABY3KFI4kjaQByAACgvykA4DXYLN1vA5QjAAAAAJYjAACcI24A22JhAHYAZQA7gPIA8kAAoMEpAAFibaEjjAphAHIAAKC1KQACYWNpdKwjryO6I70jcgDyAFkUAAFpcrMjtiNyAACgvinvIXNzAKC7KW4A5QDZCgCgwCmAAWFlaQDFI8gjyyNjAHIATWFnAGEAyWOAAWNkbgDRI9Qj1iPyIW9uv2MAoLYpdQDzAHgBcABmAADgNdhg3YABYWVsAOQj5yPrI3IAAKC3KXIAcAAAoLkpdQDzAHwBAKMoImFkaW9zdvkj/CMPJBMkFiQbJHIA8gBeFIChXSplZm0AAyQJJAwkcgBvoDQhZgAAoDQhO4CqAKpAO4C6ALpA5yFvZgCgtiJyAACgVipsIm9wZQAAoFcqAKBbKoABY2xvACMkJSQrJPIACCRhAHMAaAA7gPgA+EBsAACgmCJpAGwBMyQ4JGQAZQA7gPUA9UBlAHMAYaCXInMAAKA2Km0AbAA7gPYA9kDiIWFyAKA9I+EKXiQAAHokAAB8JJQkAACYJKkkAAAAALUkEQsAAPAkAAAAAAQleiUAAIMlcgCAoSUiYXN0AGUkbyQBCwCBtgA7bGokayS2QGwAZQDsABgDaQJ1JAAAAAB4JG0AAKDzKgCg/Sp5AD9kcgCAAmNpbXB0AIUkiCSLJJkSjyRuAHQAJWBvAGQALmBpAGwAAKAwIOUhbmsAoDEgcgAA4DXYLd2AAWltbwCdJKAkpCR2oMYD1WNtAGEA9AD+B24AZQAAoA4m9KHAA64kAAC0JGMjaGZvcmsAAKDUItZjAAFhdbgkxCRuAAABY2u9JMIkawBooA8hAKAOIfYAaRpzAACkKwBhYmNkZW1zdNMkIRPXJNsk4STjJOck6yTjIWlyAKAjKmkAcgAAoCIqAAFvdYsW3yQAoCUqAKByKm4AO4CxALFAaQBtAACgJip3AG8AAKAnKoABaXB1APUk+iT+JO4idGludACgFSpmAADgNdhh3W4AZAA7gKMAo0CApHoiRWFjZWlub3N1ABMlFSUYJRslTCVRJVklSSV1JQCgsypwAACgtyp1AOUAPwtjoK8qgKJ6ImFjZW5zACclLSU0JTYlSSVwAHAAcgBvAPgAFyV1AHIAbAB5AGUA8QA/C/EAOAuAAWFlcwA8JUElRSXwInByb3gAoLkqcQBxAACgtSppAG0AAKDoImkA7QBEC20AZQDzoDIgIguAAUVhcwBDJVclRSXwAEAlgAFkZnAATwtfJXElgAFhbHMAZSVpJW0l7CFhcgCgLiPpIW5lAKASI/UhcmYAoBMjdKAdIu8AWQvyIWVsAKCwIgABY2l9JYElcgAA4DXYxdzIY24iY3NwAACgCCAAA2Zpb3BzdZElKxuVJZolnyWkJXIAAOA12C7dcABmAADgNdhi3XIiaW1lAACgVyBjAHIAAOA12MbcgAFhZW8AqiW6JcAldAAAAWVpryW2JXIAbgBpAG8AbgDzABkFbgB0AACgFipzAHQAZaA/APEACRj0AG0LgApBQkhhYmNkZWZoaWxtbm9wcnN0dXgA4yXyJfYl+iVpJpAmpia9JtUm5ib4JlonaCdxJ3UnnietJ7EnyCfiJ+cngAFhcnQA6SXsJe4lcgDyAJkM8gD6AuEhaWwAoBwpYQByAPIA3BVhAHIAAKBkKYADY2RlbnFydAAGJhAmEyYYJiYmKyZaJgABZXUKJg0mAOA9IjEDdABlAFVhaQDjACAN7SJwdHl2AKCzKWcAgKHpJ2RlbAAgJiImJCYAoJIpAKClKeUA9wt1AG8AO4C7ALtAcgAApZIhYWJjZmhscHN0dz0mQCZFJkcmSiZMJk4mUSZVJlgmcAAAoHUpZqDlIXMAAKAgKQCgMylzAACgHinrALka8ACVHmwAAKBFKWkAbQAAoHQpbAAAoKMhAKCdIQABYWleJmImaQBsAACgGilvAG6gNiJhAGwA8wB2C4ABYWJyAG8mciZ2JnIA8gAvEnIAawAAoHMnAAFha3omgSZjAAABZWt/JoAmfWBdYAABZXOFJocmAKCMKWwAAAFkdYwmjiYAoI4pAKCQKQACYWV1eZcmmiajJqUm8iFvbllhAAFkaZ4moSZpAGwAV2HsAA8M4gCAJkBkAAJjbHFzrSawJrUmuiZhAACgNylkImhhcgAAoGkpdQBvAPKgHSCjAWgAAKCzIYABYWNnAMMm0iaUC2wAgKEcIWlwcwDLJs4migxuAOUAoAxhAHIA9ADaC3QAAKCtJYABaWxyANsm3ybjJvMhaHQAoH0pbwBvAPIANgwA4DXYL90AAWFv6ib1JnIAAAFkde8m8SYAoMEhbKDAIQCgbCl2oMED8WOAAWducwD+Jk4nUCdoAHQAAANhaGxyc3QKJxInISc1Jz0nRydyInJvdwB0oJIhYQDpAFYmYSNycG9vbgAAAWR1GiceJ28AdwDuAPAmcAAAoMAh5SFmdAABYWgnJy0ncgByAG8AdwDzAAkMYQByAHAAbwBvAG4A8wATBGklZ2h0YXJyb3dzAACgySFxAHUAaQBnAGEAcgByAG8A9wBZJugkcmVldGltZXMAoMwiZwDaYmkAbgBnAGQAbwB0AHMAZQDxABwYgAFhaG0AYCdjJ2YncgDyAAkMYQDyABMEAKAPIG8idXN0AGGgsSPjIWhlAKCxI+0haWQAoO4qAAJhYnB0fCeGJ4knmScAAW5ygCeDJ2cAAKDtJ3IAAKD+IXIA6wAcDIABYWZsAI8nkieVJ3IAAKCGKQDgNdhj3XUAcwAAoC4qaSJtZXMAAKA1KgABYXCiJ6gncgBnoCkAdAAAoJQp7yJsaW50AKASKmEAcgDyADwnAAJhY2hxuCe8J6EMwCfxIXVvAKA6IHIAAOA12MfcAAFidYAmxCdvAPKgGSCoAYABaGlyAM4n0ifWJ3IAZQDlAE0n7SFlcwCgyiJpAIChuSVlZmwAXAxjEt4n9CFyaQCgzinsInVoYXIAoGgpAKAeIWENBSgJKA0oSyhVKIYoAACLKLAoAAAAAOMo5ygAABApJCkxKW0pcSmHKaYpAACYKgAAAACxKmMidXRlAFthcQB1AO8ABR+ApHsiRWFjZWlucHN5ABwoHignKCooLygyKEEoRihJKACgtCrwASMoAAAlKACguCpvAG4AYWF1AOUAgw1koLAqaQBsAF9hcgBjAF1hgAFFYXMAOCg6KD0oAKC2KnAAAKC6KmkAbQAAoOki7yJsaW50AKATKmkA7QCIDUFkbwB0AGKixSKRFgAAAABTKACgZiqAA0FhY21zdHgAYChkKG8ocyh1KHkogihyAHIAAKDYIXIAAAFocmkoayjrAJAab6CYIfcAzAd0ADuApwCnQGkAO2D3IWFyAKApKW0AAAFpbn4ozQBuAHUA8wDOAHQAAKA2J3IA7+A12DDdIxkAAmFjb3mRKJUonSisKHIAcAAAoG8mAAFoeZkonChjAHkASWRIZHIAdABtAqUoAAAAAKgoaQDkAFsPYQByAGEA7ABsJDuArQCtQAABZ22zKLsobQBhAAChwwNmdroouijCY4CjPCJkZWdsbnByAMgozCjPKNMo1yjaKN4obwB0AACgairxoEMiCw5FoJ4qAKCgKkWgnSoAoJ8qZQAAoEYi7CF1cwCgJCrhIXJyAKByKWEAcgDyAPwMAAJhZWl07Sj8KAEpCCkAAWxz8Sj4KGwAcwBlAHQAbQDpAH8oaABwAACgMyrwImFyc2wAoOQpAAFkbFoPBSllAACgIyNloKoqc6CsKgDgrCoA/oABZmxwABUpGCkfKfQhY3lMZGKgLwBhoMQpcgAAoD8jZgAA4DXYZN1hAAABZHIoKRcDZQBzAHWgYCZpAHQAAKBgJoABY3N1ADYpRilhKQABYXU6KUApcABzoJMiAOCTIgD+cABzoJQiAOCUIgD+dQAAAWJwSylWKQChjyJlcz4NUCllAHQAZaCPIvEAPw0AoZAiZXNIDVspZQB0AGWgkCLxAEkNAKGhJWFmZilbBHIAZQFrKVwEAKChJWEAcgDyAAMNAAJjZW10dyl7KX8pgilyAADgNdjI3HQAbQDuAM4AaQDsAAYpYQByAOYAVw0AAWFyiimOKXIA5qAGJhESAAFhbpIpoylpImdodAAAAWVwmSmgKXAAcwBpAGwAbwDuANkXaADpAKAkcwCvYIACYmNtbnAArin8KY4NJSooKgCkgiJFZGVtbnByc7wpvinCKcgpzCnUKdgp3CkAoMUqbwB0AACgvSpkoIYibwB0AACgwyr1IWx0AKDBKgABRWXQKdIpAKDLKgCgiiLsIXVzAKC/KuEhcnIAoHkpgAFlaXUA4inxKfQpdAAAoYIiZW7oKewpcQDxoIYivSllAHEA8aCKItEpbQAAoMcqAAFicPgp+ikAoNUqAKDTKmMAgKJ7ImFjZW5zAAcqDSoUKhYqRihwAHAAcgBvAPgAIyh1AHIAbAB5AGUA8QCDDfEAfA2AAWFlcwAcKiIqPShwAHAAcgBvAPgAPChxAPEAOShnAACgaiYApoMiMTIzRWRlaGxtbnBzPCo/KkIqRSpHKlIqWCpjKmcqaypzKncqO4C5ALlAO4CyALJAO4CzALNAAKDGKgABb3NLKk4qdAAAoL4qdQBiAACg2CpkoIcibwB0AACgxCpzAAABb3VdKmAqbAAAoMknYgAAoNcq4SFycgCgeyn1IWx0AKDCKgABRWVvKnEqAKDMKgCgiyLsIXVzAKDAKoABZWl1AH0qjCqPKnQAAKGDImVugyqHKnEA8aCHIkYqZQBxAPGgiyJwKm0AAKDIKgABYnCTKpUqAKDUKgCg1iqAAUFhbgCdKqEqrCpyAHIAAKDZIXIAAAFocqYqqCrrAJUab6CZIfcAxQf3IWFyAKAqKWwAaQBnADuA3wDfQOELzyrZKtwq6SrsKvEqAAD1KjQrAAAAAAAAAAAAAEwrbCsAAHErvSsAAAAAAADRK3IC1CoAAAAA2CrnIWV0AKAWI8RjcgDrAOUKgAFhZXkA4SrkKucq8iFvbmVh5CFpbGNhQmRvAPQAIg5sInJlYwAAoBUjcgAA4DXYMd0AAmVpa2/7KhIrKCsuK/IBACsAAAkrZQAAATRm6g0EK28AcgDlAOsNYQBzorgDECsAAAAAEit5AG0A0WMAAWNuFislK2sAAAFhcxsrIStwAHAAcgBvAPgAFw5pAG0AAKA8InMA8AD9DQABYXMsKyEr8AAXDnIAbgA7gP4A/kDsATgrOyswG2QA5QBnAmUAcwCAgdcAO2JkAEMrRCtJK9dAYaCgInIAAKAxKgCgMCqAAWVwcwBRK1MraSvhAAkh4qKkIlsrXysAAAAAYytvAHQAAKA2I2kAcgAAoPEqb+A12GXdcgBrAACg2irhAHgociJpbWUAAKA0IIABYWlwAHYreSu3K2QA5QC+DYADYWRlbXBzdACFK6MrmiunK6wrsCuzK24iZ2xlAACitSVkbHFykCuUK5ornCvvIXduAKC/JeUhZnRloMMl8QACBwCgXCJpImdodABloLkl8QBdDG8AdAAAoOwlaSJudXMAAKA6KuwhdXMAoDkqYgAAoM0p6SFtZQCgOyrlInppdW0AoOIjgAFjaHQAwivKK80rAAFyecYrySsA4DXYydxGZGMAeQBbZPIhb2tnYQABaW/UK9creAD0ANERaCJlYWQAAAFsct4r5ytlAGYAdABhAHIAcgBvAPcAXQbpJGdodGFycm93AKCgIQAJQUhhYmNkZmdobG1vcHJzdHV3CiwNLBEsHSwnLDEsQCxLLFIsYix6LIQsjyzLLOgs7Sz/LAotcgDyAAkDYQByAACgYykAAWNyFSwbLHUAdABlADuA+gD6QPIACQ1yAOMBIywAACUseQBeZHYAZQBtYQABaXkrLDAscgBjADuA+wD7QENkgAFhYmgANyw6LD0scgDyANEO7CFhY3FhYQDyAOAOAAFpckQsSCzzIWh0AKB+KQDgNdgy3XIAYQB2AGUAO4D5APlAYQFWLF8scgAAAWxyWixcLACgvyEAoL4hbABrAACggCUAAWN0Zix2LG8CbCwAAAAAcyxyAG4AZaAcI3IAAKAcI28AcAAAoA8jcgBpAACg+CUAAWFsfiyBLGMAcgBrYTuAqACoQAABZ3CILIssbwBuAHNhZgAA4DXYZt0AA2FkaGxzdZksniynLLgsuyzFLHIAcgBvAPcACQ1vAHcAbgBhAHIAcgBvAPcA2A5hI3Jwb29uAAABbHKvLLMsZQBmAPQAWyxpAGcAaAD0AF0sdQDzAKYOaQAAocUDaGzBLMIs0mNvAG4AxWPwI2Fycm93cwCgyCGAAWNpdADRLOEs5CxvAtcsAAAAAN4scgBuAGWgHSNyAACgHSNvAHAAAKAOI24AZwBvYXIAaQAAoPklYwByAADgNdjK3IABZGlyAPMs9yz6LG8AdAAAoPAi7CFkZWlhaQBmoLUlAKC0JQABYW0DLQYtcgDyAMosbAA7gPwA/EDhIm5nbGUAoKcpgAdBQkRhY2RlZmxub3Byc3oAJy0qLTAtNC2bLZ0toS2/LcMtxy3TLdgt3C3gLfwtcgDyABADYQByAHag6CoAoOkqYQBzAOgA/gIAAW5yOC08LechcnQAoJwpgANla25wcnN0AJkpSC1NLVQtXi1iLYItYQBwAHAA4QAaHG8AdABoAGkAbgDnAKEXgAFoaXIAoSmzJFotbwBwAPQAdCVooJUh7wD4JgABaXVmLWotZwBtAOEAuygAAWJwbi14LXMjZXRuZXEAceCKIgD+AODLKgD+cyNldG5lcQBx4IsiAP4A4MwqAP4AAWhyhi2KLWUAdADhABIraSNhbmdsZQAAAWxyki2WLeUhZnQAoLIiaSJnaHQAAKCzInkAMmThIXNoAKCiIoABZWxyAKcttC24LWKiKCKuLQAAAACyLWEAcgAAoLsicQAAoFoi7CFpcACg7iIAAWJ0vC1eD2EA8gBfD3IAAOA12DPddAByAOkAlS1zAHUAAAFicM0t0C0A4IIi0iAA4IMi0iBwAGYAAOA12GfdcgBvAPAAWQt0AHIA6QCaLQABY3XkLegtcgAA4DXYy9wAAWJw7C30LW4AAAFFZXUt8S0A4IoiAP5uAAABRWV/LfktAOCLIgD+6SJnemFnAKCaKYADY2Vmb3BycwANLhAuJS4pLiMuLi40LukhcmN1YQABZGkULiEuAAFiZxguHC5hAHIAAKBfKmUAcaAnIgCgWSLlIXJwAKAYIXIAAOA12DTdcABmAADgNdho3WWgQCJhAHQA6ABqD2MAcgAA4DXYzNzjCuQRUC4AAFQuAABYLmIuAAAAAGMubS5wLnQuAAAAAIguki4AAJouJxIqEnQAcgDpAB0ScgAA4DXYNd0AAUFhWy5eLnIA8gDnAnIA8gCTB75jAAFBYWYuaS5yAPIA4AJyAPIAjAdhAPAAeh5pAHMAAKD7IoABZHB0APgReS6DLgABZmx9LoAuAOA12GnddQDzAP8RaQBtAOUABBIAAUFhiy6OLnIA8gDuAnIA8gCaBwABY3GVLgoScgAA4DXYzdwAAXB0nS6hLmwAdQDzACUScgDpACASAARhY2VmaW9zdbEuvC7ELsguzC7PLtQu2S5jAAABdXm2LrsudABlADuA/QD9QE9kAAFpecAuwy5yAGMAd2FLZG4AO4ClAKVAcgAA4DXYNt1jAHkAV2RwAGYAAOA12GrdYwByAADgNdjO3AABY23dLt8ueQBOZGwAO4D/AP9AAAVhY2RlZmhpb3N38y73Lv8uAi8MLxAvEy8YLx0vIi9jInV0ZQB6YQABYXn7Lv4u8iFvbn5hN2RvAHQAfGEAAWV0Bi8KL3QAcgDmAB8QYQC2Y3IAAOA12DfdYwB5ADZk5yJyYXJyAKDdIXAAZgAA4DXYa91jAHIAAOA12M/cAAFqbiYvKC8AoA0gagAAoAwg"); + } +}); + +// node_modules/entities/dist/esm/generated/decode-data-xml.js +var xmlDecodeTree; +var init_decode_data_xml = __esm({ + "node_modules/entities/dist/esm/generated/decode-data-xml.js"() { + init_decode_shared(); + xmlDecodeTree = /* @__PURE__ */ decodeBase64("AAJhZ2xxBwARABMAFQBtAg0AAAAAAA8AcAAmYG8AcwAnYHQAPmB0ADxg9SFvdCJg"); + } +}); + +// node_modules/entities/dist/esm/internal/bin-trie-flags.js +var BinTrieFlags; +var init_bin_trie_flags = __esm({ + "node_modules/entities/dist/esm/internal/bin-trie-flags.js"() { + (function(BinTrieFlags2) { + BinTrieFlags2[BinTrieFlags2["VALUE_LENGTH"] = 49152] = "VALUE_LENGTH"; + BinTrieFlags2[BinTrieFlags2["FLAG13"] = 8192] = "FLAG13"; + BinTrieFlags2[BinTrieFlags2["BRANCH_LENGTH"] = 8064] = "BRANCH_LENGTH"; + BinTrieFlags2[BinTrieFlags2["JUMP_TABLE"] = 127] = "JUMP_TABLE"; + })(BinTrieFlags || (BinTrieFlags = {})); + } +}); + +// node_modules/entities/dist/esm/decode.js +function isNumber(code) { + return code >= CharCodes.ZERO && code <= CharCodes.NINE; +} +function isHexadecimalCharacter(code) { + return code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_F || code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_F; +} +function isAsciiAlphaNumeric(code) { + return code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_Z || code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_Z || isNumber(code); +} +function isEntityInAttributeInvalidEnd(code) { + return code === CharCodes.EQUALS || isAsciiAlphaNumeric(code); +} +function getDecoder(decodeTree) { + let returnValue2 = ""; + const decoder = new EntityDecoder(decodeTree, (data2) => returnValue2 += fromCodePoint(data2)); + return function decodeWithTrie(input, decodeMode) { + let lastIndex = 0; + let offset2 = 0; + while ((offset2 = input.indexOf("&", offset2)) >= 0) { + returnValue2 += input.slice(lastIndex, offset2); + decoder.startEntity(decodeMode); + const length2 = decoder.write( + input, + // Skip the "&" + offset2 + 1 + ); + if (length2 < 0) { + lastIndex = offset2 + decoder.end(); + break; + } + lastIndex = offset2 + length2; + offset2 = length2 === 0 ? lastIndex + 1 : lastIndex; + } + const result3 = returnValue2 + input.slice(lastIndex); + returnValue2 = ""; + return result3; + }; +} +function determineBranch(decodeTree, current, nodeIndex, char) { + const branchCount = (current & BinTrieFlags.BRANCH_LENGTH) >> 7; + const jumpOffset = current & BinTrieFlags.JUMP_TABLE; + if (branchCount === 0) { + return jumpOffset !== 0 && char === jumpOffset ? nodeIndex : -1; + } + if (jumpOffset) { + const value2 = char - jumpOffset; + return value2 < 0 || value2 >= branchCount ? -1 : decodeTree[nodeIndex + value2] - 1; + } + const packedKeySlots = branchCount + 1 >> 1; + let lo = 0; + let hi = branchCount - 1; + while (lo <= hi) { + const mid = lo + hi >>> 1; + const slot = mid >> 1; + const packed = decodeTree[nodeIndex + slot]; + const midKey = packed >> (mid & 1) * 8 & 255; + if (midKey < char) { + lo = mid + 1; + } else if (midKey > char) { + hi = mid - 1; + } else { + return decodeTree[nodeIndex + packedKeySlots + mid]; + } + } + return -1; +} +function decodeHTML(htmlString, mode2 = DecodingMode.Legacy) { + return htmlDecoder(htmlString, mode2); +} +function decodeHTMLAttribute(htmlAttribute) { + return htmlDecoder(htmlAttribute, DecodingMode.Attribute); +} +function decodeXML(xmlString) { + return xmlDecoder(xmlString, DecodingMode.Strict); +} +var CharCodes, TO_LOWER_BIT, EntityDecoderState, DecodingMode, EntityDecoder, htmlDecoder, xmlDecoder; +var init_decode = __esm({ + "node_modules/entities/dist/esm/decode.js"() { + init_decode_codepoint(); + init_decode_data_html(); + init_decode_data_xml(); + init_bin_trie_flags(); + init_decode_codepoint(); + init_decode_data_html(); + init_decode_data_xml(); + (function(CharCodes2) { + CharCodes2[CharCodes2["NUM"] = 35] = "NUM"; + CharCodes2[CharCodes2["SEMI"] = 59] = "SEMI"; + CharCodes2[CharCodes2["EQUALS"] = 61] = "EQUALS"; + CharCodes2[CharCodes2["ZERO"] = 48] = "ZERO"; + CharCodes2[CharCodes2["NINE"] = 57] = "NINE"; + CharCodes2[CharCodes2["LOWER_A"] = 97] = "LOWER_A"; + CharCodes2[CharCodes2["LOWER_F"] = 102] = "LOWER_F"; + CharCodes2[CharCodes2["LOWER_X"] = 120] = "LOWER_X"; + CharCodes2[CharCodes2["LOWER_Z"] = 122] = "LOWER_Z"; + CharCodes2[CharCodes2["UPPER_A"] = 65] = "UPPER_A"; + CharCodes2[CharCodes2["UPPER_F"] = 70] = "UPPER_F"; + CharCodes2[CharCodes2["UPPER_Z"] = 90] = "UPPER_Z"; + })(CharCodes || (CharCodes = {})); + TO_LOWER_BIT = 32; + (function(EntityDecoderState2) { + EntityDecoderState2[EntityDecoderState2["EntityStart"] = 0] = "EntityStart"; + EntityDecoderState2[EntityDecoderState2["NumericStart"] = 1] = "NumericStart"; + EntityDecoderState2[EntityDecoderState2["NumericDecimal"] = 2] = "NumericDecimal"; + EntityDecoderState2[EntityDecoderState2["NumericHex"] = 3] = "NumericHex"; + EntityDecoderState2[EntityDecoderState2["NamedEntity"] = 4] = "NamedEntity"; + })(EntityDecoderState || (EntityDecoderState = {})); + (function(DecodingMode2) { + DecodingMode2[DecodingMode2["Legacy"] = 0] = "Legacy"; + DecodingMode2[DecodingMode2["Strict"] = 1] = "Strict"; + DecodingMode2[DecodingMode2["Attribute"] = 2] = "Attribute"; + })(DecodingMode || (DecodingMode = {})); + EntityDecoder = class { + constructor(decodeTree, emitCodePoint, errors) { + this.decodeTree = decodeTree; + this.emitCodePoint = emitCodePoint; + this.errors = errors; + this.state = EntityDecoderState.EntityStart; + this.consumed = 1; + this.result = 0; + this.treeIndex = 0; + this.excess = 1; + this.decodeMode = DecodingMode.Strict; + this.runConsumed = 0; + } + /** Resets the instance to make it reusable. */ + startEntity(decodeMode) { + this.decodeMode = decodeMode; + this.state = EntityDecoderState.EntityStart; + this.result = 0; + this.treeIndex = 0; + this.excess = 1; + this.consumed = 1; + this.runConsumed = 0; + } + /** + * Write an entity to the decoder. This can be called multiple times with partial entities. + * If the entity is incomplete, the decoder will return -1. + * + * Mirrors the implementation of `getDecoder`, but with the ability to stop decoding if the + * entity is incomplete, and resume when the next string is written. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The offset at which the entity begins. Should be 0 if this is not the first call. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + write(input, offset2) { + switch (this.state) { + case EntityDecoderState.EntityStart: { + if (input.charCodeAt(offset2) === CharCodes.NUM) { + this.state = EntityDecoderState.NumericStart; + this.consumed += 1; + return this.stateNumericStart(input, offset2 + 1); + } + this.state = EntityDecoderState.NamedEntity; + return this.stateNamedEntity(input, offset2); + } + case EntityDecoderState.NumericStart: { + return this.stateNumericStart(input, offset2); + } + case EntityDecoderState.NumericDecimal: { + return this.stateNumericDecimal(input, offset2); + } + case EntityDecoderState.NumericHex: { + return this.stateNumericHex(input, offset2); + } + case EntityDecoderState.NamedEntity: { + return this.stateNamedEntity(input, offset2); + } + } + } + /** + * Switches between the numeric decimal and hexadecimal states. + * + * Equivalent to the `Numeric character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericStart(input, offset2) { + if (offset2 >= input.length) { + return -1; + } + if ((input.charCodeAt(offset2) | TO_LOWER_BIT) === CharCodes.LOWER_X) { + this.state = EntityDecoderState.NumericHex; + this.consumed += 1; + return this.stateNumericHex(input, offset2 + 1); + } + this.state = EntityDecoderState.NumericDecimal; + return this.stateNumericDecimal(input, offset2); + } + /** + * Parses a hexadecimal numeric entity. + * + * Equivalent to the `Hexademical character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericHex(input, offset2) { + while (offset2 < input.length) { + const char = input.charCodeAt(offset2); + if (isNumber(char) || isHexadecimalCharacter(char)) { + const digit = char <= CharCodes.NINE ? char - CharCodes.ZERO : (char | TO_LOWER_BIT) - CharCodes.LOWER_A + 10; + this.result = this.result * 16 + digit; + this.consumed++; + offset2++; + } else { + return this.emitNumericEntity(char, 3); + } + } + return -1; + } + /** + * Parses a decimal numeric entity. + * + * Equivalent to the `Decimal character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericDecimal(input, offset2) { + while (offset2 < input.length) { + const char = input.charCodeAt(offset2); + if (isNumber(char)) { + this.result = this.result * 10 + (char - CharCodes.ZERO); + this.consumed++; + offset2++; + } else { + return this.emitNumericEntity(char, 2); + } + } + return -1; + } + /** + * Validate and emit a numeric entity. + * + * Implements the logic from the `Hexademical character reference start + * state` and `Numeric character reference end state` in the HTML spec. + * + * @param lastCp The last code point of the entity. Used to see if the + * entity was terminated with a semicolon. + * @param expectedLength The minimum number of characters that should be + * consumed. Used to validate that at least one digit + * was consumed. + * @returns The number of characters that were consumed. + */ + emitNumericEntity(lastCp, expectedLength) { + var _a3; + if (this.consumed <= expectedLength) { + (_a3 = this.errors) === null || _a3 === void 0 ? void 0 : _a3.absenceOfDigitsInNumericCharacterReference(this.consumed); + return 0; + } + if (lastCp === CharCodes.SEMI) { + this.consumed += 1; + } else if (this.decodeMode === DecodingMode.Strict) { + return 0; + } + this.emitCodePoint(replaceCodePoint(this.result), this.consumed); + if (this.errors) { + if (lastCp !== CharCodes.SEMI) { + this.errors.missingSemicolonAfterCharacterReference(); + } + this.errors.validateNumericCharacterReference(this.result); + } + return this.consumed; + } + /** + * Parses a named entity. + * + * Equivalent to the `Named character reference state` in the HTML spec. + * + * @param input The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNamedEntity(input, offset2) { + const { decodeTree } = this; + let current = decodeTree[this.treeIndex]; + let valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + while (offset2 < input.length) { + if (valueLength === 0 && (current & BinTrieFlags.FLAG13) !== 0) { + const runLength = (current & BinTrieFlags.BRANCH_LENGTH) >> 7; + if (this.runConsumed === 0) { + const firstChar = current & BinTrieFlags.JUMP_TABLE; + if (input.charCodeAt(offset2) !== firstChar) { + return this.result === 0 ? 0 : this.emitNotTerminatedNamedEntity(); + } + offset2++; + this.excess++; + this.runConsumed++; + } + while (this.runConsumed < runLength) { + if (offset2 >= input.length) { + return -1; + } + const charIndexInPacked = this.runConsumed - 1; + const packedWord = decodeTree[this.treeIndex + 1 + (charIndexInPacked >> 1)]; + const expectedChar = charIndexInPacked % 2 === 0 ? packedWord & 255 : packedWord >> 8 & 255; + if (input.charCodeAt(offset2) !== expectedChar) { + this.runConsumed = 0; + return this.result === 0 ? 0 : this.emitNotTerminatedNamedEntity(); + } + offset2++; + this.excess++; + this.runConsumed++; + } + this.runConsumed = 0; + this.treeIndex += 1 + (runLength >> 1); + current = decodeTree[this.treeIndex]; + valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + } + if (offset2 >= input.length) + break; + const char = input.charCodeAt(offset2); + if (char === CharCodes.SEMI && valueLength !== 0 && (current & BinTrieFlags.FLAG13) !== 0) { + return this.emitNamedEntityData(this.treeIndex, valueLength, this.consumed + this.excess); + } + this.treeIndex = determineBranch(decodeTree, current, this.treeIndex + Math.max(1, valueLength), char); + if (this.treeIndex < 0) { + return this.result === 0 || // If we are parsing an attribute + this.decodeMode === DecodingMode.Attribute && // We shouldn't have consumed any characters after the entity, + (valueLength === 0 || // And there should be no invalid characters. + isEntityInAttributeInvalidEnd(char)) ? 0 : this.emitNotTerminatedNamedEntity(); + } + current = decodeTree[this.treeIndex]; + valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + if (valueLength !== 0) { + if (char === CharCodes.SEMI) { + return this.emitNamedEntityData(this.treeIndex, valueLength, this.consumed + this.excess); + } + if (this.decodeMode !== DecodingMode.Strict && (current & BinTrieFlags.FLAG13) === 0) { + this.result = this.treeIndex; + this.consumed += this.excess; + this.excess = 0; + } + } + offset2++; + this.excess++; + } + return -1; + } + /** + * Emit a named entity that was not terminated with a semicolon. + * + * @returns The number of characters consumed. + */ + emitNotTerminatedNamedEntity() { + var _a3; + const { result: result3, decodeTree } = this; + const valueLength = (decodeTree[result3] & BinTrieFlags.VALUE_LENGTH) >> 14; + this.emitNamedEntityData(result3, valueLength, this.consumed); + (_a3 = this.errors) === null || _a3 === void 0 ? void 0 : _a3.missingSemicolonAfterCharacterReference(); + return this.consumed; + } + /** + * Emit a named entity. + * + * @param result The index of the entity in the decode tree. + * @param valueLength The number of bytes in the entity. + * @param consumed The number of characters consumed. + * + * @returns The number of characters consumed. + */ + emitNamedEntityData(result3, valueLength, consumed) { + const { decodeTree } = this; + this.emitCodePoint(valueLength === 1 ? decodeTree[result3] & ~(BinTrieFlags.VALUE_LENGTH | BinTrieFlags.FLAG13) : decodeTree[result3 + 1], consumed); + if (valueLength === 3) { + this.emitCodePoint(decodeTree[result3 + 2], consumed); + } + return consumed; + } + /** + * Signal to the parser that the end of the input was reached. + * + * Remaining data will be emitted and relevant errors will be produced. + * + * @returns The number of characters consumed. + */ + end() { + var _a3; + switch (this.state) { + case EntityDecoderState.NamedEntity: { + return this.result !== 0 && (this.decodeMode !== DecodingMode.Attribute || this.result === this.treeIndex) ? this.emitNotTerminatedNamedEntity() : 0; + } + // Otherwise, emit a numeric entity if we have one. + case EntityDecoderState.NumericDecimal: { + return this.emitNumericEntity(0, 2); + } + case EntityDecoderState.NumericHex: { + return this.emitNumericEntity(0, 3); + } + case EntityDecoderState.NumericStart: { + (_a3 = this.errors) === null || _a3 === void 0 ? void 0 : _a3.absenceOfDigitsInNumericCharacterReference(this.consumed); + return 0; + } + case EntityDecoderState.EntityStart: { + return 0; + } + } + } + }; + htmlDecoder = /* @__PURE__ */ getDecoder(htmlDecodeTree); + xmlDecoder = /* @__PURE__ */ getDecoder(xmlDecodeTree); + } +}); + +// node_modules/entities/dist/esm/escape.js +function getEscaper(regex, map) { + return function escape2(data2) { + let match; + let lastIndex = 0; + let result3 = ""; + while (match = regex.exec(data2)) { + if (lastIndex !== match.index) { + result3 += data2.substring(lastIndex, match.index); + } + result3 += map.get(match[0].charCodeAt(0)); + lastIndex = match.index + 1; + } + return result3 + data2.substring(lastIndex); + }; +} +var getCodePoint, escapeText; +var init_escape = __esm({ + "node_modules/entities/dist/esm/escape.js"() { + getCodePoint = // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + String.prototype.codePointAt == null ? (c, index) => (c.charCodeAt(index) & 64512) === 55296 ? (c.charCodeAt(index) - 55296) * 1024 + c.charCodeAt(index + 1) - 56320 + 65536 : c.charCodeAt(index) : ( + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + (input, index) => input.codePointAt(index) + ); + escapeText = /* @__PURE__ */ getEscaper(/[&<>\u00A0]/g, /* @__PURE__ */ new Map([ + [38, "&"], + [60, "<"], + [62, ">"], + [160, " "] + ])); + } +}); + +// node_modules/entities/dist/esm/internal/encode-shared.js +var init_encode_shared = __esm({ + "node_modules/entities/dist/esm/internal/encode-shared.js"() { + } +}); + +// node_modules/entities/dist/esm/generated/encode-html.js +var init_encode_html = __esm({ + "node_modules/entities/dist/esm/generated/encode-html.js"() { + init_encode_shared(); + } +}); + +// node_modules/entities/dist/esm/encode.js +var init_encode = __esm({ + "node_modules/entities/dist/esm/encode.js"() { + init_escape(); + init_encode_html(); + } +}); + +// node_modules/entities/dist/esm/index.js +var EntityLevel, EncodingMode; +var init_esm = __esm({ + "node_modules/entities/dist/esm/index.js"() { + init_decode(); + init_encode(); + init_escape(); + init_decode(); + init_encode(); + init_escape(); + (function(EntityLevel2) { + EntityLevel2[EntityLevel2["XML"] = 0] = "XML"; + EntityLevel2[EntityLevel2["HTML"] = 1] = "HTML"; + })(EntityLevel || (EntityLevel = {})); + (function(EncodingMode2) { + EncodingMode2[EncodingMode2["UTF8"] = 0] = "UTF8"; + EncodingMode2[EncodingMode2["ASCII"] = 1] = "ASCII"; + EncodingMode2[EncodingMode2["Extensive"] = 2] = "Extensive"; + EncodingMode2[EncodingMode2["Attribute"] = 3] = "Attribute"; + EncodingMode2[EncodingMode2["Text"] = 4] = "Text"; + })(EncodingMode || (EncodingMode = {})); + } +}); + +// node_modules/happy-dom/lib/utilities/XMLEncodeUtility.js +var ENCODE_XML_ATTR_REGEXP, ENCODE_HTML_ATTR_REGEXP, DECODE_TEXT_CONTENT_REGEXP, ENCODE_XML_ATTR_MAP, ENCODE_HTML_ATTR_MAP, DECODE_TEXT_CONTENT_MAP, XMLEncodeUtility; +var init_XMLEncodeUtility = __esm({ + "node_modules/happy-dom/lib/utilities/XMLEncodeUtility.js"() { + init_esm(); + ENCODE_XML_ATTR_REGEXP = /[&"<>\t\n\r]/g; + ENCODE_HTML_ATTR_REGEXP = /[&"]/g; + DECODE_TEXT_CONTENT_REGEXP = /&(?:nbsp|lt|gt|amp);/g; + ENCODE_XML_ATTR_MAP = { + "&": "&", + '"': """, + "<": "<", + ">": ">", + " ": " ", + "\n": " ", + "\r": " " + }; + ENCODE_HTML_ATTR_MAP = { + "&": "&", + '"': """ + }; + DECODE_TEXT_CONTENT_MAP = { + " ": String.fromCharCode(160), + "<": "<", + ">": ">", + "&": "&" + }; + XMLEncodeUtility = class { + /** + * Encodes attribute value. + * + * @param value Value. + * @returns Escaped value. + */ + static encodeXMLAttributeValue(value2) { + if (value2 === null) { + return ""; + } + return value2.replace(ENCODE_XML_ATTR_REGEXP, (char) => ENCODE_XML_ATTR_MAP[char]); + } + /** + * Decodes attribute value. + * + * Uses the 'entities' library for comprehensive XML character reference support. + * + * @param value Value. + * @returns Decoded value. + */ + static decodeXMLAttributeValue(value2) { + if (value2 === null) { + return ""; + } + return decodeXML(value2); + } + /** + * Encodes attribute value. + * + * @param value Value. + * @returns Escaped value. + */ + static encodeHTMLAttributeValue(value2) { + if (value2 === null) { + return ""; + } + return value2.replace(ENCODE_HTML_ATTR_REGEXP, (char) => ENCODE_HTML_ATTR_MAP[char]); + } + /** + * Decodes attribute value. + * + * Uses the 'entities' library for comprehensive HTML5 character reference support, + * including named entities, decimal numeric references ("), and + * hexadecimal numeric references ("). + * + * @param value Value. + * @returns Decoded value. + */ + static decodeHTMLAttributeValue(value2) { + if (value2 === null) { + return ""; + } + return decodeHTMLAttribute(value2); + } + /** + * Encodes text content. + * + * Uses the 'entities' library which follows the WHATWG HTML serialization spec. + * Encodes &, <, >, and non-breaking space. + * + * @param text Value. + * @returns Escaped value. + */ + static encodeTextContent(text) { + if (text === null) { + return ""; + } + return escapeText(text); + } + /** + * Decodes text content. + * + * @param text Value. + * @returns Decoded value. + */ + static decodeTextContent(text) { + if (text === null) { + return ""; + } + return text.replace(DECODE_TEXT_CONTENT_REGEXP, (entity) => DECODE_TEXT_CONTENT_MAP[entity]); + } + /** + * Decodes HTML entities. + * + * Uses the 'entities' library for comprehensive HTML5 named character reference support. + * + * @param value Value. + * @returns Decoded value. + */ + static decodeHTMLEntities(value2) { + if (value2 === null) { + return ""; + } + return decodeHTML(value2); + } + /** + * Decodes XML entities. + * + * Uses the 'entities' library for comprehensive XML character reference support, + * including named entities and numeric references. + * + * @param value Value. + * @returns Decoded value. + */ + static decodeXMLEntities(value2) { + if (value2 === null) { + return ""; + } + return decodeXML(value2); + } + }; + } +}); + +// node_modules/happy-dom/lib/html-serializer/HTMLSerializer.js +var HTMLSerializer; +var init_HTMLSerializer = __esm({ + "node_modules/happy-dom/lib/html-serializer/HTMLSerializer.js"() { + init_PropertySymbol(); + init_Node(); + init_NodeTypeEnum(); + init_HTMLElementConfig(); + init_HTMLElementConfigContentModelEnum(); + init_XMLEncodeUtility(); + HTMLSerializer = class { + options = { + serializableShadowRoots: false, + shadowRoots: null, + allShadowRoots: false, + excludeShadowRootTags: null + }; + /** + * Constructor. + * + * @param [options] Options. + * @param [options.serializableShadowRoots] If shadow roots should be serialized. + * @param [options.shadowRoots] Shadow roots to serialize. + * @param [options.allShadowRoots] If all shadow roots should be serialized. + * @param [options.excludeShadowRootTags] Tags to exclude from serialization. + */ + constructor(options2) { + if (options2) { + if (options2.serializableShadowRoots) { + this.options.serializableShadowRoots = options2.serializableShadowRoots; + } + if (options2.shadowRoots) { + this.options.shadowRoots = options2.shadowRoots; + } + if (options2.allShadowRoots) { + this.options.allShadowRoots = options2.allShadowRoots; + } + if (options2.excludeShadowRootTags) { + this.options.excludeShadowRootTags = options2.excludeShadowRootTags; + } + } + } + /** + * Renders an element as HTML. + * + * @param root Root element. + * @returns Result. + */ + serializeToString(root2) { + switch (root2[nodeType]) { + case NodeTypeEnum_default.elementNode: + const element = root2; + const prefix2 = element[prefix]; + const localName2 = element[localName]; + const config = HTMLElementConfig_default[element[localName]]; + const tagName2 = prefix2 ? `${prefix2}:${localName2}` : localName2; + if (config?.contentModel === HTMLElementConfigContentModelEnum_default.noDescendants) { + return `<${tagName2}${this.getAttributes(element)}>`; + } + let innerHTML = ""; + if (element.shadowRoot && (this.options.allShadowRoots || this.options.serializableShadowRoots && element.shadowRoot[serializable] || this.options.shadowRoots?.includes(element.shadowRoot)) && (!this.options.excludeShadowRootTags || !this.options.excludeShadowRootTags.includes(tagName2))) { + innerHTML += `"; + } + const childNodes2 = tagName2 === "template" ? root2.content[nodeArray] : root2[nodeArray]; + for (const node of childNodes2) { + innerHTML += this.serializeToString(node); + } + return `<${tagName2}${this.getAttributes(element)}>${innerHTML}`; + case Node.DOCUMENT_FRAGMENT_NODE: + case Node.DOCUMENT_NODE: + let html = ""; + for (const node of root2[nodeArray]) { + html += this.serializeToString(node); + } + return html; + case NodeTypeEnum_default.commentNode: + return ``; + case NodeTypeEnum_default.processingInstructionNode: + return ``; + case NodeTypeEnum_default.textNode: + const parentElement = root2.parentElement; + if (parentElement) { + const parentConfig = HTMLElementConfig_default[parentElement[localName]]; + if (parentConfig?.contentModel === HTMLElementConfigContentModelEnum_default.rawText) { + return root2.textContent; + } + } + return XMLEncodeUtility.encodeTextContent(root2.textContent); + case NodeTypeEnum_default.documentTypeNode: + const doctype = root2; + const identifier = doctype.publicId ? " PUBLIC" : doctype.systemId ? " SYSTEM" : ""; + const publicId2 = doctype.publicId ? ` "${doctype.publicId}"` : ""; + const systemId2 = doctype.systemId ? ` "${doctype.systemId}"` : ""; + return ``; + } + return ""; + } + /** + * Returns attributes as a string. + * + * @param element Element. + * @returns Attributes. + */ + getAttributes(element) { + let attributeString = ""; + const attributes2 = element[attributes][items]; + if (!attributes2.has(":is") && element[isValue]) { + attributeString += ' is="' + XMLEncodeUtility.encodeHTMLAttributeValue(element[isValue]) + '"'; + } + for (const attribute of attributes2.values()) { + const escapedValue = XMLEncodeUtility.encodeHTMLAttributeValue(attribute[value]); + attributeString += " " + attribute[name] + '="' + escapedValue + '"'; + } + return attributeString; + } + }; + } +}); + +// node_modules/happy-dom/lib/config/SVGElementConfig.js +var SVGElementConfig_default; +var init_SVGElementConfig = __esm({ + "node_modules/happy-dom/lib/config/SVGElementConfig.js"() { + SVGElementConfig_default = { + svg: { localName: "svg", className: "SVGSVGElement" }, + animate: { localName: "animate", className: "SVGAnimateElement" }, + animatemotion: { localName: "animateMotion", className: "SVGAnimateMotionElement" }, + animatetransform: { localName: "animateTransform", className: "SVGAnimateTransformElement" }, + circle: { localName: "circle", className: "SVGCircleElement" }, + clippath: { localName: "clipPath", className: "SVGClipPathElement" }, + defs: { localName: "defs", className: "SVGDefsElement" }, + desc: { localName: "desc", className: "SVGDescElement" }, + ellipse: { localName: "ellipse", className: "SVGEllipseElement" }, + feblend: { localName: "feBlend", className: "SVGFEBlendElement" }, + fecolormatrix: { localName: "feColorMatrix", className: "SVGFEColorMatrixElement" }, + fecomponenttransfer: { + localName: "feComponentTransfer", + className: "SVGFEComponentTransferElement" + }, + fecomposite: { localName: "feComposite", className: "SVGFECompositeElement" }, + feconvolvematrix: { localName: "feConvolveMatrix", className: "SVGFEConvolveMatrixElement" }, + fediffuselighting: { localName: "feDiffuseLighting", className: "SVGFEDiffuseLightingElement" }, + fedisplacementmap: { localName: "feDisplacementMap", className: "SVGFEDisplacementMapElement" }, + fedistantlight: { localName: "feDistantLight", className: "SVGFEDistantLightElement" }, + fedropshadow: { localName: "feDropShadow", className: "SVGFEDropShadowElement" }, + feflood: { localName: "feFlood", className: "SVGFEFloodElement" }, + fefunca: { localName: "feFuncA", className: "SVGFEFuncAElement" }, + fefuncb: { localName: "feFuncB", className: "SVGFEFuncBElement" }, + fefuncg: { localName: "feFuncG", className: "SVGFEFuncGElement" }, + fefuncr: { localName: "feFuncR", className: "SVGFEFuncRElement" }, + fegaussianblur: { localName: "feGaussianBlur", className: "SVGFEGaussianBlurElement" }, + feimage: { localName: "feImage", className: "SVGFEImageElement" }, + femerge: { localName: "feMerge", className: "SVGFEMergeElement" }, + femergenode: { localName: "feMergeNode", className: "SVGFEMergeNodeElement" }, + femorphology: { localName: "feMorphology", className: "SVGFEMorphologyElement" }, + feoffset: { localName: "feOffset", className: "SVGFEOffsetElement" }, + fepointlight: { localName: "fePointLight", className: "SVGFEPointLightElement" }, + fespecularlighting: { + localName: "feSpecularLighting", + className: "SVGFESpecularLightingElement" + }, + fespotlight: { localName: "feSpotLight", className: "SVGFESpotLightElement" }, + fetile: { localName: "feTile", className: "SVGFETileElement" }, + feturbulence: { localName: "feTurbulence", className: "SVGFETurbulenceElement" }, + filter: { localName: "filter", className: "SVGFilterElement" }, + foreignobject: { localName: "foreignObject", className: "SVGForeignObjectElement" }, + g: { localName: "g", className: "SVGGElement" }, + image: { localName: "image", className: "SVGImageElement" }, + line: { localName: "line", className: "SVGLineElement" }, + lineargradient: { localName: "linearGradient", className: "SVGLinearGradientElement" }, + marker: { localName: "marker", className: "SVGMarkerElement" }, + mask: { localName: "mask", className: "SVGMaskElement" }, + metadata: { localName: "metadata", className: "SVGMetadataElement" }, + mpath: { localName: "mpath", className: "SVGMPathElement" }, + path: { localName: "path", className: "SVGPathElement" }, + pattern: { localName: "pattern", className: "SVGPatternElement" }, + polygon: { localName: "polygon", className: "SVGPolygonElement" }, + polyline: { localName: "polyline", className: "SVGPolylineElement" }, + radialgradient: { localName: "radialGradient", className: "SVGRadialGradientElement" }, + rect: { localName: "rect", className: "SVGRectElement" }, + script: { localName: "script", className: "SVGScriptElement" }, + set: { localName: "set", className: "SVGSetElement" }, + stop: { localName: "stop", className: "SVGStopElement" }, + style: { localName: "style", className: "SVGStyleElement" }, + switch: { localName: "switch", className: "SVGSwitchElement" }, + symbol: { localName: "symbol", className: "SVGSymbolElement" }, + text: { localName: "text", className: "SVGTextElement" }, + textpath: { localName: "textPath", className: "SVGTextPathElement" }, + title: { localName: "title", className: "SVGTitleElement" }, + tspan: { localName: "tspan", className: "SVGTSpanElement" }, + use: { localName: "use", className: "SVGUseElement" }, + view: { localName: "view", className: "SVGViewElement" } + }; + } +}); + +// node_modules/happy-dom/lib/html-parser/HTMLParser.js +var MARKUP_REGEXP, ATTRIBUTE_REGEXP, DOCUMENT_TYPE_ATTRIBUTE_REGEXP, SPACE_REGEXP2, SPACE_IN_BEGINNING_REGEXP, MarkupReadStateEnum, HTMLDocumentStructureLevelEnum, HTMLParser; +var init_HTMLParser = __esm({ + "node_modules/happy-dom/lib/html-parser/HTMLParser.js"() { + init_PropertySymbol(); + init_NamespaceURI(); + init_HTMLElementConfig(); + init_HTMLElementConfigContentModelEnum(); + init_SVGElementConfig(); + init_StringUtility(); + init_XMLEncodeUtility(); + init_NodeTypeEnum(); + init_NodeFactory(); + MARKUP_REGEXP = /<([^\s/!>?]+)|<\/([^\s/!>?]+)\s*>|(|--!>)|()|(>)/gm; + ATTRIBUTE_REGEXP = /\s*([a-zA-Z0-9-_:.$@?\\<\[\]]+)\s*=\s*([^"'=<>\\`\s]+)|\s*([a-zA-Z0-9-_:.$@?\\<\[\]]+)\s*=\s*"([^"]*)("{0,1})|\s*([a-zA-Z0-9-_:.$@?\\<\[\]]+)\s*=\s*'([^']*)('{0,1})|\s*([a-zA-Z0-9-_:.$@?\\<\[\]]+)/gm; + DOCUMENT_TYPE_ATTRIBUTE_REGEXP = /"([^"]+)"/gm; + SPACE_REGEXP2 = /\s+/; + SPACE_IN_BEGINNING_REGEXP = /^\s+/; + (function(MarkupReadStateEnum3) { + MarkupReadStateEnum3["any"] = "any"; + MarkupReadStateEnum3["startTag"] = "startTag"; + MarkupReadStateEnum3["comment"] = "comment"; + MarkupReadStateEnum3["documentType"] = "documentType"; + MarkupReadStateEnum3["processingInstruction"] = "processingInstruction"; + MarkupReadStateEnum3["rawTextElement"] = "rawTextElement"; + })(MarkupReadStateEnum || (MarkupReadStateEnum = {})); + (function(HTMLDocumentStructureLevelEnum2) { + HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["root"] = 0] = "root"; + HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["doctype"] = 1] = "doctype"; + HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["documentElement"] = 2] = "documentElement"; + HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["head"] = 3] = "head"; + HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["additionalHeadWithoutBody"] = 4] = "additionalHeadWithoutBody"; + HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["body"] = 5] = "body"; + HTMLDocumentStructureLevelEnum2[HTMLDocumentStructureLevelEnum2["afterBody"] = 6] = "afterBody"; + })(HTMLDocumentStructureLevelEnum || (HTMLDocumentStructureLevelEnum = {})); + HTMLParser = class { + window; + evaluateScripts = false; + isTemplateDocumentFragment = false; + rootNode = null; + rootDocument = null; + nodeStack = []; + tagNameStack = []; + documentStructure = null; + startTagIndex = 0; + markupRegExp = null; + nextElement = null; + currentNode = null; + readState = MarkupReadStateEnum.any; + /** + * Constructor. + * + * @param window Window. + * @param [options] Options. + * @param [options.evaluateScripts] Set to "true" to enable script execution + * @param [options.isTemplateDocumentFragment] Set to "true" if parsing a template content fragment. + */ + constructor(window2, options2) { + this.window = window2; + if (options2?.evaluateScripts) { + this.evaluateScripts = true; + } + if (options2?.isTemplateDocumentFragment) { + this.isTemplateDocumentFragment = true; + } + } + /** + * Parses HTML a root element containing nodes found. + * + * @param html HTML string. + * @param [rootNode] Root node. + * @returns Root node. + */ + parse(html, rootNode2) { + this.rootNode = rootNode2 || this.window.document.createDocumentFragment(); + this.rootDocument = this.rootNode[nodeType] === NodeTypeEnum_default.documentNode ? this.rootNode : this.window.document; + this.nodeStack = [this.rootNode]; + this.tagNameStack = [null]; + this.currentNode = this.rootNode; + this.readState = MarkupReadStateEnum.any; + this.documentStructure = null; + this.startTagIndex = 0; + this.markupRegExp = new RegExp(MARKUP_REGEXP); + if (this.rootNode[nodeType] === NodeTypeEnum_default.documentNode) { + const { doctype, documentElement, head, body: body2 } = this.rootNode; + if (!documentElement || !head || !body2) { + throw new Error('Failed to parse HTML: The root node must have "documentElement", "head" and "body".\n\nWe should not end up here and it is therefore a bug in Happy DOM. Please report this issue.'); + } + this.documentStructure = { + nodes: { + doctype: doctype || null, + documentElement, + head, + body: body2 + }, + level: HTMLDocumentStructureLevelEnum.root + }; + } + if (this.rootNode instanceof this.window.HTMLHtmlElement) { + const head = this.rootDocument.createElement("head"); + const body2 = this.rootDocument.createElement("body"); + while (this.rootNode[nodeArray].length > 0) { + this.rootNode[removeChild](this.rootNode[nodeArray][this.rootNode[nodeArray].length - 1]); + } + this.rootNode[appendChild](head); + this.rootNode[appendChild](body2); + this.documentStructure = { + nodes: { + doctype: null, + documentElement: this.rootNode, + head, + body: body2 + }, + level: HTMLDocumentStructureLevelEnum.documentElement + }; + } + let match; + let lastIndex = 0; + html = String(html); + while (match = this.markupRegExp.exec(html)) { + switch (this.readState) { + case MarkupReadStateEnum.any: + if (match.index !== lastIndex && (match[1] || match[2] || match[3] || match[4] || match[5] !== void 0 || match[6])) { + this.parsePlainText(html.substring(lastIndex, match.index)); + } + if (match[1]) { + this.nextElement = this.getStartTagElement(match[1]); + this.startTagIndex = this.markupRegExp.lastIndex; + this.readState = MarkupReadStateEnum.startTag; + } else if (match[2]) { + this.parseEndTag(match[2]); + } else if (match[3]) { + this.startTagIndex = this.markupRegExp.lastIndex; + this.readState = MarkupReadStateEnum.comment; + } else if (match[5] !== void 0) { + this.startTagIndex = this.markupRegExp.lastIndex; + this.readState = MarkupReadStateEnum.documentType; + } else if (match[6]) { + this.startTagIndex = this.markupRegExp.lastIndex; + this.readState = MarkupReadStateEnum.processingInstruction; + } else { + this.parsePlainText(html.substring(lastIndex, this.markupRegExp.lastIndex)); + } + break; + case MarkupReadStateEnum.startTag: + if (match[7] || match[8] || match[2]) { + if (this.nextElement) { + const attributeString = html.substring(this.startTagIndex, match[2] ? this.markupRegExp.lastIndex - 1 : match.index); + const isSelfClosed = !!match[7]; + this.parseEndOfStartTag(attributeString, isSelfClosed); + } else { + this.readState = MarkupReadStateEnum.any; + } + } + break; + case MarkupReadStateEnum.comment: + if (match[4]) { + this.parseComment(html.substring(this.startTagIndex, match.index)); + } + break; + case MarkupReadStateEnum.documentType: + if (match[7] || match[8]) { + this.parseDocumentType(html.substring(this.startTagIndex, match.index)); + } + break; + case MarkupReadStateEnum.processingInstruction: + if (match[7] || match[8]) { + this.parseComment("?" + html.substring(this.startTagIndex, match.index)); + } + break; + case MarkupReadStateEnum.rawTextElement: + if (match[2]) { + this.parseRawTextElementContent(match[2], html.substring(this.startTagIndex, match.index)); + } + break; + } + lastIndex = this.markupRegExp.lastIndex; + } + if (lastIndex !== html.length && this.currentNode) { + this.parsePlainText(html.substring(lastIndex)); + } + return this.rootNode; + } + /** + * Parses plain text. + * + * @param text Text. + */ + parsePlainText(text) { + if (this.documentStructure) { + const level = this.documentStructure.level; + const { documentElement, head, body: body2 } = this.documentStructure.nodes; + const htmlText = (this.currentNode === this.rootNode || this.currentNode === documentElement) && level < HTMLDocumentStructureLevelEnum.head && body2[elementArray].length === 0 ? text.replace(SPACE_IN_BEGINNING_REGEXP, "") : text; + if (htmlText) { + const textNode = this.rootDocument.createTextNode(XMLEncodeUtility.decodeHTMLEntities(htmlText)); + if (this.currentNode === head && level === HTMLDocumentStructureLevelEnum.additionalHeadWithoutBody) { + documentElement[insertBefore](textNode, body2, true); + } else if (this.currentNode === this.rootNode || this.currentNode === documentElement || this.currentNode === head && level >= HTMLDocumentStructureLevelEnum.body) { + if (level === HTMLDocumentStructureLevelEnum.head) { + documentElement[insertBefore](textNode, body2, true); + } else if (body2.lastChild?.[nodeType] === NodeTypeEnum_default.textNode) { + body2.lastChild[data] += text; + } else { + body2[appendChild](textNode, true); + } + } else { + this.currentNode[appendChild](textNode, true); + } + } + } else { + const textNode = this.rootDocument.createTextNode(XMLEncodeUtility.decodeHTMLEntities(text)); + this.currentNode[appendChild](textNode, true); + } + } + /** + * Parses end of start tag. + * + * @param attributeString Attribute string. + * @param isSelfClosed Is self closed. + */ + parseEndOfStartTag(attributeString, isSelfClosed) { + if (attributeString && (!this.documentStructure || this.nextElement !== this.documentStructure.nodes.head || this.documentStructure.level < HTMLDocumentStructureLevelEnum.body)) { + const attributeRegexp = new RegExp(ATTRIBUTE_REGEXP); + let attributeMatch; + while (attributeMatch = attributeRegexp.exec(attributeString)) { + if (attributeMatch[1] && attributeMatch[2] || attributeMatch[3] && attributeMatch[5] === '"' || attributeMatch[6] && attributeMatch[8] === "'" || attributeMatch[9]) { + const name2 = attributeMatch[1] || attributeMatch[3] || attributeMatch[6] || attributeMatch[9] || ""; + const rawValue = attributeMatch[2] || attributeMatch[4] || attributeMatch[7] || ""; + const value2 = rawValue ? XMLEncodeUtility.decodeHTMLAttributeValue(rawValue) : ""; + const attributes2 = this.nextElement[attributes]; + if (this.nextElement[namespaceURI] === NamespaceURI_default.svg) { + const nameParts = name2.split(":"); + let namespaceURI2 = null; + switch (nameParts[0]) { + case "xmlns": + namespaceURI2 = !nameParts[1] || nameParts[1] === "xlink" ? NamespaceURI_default.xmlns : null; + break; + case "xlink": + namespaceURI2 = NamespaceURI_default.xlink; + break; + } + if (!attributes2.getNamedItemNS(namespaceURI2, nameParts[1] ?? name2)) { + const attribute = NodeFactory.createNode(this.rootDocument, this.window.Attr); + attribute[namespaceURI] = namespaceURI2; + attribute[name] = name2; + attribute[localName] = namespaceURI2 && nameParts[1] ? nameParts[1] : name2; + attribute[prefix] = namespaceURI2 && nameParts[1] ? nameParts[0] : null; + attribute[value] = value2; + attributes2[setNamedItem](attribute); + } + } else if (!attributes2.getNamedItem(name2)) { + const attributeItem = this.rootDocument.createAttribute(name2); + attributeItem[value] = value2; + attributes2[setNamedItem](attributeItem); + } + this.startTagIndex += attributeMatch[0].length; + } else if (!attributeMatch[1] && (attributeMatch[3] && !attributeMatch[5] || attributeMatch[6] && !attributeMatch[8])) { + return; + } + } + } + const tagName2 = this.nextElement[tagName]; + const lowerTagName = tagName2.toLowerCase(); + const config = HTMLElementConfig_default[lowerTagName]; + let previousCurrentNode = null; + while (previousCurrentNode !== this.rootNode) { + const parentLowerTagName = this.currentNode[tagName]?.toLowerCase(); + const parentConfig = parentLowerTagName ? HTMLElementConfig_default[parentLowerTagName] : null; + if (previousCurrentNode === this.currentNode) { + throw new Error("Failed to parse HTML: The parser is stuck in an infinite loop. Please report this issue."); + } + previousCurrentNode = this.currentNode; + if (config?.contentModel === HTMLElementConfigContentModelEnum_default.noFirstLevelSelfDescendants && this.tagNameStack[this.tagNameStack.length - 1] === tagName2 || parentConfig?.contentModel === HTMLElementConfigContentModelEnum_default.textOrComments || parentConfig?.contentModel === HTMLElementConfigContentModelEnum_default.noForbiddenFirstLevelDescendants && parentConfig?.forbiddenDescendants?.includes(lowerTagName) || parentConfig?.contentModel === HTMLElementConfigContentModelEnum_default.permittedDescendants && !parentConfig?.permittedDescendants?.includes(lowerTagName) && (!config || !config.addPermittedParent || HTMLElementConfig_default[config.addPermittedParent].permittedParents && !HTMLElementConfig_default[config.addPermittedParent].permittedParents.includes(parentLowerTagName) || HTMLElementConfig_default[config.addPermittedParent].permittedDescendants && !HTMLElementConfig_default[config.addPermittedParent].permittedDescendants.includes(lowerTagName))) { + if (parentConfig?.contentModel === HTMLElementConfigContentModelEnum_default.permittedDescendants && parentConfig.moveForbiddenDescendant && !parentConfig.moveForbiddenDescendant.exclude.includes(lowerTagName)) { + let before = this.currentNode; + while (before) { + if (!before.parentNode || !HTMLElementConfig_default[before.parentNode[localName]]?.permittedDescendants || HTMLElementConfig_default[before.parentNode[localName]]?.permittedDescendants?.includes(lowerTagName)) { + break; + } else { + before = before.parentNode; + } + } + if (before && before.parentNode) { + before.parentNode.insertBefore(this.nextElement, before); + } else { + before.appendChild(this.nextElement); + } + this.startTagIndex = this.markupRegExp.lastIndex; + this.readState = MarkupReadStateEnum.any; + return; + } + this.nodeStack.pop(); + this.tagNameStack.pop(); + this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode; + } else if (config?.contentModel === HTMLElementConfigContentModelEnum_default.noSelfDescendants && this.tagNameStack.includes(tagName2)) { + while (this.currentNode !== this.rootNode) { + if (this.currentNode[tagName] === tagName2) { + this.nodeStack.pop(); + this.tagNameStack.pop(); + this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode; + break; + } + this.nodeStack.pop(); + this.tagNameStack.pop(); + this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode; + } + } else if (!this.isTemplateDocumentFragment && config?.permittedParents && !config.permittedParents.includes(parentLowerTagName)) { + if (!config.addPermittedParent || HTMLElementConfig_default[config.addPermittedParent].permittedParents && !HTMLElementConfig_default[config.addPermittedParent].permittedParents.includes(parentLowerTagName) || HTMLElementConfig_default[config.addPermittedParent].permittedDescendants && !HTMLElementConfig_default[config.addPermittedParent].permittedDescendants.includes(lowerTagName)) { + this.readState = MarkupReadStateEnum.any; + this.startTagIndex = this.markupRegExp.lastIndex; + return; + } + const permittedParent = this.rootDocument.createElement(config.addPermittedParent); + this.currentNode[appendChild](permittedParent, true); + this.nodeStack.push(permittedParent); + this.tagNameStack.push(permittedParent[tagName]); + this.currentNode = permittedParent; + } else { + break; + } + } + if (this.documentStructure) { + const { documentElement, head, body: body2 } = this.documentStructure.nodes; + const level = this.documentStructure.level; + if ((!config || config.contentModel !== HTMLElementConfigContentModelEnum_default.rawText) && this.nextElement !== documentElement && this.nextElement !== head && this.nextElement !== body2) { + if (documentElement && (this.currentNode === this.rootNode || this.currentNode === documentElement || this.currentNode === head && level >= HTMLDocumentStructureLevelEnum.body)) { + if (level < HTMLDocumentStructureLevelEnum.body) { + this.documentStructure.level = HTMLDocumentStructureLevelEnum.afterBody; + } + body2[appendChild](this.nextElement, true); + } else { + this.currentNode[appendChild](this.nextElement, true); + } + } + } else { + this.currentNode[appendChild](this.nextElement, true); + } + if (!this.documentStructure || this.nextElement !== this.documentStructure.nodes.body || this.documentStructure.level <= HTMLDocumentStructureLevelEnum.body) { + this.currentNode = this.nextElement; + this.nodeStack.push(this.currentNode); + this.tagNameStack.push(tagName2); + if (this.documentStructure && this.nextElement === this.documentStructure.nodes.body) { + this.documentStructure.level = HTMLDocumentStructureLevelEnum.afterBody; + } + if (config?.contentModel === HTMLElementConfigContentModelEnum_default.noDescendants || isSelfClosed && this.currentNode[namespaceURI] === NamespaceURI_default.svg) { + this.nodeStack.pop(); + this.tagNameStack.pop(); + this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode; + this.readState = MarkupReadStateEnum.any; + } else { + this.readState = config?.contentModel === HTMLElementConfigContentModelEnum_default.rawText ? MarkupReadStateEnum.rawTextElement : MarkupReadStateEnum.any; + } + } else { + this.readState = MarkupReadStateEnum.any; + } + this.startTagIndex = this.markupRegExp.lastIndex; + } + /** + * Parses end tag. + * + * @param tagName Tag name. + */ + parseEndTag(tagName2) { + const name2 = this.currentNode[namespaceURI] === NamespaceURI_default.html ? StringUtility.asciiUpperCase(tagName2) : SVGElementConfig_default[StringUtility.asciiLowerCase(tagName2)]?.localName || tagName2; + const index = this.tagNameStack.lastIndexOf(name2); + if (index !== -1) { + this.nodeStack.splice(index, this.nodeStack.length - index); + this.tagNameStack.splice(index, this.tagNameStack.length - index); + this.currentNode = this.nodeStack[this.nodeStack.length - 1] || this.rootNode; + } + } + /** + * Parses comment. + * + * @param comment Comment. + */ + parseComment(comment) { + const commentNode = this.rootDocument.createComment(XMLEncodeUtility.decodeHTMLEntities(comment)); + if (this.documentStructure) { + const level = this.documentStructure.level; + const { documentElement, head, body: body2 } = this.documentStructure.nodes; + let beforeNode = null; + if (this.currentNode === this.rootNode && level === HTMLDocumentStructureLevelEnum.root) { + beforeNode = documentElement; + } else if (this.currentNode === documentElement && level === HTMLDocumentStructureLevelEnum.documentElement) { + beforeNode = head; + } else if (this.currentNode === documentElement && level === HTMLDocumentStructureLevelEnum.head) { + beforeNode = body2; + } + this.currentNode[insertBefore](commentNode, beforeNode, true); + } else { + this.currentNode[appendChild](commentNode, true); + } + this.readState = MarkupReadStateEnum.any; + } + /** + * Parses document type. + * + * @param text Text. + */ + parseDocumentType(text) { + const decodedText = XMLEncodeUtility.decodeHTMLEntities(text); + if (this.documentStructure) { + let { doctype } = this.documentStructure.nodes; + const documentType = this.getDocumentType(decodedText); + if (documentType) { + if (this.currentNode === this.rootNode && this.documentStructure.level === HTMLDocumentStructureLevelEnum.root) { + if (doctype) { + doctype[name] = documentType.name; + doctype[publicId] = documentType.publicId; + doctype[systemId] = documentType.systemId; + } else { + doctype = this.rootNode.implementation.createDocumentType(documentType.name, documentType.publicId, documentType.systemId); + this.rootNode.insertBefore(doctype, this.rootNode.documentElement); + } + this.documentStructure.level = HTMLDocumentStructureLevelEnum.doctype; + } + } else { + this.parseComment(decodedText); + } + } else { + if (!this.getDocumentType(decodedText)) { + this.parseComment(decodedText); + } + } + this.readState = MarkupReadStateEnum.any; + } + /** + * Parses raw text content for elements such as \r - \r -\r +`, "latin1"); + } else { + socket.write(`${header}\r +`, "latin1"); + } + } else if (contentLength2 === null) { + socket.write("\r\n0\r\n\r\n", "latin1"); + } + if (contentLength2 !== null && bytesWritten !== contentLength2) { + if (client[kStrictContentLength]) { + throw new RequestContentLengthMismatchError(); + } else { + process.emitWarning(new RequestContentLengthMismatchError()); + } + } + if (socket[kParser].timeout && socket[kParser].timeoutType === TIMEOUT_HEADERS) { + if (socket[kParser].timeout.refresh) { + socket[kParser].timeout.refresh(); + } + } + client[kResume](); + } + /** + * @param {Error} [err] + * @returns {void} + */ + destroy(err) { + const { socket, client, abort: abort2 } = this; + socket[kWriting] = false; + if (err) { + assert(client[kRunning] <= 1, "pipeline should only contain this request"); + abort2(err); + } + } + }; + module2.exports = connectH1; + } +}); + +// node_modules/undici/lib/dispatcher/client-h2.js +var require_client_h2 = __commonJS({ + "node_modules/undici/lib/dispatcher/client-h2.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { pipeline } = require("node:stream"); + var util = require_util(); + var { + RequestContentLengthMismatchError, + RequestAbortedError, + SocketError, + InformationalError, + InvalidArgumentError, + HeadersTimeoutError, + BodyTimeoutError + } = require_errors2(); + var { + kUrl, + kReset, + kClient, + kRunning, + kPending, + kQueue, + kPendingIdx, + kRunningIdx, + kError, + kSocket, + kStrictContentLength, + kOnError, + kMaxConcurrentStreams, + kHTTP2Session, + kHostAuthority, + kResume, + kSize, + kHTTPContext, + kClosed, + kKeepAliveDefaultTimeout, + kHeadersTimeout, + kBodyTimeout, + kEnableConnectProtocol, + kRemoteSettings, + kHTTP2Stream, + kHTTP2SessionState, + kHTTP2Options + } = require_symbols(); + var { channels } = require_diagnostics(); + var kOpenStreams = /* @__PURE__ */ Symbol("open streams"); + var kRequestStreamId = /* @__PURE__ */ Symbol("request stream id"); + var kRequestStream = /* @__PURE__ */ Symbol("request stream"); + var kRequestStreamCleanup = /* @__PURE__ */ Symbol("request stream cleanup"); + var kRequestStreamState = /* @__PURE__ */ Symbol("request stream state"); + var kReceivedGoAway = /* @__PURE__ */ Symbol("received goaway"); + var kGoAwayReplayAttempts = /* @__PURE__ */ Symbol("goaway replay attempts"); + var kRefusedStreamRetry = /* @__PURE__ */ Symbol("refused stream retry"); + var MAX_GOAWAY_REPLAY_ATTEMPTS = 1; + var extractBody; + var http2; + try { + http2 = require("node:http2"); + } catch { + http2 = { constants: {} }; + } + var { + constants: { + HTTP2_HEADER_AUTHORITY, + HTTP2_HEADER_METHOD, + HTTP2_HEADER_PATH, + HTTP2_HEADER_SCHEME, + HTTP2_HEADER_CONTENT_LENGTH, + HTTP2_HEADER_EXPECT, + HTTP2_HEADER_STATUS, + HTTP2_HEADER_PROTOCOL, + NGHTTP2_NO_ERROR, + NGHTTP2_REFUSED_STREAM + } + } = http2; + function getGoAwayError(session, errorCode) { + return session[kError] || (errorCode === NGHTTP2_NO_ERROR ? new InformationalError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`) : new SocketError(`HTTP/2: "GOAWAY" frame received with code ${errorCode}`, util.getSocketInfo(session[kSocket]))); + } + function resetHttp2Session(session, err) { + const client = session[kClient]; + const socket = session[kSocket]; + if (client[kHTTP2Session] === session) { + client[kSocket] = null; + client[kHTTPContext] = null; + client[kHTTP2Session] = null; + } + if (socket != null && socket[kError] == null) { + socket[kError] = err; + } + if (!session.closed && !session.destroyed) { + try { + session.destroy(err); + } catch { + } + } + util.destroy(socket, err); + } + function getGoAwayPendingIdx(client, lastStreamID) { + const maxAcceptedStreamID = Number.isInteger(lastStreamID) ? lastStreamID : Number.MAX_SAFE_INTEGER; + for (let i = client[kRunningIdx]; i < client[kPendingIdx]; i++) { + const request = client[kQueue][i]; + if (request == null) { + continue; + } + if (typeof request[kRequestStreamId] !== "number" || request[kRequestStreamId] > maxAcceptedStreamID) { + return i; + } + } + return client[kPendingIdx]; + } + function detachRequestFromStream(request) { + request[kRequestStreamId] = null; + request[kRequestStream] = null; + request[kRequestStreamCleanup] = null; + } + function bindRequestToStream(request, stream, cleanup) { + const previousCleanup = request[kRequestStreamCleanup]; + const previousStream = request[kRequestStream]; + detachRequestFromStream(request); + previousCleanup?.(previousStream); + request[kRequestStreamId] = stream.id; + request[kRequestStream] = stream; + request[kRequestStreamCleanup] = cleanup; + } + function clearRequestStream(request) { + const cleanup = request[kRequestStreamCleanup]; + const stream = request[kRequestStream]; + detachRequestFromStream(request); + cleanup?.(stream); + } + function requeueUnsentRequest(client, request) { + client[kQueue].splice(client[kPendingIdx] + 1, 0, request); + } + function completeRequest(client, request, resetPendingIdx = false) { + const queue = client[kQueue]; + const runningIdx = client[kRunningIdx]; + if (runningIdx < client[kPendingIdx] && queue[runningIdx] === request) { + queue[runningIdx] = null; + client[kRunningIdx] = runningIdx + 1; + return; + } + const index = queue.indexOf(request, runningIdx); + if (index === -1 || index >= client[kPendingIdx]) { + return; + } + queue.splice(index, 1); + client[kPendingIdx]--; + if (resetPendingIdx && client[kPendingIdx] < client[kRunningIdx]) { + client[kPendingIdx] = client[kRunningIdx]; + } + } + function canReplayRequest(request) { + const { body: body2 } = request; + return body2 == null || util.isBuffer(body2) || util.isBlobLike(body2); + } + function registerGoAwayRefusal(request) { + const attempts = (request[kGoAwayReplayAttempts] ?? 0) + 1; + request[kGoAwayReplayAttempts] = attempts; + return attempts <= MAX_GOAWAY_REPLAY_ATTEMPTS; + } + function closeStream(stream, code = NGHTTP2_REFUSED_STREAM) { + if (stream != null && !stream.destroyed && !stream.closed) { + try { + stream.close(code); + } catch { + } + } + } + function detachRequestStreamForClose(request) { + const stream = request[kRequestStream]; + clearRequestStream(request); + severRequestStream(stream); + return stream; + } + function severRequestStream(stream) { + if (stream == null || stream[kRequestStreamState] == null) { + return; + } + stream[kRequestStreamState] = null; + stream.off("close", completeRequestStream); + stream.off("close", onUpgradeStreamClose); + if (stream[kHTTP2Session] != null) { + closeStreamSession(stream); + } + if (!stream.destroyed && !stream.closed) { + stream.once("error", noop); + } + } + function connectH2(client, socket) { + client[kSocket] = socket; + const http2InitialWindowSize = client[kHTTP2Options].sessionOptions?.initialWindowSize; + const http2ConnectionWindowSize = client[kHTTP2Options].connectionWindowSize; + const session = http2.connect(client[kUrl], { + createConnection: () => socket, + peerMaxConcurrentStreams: client[kHTTP2Options].maxConcurrentStreams, + settings: { + // TODO(metcoder95): add support for PUSH + enablePush: false, + ...http2InitialWindowSize != null ? { initialWindowSize: http2InitialWindowSize } : null + } + }); + client[kSocket] = socket; + session[kOpenStreams] = 0; + session[kClient] = client; + session[kSocket] = socket; + session[kHTTP2SessionState] = { + idleTimeout: null, + // Armed while the peer advertises MAX_CONCURRENT_STREAMS = 0 and we have + // work that cannot start. See setNoStreamsTimeout. + noStreamsTimeout: null, + // Sockets start out ref'd. Session ref/unref proxies to the socket, so a + // single cached flag lets us skip redundant uv ref/unref calls, provided + // every ref/unref of the session or its socket goes through + // refH2Session/unrefH2Session. + refed: true, + ping: { + interval: client[kHTTP2Options].pingInterval === 0 ? null : setInterval(onHttp2SendPing, client[kHTTP2Options].pingInterval, session).unref() + } + }; + session[kReceivedGoAway] = false; + session[kEnableConnectProtocol] = false; + session[kRemoteSettings] = false; + if (http2ConnectionWindowSize) { + util.addListener(session, "connect", applyConnectionWindowSize.bind(session, http2ConnectionWindowSize)); + } + util.addListener(session, "error", onHttp2SessionError); + util.addListener(session, "frameError", onHttp2FrameError); + util.addListener(session, "goaway", onHttp2SessionGoAway); + util.addListener(session, "close", onHttp2SessionClose); + util.addListener(session, "remoteSettings", onHttp2RemoteSettings); + unrefH2Session(session); + client[kHTTP2Session] = session; + socket[kHTTP2Session] = session; + util.addListener(socket, "error", onHttp2SocketError); + util.addListener(socket, "end", onHttp2SocketEnd); + util.addListener(socket, "close", onHttp2SocketClose); + socket[kClosed] = false; + socket.on("close", onSocketClose); + return { + version: "h2", + defaultPipelining: Infinity, + /** + * @param {import('../core/request.js')} request + * @returns {boolean} + */ + write(request) { + return writeH2(client, request); + }, + /** + * @returns {void} + */ + resume() { + resumeH2(client); + }, + /** + * @param {Error | null} err + * @param {() => void} callback + */ + destroy(err, callback) { + if (socket[kClosed]) { + queueMicrotask(callback); + } else { + socket.destroy(err).on("close", callback); + } + }, + /** + * @type {boolean} + */ + get destroyed() { + return socket.destroyed; + }, + /** + * @param {import('../core/request.js')} request + * @returns {boolean} + */ + busy(request) { + if (session[kRemoteSettings] === false && client[kRunning] > 0) { + return true; + } + if (client[kRunning] >= client[kMaxConcurrentStreams]) { + return true; + } + if (request != null) { + if (client[kRunning] > 0) { + if ((request.upgrade === "websocket" || request.method === "CONNECT") && session[kRemoteSettings] === false) return true; + } else { + return (request.upgrade === "websocket" || request.method === "CONNECT") && session[kRemoteSettings] === false; + } + } + return false; + } + }; + } + function refH2Session(session) { + const state2 = session[kHTTP2SessionState]; + if (state2.refed === false) { + state2.refed = true; + session.ref(); + } + } + function unrefH2Session(session) { + const state2 = session[kHTTP2SessionState]; + if (state2.refed === true) { + state2.refed = false; + session.unref(); + } + } + function resumeH2(client) { + const socket = client[kSocket]; + const session = client[kHTTP2Session]; + if (socket?.destroyed === false) { + if (client[kSize] === 0 || client[kMaxConcurrentStreams] === 0) { + unrefH2Session(session); + } else { + refH2Session(session); + } + if (client[kSize] === 0 && session[kOpenStreams] === 0) { + setHttp2IdleTimeout(session); + } else { + clearHttp2IdleTimeout(session); + } + if (client[kMaxConcurrentStreams] === 0 && client[kRunning] === 0 && client[kPending] > 0) { + setNoStreamsTimeout(session); + } else { + clearNoStreamsTimeout(session); + } + } + } + function clearNoStreamsTimeout(session) { + const state2 = session[kHTTP2SessionState]; + if (state2?.noStreamsTimeout != null) { + clearTimeout(state2.noStreamsTimeout); + state2.noStreamsTimeout = null; + } + } + function setNoStreamsTimeout(session) { + const client = session[kClient]; + const state2 = session[kHTTP2SessionState]; + const timeout = client[kHeadersTimeout]; + if (!timeout || state2.noStreamsTimeout != null) { + return; + } + state2.noStreamsTimeout = setTimeout(onNoStreamsTimeout, timeout, session).unref(); + } + function onNoStreamsTimeout(session) { + const client = session[kClient]; + const state2 = session[kHTTP2SessionState]; + state2.noStreamsTimeout = null; + if (client[kHTTP2Session] !== session || client[kMaxConcurrentStreams] !== 0 || client[kRunning] !== 0 || client[kPending] === 0) { + return; + } + const err = new HeadersTimeoutError( + `HTTP/2: server did not accept a new stream within ${client[kHeadersTimeout]}` + ); + const requests = client[kQueue].splice(client[kPendingIdx]); + for (let i = 0; i < requests.length; i++) { + if (requests[i] != null) { + util.errorRequest(client, requests[i], err); + } + } + session[kError] = err; + resetHttp2Session(session, err); + } + function clearHttp2IdleTimeout(session) { + const state2 = session[kHTTP2SessionState]; + if (state2?.idleTimeout != null) { + clearTimeout(state2.idleTimeout); + state2.idleTimeout = null; + } + } + function setHttp2IdleTimeout(session) { + const client = session[kClient]; + if (client[kHTTP2Session] !== session || session.closed || session.destroyed) { + return; + } + if (session[kOpenStreams] !== 0 || client[kSize] !== 0) { + clearHttp2IdleTimeout(session); + return; + } + const state2 = session[kHTTP2SessionState]; + if (state2.idleTimeout == null) { + state2.idleTimeout = setTimeout(onHttp2SessionIdleTimeout, client[kKeepAliveDefaultTimeout], session).unref(); + } + } + function onHttp2SessionIdleTimeout(session) { + const client = session[kClient]; + const socket = session[kSocket]; + const state2 = session[kHTTP2SessionState]; + state2.idleTimeout = null; + if (client[kHTTP2Session] !== session || session[kOpenStreams] !== 0 || client[kSize] !== 0 || session.closed || session.destroyed) { + return; + } + const err = new InformationalError("socket idle timeout"); + socket[kError] = err; + util.destroy(socket, err); + } + function applyConnectionWindowSize(connectionWindowSize) { + try { + if (typeof this.setLocalWindowSize === "function") { + this.setLocalWindowSize(connectionWindowSize); + } + } catch { + } + } + function onHttp2RemoteSettings(settings2) { + this[kClient][kMaxConcurrentStreams] = settings2.maxConcurrentStreams ?? this[kClient][kMaxConcurrentStreams]; + if (this[kRemoteSettings] === true && this[kEnableConnectProtocol] === true && settings2.enableConnectProtocol === false) { + const err = new InformationalError("HTTP/2: Server disabled extended CONNECT protocol against RFC-8441"); + this[kSocket][kError] = err; + this[kClient][kOnError](err); + return; + } + this[kEnableConnectProtocol] = settings2.enableConnectProtocol ?? this[kEnableConnectProtocol]; + this[kRemoteSettings] = true; + this[kClient][kResume](); + } + function onHttp2SendPing(session) { + const state2 = session[kHTTP2SessionState]; + if ((session.closed || session.destroyed) && state2.ping.interval != null) { + clearInterval(state2.ping.interval); + state2.ping.interval = null; + return; + } + session.ping(onPing.bind(session)); + function onPing(err, duration2) { + const client = this[kClient]; + const socket = this[kSocket]; + if (err != null) { + const error2 = new InformationalError(`HTTP/2: "PING" errored - type ${err.message}`); + socket[kError] = error2; + client[kOnError](error2); + } else { + client.emit("ping", duration2); + } + } + } + function onHttp2SessionError(err) { + assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); + this[kSocket][kError] = err; + if (this[kReceivedGoAway]) { + return; + } + this[kClient][kOnError](err); + } + function onHttp2FrameError(type2, code, id2) { + if (id2 === 0) { + if (this[kReceivedGoAway]) { + return; + } + const err = new InformationalError(`HTTP/2: "frameError" received - type ${type2}, code ${code}`); + this[kSocket][kError] = err; + this[kClient][kOnError](err); + } + } + function onHttp2SessionGoAway(errorCode, lastStreamID) { + if (this[kReceivedGoAway]) { + return; + } + this[kReceivedGoAway] = true; + const err = getGoAwayError(this, errorCode); + const client = this[kClient]; + const previousPendingIdx = client[kPendingIdx]; + const pendingIdx = getGoAwayPendingIdx(client, lastStreamID); + const retriableRequests = []; + const streamsToClose = []; + for (let i = pendingIdx; i < previousPendingIdx; i++) { + const request = client[kQueue][i]; + if (request != null) { + streamsToClose.push(detachRequestStreamForClose(request)); + if (canReplayRequest(request) && registerGoAwayRefusal(request)) { + retriableRequests.push(request); + } else { + util.errorRequest(client, request, err); + } + } + } + for (let i = 0; i < streamsToClose.length; i++) { + closeStream(streamsToClose[i]); + } + if (pendingIdx !== previousPendingIdx) { + const remainingPendingRequests = client[kQueue].slice(previousPendingIdx); + client[kQueue].length = pendingIdx; + client[kQueue].push(...retriableRequests, ...remainingPendingRequests); + } + if (client[kHTTP2Session] === this) { + client[kSocket] = null; + client[kHTTPContext] = null; + client[kHTTP2Session] = null; + } + clearHttp2IdleTimeout(this); + clearNoStreamsTimeout(this); + if (!this.closed && !this.destroyed) { + this.close(); + } + client[kPendingIdx] = pendingIdx; + client.emit("disconnect", client[kUrl], [client], err); + client[kResume](); + } + function onHttp2SessionClose() { + const { [kClient]: client, [kHTTP2SessionState]: state2, [kSocket]: socket } = this; + const err = socket[kError] || this[kError] || new SocketError("closed", util.getSocketInfo(socket)); + if (client[kHTTP2Session] === this) { + client[kSocket] = null; + client[kHTTPContext] = null; + client[kHTTP2Session] = null; + } + clearHttp2IdleTimeout(this); + clearNoStreamsTimeout(this); + if (state2.ping.interval != null) { + clearInterval(state2.ping.interval); + state2.ping.interval = null; + } + if (client.destroyed) { + assert(client[kPending] === 0); + const requests = client[kQueue].splice(client[kRunningIdx]); + for (let i = 0; i < requests.length; i++) { + const request = requests[i]; + if (request != null) { + util.errorRequest(client, request, err); + } + } + } + } + function onHttp2SocketClose() { + const err = this[kError] || new SocketError("closed", util.getSocketInfo(this)); + const session = this[kHTTP2Session]; + const client = session[kClient]; + if (client[kSocket] !== this) { + if (session[kReceivedGoAway] || client[kHTTP2Session] != null && client[kHTTP2Session] !== session) { + return; + } + } + client[kSocket] = null; + client[kHTTPContext] = null; + if (client[kHTTP2Session] === session) { + client[kHTTP2Session] = null; + } + session.destroy(err); + client[kPendingIdx] = client[kRunningIdx]; + assert(client[kRunning] === 0); + client.emit("disconnect", client[kUrl], [client], err); + client[kResume](); + } + function onHttp2SocketError(err) { + assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); + this[kError] = err; + if (this[kHTTP2Session]?.[kReceivedGoAway]) { + return; + } + this[kHTTP2Session]?.[kClient]?.[kOnError](err); + } + function onHttp2SocketEnd() { + util.destroy(this, new SocketError("other side closed", util.getSocketInfo(this))); + } + function onSocketClose() { + this[kClosed] = true; + } + function noop() { + } + function closeStreamSession(stream) { + const session = stream[kHTTP2Session]; + stream[kHTTP2Session] = null; + session[kOpenStreams] -= 1; + if (session[kOpenStreams] === 0) { + unrefH2Session(session); + setHttp2IdleTimeout(session); + } + } + function onUpgradeStreamClose() { + this.off("error", noop); + const state2 = this[kRequestStreamState]; + this[kRequestStreamState] = null; + failUpgradeStream(state2, new InformationalError("HTTP/2: stream closed before response headers")); + closeStreamSession(this); + } + function completeRequestStream() { + const state2 = this[kRequestStreamState]; + if (state2 == null) { + return; + } + releaseRequestStream(this); + if (state2.pendingEnd && !state2.request.aborted && !state2.request.completed) { + state2.request.onResponseEnd(state2.trailers || {}); + } else if (!state2.request.aborted && !state2.request.completed) { + util.errorRequest( + state2.client, + state2.request, + new InformationalError("HTTP/2: stream closed before the response was complete") + ); + } + finalizeRequest(state2); + closeStreamSession(this); + this[kRequestStreamState] = null; + } + function shouldSendContentLength(method2) { + return method2 !== "GET" && method2 !== "HEAD" && method2 !== "OPTIONS" && method2 !== "TRACE" && method2 !== "CONNECT"; + } + function buildRequestHeaders(reqHeaders) { + const headers2 = {}; + for (let n = 0; n < reqHeaders.length; n += 2) { + const key = reqHeaders[n + 0]; + const val = reqHeaders[n + 1]; + const current = headers2[key]; + if (key === "cookie") { + if (current != null) { + headers2[key] = Array.isArray(current) ? (current.push(val), current) : [current, val]; + } else { + headers2[key] = val; + } + continue; + } + if (typeof val === "string") { + headers2[key] = current ? `${current}, ${val}` : val; + continue; + } + for (let i = 0; i < val.length; i++) { + headers2[key] = headers2[key] ? `${headers2[key]}, ${val[i]}` : val[i]; + } + } + return headers2; + } + function removeUpgradeStreamListeners(stream) { + stream.off("response", onUpgradeResponse); + stream.off("error", onUpgradeStreamError); + stream.off("end", onUpgradeStreamEnd); + stream.off("timeout", onUpgradeStreamTimeout); + stream.off("error", noop); + } + function releaseUpgradeStream(stream) { + if (stream == null) { + return; + } + const state2 = stream[kRequestStreamState]; + if (state2 == null) { + return; + } + const { request } = state2; + if (request[kRequestStream] === stream) { + detachRequestFromStream(request); + } + removeUpgradeStreamListeners(stream); + if (!stream.destroyed && !stream.closed) { + stream.once("error", noop); + } + } + function failUpgradeStream(state2, err) { + if (state2 == null) { + return; + } + const { request } = state2; + if (state2.responseReceived || request.aborted || request.completed) { + return; + } + releaseUpgradeStream(state2.stream); + state2.abort(err, true); + } + function onUpgradeStreamError() { + const state2 = this[kRequestStreamState]; + if (typeof this.rstCode === "number" && this.rstCode !== 0) { + failUpgradeStream(state2, new InformationalError(`HTTP/2: "stream error" received - code ${this.rstCode}`)); + } else { + failUpgradeStream(state2, new InformationalError("HTTP/2: stream errored before response headers")); + } + } + function onUpgradeStreamEnd() { + failUpgradeStream(this[kRequestStreamState], new InformationalError("HTTP/2: stream half-closed (remote)")); + } + function onUpgradeStreamTimeout() { + const state2 = this[kRequestStreamState]; + failUpgradeStream(state2, new InformationalError(`HTTP/2: "stream timeout after ${state2.headersTimeout}"`)); + } + function onUpgradeResponse(headers2, _flags) { + const stream = this; + const state2 = stream[kRequestStreamState]; + const { request } = state2; + state2.responseReceived = true; + const statusCode = headers2[HTTP2_HEADER_STATUS]; + delete headers2[HTTP2_HEADER_STATUS]; + request.onRequestUpgrade(statusCode, headers2, stream); + if (request.aborted || request.completed) { + return; + } + removeUpgradeStreamListeners(stream); + detachRequestFromStream(request); + finalizeRequest(state2); + } + function setupUpgradeStream(stream, state2) { + const { request, headersTimeout, session } = state2; + stream[kHTTP2Stream] = true; + stream[kHTTP2Session] = session; + stream[kRequestStreamState] = state2; + state2.stream = stream; + bindRequestToStream(request, stream, releaseUpgradeStream); + stream.once("response", onUpgradeResponse); + stream.on("error", onUpgradeStreamError); + stream.once("end", onUpgradeStreamEnd); + stream.on("timeout", onUpgradeStreamTimeout); + stream.once("close", onUpgradeStreamClose); + clearHttp2IdleTimeout(session); + ++session[kOpenStreams]; + stream.setTimeout(headersTimeout); + } + function finalizeRequest(state2, resetPendingIdx = false) { + if (state2.requestFinalized) { + return; + } + state2.requestFinalized = true; + completeRequest(state2.client, state2.request, resetPendingIdx); + state2.client[kResume](); + } + function openStream(client, request, session, abort2, headers2, options2) { + try { + return session.request(headers2, options2); + } catch (err) { + if (err?.code === "ERR_HTTP2_INVALID_SESSION" || err?.code === "ERR_HTTP2_GOAWAY_SESSION") { + const wrappedErr2 = new SocketError(err.message, util.getSocketInfo(session[kSocket])); + wrappedErr2.cause = err; + session[kError] = wrappedErr2; + resetHttp2Session(session, wrappedErr2); + requeueUnsentRequest(client, request); + return null; + } + const wrappedErr = new InformationalError(err.message, { cause: err }); + session[kError] = wrappedErr; + session[kSocket][kError] = wrappedErr; + session.destroy(wrappedErr); + util.destroy(session[kSocket], wrappedErr); + abort2(wrappedErr); + return null; + } + } + function writeH2(client, request) { + const headersTimeout = request.headersTimeout ?? client[kHeadersTimeout]; + const bodyTimeout = request.bodyTimeout ?? client[kBodyTimeout]; + const session = client[kHTTP2Session]; + const { method: method2, path: path2, host: host2, upgrade, expectContinue, signal: signal2, protocol, headers: reqHeaders } = request; + if (upgrade != null && upgrade !== "websocket") { + util.errorRequest(client, request, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`)); + return false; + } + const headers2 = buildRequestHeaders(reqHeaders); + headers2[HTTP2_HEADER_AUTHORITY] = host2 || client[kHostAuthority]; + headers2[HTTP2_HEADER_METHOD] = method2; + const state2 = { + abort: null, + body: request.body, + client, + contentLength: null, + expectsPayload: false, + request, + headersTimeout, + bodyTimeout, + requestFinalized: false, + responseReceived: false, + bodySent: false, + pendingEnd: false, + trailers: null, + session, + stream: null + }; + const abort2 = (err, resetPendingIdx = false) => { + if (request.aborted || request.completed) { + return; + } + err = err || new RequestAbortedError(); + util.errorRequest(client, request, err); + if (state2.stream != null) { + clearRequestStream(request); + const stream2 = state2.stream; + stream2.close(); + if (!stream2.destroyed) { + util.destroy(stream2); + } + client[kOnError](err); + finalizeRequest(state2, resetPendingIdx); + } + util.destroy(state2.body, err); + }; + state2.abort = abort2; + let stream = null; + try { + request.onRequestStart(abort2, null); + } catch (err) { + util.errorRequest(client, request, err); + } + if (request.aborted) { + return false; + } + if (upgrade || method2 === "CONNECT") { + refH2Session(session); + if (upgrade === "websocket") { + if (session[kEnableConnectProtocol] === false) { + util.errorRequest(client, request, new InformationalError("HTTP/2: Extended CONNECT protocol not supported by server")); + unrefH2Session(session); + return false; + } + headers2[HTTP2_HEADER_METHOD] = "CONNECT"; + headers2[HTTP2_HEADER_PROTOCOL] = "websocket"; + headers2[HTTP2_HEADER_PATH] = path2; + if (protocol === "ws:" || protocol === "wss:") { + headers2[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https"; + } else { + headers2[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https"; + } + stream = openStream(client, request, session, abort2, headers2, { endStream: false, signal: signal2 }); + if (stream == null) { + unrefH2Session(session); + return false; + } + setupUpgradeStream(stream, state2); + return true; + } + stream = openStream(client, request, session, abort2, headers2, { endStream: false, signal: signal2 }); + if (stream == null) { + unrefH2Session(session); + return false; + } + setupUpgradeStream(stream, state2); + return true; + } + headers2[HTTP2_HEADER_PATH] = path2; + headers2[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https"; + const expectsPayload = method2 === "PUT" || method2 === "POST" || method2 === "PATCH" || method2 === "QUERY" || method2 === "PROPFIND" || method2 === "PROPPATCH"; + let body2 = state2.body; + if (body2 && typeof body2.read === "function") { + body2.read(0); + } + let contentLength2 = util.bodyLength(body2); + if (util.isFormDataLike(body2)) { + extractBody ??= require_body().extractBody; + const [bodyStream, contentType2] = extractBody(body2); + headers2["content-type"] = contentType2; + body2 = bodyStream.stream; + contentLength2 = bodyStream.length; + } + if (contentLength2 == null) { + contentLength2 = request.contentLength; + } + if (contentLength2 === 0 && !expectsPayload) { + contentLength2 = null; + } + if (shouldSendContentLength(method2) && contentLength2 > 0 && request.contentLength != null && request.contentLength !== contentLength2) { + if (client[kStrictContentLength]) { + util.errorRequest(client, request, new RequestContentLengthMismatchError()); + return false; + } + process.emitWarning(new RequestContentLengthMismatchError()); + } + if (contentLength2 != null) { + assert(body2 || contentLength2 === 0, "no body must not have content length"); + headers2[HTTP2_HEADER_CONTENT_LENGTH] = `${contentLength2}`; + } + refH2Session(session); + if (channels.sendHeaders.hasSubscribers) { + let header = ""; + for (const key in headers2) { + header += `${key}: ${headers2[key]}\r +`; + } + channels.sendHeaders.publish({ request, headers: header, socket: session[kSocket] }); + } + const shouldEndStream = body2 === null || contentLength2 === 0; + state2.body = body2; + state2.contentLength = contentLength2; + state2.expectsPayload = expectsPayload; + if (expectContinue) { + headers2[HTTP2_HEADER_EXPECT] = "100-continue"; + } + stream = openStream(client, request, session, abort2, headers2, { endStream: shouldEndStream, signal: signal2 }); + if (stream == null) { + return false; + } + stream[kHTTP2Stream] = true; + stream[kRequestStreamState] = state2; + state2.stream = stream; + clearHttp2IdleTimeout(session); + ++session[kOpenStreams]; + if (headersTimeout) { + stream.setTimeout(headersTimeout); + } + stream[kHTTP2Session] = session; + stream.on("close", completeRequestStream); + bindRequestToStream(request, stream, releaseRequestStream); + if (expectContinue) { + stream.once("continue", writeBodyH2); + } + stream.on("response", onResponse); + stream.on("end", onEnd); + stream.on("error", onError); + stream.on("frameError", onFrameError); + stream.on("aborted", onAborted); + if (headersTimeout || bodyTimeout) { + stream.on("timeout", onTimeout); + } + stream.on("trailers", onTrailers); + if (!expectContinue) { + writeBodyH2.call(stream); + } + return true; + } + function removeRequestStreamListeners(stream) { + stream.off("error", noop); + stream.off("continue", writeBodyH2); + stream.off("response", onResponse); + stream.off("end", onEnd); + stream.off("error", onError); + stream.off("frameError", onFrameError); + stream.off("aborted", onAborted); + stream.off("timeout", onTimeout); + stream.off("trailers", onTrailers); + stream.off("data", onData); + } + function releaseRequestStream(stream) { + if (stream == null) { + return; + } + const state2 = stream[kRequestStreamState]; + if (state2 == null) { + return; + } + const { request } = state2; + if (request[kRequestStream] === stream) { + detachRequestFromStream(request); + } + if (!stream.destroyed && !stream.closed) { + removeRequestStreamListeners(stream); + stream.once("error", noop); + } + } + function onData(chunk) { + const stream = this; + const state2 = stream[kRequestStreamState]; + if (state2 == null) { + return; + } + const { request } = state2; + if (request.aborted || request.completed) { + return; + } + if (request.onResponseData(chunk) === false) { + stream.pause(); + } + } + function onResponse(headers2) { + const stream = this; + const state2 = stream[kRequestStreamState]; + if (state2 == null) { + return; + } + const { request } = state2; + stream.off("response", onResponse); + if (state2.body != null && !state2.bodySent && !stream.writableEnded) { + stream.removeListener("continue", writeBodyH2); + stream.end(); + } + const statusCode = headers2[HTTP2_HEADER_STATUS]; + delete headers2[HTTP2_HEADER_STATUS]; + request.onResponseStarted(); + state2.responseReceived = true; + if (state2.headersTimeout || state2.bodyTimeout) { + stream.setTimeout(state2.bodyTimeout); + } + if (request.aborted || request.completed) { + releaseRequestStream(stream); + return; + } + if (request.onResponseStart(Number(statusCode), headers2, stream.resume.bind(stream), "") === false) { + stream.pause(); + } + stream.on("data", onData); + } + function onEnd() { + const stream = this; + const state2 = stream[kRequestStreamState]; + if (state2 == null) { + return; + } + const { request } = state2; + stream.off("end", onEnd); + if (state2.responseReceived) { + if (!request.aborted && !request.completed) { + state2.pendingEnd = true; + completeRequestStream.call(stream); + } + } else { + state2.abort(new InformationalError("HTTP/2: stream half-closed (remote)"), true); + } + } + function retryRefusedStream(stream, state2) { + const { client, request } = state2; + if (state2.responseReceived || request.aborted || request.completed || request[kRefusedStreamRetry] || !canReplayRequest(request)) { + return false; + } + request[kRefusedStreamRetry] = true; + detachRequestStreamForClose(request); + state2.stream = null; + state2.requestFinalized = true; + completeRequest(client, request); + client[kQueue].splice(client[kPendingIdx], 0, request); + client[kResume](); + return true; + } + function onError(err) { + const stream = this; + const state2 = stream[kRequestStreamState]; + if (state2 == null) { + return; + } + stream.off("error", onError); + if (typeof stream.rstCode === "number" && stream.rstCode !== NGHTTP2_NO_ERROR) { + err.http2ErrorCode = stream.rstCode; + } + if (stream.rstCode === NGHTTP2_REFUSED_STREAM && retryRefusedStream(stream, state2)) { + return; + } + state2.abort(err); + } + function onFrameError(type2, code) { + const stream = this; + const state2 = stream[kRequestStreamState]; + if (state2 == null) { + return; + } + stream.off("frameError", onFrameError); + state2.abort(new InformationalError(`HTTP/2: "frameError" received - type ${type2}, code ${code}`)); + } + function onAborted() { + this.off("data", onData); + } + function onTimeout() { + const stream = this; + const state2 = stream[kRequestStreamState]; + if (state2 == null) { + return; + } + stream.off("timeout", onTimeout); + const err = state2.responseReceived ? new BodyTimeoutError(`HTTP/2: "stream timeout after ${state2.bodyTimeout}"`) : new HeadersTimeoutError(`HTTP/2: "headers timeout after ${state2.headersTimeout}"`); + state2.abort(err); + } + function onTrailers(trailers) { + const stream = this; + const state2 = stream[kRequestStreamState]; + if (state2 == null) { + return; + } + const { request } = state2; + stream.off("trailers", onTrailers); + stream.off("data", onData); + if (request.aborted || request.completed) { + return; + } + state2.trailers = trailers; + } + function writeBodyH2() { + const stream = this; + const state2 = stream[kRequestStreamState]; + state2.bodySent = true; + const { abort: abort2, body: body2, client, contentLength: contentLength2, expectsPayload, request } = state2; + if (!body2 || contentLength2 === 0) { + writeBuffer( + abort2, + stream, + null, + client, + request, + client[kSocket], + contentLength2, + expectsPayload + ); + } else if (util.isBuffer(body2)) { + writeBuffer( + abort2, + stream, + body2, + client, + request, + client[kSocket], + contentLength2, + expectsPayload + ); + } else if (util.isBlobLike(body2)) { + if (typeof body2.stream === "function") { + writeIterable( + abort2, + stream, + body2.stream(), + client, + request, + client[kSocket], + contentLength2, + expectsPayload + ); + } else { + writeBlob( + abort2, + stream, + body2, + client, + request, + client[kSocket], + contentLength2, + expectsPayload + ); + } + } else if (util.isStream(body2)) { + writeStream( + abort2, + client[kSocket], + expectsPayload, + stream, + body2, + client, + request, + contentLength2 + ); + } else if (util.isIterable(body2)) { + writeIterable( + abort2, + stream, + body2, + client, + request, + client[kSocket], + contentLength2, + expectsPayload + ); + } else { + assert(false); + } + } + function writeBuffer(abort2, h2stream, body2, client, request, socket, contentLength2, expectsPayload) { + try { + if (body2 != null && util.isBuffer(body2)) { + assert(contentLength2 === body2.byteLength, "buffer body must have content length"); + h2stream.cork(); + h2stream.write(body2); + h2stream.uncork(); + h2stream.end(); + request.onBodySent(body2); + } + if (!expectsPayload) { + socket[kReset] = true; + } + request.onRequestSent(); + client[kResume](); + } catch (error2) { + abort2(error2); + } + } + function writeStream(abort2, socket, expectsPayload, h2stream, body2, client, request, contentLength2) { + assert(contentLength2 !== 0 || client[kRunning] === 0, "stream body cannot be pipelined"); + const pipe = pipeline( + body2, + h2stream, + (err) => { + if (err) { + util.destroy(pipe, err); + abort2(err); + } else { + util.removeAllListeners(pipe); + request.onRequestSent(); + if (!expectsPayload) { + socket[kReset] = true; + } + client[kResume](); + } + } + ); + util.addListener(pipe, "data", onPipeData); + function onPipeData(chunk) { + request.onBodySent(chunk); + } + } + async function writeBlob(abort2, h2stream, body2, client, request, socket, contentLength2, expectsPayload) { + try { + if (contentLength2 != null && contentLength2 !== body2.size) { + throw new RequestContentLengthMismatchError(); + } + const buffer2 = Buffer.from(await body2.arrayBuffer()); + h2stream.cork(); + h2stream.write(buffer2); + h2stream.uncork(); + h2stream.end(); + request.onBodySent(buffer2); + request.onRequestSent(); + if (!expectsPayload) { + socket[kReset] = true; + } + client[kResume](); + } catch (err) { + abort2(err); + } + } + async function writeIterable(abort2, h2stream, body2, client, request, socket, contentLength2, expectsPayload) { + assert(contentLength2 !== 0 || client[kRunning] === 0, "iterator body cannot be pipelined"); + let callback = null; + function onDrain() { + if (callback) { + const cb = callback; + callback = null; + cb(); + } + } + const waitForDrain = () => new Promise((resolve, reject) => { + assert(callback === null); + if (socket[kError]) { + reject(socket[kError]); + } else { + callback = resolve; + } + }); + h2stream.on("close", onDrain).on("drain", onDrain); + try { + for await (const chunk of body2) { + if (socket[kError]) { + throw socket[kError]; + } + const res = h2stream.write(chunk); + request.onBodySent(chunk); + if (!res) { + await waitForDrain(); + } + } + h2stream.end(); + request.onRequestSent(); + if (!expectsPayload) { + socket[kReset] = true; + } + client[kResume](); + } catch (err) { + abort2(err); + } finally { + h2stream.off("close", onDrain).off("drain", onDrain); + } + } + module2.exports = connectH2; + } +}); + +// node_modules/undici/lib/dispatcher/client.js +var require_client = __commonJS({ + "node_modules/undici/lib/dispatcher/client.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var net = require("node:net"); + var http = require("node:http"); + var util = require_util(); + var { ClientStats } = require_stats(); + var { channels } = require_diagnostics(); + var Request3 = require_request(); + var DispatcherBase = require_dispatcher_base(); + var { + InvalidArgumentError, + InformationalError, + ClientDestroyedError + } = require_errors2(); + var buildConnector = require_connect(); + var { + kUrl, + kServerName, + kClient, + kBusy, + kConnect, + kResuming, + kRunning, + kPending, + kSize, + kQueue, + kConnected, + kConnecting, + kNeedDrain, + kKeepAliveDefaultTimeout, + kHostHeader, + kPendingIdx, + kRunningIdx, + kError, + kPipelining, + kKeepAliveTimeoutValue, + kMaxHeadersSize, + kKeepAliveMaxTimeout, + kKeepAliveTimeoutThreshold, + kHeadersTimeout, + kBodyTimeout, + kStrictContentLength, + kConnector, + kMaxRequests, + kCounter, + kClose, + kDestroy, + kDispatch, + kLocalAddress, + kMaxResponseSize, + kOnError, + kHTTPContext, + kMaxConcurrentStreams, + kHostAuthority, + kResume, + kHTTP2Options + } = require_symbols(); + var connectH1 = require_client_h1(); + var connectH2 = require_client_h2(); + var kClosedResolve = /* @__PURE__ */ Symbol("kClosedResolve"); + var getDefaultNodeMaxHeaderSize = http && http.maxHeaderSize && Number.isInteger(http.maxHeaderSize) && http.maxHeaderSize > 0 ? () => http.maxHeaderSize : () => { + throw new InvalidArgumentError("http module not available or http.maxHeaderSize invalid"); + }; + var noop = () => { + }; + function getPipelining(client) { + return client[kPipelining] ?? client[kHTTPContext]?.defaultPipelining ?? 1; + } + var h2NamespaceOptsWarning = false; + function emitH2OptionsNamespaceWarning(optName) { + if (h2NamespaceOptsWarning === true) return; + process.emitWarning(`Use h2Options.${optName} instead. ${optName} for H2 will be deprecated in future major.`, { + code: "UNDICI-H2-OPTIONS" + }); + h2NamespaceOptsWarning = true; + } + function getMaxConcurrent(client) { + if (client[kHTTPContext]?.version === "h2") { + return client[kMaxConcurrentStreams]; + } + return getPipelining(client); + } + var Client = class extends DispatcherBase { + /** + * + * @param {string|URL} url + * @param {import('../../types/client.js').Client.Options} options + */ + constructor(url2, { + maxHeaderSize, + headersTimeout, + socketTimeout, + requestTimeout, + connectTimeout, + bodyTimeout, + idleTimeout, + keepAlive, + keepAliveTimeout, + maxKeepAliveTimeout, + keepAliveMaxTimeout, + keepAliveTimeoutThreshold, + socketPath, + pipelining, + tls, + strictContentLength, + maxCachedSessions, + connect: connect2, + maxRequestsPerClient, + localAddress, + maxResponseSize, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + // h2 + maxConcurrentStreams, + allowH2, + useH2c, + initialWindowSize, + connectionWindowSize, + pingInterval, + webSocket: webSocket2, + h2Options + } = {}) { + if (keepAlive !== void 0) { + throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); + } + if (socketTimeout !== void 0) { + throw new InvalidArgumentError("unsupported socketTimeout, use headersTimeout & bodyTimeout instead"); + } + if (requestTimeout !== void 0) { + throw new InvalidArgumentError("unsupported requestTimeout, use headersTimeout & bodyTimeout instead"); + } + if (idleTimeout !== void 0) { + throw new InvalidArgumentError("unsupported idleTimeout, use keepAliveTimeout instead"); + } + if (maxKeepAliveTimeout !== void 0) { + throw new InvalidArgumentError("unsupported maxKeepAliveTimeout, use keepAliveMaxTimeout instead"); + } + if (maxHeaderSize != null) { + if (!Number.isInteger(maxHeaderSize) || maxHeaderSize < 1) { + throw new InvalidArgumentError("invalid maxHeaderSize"); + } + } else { + maxHeaderSize = getDefaultNodeMaxHeaderSize(); + } + if (socketPath != null && typeof socketPath !== "string") { + throw new InvalidArgumentError("invalid socketPath"); + } + if (connectTimeout != null && (!Number.isFinite(connectTimeout) || connectTimeout < 0)) { + throw new InvalidArgumentError("invalid connectTimeout"); + } + if (keepAliveTimeout != null && (!Number.isFinite(keepAliveTimeout) || keepAliveTimeout <= 0)) { + throw new InvalidArgumentError("invalid keepAliveTimeout"); + } + if (keepAliveMaxTimeout != null && (!Number.isFinite(keepAliveMaxTimeout) || keepAliveMaxTimeout <= 0)) { + throw new InvalidArgumentError("invalid keepAliveMaxTimeout"); + } + if (keepAliveTimeoutThreshold != null && !Number.isFinite(keepAliveTimeoutThreshold)) { + throw new InvalidArgumentError("invalid keepAliveTimeoutThreshold"); + } + if (headersTimeout != null && (!Number.isInteger(headersTimeout) || headersTimeout < 0)) { + throw new InvalidArgumentError("headersTimeout must be a positive integer or zero"); + } + if (bodyTimeout != null && (!Number.isInteger(bodyTimeout) || bodyTimeout < 0)) { + throw new InvalidArgumentError("bodyTimeout must be a positive integer or zero"); + } + if (connect2 != null && typeof connect2 !== "function" && typeof connect2 !== "object") { + throw new InvalidArgumentError("connect must be a function or an object"); + } + if (maxRequestsPerClient != null && (!Number.isInteger(maxRequestsPerClient) || maxRequestsPerClient < 0)) { + throw new InvalidArgumentError("maxRequestsPerClient must be a positive number"); + } + if (localAddress != null && (typeof localAddress !== "string" || net.isIP(localAddress) === 0)) { + throw new InvalidArgumentError("localAddress must be valid string IP address"); + } + if (maxResponseSize != null && (!Number.isInteger(maxResponseSize) || maxResponseSize < -1)) { + throw new InvalidArgumentError("maxResponseSize must be a positive number"); + } + if (autoSelectFamilyAttemptTimeout != null && (!Number.isInteger(autoSelectFamilyAttemptTimeout) || autoSelectFamilyAttemptTimeout < -1)) { + throw new InvalidArgumentError("autoSelectFamilyAttemptTimeout must be a positive number"); + } + if (allowH2 != null && typeof allowH2 !== "boolean") { + throw new InvalidArgumentError("allowH2 must be a valid boolean value"); + } + if (allowH2 !== false) { + if (h2Options != null) { + if (h2Options.useH2c != null && typeof h2Options.useH2c !== "boolean") { + throw new InvalidArgumentError("h2Options.useH2c must be a valid boolean value"); + } + if (h2Options.settings?.initialWindowSize != null && (!Number.isInteger(h2Options.settings.initialWindowSize) || h2Options.settings.initialWindowSize < 1)) { + throw new InvalidArgumentError("h2Options.settings.initialWindowSize must be a positive integer, greater than 0"); + } + if (h2Options.maxConcurrentStreams != null && (!Number.isInteger(h2Options.connectionWindowSize) || h2Options.maxConcurrentStreams < 1)) { + throw new InvalidArgumentError("h2Options.maxConcurrentStreams must be a positive integer, greater than 0"); + } + if (h2Options.connectionWindowSize != null && (!Number.isInteger(h2Options.connectionWindowSize) || h2Options.connectionWindowSize < 1)) { + throw new InvalidArgumentError("h2Options.connectionWindowSize must be a positive integer, greater than 0"); + } + if (h2Options.pingInterval != null && (typeof h2Options.pingInterval !== "number" || !Number.isInteger(h2Options.pingInterval) || h2Options.pingInterval < 0)) { + throw new InvalidArgumentError("h2Options.pingInterval must be a positive integer, greater or equal to 0"); + } + } else { + if (useH2c != null && typeof useH2c !== "boolean") { + emitH2OptionsNamespaceWarning("useH2c"); + throw new InvalidArgumentError("useH2c must be a valid boolean value"); + } + if (maxConcurrentStreams != null && (typeof maxConcurrentStreams !== "number" || maxConcurrentStreams < 1)) { + emitH2OptionsNamespaceWarning("maxConcurrentStreams"); + throw new InvalidArgumentError("maxConcurrentStreams must be a positive integer, greater than 0"); + } + if (initialWindowSize != null && (!Number.isInteger(initialWindowSize) || initialWindowSize < 1)) { + emitH2OptionsNamespaceWarning("initialWindowSize"); + throw new InvalidArgumentError("initialWindowSize must be a positive integer, greater than 0"); + } + if (connectionWindowSize != null && (!Number.isInteger(connectionWindowSize) || connectionWindowSize < 1)) { + emitH2OptionsNamespaceWarning("connectionWindowSize"); + throw new InvalidArgumentError("connectionWindowSize must be a positive integer, greater than 0"); + } + if (pingInterval != null && (typeof pingInterval !== "number" || !Number.isInteger(pingInterval) || pingInterval < 0)) { + emitH2OptionsNamespaceWarning("pingInterval"); + throw new InvalidArgumentError("pingInterval must be a positive integer, greater or equal to 0"); + } + } + } + super({ webSocket: webSocket2 }); + if (typeof connect2 !== "function") { + connect2 = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + useH2c: h2Options?.useH2c ?? useH2c, + timeout: connectTimeout, + ...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, + ...connect2 + }); + } else { + const customConnect = connect2; + connect2 = (opts, callback) => customConnect({ + ...opts, + ...socketPath != null ? { socketPath } : null, + ...allowH2 != null ? { allowH2 } : null + }, callback); + } + this[kUrl] = util.parseOrigin(url2); + this[kHostAuthority] = `${this[kUrl].hostname}${this[kUrl].port ? `:${this[kUrl].port}` : ""}`; + this[kConnector] = connect2; + this[kPipelining] = pipelining != null ? pipelining : 1; + this[kMaxHeadersSize] = maxHeaderSize; + this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout; + this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 6e5 : keepAliveMaxTimeout; + this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 2e3 : keepAliveTimeoutThreshold; + this[kKeepAliveTimeoutValue] = this[kKeepAliveDefaultTimeout]; + this[kServerName] = null; + this[kLocalAddress] = localAddress != null ? localAddress : null; + this[kResuming] = 0; + this[kNeedDrain] = 0; + this[kHostHeader] = `host: ${this[kHostAuthority]}\r `; + this[kBodyTimeout] = bodyTimeout != null ? bodyTimeout : 3e5; + this[kHeadersTimeout] = headersTimeout != null ? headersTimeout : 3e5; + this[kStrictContentLength] = strictContentLength == null ? true : strictContentLength; + this[kMaxRequests] = maxRequestsPerClient; + this[kClosedResolve] = null; + this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1; + this[kHTTPContext] = null; + this[kHTTP2Options] = { + pingInterval: h2Options?.pingInterval ?? pingInterval ?? 6e4, + connectionWindowSize: h2Options?.connectionWindowSize ?? connectionWindowSize ?? 524288, + maxConcurrentStreams: h2Options?.maxConcurrentStreams ?? maxConcurrentStreams ?? 100, + // Max peerConcurrentStreams for a Node h2 server + sessionOptions: { + // HTTP/2 window sizes are set to higher defaults than Node.js core for better performance: + // - initialWindowSize: 262144 (256KB) vs Node.js default 65535 (64KB - 1) + // Allows more data to be sent before requiring acknowledgment, improving throughput + // especially on high-latency networks. This matches common production HTTP/2 servers. + // - connectionWindowSize: 524288 (512KB) vs Node.js default (none set) + // Provides better flow control for the entire connection across multiple streams. + initialWindowSize: h2Options?.initialWindowSize ?? initialWindowSize ?? 262144 + } + }; + this[kQueue] = []; + this[kRunningIdx] = 0; + this[kPendingIdx] = 0; + this[kResume] = (sync) => resume(this, sync); + this[kOnError] = (err) => onError(this, err); + } + get pipelining() { + return this[kPipelining]; + } + set pipelining(value2) { + this[kPipelining] = value2; + this[kResume](true); + } + get stats() { + return new ClientStats(this); + } + get [kPending]() { + return this[kQueue].length - this[kPendingIdx]; + } + get [kRunning]() { + return this[kPendingIdx] - this[kRunningIdx]; + } + get [kSize]() { + return this[kQueue].length - this[kRunningIdx]; + } + get [kConnected]() { + return !!this[kHTTPContext] && !this[kConnecting] && !this[kHTTPContext].destroyed; + } + get [kBusy]() { + const allowsMux = this[kHTTPContext]?.version === "h2"; + return Boolean( + this[kHTTPContext]?.busy(null) || this[kSize] >= (getMaxConcurrent(this) || 1) || this[kPending] > 0 && !allowsMux + ); + } + [kConnect](cb) { + connect(this); + this.once("connect", cb); + } + [kDispatch](opts, handler) { + const request = new Request3(this[kUrl].origin, opts, handler); + this[kQueue].push(request); + if (this[kResuming]) { + } else if (util.bodyLength(request.body) == null && util.isIterable(request.body)) { + this[kResuming] = 1; + queueMicrotask(() => resume(this)); + } else { + this[kResume](true); + } + if (this[kResuming] && this[kNeedDrain] !== 2 && this[kBusy]) { + this[kNeedDrain] = 2; + } + return this[kNeedDrain] < 2; + } + [kClose]() { + return new Promise((resolve) => { + if (this[kSize]) { + this[kClosedResolve] = resolve; + } else { + resolve(null); + } + }); + } + [kDestroy](err) { + return new Promise((resolve) => { + const requests = this[kQueue].splice(this[kPendingIdx]); + for (let i = 0; i < requests.length; i++) { + const request = requests[i]; + if (request != null) { + util.errorRequest(this, request, err); + } + } + const callback = () => { + if (this[kClosedResolve]) { + this[kClosedResolve](); + this[kClosedResolve] = null; + } + resolve(null); + }; + if (this[kHTTPContext]) { + this[kHTTPContext].destroy(err, callback); + this[kHTTPContext] = null; + } else { + queueMicrotask(callback); + } + this[kResume](); + }); + } + }; + function onError(client, err) { + if (client[kRunning] === 0 && err.code !== "UND_ERR_INFO" && err.code !== "UND_ERR_SOCKET") { + assert(client[kPendingIdx] === client[kRunningIdx]); + const requests = client[kQueue].splice(client[kRunningIdx]); + for (let i = 0; i < requests.length; i++) { + const request = requests[i]; + if (request != null) { + util.errorRequest(client, request, err); + } + } + assert(client[kSize] === 0); + } + } + function connect(client) { + assert(!client[kConnecting]); + assert(!client[kHTTPContext]); + let { host: host2, hostname, protocol, port } = client[kUrl]; + if (hostname[0] === "[") { + const idx = hostname.indexOf("]"); + assert(idx !== -1); + const ip = hostname.substring(1, idx); + assert(net.isIPv6(ip)); + hostname = ip; + } + client[kConnecting] = true; + if (channels.beforeConnect.hasSubscribers) { + channels.beforeConnect.publish({ + connectParams: { + host: host2, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector] + }); + } + try { + client[kConnector]({ + host: host2, + hostname, + protocol, + port, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, (err, socket) => { + if (err) { + handleConnectError(client, err, { host: host2, hostname, protocol, port }); + client[kResume](); + return; + } + if (client.destroyed) { + util.destroy(socket.on("error", noop), new ClientDestroyedError()); + client[kResume](); + return; + } + assert(socket); + try { + client[kHTTPContext] = socket.alpnProtocol === "h2" ? connectH2(client, socket) : connectH1(client, socket); + } catch (err2) { + socket.destroy().on("error", noop); + handleConnectError(client, err2, { host: host2, hostname, protocol, port }); + client[kResume](); + return; + } + client[kConnecting] = false; + socket[kCounter] = 0; + socket[kMaxRequests] = client[kMaxRequests]; + socket[kClient] = client; + socket[kError] = null; + if (channels.connected.hasSubscribers) { + channels.connected.publish({ + connectParams: { + host: host2, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + socket + }); + } + client.emit("connect", client[kUrl], [client]); + client[kResume](); + }); + } catch (err) { + handleConnectError(client, err, { host: host2, hostname, protocol, port }); + client[kResume](); + } + } + function handleConnectError(client, err, { host: host2, hostname, protocol, port }) { + if (client.destroyed) { + return; + } + client[kConnecting] = false; + if (channels.connectError.hasSubscribers) { + channels.connectError.publish({ + connectParams: { + host: host2, + hostname, + protocol, + port, + version: client[kHTTPContext]?.version, + servername: client[kServerName], + localAddress: client[kLocalAddress] + }, + connector: client[kConnector], + error: err + }); + } + if (err.code === "ERR_TLS_CERT_ALTNAME_INVALID") { + const running = client[kQueue].splice(client[kRunningIdx], client[kRunning]); + client[kPendingIdx] = client[kRunningIdx]; + for (let i = 0; i < running.length; i++) { + util.errorRequest(client, running[i], err); + } + while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) { + const request = client[kQueue].splice(client[kPendingIdx], 1)[0]; + util.errorRequest(client, request, err); + } + } else { + onError(client, err); + } + client.emit("connectionError", client[kUrl], [client], err); + } + function emitDrain(client) { + client[kNeedDrain] = 0; + client.emit("drain", client[kUrl], [client]); + } + function resume(client, sync) { + if (client[kResuming] === 2) { + return; + } + client[kResuming] = 2; + _resume(client, sync); + client[kResuming] = 0; + if (client[kRunningIdx] > 256) { + client[kQueue].splice(0, client[kRunningIdx]); + client[kPendingIdx] -= client[kRunningIdx]; + client[kRunningIdx] = 0; + } + } + function _resume(client, sync) { + while (true) { + if (client.destroyed) { + assert(client[kPending] === 0); + return; + } + if (client[kClosedResolve] && !client[kSize]) { + client[kClosedResolve](); + client[kClosedResolve] = null; + return; + } + if (client[kHTTPContext]) { + client[kHTTPContext].resume(); + } + if (client[kBusy]) { + client[kNeedDrain] = 2; + } else if (client[kNeedDrain] === 2) { + if (sync) { + client[kNeedDrain] = 1; + queueMicrotask(() => emitDrain(client)); + } else { + emitDrain(client); + } + continue; + } + if (client[kPending] === 0) { + return; + } + if (client[kRunning] >= (getMaxConcurrent(client) || 1)) { + return; + } + const request = client[kQueue][client[kPendingIdx]]; + if (request === null) { + return; + } + if (client[kUrl].protocol === "https:" && client[kServerName] !== request.servername) { + if (client[kRunning] > 0) { + return; + } + client[kServerName] = request.servername; + client[kHTTPContext]?.destroy(new InformationalError("servername changed"), () => { + client[kHTTPContext] = null; + resume(client); + }); + } + if (client[kConnecting]) { + return; + } + if (!client[kHTTPContext]) { + client[kServerName] = request.servername; + connect(client); + return; + } + if (client[kHTTPContext].destroyed) { + return; + } + if (client[kHTTPContext].busy(request)) { + return; + } + if (!request.aborted && client[kHTTPContext].write(request)) { + client[kPendingIdx]++; + } else { + client[kQueue].splice(client[kPendingIdx], 1); + } + } + } + module2.exports = Client; + } +}); + +// node_modules/undici/lib/dispatcher/fixed-queue.js +var require_fixed_queue = __commonJS({ + "node_modules/undici/lib/dispatcher/fixed-queue.js"(exports2, module2) { + "use strict"; + var kSize = 2048; + var kMask = kSize - 1; + var FixedCircularBuffer = class { + /** @type {number} */ + bottom = 0; + /** @type {number} */ + top = 0; + /** @type {Array} */ + list = new Array(kSize).fill(void 0); + /** @type {T|null} */ + next = null; + /** @returns {boolean} */ + isEmpty() { + return this.top === this.bottom; + } + /** @returns {boolean} */ + isFull() { + return (this.top + 1 & kMask) === this.bottom; + } + /** + * @param {T} data + * @returns {void} + */ + push(data2) { + this.list[this.top] = data2; + this.top = this.top + 1 & kMask; + } + /** @returns {T|null} */ + shift() { + const nextItem = this.list[this.bottom]; + if (nextItem === void 0) { + return null; + } + this.list[this.bottom] = void 0; + this.bottom = this.bottom + 1 & kMask; + return nextItem; + } + }; + module2.exports = class FixedQueue { + constructor() { + this.head = this.tail = new FixedCircularBuffer(); + } + /** @returns {boolean} */ + isEmpty() { + return this.head.isEmpty(); + } + /** @param {T} data */ + push(data2) { + if (this.head.isFull()) { + this.head = this.head.next = new FixedCircularBuffer(); + } + this.head.push(data2); + } + /** @returns {T|null} */ + shift() { + const tail = this.tail; + const next = tail.shift(); + if (tail.isEmpty() && tail.next !== null) { + this.tail = tail.next; + tail.next = null; + } + return next; + } + }; + } +}); + +// node_modules/undici/lib/dispatcher/pool-base.js +var require_pool_base = __commonJS({ + "node_modules/undici/lib/dispatcher/pool-base.js"(exports2, module2) { + "use strict"; + var { PoolStats } = require_stats(); + var DispatcherBase = require_dispatcher_base(); + var FixedQueue = require_fixed_queue(); + var { kConnected, kSize, kRunning, kPending, kQueued, kBusy, kFree, kUrl, kClose, kDestroy, kDispatch } = require_symbols(); + var kClients = /* @__PURE__ */ Symbol("clients"); + var kNeedDrain = /* @__PURE__ */ Symbol("needDrain"); + var kQueue = /* @__PURE__ */ Symbol("queue"); + var kClosedResolve = /* @__PURE__ */ Symbol("closed resolve"); + var kOnDrain = /* @__PURE__ */ Symbol("onDrain"); + var kOnConnect = /* @__PURE__ */ Symbol("onConnect"); + var kOnDisconnect = /* @__PURE__ */ Symbol("onDisconnect"); + var kOnConnectionError = /* @__PURE__ */ Symbol("onConnectionError"); + var kGetDispatcher = /* @__PURE__ */ Symbol("get dispatcher"); + var kHasDispatcher = /* @__PURE__ */ Symbol("has dispatcher"); + var kAddClient = /* @__PURE__ */ Symbol("add client"); + var kRemoveClient = /* @__PURE__ */ Symbol("remove client"); + var PoolBase = class extends DispatcherBase { + [kQueue] = new FixedQueue(); + [kQueued] = 0; + [kClients] = []; + [kNeedDrain] = false; + [kOnDrain](client, origin, targets) { + const queue = this[kQueue]; + let needDrain = false; + while (!needDrain) { + const item = queue.shift(); + if (!item) { + break; + } + this[kQueued]--; + needDrain = !client.dispatch(item.opts, item.handler); + } + client[kNeedDrain] = needDrain; + if (!needDrain && this[kNeedDrain]) { + this[kNeedDrain] = false; + this.emit("drain", origin, [this, ...targets]); + } + if (this[kClosedResolve] && queue.isEmpty()) { + const closeAll = []; + for (let i = 0; i < this[kClients].length; i++) { + const client2 = this[kClients][i]; + if (!client2.destroyed) { + closeAll.push(client2.close()); + } + } + return Promise.all(closeAll).then(this[kClosedResolve]); + } + } + [kOnConnect] = (origin, targets) => { + this.emit("connect", origin, [this, ...targets]); + }; + [kOnDisconnect] = (origin, targets, err) => { + this.emit("disconnect", origin, [this, ...targets], err); + }; + [kOnConnectionError] = (origin, targets, err) => { + this.emit("connectionError", origin, [this, ...targets], err); + }; + get [kBusy]() { + return this[kNeedDrain]; + } + get [kConnected]() { + let ret = 0; + for (const { [kConnected]: connected } of this[kClients]) { + ret += connected; + } + return ret; + } + get [kFree]() { + let ret = 0; + for (const { [kConnected]: connected, [kNeedDrain]: needDrain } of this[kClients]) { + ret += connected && !needDrain; + } + return ret; + } + get [kPending]() { + let ret = this[kQueued]; + for (const { [kPending]: pending } of this[kClients]) { + ret += pending; + } + return ret; + } + get [kRunning]() { + let ret = 0; + for (const { [kRunning]: running } of this[kClients]) { + ret += running; + } + return ret; + } + get [kSize]() { + let ret = this[kQueued]; + for (const { [kSize]: size } of this[kClients]) { + ret += size; + } + return ret; + } + get stats() { + return new PoolStats(this); + } + [kClose]() { + if (this[kQueue].isEmpty()) { + const closeAll = []; + for (let i = 0; i < this[kClients].length; i++) { + const client = this[kClients][i]; + if (!client.destroyed) { + closeAll.push(client.close()); + } + } + return Promise.all(closeAll); + } else { + return new Promise((resolve) => { + this[kClosedResolve] = resolve; + }); + } + } + [kDestroy](err) { + while (true) { + const item = this[kQueue].shift(); + if (!item) { + break; + } + item.handler.onResponseError(null, err); + } + const destroyAll = new Array(this[kClients].length); + for (let i = 0; i < this[kClients].length; i++) { + destroyAll[i] = this[kClients][i].destroy(err); + } + return Promise.all(destroyAll); + } + [kDispatch](opts, handler) { + const dispatcher = this[kGetDispatcher](); + if (!dispatcher) { + this[kNeedDrain] = true; + this[kQueue].push({ opts, handler }); + this[kQueued]++; + } else if (!dispatcher.dispatch(opts, handler)) { + dispatcher[kNeedDrain] = true; + this[kNeedDrain] = !this[kHasDispatcher](); + } + return !this[kNeedDrain]; + } + [kHasDispatcher]() { + for (let i = 0; i < this[kClients].length; i++) { + const dispatcher = this[kClients][i]; + if (!dispatcher[kNeedDrain] && dispatcher.closed !== true && dispatcher.destroyed !== true) { + return true; + } + } + return false; + } + [kAddClient](client) { + client.on("drain", this[kOnDrain].bind(this, client)).on("connect", this[kOnConnect]).on("disconnect", this[kOnDisconnect]).on("connectionError", this[kOnConnectionError]); + this[kClients].push(client); + if (this[kNeedDrain]) { + queueMicrotask(() => { + if (this[kNeedDrain]) { + this[kOnDrain](client, client[kUrl], [client, this]); + } + }); + } + return this; + } + [kRemoveClient](client) { + const idx = this[kClients].indexOf(client); + if (idx !== -1) { + this[kClients].splice(idx, 1); + } + client.close(() => { + }); + this[kNeedDrain] = !this[kClients].some((dispatcher) => !dispatcher[kNeedDrain] && dispatcher.closed !== true && dispatcher.destroyed !== true); + } + }; + module2.exports = { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher, + kHasDispatcher + }; + } +}); + +// node_modules/undici/lib/dispatcher/pool.js +var require_pool = __commonJS({ + "node_modules/undici/lib/dispatcher/pool.js"(exports2, module2) { + "use strict"; + var { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kGetDispatcher, + kHasDispatcher, + kRemoveClient + } = require_pool_base(); + var Client = require_client(); + var { + InvalidArgumentError + } = require_errors2(); + var util = require_util(); + var { kUrl } = require_symbols(); + var buildConnector = require_connect(); + var kOptions = /* @__PURE__ */ Symbol("options"); + var kConnections = /* @__PURE__ */ Symbol("connections"); + var kFactory = /* @__PURE__ */ Symbol("factory"); + function defaultFactory(origin, opts) { + return new Client(origin, opts); + } + var Pool = class extends PoolBase { + constructor(origin, { + connections, + factory = defaultFactory, + connect, + connectTimeout, + tls, + maxCachedSessions, + socketPath, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + allowH2, + useH2c, + clientTtl, + ...options2 + } = {}) { + if (connections != null && (!Number.isFinite(connections) || connections < 0)) { + throw new InvalidArgumentError("invalid connections"); + } + if (typeof factory !== "function") { + throw new InvalidArgumentError("factory must be a function."); + } + if (connect != null && typeof connect !== "function" && typeof connect !== "object") { + throw new InvalidArgumentError("connect must be a function or an object"); + } + if (typeof connect !== "function") { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + useH2c, + socketPath, + timeout: connectTimeout, + ...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, + ...connect + }); + } + super(options2); + this[kConnections] = connections || null; + this[kUrl] = util.parseOrigin(origin); + this[kOptions] = { ...util.deepClone(options2), connect, allowH2, useH2c, clientTtl, socketPath }; + this[kFactory] = factory; + this.on("connect", (origin2, targets) => { + if (clientTtl != null && clientTtl > 0) { + for (const target2 of targets) { + Object.assign(target2, { ttl: Date.now() }); + } + } + }); + this.on("connectionError", (origin2, targets, error2) => { + for (const target2 of targets) { + const idx = this[kClients].indexOf(target2); + if (idx !== -1) { + this[kClients].splice(idx, 1); + } + } + }); + } + [kGetDispatcher]() { + const clientTtlOption = this[kOptions].clientTtl; + for (let i = 0; i < this[kClients].length; i++) { + const client = this[kClients][i]; + if (clientTtlOption != null && clientTtlOption > 0 && client.ttl && Date.now() - client.ttl > clientTtlOption) { + this[kRemoveClient](client); + i--; + } else if (!client[kNeedDrain]) { + return client; + } + } + if (!this[kConnections] || this[kClients].length < this[kConnections]) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]); + this[kAddClient](dispatcher); + return dispatcher; + } + } + [kHasDispatcher]() { + const clientTtlOption = this[kOptions].clientTtl; + for (let i = 0; i < this[kClients].length; i++) { + const client = this[kClients][i]; + if (clientTtlOption != null && clientTtlOption > 0 && client.ttl && Date.now() - client.ttl > clientTtlOption) { + this[kRemoveClient](client); + i--; + } else if (!client[kNeedDrain]) { + return true; + } + } + if (!this[kConnections] || this[kClients].length < this[kConnections]) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]); + this[kAddClient](dispatcher); + return true; + } + return false; + } + }; + module2.exports = Pool; + } +}); + +// node_modules/undici/lib/dispatcher/balanced-pool.js +var require_balanced_pool = __commonJS({ + "node_modules/undici/lib/dispatcher/balanced-pool.js"(exports2, module2) { + "use strict"; + var { + BalancedPoolMissingUpstreamError, + InvalidArgumentError + } = require_errors2(); + var { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kRemoveClient, + kGetDispatcher + } = require_pool_base(); + var Pool = require_pool(); + var { kUrl } = require_symbols(); + var util = require_util(); + var kFactory = /* @__PURE__ */ Symbol("factory"); + var kOptions = /* @__PURE__ */ Symbol("options"); + var kGreatestCommonDivisor = /* @__PURE__ */ Symbol("kGreatestCommonDivisor"); + var kCurrentWeight = /* @__PURE__ */ Symbol("kCurrentWeight"); + var kIndex = /* @__PURE__ */ Symbol("kIndex"); + var kWeight = /* @__PURE__ */ Symbol("kWeight"); + var kMaxWeightPerServer = /* @__PURE__ */ Symbol("kMaxWeightPerServer"); + var kErrorPenalty = /* @__PURE__ */ Symbol("kErrorPenalty"); + function getGreatestCommonDivisor(a, b) { + if (a === 0) return b; + while (b !== 0) { + const t = b; + b = a % b; + a = t; + } + return a; + } + function defaultFactory(origin, opts) { + return new Pool(origin, opts); + } + var BalancedPool = class extends PoolBase { + constructor(upstreams = [], { factory = defaultFactory, ...opts } = {}) { + if (typeof factory !== "function") { + throw new InvalidArgumentError("factory must be a function."); + } + super(); + this[kOptions] = { ...util.deepClone(opts) }; + this[kIndex] = -1; + this[kCurrentWeight] = 0; + this[kMaxWeightPerServer] = this[kOptions].maxWeightPerServer || 100; + this[kErrorPenalty] = this[kOptions].errorPenalty || 15; + if (!Array.isArray(upstreams)) { + upstreams = [upstreams]; + } + this[kFactory] = factory; + for (const upstream of upstreams) { + this.addUpstream(upstream); + } + this._updateBalancedPoolStats(); + } + addUpstream(upstream) { + const upstreamOrigin = util.parseOrigin(upstream).origin; + if (this[kClients].find((pool3) => pool3[kUrl].origin === upstreamOrigin && pool3.closed !== true && pool3.destroyed !== true)) { + return this; + } + const pool2 = this[kFactory](upstreamOrigin, this[kOptions]); + this[kAddClient](pool2); + pool2.on("connect", () => { + pool2[kWeight] = Math.min(this[kMaxWeightPerServer], pool2[kWeight] + this[kErrorPenalty]); + }); + pool2.on("connectionError", () => { + pool2[kWeight] = Math.max(1, pool2[kWeight] - this[kErrorPenalty]); + this._updateBalancedPoolStats(); + }); + pool2.on("disconnect", (...args) => { + const err = args[2]; + if (err && err.code === "UND_ERR_SOCKET") { + pool2[kWeight] = Math.max(1, pool2[kWeight] - this[kErrorPenalty]); + this._updateBalancedPoolStats(); + } + }); + for (const client of this[kClients]) { + client[kWeight] = this[kMaxWeightPerServer]; + } + this._updateBalancedPoolStats(); + return this; + } + _updateBalancedPoolStats() { + let result3 = 0; + for (let i = 0; i < this[kClients].length; i++) { + result3 = getGreatestCommonDivisor(this[kClients][i][kWeight], result3); + } + this[kGreatestCommonDivisor] = result3; + } + removeUpstream(upstream) { + const upstreamOrigin = util.parseOrigin(upstream).origin; + const pool2 = this[kClients].find((pool3) => pool3[kUrl].origin === upstreamOrigin && pool3.closed !== true && pool3.destroyed !== true); + if (pool2) { + this[kRemoveClient](pool2); + } + return this; + } + getUpstream(upstream) { + const upstreamOrigin = util.parseOrigin(upstream).origin; + return this[kClients].find((pool2) => pool2[kUrl].origin === upstreamOrigin && pool2.closed !== true && pool2.destroyed !== true); + } + get upstreams() { + return this[kClients].filter((dispatcher) => dispatcher.closed !== true && dispatcher.destroyed !== true).map((p) => p[kUrl].origin); + } + [kGetDispatcher]() { + if (this[kClients].length === 0) { + throw new BalancedPoolMissingUpstreamError(); + } + let counter = 0; + let maxWeightIndex = -1; + while (counter++ < this[kClients].length) { + this[kIndex] = (this[kIndex] + 1) % this[kClients].length; + const pool2 = this[kClients][this[kIndex]]; + if (this[kIndex] === 0) { + this[kCurrentWeight] = this[kCurrentWeight] - this[kGreatestCommonDivisor]; + if (this[kCurrentWeight] <= 0) { + this[kCurrentWeight] = this[kMaxWeightPerServer]; + } + } + if (pool2[kNeedDrain] || pool2.closed === true || pool2.destroyed === true) { + continue; + } + if (maxWeightIndex === -1 || pool2[kWeight] > this[kClients][maxWeightIndex][kWeight]) { + maxWeightIndex = this[kIndex]; + } + if (pool2[kWeight] >= this[kCurrentWeight]) { + return pool2; + } + } + if (maxWeightIndex === -1) { + return; + } + this[kCurrentWeight] = this[kClients][maxWeightIndex][kWeight]; + this[kIndex] = maxWeightIndex; + return this[kClients][maxWeightIndex]; + } + }; + module2.exports = BalancedPool; + } +}); + +// node_modules/undici/lib/dispatcher/round-robin-pool.js +var require_round_robin_pool = __commonJS({ + "node_modules/undici/lib/dispatcher/round-robin-pool.js"(exports2, module2) { + "use strict"; + var { + PoolBase, + kClients, + kNeedDrain, + kAddClient, + kGetDispatcher, + kHasDispatcher, + kRemoveClient + } = require_pool_base(); + var Client = require_client(); + var { + InvalidArgumentError + } = require_errors2(); + var util = require_util(); + var { kUrl } = require_symbols(); + var buildConnector = require_connect(); + var kOptions = /* @__PURE__ */ Symbol("options"); + var kConnections = /* @__PURE__ */ Symbol("connections"); + var kFactory = /* @__PURE__ */ Symbol("factory"); + var kIndex = /* @__PURE__ */ Symbol("index"); + function defaultFactory(origin, opts) { + return new Client(origin, opts); + } + var RoundRobinPool = class extends PoolBase { + constructor(origin, { + connections, + factory = defaultFactory, + connect, + connectTimeout, + tls, + maxCachedSessions, + socketPath, + autoSelectFamily, + autoSelectFamilyAttemptTimeout, + allowH2, + clientTtl, + ...options2 + } = {}) { + if (connections != null && (!Number.isFinite(connections) || connections < 0)) { + throw new InvalidArgumentError("invalid connections"); + } + if (typeof factory !== "function") { + throw new InvalidArgumentError("factory must be a function."); + } + if (connect != null && typeof connect !== "function" && typeof connect !== "object") { + throw new InvalidArgumentError("connect must be a function or an object"); + } + if (typeof connect !== "function") { + connect = buildConnector({ + ...tls, + maxCachedSessions, + allowH2, + socketPath, + timeout: connectTimeout, + ...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0, + ...connect + }); + } + super(); + this[kConnections] = connections || null; + this[kUrl] = util.parseOrigin(origin); + this[kOptions] = { ...util.deepClone(options2), connect, allowH2, clientTtl, socketPath }; + this[kFactory] = factory; + this[kIndex] = -1; + this.on("connect", (origin2, targets) => { + if (clientTtl != null && clientTtl > 0) { + for (const target2 of targets) { + Object.assign(target2, { ttl: Date.now() }); + } + } + }); + this.on("connectionError", (origin2, targets, error2) => { + for (const target2 of targets) { + const idx = this[kClients].indexOf(target2); + if (idx !== -1) { + this[kClients].splice(idx, 1); + } + } + }); + } + [kGetDispatcher]() { + const clientTtlOption = this[kOptions].clientTtl; + if (this[kClients].length === 0) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]); + this[kAddClient](dispatcher); + return dispatcher; + } + let checked2 = 0; + while (checked2 < this[kClients].length) { + this[kIndex] = (this[kIndex] + 1) % this[kClients].length; + const client = this[kClients][this[kIndex]]; + if (clientTtlOption != null && clientTtlOption > 0 && client.ttl && Date.now() - client.ttl > clientTtlOption) { + this[kRemoveClient](client); + this[kIndex]--; + continue; + } + if (!client[kNeedDrain]) { + return client; + } + checked2++; + } + if (!this[kConnections] || this[kClients].length < this[kConnections]) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]); + this[kAddClient](dispatcher); + return dispatcher; + } + } + [kHasDispatcher]() { + const clientTtlOption = this[kOptions].clientTtl; + for (let i = 0; i < this[kClients].length; i++) { + const client = this[kClients][i]; + if (clientTtlOption != null && clientTtlOption > 0 && client.ttl && Date.now() - client.ttl > clientTtlOption) { + this[kRemoveClient](client); + if (i <= this[kIndex]) { + this[kIndex]--; + } + i--; + } else if (!client[kNeedDrain]) { + return true; + } + } + if (!this[kConnections] || this[kClients].length < this[kConnections]) { + const dispatcher = this[kFactory](this[kUrl], this[kOptions]); + this[kAddClient](dispatcher); + return true; + } + return false; + } + }; + module2.exports = RoundRobinPool; + } +}); + +// node_modules/undici/lib/dispatcher/agent.js +var require_agent = __commonJS({ + "node_modules/undici/lib/dispatcher/agent.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError, MaxOriginsReachedError } = require_errors2(); + var { kBusy, kClients, kConnected, kRunning, kClose, kDestroy, kDispatch, kUrl } = require_symbols(); + var DispatcherBase = require_dispatcher_base(); + var Pool = require_pool(); + var Client = require_client(); + var util = require_util(); + var kOnConnect = /* @__PURE__ */ Symbol("onConnect"); + var kOnDisconnect = /* @__PURE__ */ Symbol("onDisconnect"); + var kOnConnectionError = /* @__PURE__ */ Symbol("onConnectionError"); + var kOnDrain = /* @__PURE__ */ Symbol("onDrain"); + var kFactory = /* @__PURE__ */ Symbol("factory"); + var kOptions = /* @__PURE__ */ Symbol("options"); + var kOrigins = /* @__PURE__ */ Symbol("origins"); + function defaultFactory(origin, opts) { + return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); + } + var Agent = class extends DispatcherBase { + constructor({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options2 } = {}) { + if (typeof factory !== "function") { + throw new InvalidArgumentError("factory must be a function."); + } + if (connect != null && typeof connect !== "function" && typeof connect !== "object") { + throw new InvalidArgumentError("connect must be a function or an object"); + } + if (typeof maxOrigins !== "number" || Number.isNaN(maxOrigins) || maxOrigins <= 0) { + throw new InvalidArgumentError("maxOrigins must be a number greater than 0"); + } + super(options2); + if (connect && typeof connect !== "function") { + connect = { ...connect }; + } + this[kOptions] = { ...util.deepClone(options2), maxOrigins, connect }; + this[kFactory] = factory; + this[kClients] = /* @__PURE__ */ new Map(); + this[kOrigins] = /* @__PURE__ */ new Set(); + this[kOnDrain] = (origin, targets) => { + this.emit("drain", origin, [this, ...targets]); + }; + this[kOnConnect] = (origin, targets) => { + this.emit("connect", origin, [this, ...targets]); + }; + this[kOnDisconnect] = (origin, targets, err) => { + this.emit("disconnect", origin, [this, ...targets], err); + }; + this[kOnConnectionError] = (origin, targets, err) => { + this.emit("connectionError", origin, [this, ...targets], err); + }; + } + get [kRunning]() { + let ret = 0; + for (const dispatcher of this[kClients].values()) { + ret += dispatcher[kRunning]; + } + return ret; + } + [kDispatch](opts, handler) { + let origin; + if (opts.origin && (typeof opts.origin === "string" || opts.origin instanceof URL)) { + origin = String(opts.origin); + } else { + throw new InvalidArgumentError("opts.origin must be a non-empty string or URL."); + } + const allowH2 = opts.allowH2 ?? this[kOptions].allowH2; + const key = allowH2 === false ? `${origin}#http1-only` : origin; + if (this[kOrigins].size >= this[kOptions].maxOrigins && !this[kOrigins].has(origin)) { + throw new MaxOriginsReachedError(); + } + let dispatcher = this[kClients].get(key); + if (!dispatcher) { + dispatcher = this[kFactory](opts.origin, allowH2 === false ? { ...this[kOptions], allowH2: false } : this[kOptions]); + const closeClientIfUnused = () => { + if (this[kClients].get(key) !== dispatcher) { + return; + } + if (dispatcher[kConnected] > 0 || dispatcher[kBusy]) { + return; + } + this[kClients].delete(key); + if (!dispatcher.destroyed) { + dispatcher.close(); + } + let hasOrigin = false; + for (const k of this[kClients].keys()) { + if (k === origin || k === `${origin}#http1-only`) { + hasOrigin = true; + break; + } + } + if (!hasOrigin) { + this[kOrigins].delete(origin); + } + }; + dispatcher.on("drain", this[kOnDrain]).on("connect", this[kOnConnect]).on("disconnect", (origin2, targets, err) => { + closeClientIfUnused(); + this[kOnDisconnect](origin2, targets, err); + }).on("connectionError", (origin2, targets, err) => { + closeClientIfUnused(); + this[kOnConnectionError](origin2, targets, err); + }); + this[kClients].set(key, dispatcher); + this[kOrigins].add(origin); + } + return dispatcher.dispatch(opts, handler); + } + [kClose]() { + const closePromises = []; + for (const dispatcher of this[kClients].values()) { + closePromises.push(dispatcher.close()); + } + this[kClients].clear(); + return Promise.all(closePromises); + } + [kDestroy](err) { + const destroyPromises = []; + for (const dispatcher of this[kClients].values()) { + destroyPromises.push(dispatcher.destroy(err)); + } + this[kClients].clear(); + return Promise.all(destroyPromises); + } + get stats() { + const allClientStats = {}; + for (const dispatcher of this[kClients].values()) { + if (dispatcher.stats) { + allClientStats[dispatcher[kUrl].origin] = dispatcher.stats; + } + } + return allClientStats; + } + }; + module2.exports = Agent; + } +}); + +// node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +var require_dispatcher1_wrapper = __commonJS({ + "node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js"(exports2, module2) { + "use strict"; + var Dispatcher = require_dispatcher(); + var { InvalidArgumentError } = require_errors2(); + var { toRawHeaders } = require_util(); + var LegacyHandlerWrapper = class { + #handler; + constructor(handler) { + this.#handler = handler; + } + onRequestStart(controller, context2) { + this.#handler.onConnect?.((reason2) => controller.abort(reason2), context2); + } + onRequestUpgrade(controller, statusCode, headers2, socket) { + const rawHeaders = controller?.rawHeaders ?? toRawHeaders(headers2 ?? {}); + this.#handler.onUpgrade?.(statusCode, rawHeaders, socket); + } + onResponseStart(controller, statusCode, headers2, statusMessage) { + const rawHeaders = controller?.rawHeaders ?? toRawHeaders(headers2 ?? {}); + if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) { + controller.pause(); + } + } + onResponseData(controller, chunk) { + if (this.#handler.onData?.(chunk) === false) { + controller.pause(); + } + } + onResponseEnd(controller, trailers) { + const rawTrailers = controller?.rawTrailers ?? toRawHeaders(trailers ?? {}); + this.#handler.onComplete?.(rawTrailers); + } + onResponseError(_controller, err) { + if (!this.#handler.onError) { + throw err; + } + this.#handler.onError(err); + } + onBodySent(chunk) { + this.#handler.onBodySent?.(chunk); + } + onRequestSent() { + this.#handler.onRequestSent?.(); + } + onResponseStarted() { + this.#handler.onResponseStarted?.(); + } + }; + var Dispatcher1Wrapper = class _Dispatcher1Wrapper extends Dispatcher { + #dispatcher; + constructor(dispatcher) { + super(); + if (!dispatcher || typeof dispatcher.dispatch !== "function") { + throw new InvalidArgumentError("Argument dispatcher must implement dispatch"); + } + this.#dispatcher = dispatcher; + } + static wrapHandler(handler) { + if (!handler || typeof handler !== "object") { + throw new InvalidArgumentError("handler must be an object"); + } + if (typeof handler.onRequestStart === "function") { + return handler; + } + return new LegacyHandlerWrapper(handler); + } + dispatch(opts, handler) { + if (opts.allowH2 !== false) { + opts = { ...opts, allowH2: false }; + } + return this.#dispatcher.dispatch(opts, _Dispatcher1Wrapper.wrapHandler(handler)); + } + close(...args) { + return this.#dispatcher.close(...args); + } + destroy(...args) { + return this.#dispatcher.destroy(...args); + } + }; + module2.exports = Dispatcher1Wrapper; + } +}); + +// node_modules/undici/lib/core/socks5-utils.js +var require_socks5_utils = __commonJS({ + "node_modules/undici/lib/core/socks5-utils.js"(exports2, module2) { + "use strict"; + var { Buffer: Buffer10 } = require("node:buffer"); + var net = require("node:net"); + var { InvalidArgumentError } = require_errors2(); + function parseAddress(address) { + if (net.isIPv4(address)) { + const parts = address.split(".").map(Number); + return { + type: 1, + // IPv4 + buffer: Buffer10.from(parts) + }; + } + if (net.isIPv6(address)) { + return { + type: 4, + // IPv6 + buffer: parseIPv6(address) + }; + } + const domainBuffer = Buffer10.from(address, "utf8"); + if (domainBuffer.length > 255) { + throw new InvalidArgumentError("Domain name too long (max 255 bytes)"); + } + return { + type: 3, + // Domain + buffer: Buffer10.concat([Buffer10.from([domainBuffer.length]), domainBuffer]) + }; + } + function parseIPv6(address) { + const buffer2 = Buffer10.alloc(16); + let normalizedAddress = address; + if (address.includes(".")) { + const lastColonIndex = address.lastIndexOf(":"); + const ipv4Part = address.slice(lastColonIndex + 1); + if (net.isIPv4(ipv4Part)) { + const octets = ipv4Part.split(".").map(Number); + const high = (octets[0] << 8 | octets[1]).toString(16); + const low = (octets[2] << 8 | octets[3]).toString(16); + normalizedAddress = `${address.slice(0, lastColonIndex)}:${high}:${low}`; + } + } + const doubleColonIndex = normalizedAddress.indexOf("::"); + if (doubleColonIndex !== -1) { + const before = normalizedAddress.slice(0, doubleColonIndex); + const after = normalizedAddress.slice(doubleColonIndex + 2); + const beforeParts = before === "" ? [] : before.split(":"); + const afterParts = after === "" ? [] : after.split(":"); + let bufferIndex = 0; + for (const part of beforeParts) { + buffer2.writeUInt16BE(parseInt(part, 16), bufferIndex); + bufferIndex += 2; + } + bufferIndex = 16 - afterParts.length * 2; + for (const part of afterParts) { + buffer2.writeUInt16BE(parseInt(part, 16), bufferIndex); + bufferIndex += 2; + } + } else { + const parts = normalizedAddress.split(":"); + for (let i = 0; i < parts.length; i++) { + buffer2.writeUInt16BE(parseInt(parts[i], 16), i * 2); + } + } + return buffer2; + } + function buildAddressBuffer(type2, addressBuffer, port) { + const portBuffer = Buffer10.allocUnsafe(2); + portBuffer.writeUInt16BE(port, 0); + return Buffer10.concat([ + Buffer10.from([type2]), + addressBuffer, + portBuffer + ]); + } + function parseResponseAddress(buffer2, offset2 = 0) { + if (buffer2.length < offset2 + 1) { + throw new InvalidArgumentError("Buffer too small to contain address type"); + } + const addressType = buffer2[offset2]; + let address; + let currentOffset = offset2 + 1; + switch (addressType) { + case 1: { + if (buffer2.length < currentOffset + 6) { + throw new InvalidArgumentError("Buffer too small for IPv4 address"); + } + address = Array.from(buffer2.subarray(currentOffset, currentOffset + 4)).join("."); + currentOffset += 4; + break; + } + case 3: { + if (buffer2.length < currentOffset + 1) { + throw new InvalidArgumentError("Buffer too small for domain length"); + } + const domainLength = buffer2[currentOffset]; + currentOffset += 1; + if (buffer2.length < currentOffset + domainLength + 2) { + throw new InvalidArgumentError("Buffer too small for domain address"); + } + address = buffer2.subarray(currentOffset, currentOffset + domainLength).toString("utf8"); + currentOffset += domainLength; + break; + } + case 4: { + if (buffer2.length < currentOffset + 18) { + throw new InvalidArgumentError("Buffer too small for IPv6 address"); + } + const parts = []; + for (let i = 0; i < 8; i++) { + const value2 = buffer2.readUInt16BE(currentOffset + i * 2); + parts.push(value2.toString(16)); + } + address = parts.join(":"); + currentOffset += 16; + break; + } + default: + throw new InvalidArgumentError(`Invalid address type: ${addressType}`); + } + if (buffer2.length < currentOffset + 2) { + throw new InvalidArgumentError("Buffer too small for port"); + } + const port = buffer2.readUInt16BE(currentOffset); + currentOffset += 2; + return { + address, + port, + bytesRead: currentOffset - offset2 + }; + } + function createReplyError(replyCode) { + const messages = { + 1: "General SOCKS server failure", + 2: "Connection not allowed by ruleset", + 3: "Network unreachable", + 4: "Host unreachable", + 5: "Connection refused", + 6: "TTL expired", + 7: "Command not supported", + 8: "Address type not supported" + }; + const message = messages[replyCode] || `Unknown SOCKS5 error code: ${replyCode}`; + const error2 = new Error(message); + error2.code = `SOCKS5_${replyCode}`; + return error2; + } + module2.exports = { + parseAddress, + parseIPv6, + buildAddressBuffer, + parseResponseAddress, + createReplyError + }; + } +}); + +// node_modules/undici/lib/core/socks5-client.js +var require_socks5_client = __commonJS({ + "node_modules/undici/lib/core/socks5-client.js"(exports2, module2) { + "use strict"; + var { EventEmitter } = require("node:events"); + var { Buffer: Buffer10 } = require("node:buffer"); + var { InvalidArgumentError, Socks5ProxyError } = require_errors2(); + var { debuglog } = require("node:util"); + var { parseAddress } = require_socks5_utils(); + var debug = debuglog("undici:socks5"); + var EMPTY_BUFFER = Buffer10.alloc(0); + var SOCKS_VERSION = 5; + var AUTH_METHODS = { + NO_AUTH: 0, + GSSAPI: 1, + USERNAME_PASSWORD: 2, + NO_ACCEPTABLE: 255 + }; + var COMMANDS = { + CONNECT: 1, + BIND: 2, + UDP_ASSOCIATE: 3 + }; + var ADDRESS_TYPES = { + IPV4: 1, + DOMAIN: 3, + IPV6: 4 + }; + var REPLY_CODES = { + SUCCEEDED: 0, + GENERAL_FAILURE: 1, + CONNECTION_NOT_ALLOWED: 2, + NETWORK_UNREACHABLE: 3, + HOST_UNREACHABLE: 4, + CONNECTION_REFUSED: 5, + TTL_EXPIRED: 6, + COMMAND_NOT_SUPPORTED: 7, + ADDRESS_TYPE_NOT_SUPPORTED: 8 + }; + var STATES = { + INITIAL: "initial", + HANDSHAKING: "handshaking", + AUTHENTICATING: "authenticating", + AUTHENTICATED: "authenticated", + CONNECTING: "connecting", + CONNECTED: "connected", + ERROR: "error", + CLOSED: "closed" + }; + var Socks5Client = class extends EventEmitter { + constructor(socket, options2 = {}) { + super(); + if (!socket) { + throw new InvalidArgumentError("socket is required"); + } + this.socket = socket; + this.options = options2; + this.state = STATES.INITIAL; + this.buffer = EMPTY_BUFFER; + this.onSocketData = this.onData.bind(this); + this.onSocketError = this.onError.bind(this); + this.onSocketClose = this.onClose.bind(this); + this.authMethods = []; + if (options2.username && options2.password) { + this.authMethods.push(AUTH_METHODS.USERNAME_PASSWORD); + } + this.authMethods.push(AUTH_METHODS.NO_AUTH); + this.socket.on("data", this.onSocketData); + this.socket.on("error", this.onSocketError); + this.socket.on("close", this.onSocketClose); + } + /** + * Handle incoming data from the socket + */ + onData(data2) { + debug("received data", data2.length, "bytes in state", this.state); + this.buffer = Buffer10.concat([this.buffer, data2]); + try { + switch (this.state) { + case STATES.HANDSHAKING: + this.handleHandshakeResponse(); + break; + case STATES.AUTHENTICATING: + this.handleAuthResponse(); + break; + case STATES.CONNECTING: + this.handleConnectResponse(); + break; + } + } catch (err) { + this.onError(err); + } + } + /** + * Handle socket errors + */ + onError(err) { + debug("socket error", err); + this.state = STATES.ERROR; + this.emit("error", err); + this.destroy(); + } + /** + * Handle socket close + */ + onClose() { + debug("socket closed"); + this.state = STATES.CLOSED; + this.emit("close"); + } + /** + * Destroy the client and underlying socket + */ + destroy() { + if (this.socket && !this.socket.destroyed) { + this.socket.destroy(); + } + } + markAuthenticated() { + this.state = STATES.AUTHENTICATED; + this.emit("authenticated"); + } + /** + * Start the SOCKS5 handshake + */ + handshake() { + if (this.state !== STATES.INITIAL) { + throw new InvalidArgumentError("Handshake already started"); + } + debug("starting handshake with", this.authMethods.length, "auth methods"); + this.state = STATES.HANDSHAKING; + const request = Buffer10.alloc(2 + this.authMethods.length); + request[0] = SOCKS_VERSION; + request[1] = this.authMethods.length; + this.authMethods.forEach((method2, i) => { + request[2 + i] = method2; + }); + this.socket.write(request); + } + /** + * Handle handshake response from server + */ + handleHandshakeResponse() { + if (this.buffer.length < 2) { + return; + } + const version = this.buffer[0]; + const method2 = this.buffer[1]; + if (version !== SOCKS_VERSION) { + throw new Socks5ProxyError(`Invalid SOCKS version: ${version}`, "UND_ERR_SOCKS5_VERSION"); + } + if (method2 === AUTH_METHODS.NO_ACCEPTABLE) { + throw new Socks5ProxyError("No acceptable authentication method", "UND_ERR_SOCKS5_AUTH_REJECTED"); + } + this.buffer = this.buffer.subarray(2); + debug("server selected auth method", method2); + if (method2 === AUTH_METHODS.NO_AUTH) { + this.markAuthenticated(); + } else if (method2 === AUTH_METHODS.USERNAME_PASSWORD) { + this.state = STATES.AUTHENTICATING; + this.sendAuthRequest(); + } else { + throw new Socks5ProxyError(`Unsupported authentication method: ${method2}`, "UND_ERR_SOCKS5_AUTH_METHOD"); + } + } + /** + * Send username/password authentication request + */ + sendAuthRequest() { + const { username, password } = this.options; + if (!username || !password) { + throw new InvalidArgumentError("Username and password required for authentication"); + } + debug("sending username/password auth"); + const usernameBuffer = Buffer10.from(username); + const passwordBuffer = Buffer10.from(password); + if (usernameBuffer.length > 255 || passwordBuffer.length > 255) { + throw new InvalidArgumentError("Username or password too long"); + } + const request = Buffer10.alloc(3 + usernameBuffer.length + passwordBuffer.length); + request[0] = 1; + request[1] = usernameBuffer.length; + usernameBuffer.copy(request, 2); + request[2 + usernameBuffer.length] = passwordBuffer.length; + passwordBuffer.copy(request, 3 + usernameBuffer.length); + this.socket.write(request); + } + /** + * Handle authentication response + */ + handleAuthResponse() { + if (this.buffer.length < 2) { + return; + } + const version = this.buffer[0]; + const status = this.buffer[1]; + if (version !== 1) { + throw new Socks5ProxyError(`Invalid auth sub-negotiation version: ${version}`, "UND_ERR_SOCKS5_AUTH_VERSION"); + } + if (status !== 0) { + throw new Socks5ProxyError("Authentication failed", "UND_ERR_SOCKS5_AUTH_FAILED"); + } + this.buffer = this.buffer.subarray(2); + debug("authentication successful"); + this.markAuthenticated(); + } + /** + * Send CONNECT command + * @param {string} address - Target address (IP or domain) + * @param {number} port - Target port + */ + connect(address, port) { + if (this.state === STATES.CONNECTING || this.state === STATES.CONNECTED) { + throw new InvalidArgumentError("Connection already in progress"); + } + if (this.state !== STATES.AUTHENTICATED) { + throw new InvalidArgumentError("Client must be authenticated before CONNECT"); + } + debug("connecting to", address, port); + this.state = STATES.CONNECTING; + const request = this.buildConnectRequest(COMMANDS.CONNECT, address, port); + this.socket.write(request); + } + /** + * Build a SOCKS5 request + */ + buildConnectRequest(command, address, port) { + const { type: addressType, buffer: addressBuffer } = parseAddress(address); + const request = Buffer10.alloc(4 + addressBuffer.length + 2); + request[0] = SOCKS_VERSION; + request[1] = command; + request[2] = 0; + request[3] = addressType; + addressBuffer.copy(request, 4); + request.writeUInt16BE(port, 4 + addressBuffer.length); + return request; + } + /** + * Handle CONNECT response + */ + handleConnectResponse() { + if (this.buffer.length < 4) { + return; + } + const version = this.buffer[0]; + const reply = this.buffer[1]; + const addressType = this.buffer[3]; + if (version !== SOCKS_VERSION) { + throw new Socks5ProxyError(`Invalid SOCKS version in reply: ${version}`, "UND_ERR_SOCKS5_REPLY_VERSION"); + } + let responseLength = 4; + if (addressType === ADDRESS_TYPES.IPV4) { + responseLength += 4 + 2; + } else if (addressType === ADDRESS_TYPES.DOMAIN) { + if (this.buffer.length < 5) { + return; + } + responseLength += 1 + this.buffer[4] + 2; + } else if (addressType === ADDRESS_TYPES.IPV6) { + responseLength += 16 + 2; + } else { + throw new Socks5ProxyError(`Invalid address type in reply: ${addressType}`, "UND_ERR_SOCKS5_ADDR_TYPE"); + } + if (this.buffer.length < responseLength) { + return; + } + if (reply !== REPLY_CODES.SUCCEEDED) { + const errorMessage = this.getReplyErrorMessage(reply); + throw new Socks5ProxyError(`SOCKS5 connection failed: ${errorMessage}`, `UND_ERR_SOCKS5_REPLY_${reply}`); + } + let boundAddress; + let offset2 = 4; + if (addressType === ADDRESS_TYPES.IPV4) { + boundAddress = Array.from(this.buffer.subarray(offset2, offset2 + 4)).join("."); + offset2 += 4; + } else if (addressType === ADDRESS_TYPES.DOMAIN) { + const domainLength = this.buffer[offset2]; + offset2 += 1; + boundAddress = this.buffer.subarray(offset2, offset2 + domainLength).toString(); + offset2 += domainLength; + } else if (addressType === ADDRESS_TYPES.IPV6) { + const parts = []; + for (let i = 0; i < 8; i++) { + const value2 = this.buffer.readUInt16BE(offset2 + i * 2); + parts.push(value2.toString(16)); + } + boundAddress = parts.join(":"); + offset2 += 16; + } + const boundPort = this.buffer.readUInt16BE(offset2); + this.buffer = EMPTY_BUFFER; + this.state = STATES.CONNECTED; + this.socket.removeListener("data", this.onSocketData); + debug("connected, bound address:", boundAddress, "port:", boundPort); + this.emit("connected", { address: boundAddress, port: boundPort }); + } + /** + * Get human-readable error message for reply code + */ + getReplyErrorMessage(reply) { + switch (reply) { + case REPLY_CODES.GENERAL_FAILURE: + return "General SOCKS server failure"; + case REPLY_CODES.CONNECTION_NOT_ALLOWED: + return "Connection not allowed by ruleset"; + case REPLY_CODES.NETWORK_UNREACHABLE: + return "Network unreachable"; + case REPLY_CODES.HOST_UNREACHABLE: + return "Host unreachable"; + case REPLY_CODES.CONNECTION_REFUSED: + return "Connection refused"; + case REPLY_CODES.TTL_EXPIRED: + return "TTL expired"; + case REPLY_CODES.COMMAND_NOT_SUPPORTED: + return "Command not supported"; + case REPLY_CODES.ADDRESS_TYPE_NOT_SUPPORTED: + return "Address type not supported"; + default: + return `Unknown error code: ${reply}`; + } + } + }; + module2.exports = { + Socks5Client, + AUTH_METHODS, + COMMANDS, + ADDRESS_TYPES, + REPLY_CODES, + STATES + }; + } +}); + +// node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +var require_socks5_proxy_agent = __commonJS({ + "node_modules/undici/lib/dispatcher/socks5-proxy-agent.js"(exports2, module2) { + "use strict"; + var { URL: URL13 } = require("node:url"); + var tls; + var DispatcherBase = require_dispatcher_base(); + var { InvalidArgumentError } = require_errors2(); + var { Socks5Client, STATES } = require_socks5_client(); + var { kBusy, kConnected, kDispatch, kClose, kDestroy } = require_symbols(); + var Pool = require_pool(); + var buildConnector = require_connect(); + var { debuglog } = require("node:util"); + var debug = debuglog("undici:socks5-proxy"); + var kProxyUrl = /* @__PURE__ */ Symbol("proxy url"); + var kProxyHeaders = /* @__PURE__ */ Symbol("proxy headers"); + var kProxyAuth = /* @__PURE__ */ Symbol("proxy auth"); + var kProxyProtocol = /* @__PURE__ */ Symbol("proxy protocol"); + var kPools = /* @__PURE__ */ Symbol("pools"); + var kConnector = /* @__PURE__ */ Symbol("connector"); + var kRequestTls = /* @__PURE__ */ Symbol("request tls settings"); + var experimentalWarningEmitted = false; + var Socks5ProxyAgent = class extends DispatcherBase { + constructor(proxyUrl2, options2 = {}) { + super(); + if (!experimentalWarningEmitted) { + process.emitWarning( + "SOCKS5 proxy support is experimental and subject to change", + "ExperimentalWarning" + ); + experimentalWarningEmitted = true; + } + if (!proxyUrl2) { + throw new InvalidArgumentError("Proxy URL is mandatory"); + } + const url2 = typeof proxyUrl2 === "string" ? new URL13(proxyUrl2) : proxyUrl2; + if (url2.protocol !== "socks5:" && url2.protocol !== "socks:") { + throw new InvalidArgumentError("Proxy URL must use socks5:// or socks:// protocol"); + } + this[kProxyUrl] = url2; + this[kProxyHeaders] = options2.headers || {}; + this[kProxyProtocol] = options2.proxyTls ? "https:" : "http:"; + this[kRequestTls] = options2.requestTls; + this[kProxyAuth] = { + username: options2.username || (url2.username ? decodeURIComponent(url2.username) : null), + password: options2.password || (url2.password ? decodeURIComponent(url2.password) : null) + }; + this[kConnector] = options2.connect || buildConnector({ + ...options2.proxyTls, + servername: options2.proxyTls?.servername || url2.hostname + }); + this[kPools] = /* @__PURE__ */ new Map(); + } + /** + * Create a SOCKS5 connection to the proxy + */ + async createSocks5Connection(targetHost, targetPort) { + const proxyHost = this[kProxyUrl].hostname; + const proxyPort = parseInt(this[kProxyUrl].port) || 1080; + debug("creating SOCKS5 connection to", proxyHost, proxyPort); + const socketReady = Promise.withResolvers(); + this[kConnector]({ + hostname: proxyHost, + host: proxyHost, + port: proxyPort, + protocol: this[kProxyProtocol] + }, (err, socket2) => { + if (err) { + socketReady.reject(err); + } else { + socketReady.resolve(socket2); + } + }); + const socket = await socketReady.promise; + const socks5Client = new Socks5Client(socket, this[kProxyAuth]); + socks5Client.on("error", (err) => { + debug("SOCKS5 error:", err); + socket.destroy(); + }); + await socks5Client.handshake(); + const authenticationReady = Promise.withResolvers(); + const authenticationTimeout = setTimeout(() => { + authenticationReady.reject(new Error("SOCKS5 authentication timeout")); + }, 5e3); + const onAuthenticated = () => { + clearTimeout(authenticationTimeout); + socks5Client.removeListener("error", onAuthenticationError); + authenticationReady.resolve(); + }; + const onAuthenticationError = (err) => { + clearTimeout(authenticationTimeout); + socks5Client.removeListener("authenticated", onAuthenticated); + authenticationReady.reject(err); + }; + if (socks5Client.state === STATES.AUTHENTICATED) { + clearTimeout(authenticationTimeout); + authenticationReady.resolve(); + } else { + socks5Client.once("authenticated", onAuthenticated); + socks5Client.once("error", onAuthenticationError); + } + await authenticationReady.promise; + await socks5Client.connect(targetHost, targetPort); + const connectionReady = Promise.withResolvers(); + const connectionTimeout = setTimeout(() => { + connectionReady.reject(new Error("SOCKS5 connection timeout")); + }, 5e3); + const onConnected = (info) => { + debug("SOCKS5 tunnel established to", targetHost, targetPort, "via", info); + clearTimeout(connectionTimeout); + socks5Client.removeListener("error", onConnectionError); + connectionReady.resolve(); + }; + const onConnectionError = (err) => { + clearTimeout(connectionTimeout); + socks5Client.removeListener("connected", onConnected); + connectionReady.reject(err); + }; + socks5Client.once("connected", onConnected); + socks5Client.once("error", onConnectionError); + await connectionReady.promise; + return socket; + } + /** + * Dispatch a request through the SOCKS5 proxy + */ + [kDispatch](opts, handler) { + const { origin } = opts; + debug("dispatching request to", origin, "via SOCKS5"); + try { + const originKey = String(origin); + let pool2 = this[kPools].get(originKey); + if (!pool2 || pool2.destroyed || pool2.closed) { + pool2 = new Pool(origin, { + pipelining: opts.pipelining, + connections: opts.connections, + connect: async (connectOpts, callback) => { + try { + const url2 = new URL13(origin); + const targetHost = url2.hostname; + const targetPort = parseInt(url2.port) || (url2.protocol === "https:" ? 443 : 80); + debug("establishing SOCKS5 connection to", targetHost, targetPort); + const socket = await this.createSocks5Connection(targetHost, targetPort); + let finalSocket = socket; + if (url2.protocol === "https:") { + if (!tls) { + tls = require("node:tls"); + } + debug("upgrading to TLS"); + finalSocket = tls.connect({ + ...this[kRequestTls], + socket, + servername: this[kRequestTls]?.servername || targetHost + }); + const tlsReady = Promise.withResolvers(); + finalSocket.once("secureConnect", tlsReady.resolve); + finalSocket.once("error", tlsReady.reject); + await tlsReady.promise; + } + callback(null, finalSocket); + } catch (err) { + debug("SOCKS5 connection error:", err); + callback(err); + } + } + }); + this[kPools].set(originKey, pool2); + const closePoolIfUnused = () => { + if (this[kPools].get(originKey) !== pool2 || pool2[kConnected] > 0 || pool2[kBusy]) { + return; + } + this[kPools].delete(originKey); + if (!pool2.destroyed) { + pool2.close(); + } + }; + pool2.on("disconnect", closePoolIfUnused); + pool2.on("connectionError", closePoolIfUnused); + } + return pool2[kDispatch](opts, handler); + } catch (err) { + debug("dispatch error:", err); + if (typeof handler.onResponseError === "function") { + handler.onResponseError(null, err); + return false; + } else if (typeof handler.onError === "function") { + handler.onError(err); + return false; + } else { + throw err; + } + } + } + async [kClose]() { + const closePromises = []; + for (const pool2 of this[kPools].values()) { + closePromises.push(pool2.close()); + } + this[kPools].clear(); + await Promise.all(closePromises); + } + async [kDestroy](err) { + const destroyPromises = []; + for (const pool2 of this[kPools].values()) { + destroyPromises.push(pool2.destroy(err)); + } + this[kPools].clear(); + await Promise.all(destroyPromises); + } + }; + module2.exports = Socks5ProxyAgent; + } +}); + +// node_modules/undici/lib/dispatcher/proxy-agent.js +var require_proxy_agent = __commonJS({ + "node_modules/undici/lib/dispatcher/proxy-agent.js"(exports2, module2) { + "use strict"; + var { kProxy, kClose, kDestroy, kDispatch } = require_symbols(); + var Agent = require_agent(); + var Pool = require_pool(); + var DispatcherBase = require_dispatcher_base(); + var { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError, ProxyConnectionError } = require_errors2(); + var buildConnector = require_connect(); + var Client = require_client(); + var { channels } = require_diagnostics(); + var Socks5ProxyAgent = require_socks5_proxy_agent(); + var kAgent = /* @__PURE__ */ Symbol("proxy agent"); + var kClient = /* @__PURE__ */ Symbol("proxy client"); + var kProxyHeaders = /* @__PURE__ */ Symbol("proxy headers"); + var kRequestTls = /* @__PURE__ */ Symbol("request tls settings"); + var kProxyTls = /* @__PURE__ */ Symbol("proxy tls settings"); + var kConnectEndpoint = /* @__PURE__ */ Symbol("connect endpoint function"); + var kConnectEndpointHTTP1 = /* @__PURE__ */ Symbol("connect endpoint function (http/1.1 only)"); + var kTunnelProxy = /* @__PURE__ */ Symbol("tunnel proxy"); + var proxyAuthorization = "proxy-authorization"; + function defaultProtocolPort(protocol) { + return protocol === "https:" ? 443 : 80; + } + function defaultFactory(origin, opts) { + return new Pool(origin, opts); + } + var noop = () => { + }; + function defaultAgentFactory(origin, opts) { + if (opts.connections === 1) { + return new Client(origin, opts); + } + return new Pool(origin, opts); + } + function shouldProxyTunnel(requestProtocol, proxyTunnel) { + return proxyTunnel === true || requestProtocol !== "http:"; + } + var Http1ProxyWrapper = class extends DispatcherBase { + #client; + #proxyServername; + constructor(proxyUrl2, { headers: headers2 = {}, connect, factory, proxyServername }) { + if (!proxyUrl2) { + throw new InvalidArgumentError("Proxy URL is mandatory"); + } + super(); + this[kProxyHeaders] = headers2; + this.#proxyServername = proxyServername; + if (factory) { + this.#client = factory(proxyUrl2, { connect }); + } else { + this.#client = new Client(proxyUrl2, { connect }); + } + } + [kDispatch](opts, handler) { + const onResponseStart = handler.onResponseStart; + handler.onResponseStart = function(controller, statusCode, data2, statusMessage) { + if (statusCode === 407) { + if (typeof handler.onResponseError === "function") { + handler.onResponseError(controller, new InvalidArgumentError("Proxy Authentication Required (407)")); + } + return; + } + if (onResponseStart) onResponseStart.call(this, controller, statusCode, data2, statusMessage); + }; + const { + origin, + path: path2 = "/", + headers: headers2 = {} + } = opts; + opts.path = origin + path2; + if (!("host" in headers2) && !("Host" in headers2)) { + const { host: host2 } = new URL(origin); + headers2.host = host2; + } + opts.headers = { ...this[kProxyHeaders], ...headers2 }; + if (this.#proxyServername != null) { + opts.servername = this.#proxyServername; + } + return this.#client[kDispatch](opts, handler); + } + [kClose]() { + return this.#client.close(); + } + [kDestroy](err) { + return this.#client.destroy(err); + } + }; + var ProxyAgent2 = class extends DispatcherBase { + constructor(opts) { + if (!opts || typeof opts === "object" && !(opts instanceof URL) && !opts.uri) { + throw new InvalidArgumentError("Proxy uri is mandatory"); + } + const { clientFactory = defaultFactory } = opts; + if (typeof clientFactory !== "function") { + throw new InvalidArgumentError("Proxy opts.clientFactory must be a function."); + } + const { proxyTunnel, connectTimeout } = opts; + super(); + const url2 = this.#getUrl(opts); + const { href: href2, origin, port, protocol, username, password, hostname: proxyHostname } = url2; + this[kProxy] = { uri: href2, protocol }; + this[kRequestTls] = opts.requestTls; + this[kProxyTls] = opts.proxyTls; + this[kProxyHeaders] = opts.headers || {}; + this[kTunnelProxy] = proxyTunnel; + if (opts.auth && opts.token) { + throw new InvalidArgumentError("opts.auth cannot be used in combination with opts.token"); + } else if (opts.auth) { + this[kProxyHeaders]["proxy-authorization"] = `Basic ${opts.auth}`; + } else if (opts.token) { + this[kProxyHeaders]["proxy-authorization"] = opts.token; + } else if (username && password) { + this[kProxyHeaders]["proxy-authorization"] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:${decodeURIComponent(password)}`).toString("base64")}`; + } else if (username) { + this[kProxyHeaders]["proxy-authorization"] = `Basic ${Buffer.from(`${decodeURIComponent(username)}:`).toString("base64")}`; + } + const connect = buildConnector({ timeout: connectTimeout, ...opts.proxyTls }); + const connectHTTP1 = buildConnector({ timeout: connectTimeout, ...opts.proxyTls, allowH2: false }); + this[kConnectEndpoint] = buildConnector({ timeout: connectTimeout, ...opts.requestTls }); + this[kConnectEndpointHTTP1] = buildConnector({ timeout: connectTimeout, ...opts.requestTls, allowH2: false }); + const agentFactory = opts.factory || defaultAgentFactory; + const factory = (origin2, options2) => { + const { protocol: protocol2 } = new URL(origin2); + if (this[kProxy].protocol === "socks5:" || this[kProxy].protocol === "socks:") { + return new Socks5ProxyAgent(this[kProxy].uri, { + headers: this[kProxyHeaders], + connect, + factory: agentFactory, + username: opts.username || username, + password: opts.password || password, + proxyTls: opts.proxyTls, + requestTls: opts.requestTls + }); + } + if (!shouldProxyTunnel(protocol2, this[kTunnelProxy])) { + const forwardConnect = this[kProxy].protocol === "https:" ? (opts2, cb) => connectHTTP1(opts2, (err, socket) => { + if (err && err.code === "ERR_TLS_CERT_ALTNAME_INVALID") { + cb(new SecureProxyConnectionError(err)); + } else { + cb(err, socket); + } + }) : connectHTTP1; + return new Http1ProxyWrapper(this[kProxy].uri, { + headers: this[kProxyHeaders], + connect: forwardConnect, + factory: agentFactory, + proxyServername: this[kProxy].protocol === "https:" ? this[kProxyTls]?.servername || proxyHostname : void 0 + }); + } + return agentFactory(origin2, options2); + }; + if (protocol === "socks5:" || protocol === "socks:") { + this[kClient] = null; + } else { + this[kClient] = clientFactory(url2, { connect }); + } + this[kAgent] = new Agent({ + ...opts, + factory, + connect: async (opts2, callback) => { + if (!this[kClient]) { + callback(new InvalidArgumentError("Cannot establish tunnel connection without a proxy client")); + return; + } + let requestedPath = opts2.host; + if (!opts2.port) { + requestedPath += `:${defaultProtocolPort(opts2.protocol)}`; + } + try { + const connectParams = { + origin, + port, + path: requestedPath, + signal: opts2.signal, + headers: { + ...this[kProxyHeaders], + host: opts2.host, + ...opts2.connections == null || opts2.connections > 0 ? { "proxy-connection": "keep-alive" } : {} + }, + servername: this[kProxyTls]?.servername || proxyHostname + }; + const { socket, statusCode } = await this[kClient].connect(connectParams); + if (statusCode !== 200) { + socket.on("error", noop).destroy(); + callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)); + return; + } + if (channels.proxyConnected.hasSubscribers) { + channels.proxyConnected.publish({ + socket, + connectParams + }); + } + if (opts2.protocol !== "https:") { + callback(null, socket); + return; + } + let servername; + if (this[kRequestTls]) { + servername = this[kRequestTls].servername; + } else { + servername = opts2.servername; + } + const connectEndpoint = opts2.allowH2 === false ? this[kConnectEndpointHTTP1] : this[kConnectEndpoint]; + connectEndpoint({ ...opts2, servername, httpSocket: socket }, callback); + } catch (err) { + if (err.code === "ERR_TLS_CERT_ALTNAME_INVALID") { + callback(new SecureProxyConnectionError(err)); + } else if (err.code === "UND_ERR_SOCKET") { + callback(new ProxyConnectionError(err)); + } else { + callback(err); + } + } + } + }); + } + dispatch(opts, handler) { + const headers2 = buildHeaders(opts.headers); + throwIfProxyAuthIsSent(headers2); + if (headers2 && !("host" in headers2) && !("Host" in headers2)) { + const { host: host2 } = new URL(opts.origin); + headers2.host = host2; + } + return this[kAgent].dispatch( + { + ...opts, + headers: headers2 + }, + handler + ); + } + /** + * @param {import('../../types/proxy-agent').ProxyAgent.Options | string | URL} opts + * @returns {URL} + */ + #getUrl(opts) { + if (typeof opts === "string") { + return new URL(opts); + } else if (opts instanceof URL) { + return opts; + } else { + return new URL(opts.uri); + } + } + [kClose]() { + const promises = [this[kAgent].close()]; + if (this[kClient]) { + promises.push(this[kClient].close()); + } + return Promise.all(promises); + } + [kDestroy]() { + const promises = [this[kAgent].destroy()]; + if (this[kClient]) { + promises.push(this[kClient].destroy()); + } + return Promise.all(promises); + } + }; + function buildHeaders(headers2) { + if (Array.isArray(headers2)) { + const headersPair = {}; + for (let i = 0; i < headers2.length; i += 2) { + if (isProxyAuthorizationHeader(headers2[i])) { + throwProxyAuthError(); + } + headersPair[headers2[i]] = headers2[i + 1]; + } + return headersPair; + } + return headers2; + } + function throwIfProxyAuthIsSent(headers2) { + for (const key in headers2) { + if (isProxyAuthorizationHeader(key)) { + throwProxyAuthError(); + } + } + } + function isProxyAuthorizationHeader(key) { + return key.length === proxyAuthorization.length && key.toLowerCase() === proxyAuthorization; + } + function throwProxyAuthError() { + throw new InvalidArgumentError("Proxy-Authorization should be sent in ProxyAgent constructor"); + } + module2.exports = ProxyAgent2; + } +}); + +// node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +var require_env_http_proxy_agent = __commonJS({ + "node_modules/undici/lib/dispatcher/env-http-proxy-agent.js"(exports2, module2) { + "use strict"; + var DispatcherBase = require_dispatcher_base(); + var { kClose, kDestroy, kClosed, kDestroyed, kDispatch, kNoProxyAgent, kHttpProxyAgent, kHttpsProxyAgent } = require_symbols(); + var ProxyAgent2 = require_proxy_agent(); + var Agent = require_agent(); + var DEFAULT_PORTS = { + "http:": 80, + "https:": 443 + }; + var EnvHttpProxyAgent = class extends DispatcherBase { + #noProxyValue = null; + #noProxyEntries = null; + #opts = null; + constructor(opts = {}) { + super(); + this.#opts = opts; + const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts; + this[kNoProxyAgent] = new Agent(agentOpts); + const HTTP_PROXY = httpProxy ?? process.env.http_proxy ?? process.env.HTTP_PROXY; + if (HTTP_PROXY) { + this[kHttpProxyAgent] = new ProxyAgent2({ ...agentOpts, uri: HTTP_PROXY }); + } else { + this[kHttpProxyAgent] = this[kNoProxyAgent]; + } + const HTTPS_PROXY = httpsProxy ?? process.env.https_proxy ?? process.env.HTTPS_PROXY; + if (HTTPS_PROXY) { + this[kHttpsProxyAgent] = new ProxyAgent2({ ...agentOpts, uri: HTTPS_PROXY }); + } else { + this[kHttpsProxyAgent] = this[kHttpProxyAgent]; + } + this.#parseNoProxy(); + } + [kDispatch](opts, handler) { + const url2 = new URL(opts.origin); + const agent = this.#getProxyAgentForUrl(url2); + return agent.dispatch(opts, handler); + } + [kClose]() { + return Promise.all([ + this[kNoProxyAgent].close(), + !this[kHttpProxyAgent][kClosed] && this[kHttpProxyAgent].close(), + !this[kHttpsProxyAgent][kClosed] && this[kHttpsProxyAgent].close() + ]); + } + [kDestroy](err) { + return Promise.all([ + this[kNoProxyAgent].destroy(err), + !this[kHttpProxyAgent][kDestroyed] && this[kHttpProxyAgent].destroy(err), + !this[kHttpsProxyAgent][kDestroyed] && this[kHttpsProxyAgent].destroy(err) + ]); + } + #getProxyAgentForUrl(url2) { + let { protocol, host: hostname, port } = url2; + hostname = hostname.replace(/:\d*$/, "").replace(/^\[(.+)\]$/, "$1").toLowerCase(); + port = Number.parseInt(port, 10) || DEFAULT_PORTS[protocol] || 0; + if (!this.#shouldProxy(hostname, port)) { + return this[kNoProxyAgent]; + } + if (protocol === "https:") { + return this[kHttpsProxyAgent]; + } + return this[kHttpProxyAgent]; + } + #shouldProxy(hostname, port) { + if (this.#noProxyChanged) { + this.#parseNoProxy(); + } + if (this.#noProxyEntries.length === 0) { + return true; + } + if (this.#noProxyValue === "*") { + return false; + } + for (let i = 0; i < this.#noProxyEntries.length; i++) { + const entry = this.#noProxyEntries[i]; + if (entry.port && entry.port !== port) { + continue; + } + if (hostname === entry.hostname) { + return false; + } + if (hostname.slice(-(entry.hostname.length + 1)) === `.${entry.hostname}`) { + return false; + } + } + return true; + } + #parseNoProxy() { + const noProxyValue = this.#opts.noProxy ?? this.#noProxyEnv; + const noProxySplit = noProxyValue.split(/[,\s]/); + const noProxyEntries = []; + for (let i = 0; i < noProxySplit.length; i++) { + const entry = noProxySplit[i]; + if (!entry) { + continue; + } + let hostname, port; + const ipv6WithPort = entry.match(/^\[(.+)\]:(\d+)$/); + if (ipv6WithPort) { + hostname = ipv6WithPort[1]; + port = Number.parseInt(ipv6WithPort[2], 10); + } else { + const unbracketed = entry.replace(/^\[(.+)\]$/, "$1"); + const colonCount = (unbracketed.match(/:/g) || []).length; + const parsed = colonCount === 1 && unbracketed.match(/^(.+):(\d+)$/); + hostname = parsed ? parsed[1] : unbracketed; + port = parsed ? Number.parseInt(parsed[2], 10) : 0; + } + noProxyEntries.push({ + // strip leading dot or asterisk with dot + hostname: hostname.replace(/^\*?\./, "").toLowerCase(), + port + }); + } + this.#noProxyValue = noProxyValue; + this.#noProxyEntries = noProxyEntries; + } + get #noProxyChanged() { + if (this.#opts.noProxy !== void 0) { + return false; + } + return this.#noProxyValue !== this.#noProxyEnv; + } + get #noProxyEnv() { + return process.env.no_proxy ?? process.env.NO_PROXY ?? ""; + } + }; + module2.exports = EnvHttpProxyAgent; + } +}); + +// node_modules/undici/lib/handler/retry-handler.js +var require_retry_handler = __commonJS({ + "node_modules/undici/lib/handler/retry-handler.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { kRetryHandlerDefaultRetry } = require_symbols(); + var { RequestRetryError } = require_errors2(); + var { + isDisturbed, + parseRangeHeader, + wrapRequestBody + } = require_util(); + function calculateRetryAfterHeader(retryAfter) { + const retryTime = new Date(retryAfter).getTime(); + return isNaN(retryTime) ? null : retryTime - Date.now(); + } + function validatePartialResponseContentLength(headers2, range, statusCode, retryCount) { + const contentLength2 = headers2["content-length"]; + if (contentLength2 == null) { + return; + } + if (!Number.isFinite(range.start) || !Number.isFinite(range.end)) { + return; + } + const length2 = Number(contentLength2); + const expectedLength = range.end - range.start + 1; + if (!Number.isFinite(length2) || length2 !== expectedLength) { + throw new RequestRetryError("Content-Length mismatch", statusCode, { + headers: headers2, + data: { count: retryCount } + }); + } + } + var RetryController = class { + constructor() { + this.target = null; + } + pause() { + this.target?.pause(); + } + resume() { + this.target?.resume(); + } + abort(reason2) { + this.target?.abort(reason2); + } + get paused() { + return this.target?.paused ?? false; + } + get aborted() { + return this.target?.aborted ?? false; + } + get reason() { + return this.target?.reason ?? null; + } + get rawHeaders() { + return this.target?.rawHeaders ?? null; + } + get rawTrailers() { + return this.target?.rawTrailers ?? null; + } + }; + var RetryHandler = class _RetryHandler { + constructor(opts, { dispatch: dispatch2, handler }) { + const { retryOptions, ...dispatchOpts } = opts; + const { + // Retry scoped + retry: retryFn, + maxRetries, + maxTimeout, + minTimeout, + timeoutFactor, + // Response scoped + methods, + errorCodes, + retryAfter, + statusCodes, + throwOnError + } = retryOptions ?? {}; + this.error = null; + this.dispatch = dispatch2; + this.handler = handler; + this.opts = { ...dispatchOpts, body: wrapRequestBody(opts.body) }; + this.retryOpts = { + throwOnError: throwOnError ?? true, + retry: retryFn ?? _RetryHandler[kRetryHandlerDefaultRetry], + retryAfter: retryAfter ?? true, + maxTimeout: maxTimeout ?? 30 * 1e3, + // 30s, + minTimeout: minTimeout ?? 500, + // .5s + timeoutFactor: timeoutFactor ?? 2, + maxRetries: maxRetries ?? 5, + // What errors we should retry + methods: methods ?? ["GET", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE", "QUERY"], + // Indicates which errors to retry + statusCodes: statusCodes ?? [500, 502, 503, 504, 429], + // List of errors to retry + errorCodes: errorCodes ?? [ + "ECONNRESET", + "ECONNREFUSED", + "ENOTFOUND", + "ENETDOWN", + "ENETUNREACH", + "EHOSTDOWN", + "EHOSTUNREACH", + "EPIPE", + "UND_ERR_SOCKET" + ] + }; + this.retryCount = 0; + this.retryCountCheckpoint = 0; + this.headersSent = false; + this.start = 0; + this.end = null; + this.etag = null; + this.statusCode = null; + this.headers = null; + this.controllerProxy = new RetryController(); + } + onResponseStartWithRetry(controller, statusCode, headers2, statusMessage, err) { + if (this.retryOpts.throwOnError) { + if (this.retryOpts.statusCodes.includes(statusCode) === false) { + this.headersSent = true; + this.handler.onResponseStart?.(this.controllerProxy, statusCode, headers2, statusMessage); + } else { + this.error = err; + } + return; + } + if (isDisturbed(this.opts.body)) { + this.headersSent = true; + this.handler.onResponseStart?.(this.controllerProxy, statusCode, headers2, statusMessage); + return; + } + function shouldRetry(passedErr) { + if (passedErr) { + this.headersSent = true; + this.handler.onResponseStart?.(this.controllerProxy, statusCode, headers2, statusMessage); + controller.resume(); + return; + } + this.error = err; + controller.resume(); + } + controller.pause(); + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + shouldRetry.bind(this) + ); + } + onRequestStart(controller, context2) { + this.controllerProxy.target = controller; + if (!this.headersSent) { + this.handler.onRequestStart?.(this.controllerProxy, context2); + } + } + onRequestUpgrade(_controller, statusCode, headers2, socket) { + this.handler.onRequestUpgrade?.(this.controllerProxy, statusCode, headers2, socket); + } + static [kRetryHandlerDefaultRetry](err, { state: state2, opts }, cb) { + const { statusCode, code, headers: headers2 } = err; + const { method: method2, retryOptions } = opts; + const { + maxRetries, + minTimeout, + maxTimeout, + timeoutFactor, + statusCodes, + errorCodes, + methods + } = retryOptions; + const { counter } = state2; + if (code && code !== "UND_ERR_REQ_RETRY" && !errorCodes.includes(code)) { + cb(err); + return; + } + if (Array.isArray(methods) && !methods.includes(method2)) { + cb(err); + return; + } + if (statusCode != null && Array.isArray(statusCodes) && !statusCodes.includes(statusCode)) { + cb(err); + return; + } + if (counter > maxRetries) { + cb(err); + return; + } + let retryAfterHeader = headers2?.["retry-after"]; + if (retryAfterHeader) { + retryAfterHeader = Number(retryAfterHeader); + retryAfterHeader = Number.isNaN(retryAfterHeader) ? calculateRetryAfterHeader(headers2["retry-after"]) : retryAfterHeader * 1e3; + } + const retryTimeout = retryAfterHeader === 0 ? 0 : retryAfterHeader > 0 ? Math.min(retryAfterHeader, maxTimeout) : Math.min(minTimeout * timeoutFactor ** (counter - 1), maxTimeout); + setTimeout(() => cb(null), retryTimeout); + } + onResponseStart(controller, statusCode, headers2, statusMessage) { + if (statusCode < 200) { + this.handler.onResponseStart?.(this.controllerProxy, statusCode, headers2, statusMessage); + return; + } + this.error = null; + this.retryCount += 1; + this.statusCode = statusCode; + this.headers = headers2; + if (statusCode >= 300) { + const err = new RequestRetryError("Request failed", statusCode, { + headers: headers2, + data: { + count: this.retryCount + } + }); + this.onResponseStartWithRetry(controller, statusCode, headers2, statusMessage, err); + return; + } + if (this.headersSent) { + if (statusCode !== 206 && (this.start > 0 || statusCode !== 200)) { + throw new RequestRetryError("server does not support the range header and the payload was partially consumed", statusCode, { + headers: headers2, + data: { count: this.retryCount } + }); + } + const contentRange = parseRangeHeader(headers2["content-range"]); + if (!contentRange) { + throw new RequestRetryError("Content-Range mismatch", statusCode, { + headers: headers2, + data: { count: this.retryCount } + }); + } + if (this.etag != null && this.etag !== headers2.etag) { + throw new RequestRetryError("ETag mismatch", statusCode, { + headers: headers2, + data: { count: this.retryCount } + }); + } + validatePartialResponseContentLength(headers2, contentRange, statusCode, this.retryCount); + const { start: start2, size, end: end2 = size ? size - 1 : null } = contentRange; + assert(this.start === start2, "content-range mismatch"); + assert(this.end == null || this.end === end2, "content-range mismatch"); + return; + } + if (this.end == null) { + if (statusCode === 206) { + const range = parseRangeHeader(headers2["content-range"]); + if (range == null || range.end == null) { + this.headersSent = true; + this.handler.onResponseStart?.( + this.controllerProxy, + statusCode, + headers2, + statusMessage + ); + return; + } + validatePartialResponseContentLength(headers2, range, statusCode, this.retryCount); + const { start: start2, size, end: end2 = size ? size - 1 : null } = range; + assert( + start2 != null && Number.isFinite(start2), + "content-range mismatch" + ); + assert(end2 != null && Number.isFinite(end2), "invalid content-length"); + this.start = start2; + this.end = end2; + } + if (this.end == null && this.opts.method !== "HEAD") { + const contentLength2 = headers2["content-length"]; + this.end = contentLength2 != null ? Number(contentLength2) - 1 : null; + } + assert(Number.isFinite(this.start)); + assert( + this.end == null || Number.isFinite(this.end), + "invalid content-length" + ); + this.resume = true; + this.etag = headers2.etag != null ? headers2.etag : null; + if (this.etag != null && this.etag[0] === "W" && this.etag[1] === "/") { + this.etag = null; + } + this.headersSent = true; + this.handler.onResponseStart?.( + this.controllerProxy, + statusCode, + headers2, + statusMessage + ); + } else { + throw new RequestRetryError("Request failed", statusCode, { + headers: headers2, + data: { count: this.retryCount } + }); + } + } + onResponseData(_controller, chunk) { + if (this.error) { + return; + } + this.start += chunk.length; + this.handler.onResponseData?.(this.controllerProxy, chunk); + } + onResponseEnd(_controller, trailers) { + if (this.error && this.retryOpts.throwOnError) { + throw this.error; + } + if (!this.error) { + if (this.end != null && Number.isFinite(this.end)) { + if (this.start !== this.end + 1) { + throw new RequestRetryError("Content-Range mismatch", this.statusCode, { + headers: this.headers, + data: { count: this.retryCount } + }); + } + } + this.retryCount = 0; + return this.handler.onResponseEnd?.(this.controllerProxy, trailers); + } + this.retry(); + } + retry() { + if (this.start !== 0) { + const headers2 = { range: `bytes=${this.start}-${this.end ?? ""}` }; + if (this.etag != null) { + headers2["if-match"] = this.etag; + } + this.opts = { + ...this.opts, + headers: { + ...this.opts.headers, + ...headers2 + } + }; + } + try { + this.retryCountCheckpoint = this.retryCount; + this.dispatch(this.opts, this); + } catch (err) { + this.handler.onResponseError?.(this.controllerProxy, err); + } + } + onResponseError(controller, err) { + if (controller?.aborted || isDisturbed(this.opts.body)) { + this.handler.onResponseError?.(this.controllerProxy, err); + return; + } + function shouldRetry(returnedErr) { + if (!returnedErr) { + this.retry(); + return; + } + this.handler?.onResponseError?.(this.controllerProxy, returnedErr); + } + if (this.retryCount - this.retryCountCheckpoint > 0) { + this.retryCount = this.retryCountCheckpoint + (this.retryCount - this.retryCountCheckpoint); + } else { + this.retryCount += 1; + } + this.retryOpts.retry( + err, + { + state: { counter: this.retryCount }, + opts: { retryOptions: this.retryOpts, ...this.opts } + }, + shouldRetry.bind(this) + ); + } + }; + module2.exports = RetryHandler; + } +}); + +// node_modules/undici/lib/dispatcher/retry-agent.js +var require_retry_agent = __commonJS({ + "node_modules/undici/lib/dispatcher/retry-agent.js"(exports2, module2) { + "use strict"; + var Dispatcher = require_dispatcher(); + var RetryHandler = require_retry_handler(); + var RetryAgent = class extends Dispatcher { + #agent = null; + #options = null; + constructor(agent, options2 = {}) { + super(options2); + this.#agent = agent; + this.#options = options2; + } + dispatch(opts, handler) { + const retry = new RetryHandler({ + ...opts, + retryOptions: this.#options + }, { + dispatch: this.#agent.dispatch.bind(this.#agent), + handler + }); + return this.#agent.dispatch(opts, retry); + } + close() { + return this.#agent.close(); + } + destroy() { + return this.#agent.destroy(); + } + }; + module2.exports = RetryAgent; + } +}); + +// node_modules/undici/lib/dispatcher/h2c-client.js +var require_h2c_client = __commonJS({ + "node_modules/undici/lib/dispatcher/h2c-client.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError } = require_errors2(); + var Client = require_client(); + var H2CClient = class extends Client { + constructor(origin, clientOpts) { + if (typeof origin === "string") { + origin = new URL(origin); + } + if (origin.protocol !== "http:") { + throw new InvalidArgumentError( + "h2c-client: Only h2c protocol is supported" + ); + } + const { maxConcurrentStreams, pipelining, ...opts } = clientOpts ?? {}; + const defaultMaxConcurrentStreams = maxConcurrentStreams ?? 100; + let defaultPipelining = 100; + if (maxConcurrentStreams != null && (!Number.isInteger(maxConcurrentStreams) || maxConcurrentStreams < 1)) { + throw new InvalidArgumentError("maxConcurrentStreams must be a positive integer, greater than 0"); + } + if (pipelining != null && Number.isInteger(pipelining) && pipelining > 0) { + defaultPipelining = pipelining; + } + if (defaultPipelining > defaultMaxConcurrentStreams) { + throw new InvalidArgumentError( + "h2c-client: pipelining cannot be greater than maxConcurrentStreams" + ); + } + super(origin, { + ...opts, + maxConcurrentStreams: defaultMaxConcurrentStreams, + pipelining: defaultPipelining, + allowH2: true, + useH2c: true + }); + } + }; + module2.exports = H2CClient; + } +}); + +// node_modules/undici/lib/api/readable.js +var require_readable = __commonJS({ + "node_modules/undici/lib/api/readable.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { addAbortListener } = require("node:events"); + var { Readable: Readable2 } = require("node:stream"); + var { RequestAbortedError, NotSupportedError, InvalidArgumentError, AbortError } = require_errors2(); + var util = require_util(); + var { ReadableStreamFrom } = require_util(); + var kConsume = /* @__PURE__ */ Symbol("kConsume"); + var kReading = /* @__PURE__ */ Symbol("kReading"); + var kBody = /* @__PURE__ */ Symbol("kBody"); + var kAbort = /* @__PURE__ */ Symbol("kAbort"); + var kContentType = /* @__PURE__ */ Symbol("kContentType"); + var kContentLength = /* @__PURE__ */ Symbol("kContentLength"); + var kUsed = /* @__PURE__ */ Symbol("kUsed"); + var kBytesRead = /* @__PURE__ */ Symbol("kBytesRead"); + var noop = () => { + }; + var BodyReadable = class extends Readable2 { + /** + * @param {object} opts + * @param {(this: Readable, size: number) => void} opts.resume + * @param {() => (void | null)} opts.abort + * @param {string} [opts.contentType = ''] + * @param {number} [opts.contentLength] + * @param {number} [opts.highWaterMark = 64 * 1024] + */ + constructor({ + resume, + abort: abort2, + contentType: contentType2 = "", + contentLength: contentLength2, + highWaterMark = 64 * 1024 + // Same as nodejs fs streams. + }) { + super({ + autoDestroy: true, + read: resume, + highWaterMark + }); + this._readableState.dataEmitted = false; + this[kAbort] = abort2; + this[kConsume] = null; + this[kBytesRead] = 0; + this[kBody] = null; + this[kUsed] = false; + this[kContentType] = contentType2; + this[kContentLength] = Number.isFinite(contentLength2) ? contentLength2 : null; + this[kReading] = false; + } + /** + * @param {Error|null} err + * @param {(error:(Error|null)) => void} callback + * @returns {void} + */ + _destroy(err, callback) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError(); + } + if (err) { + this[kAbort](); + } + if (!this[kUsed]) { + setImmediate(callback, err); + } else { + callback(err); + } + } + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + on(event, listener) { + if (event === "data" || event === "readable") { + this[kReading] = true; + this[kUsed] = true; + } + return super.on(event, listener); + } + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + addListener(event, listener) { + return this.on(event, listener); + } + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + off(event, listener) { + const ret = super.off(event, listener); + if (event === "data" || event === "readable") { + this[kReading] = this.listenerCount("data") > 0 || this.listenerCount("readable") > 0; + } + return ret; + } + /** + * @param {string|symbol} event + * @param {(...args: any[]) => void} listener + * @returns {this} + */ + removeListener(event, listener) { + return this.off(event, listener); + } + /** + * @param {Buffer|null} chunk + * @returns {boolean} + */ + push(chunk) { + if (chunk) { + this[kBytesRead] += chunk.length; + if (this[kConsume]) { + consumePush(this[kConsume], chunk); + return this[kReading] ? super.push(chunk) : true; + } + } + return super.push(chunk); + } + /** + * Consumes and returns the body as a string. + * + * @see https://fetch.spec.whatwg.org/#dom-body-text + * @returns {Promise} + */ + text() { + return consume(this, "text"); + } + /** + * Consumes and returns the body as a JavaScript Object. + * + * @see https://fetch.spec.whatwg.org/#dom-body-json + * @returns {Promise} + */ + json() { + return consume(this, "json"); + } + /** + * Consumes and returns the body as a Blob + * + * @see https://fetch.spec.whatwg.org/#dom-body-blob + * @returns {Promise} + */ + blob() { + return consume(this, "blob"); + } + /** + * Consumes and returns the body as an Uint8Array. + * + * @see https://fetch.spec.whatwg.org/#dom-body-bytes + * @returns {Promise} + */ + bytes() { + return consume(this, "bytes"); + } + /** + * Consumes and returns the body as an ArrayBuffer. + * + * @see https://fetch.spec.whatwg.org/#dom-body-arraybuffer + * @returns {Promise} + */ + arrayBuffer() { + return consume(this, "arrayBuffer"); + } + /** + * Not implemented + * + * @see https://fetch.spec.whatwg.org/#dom-body-formdata + * @throws {NotSupportedError} + */ + async formData() { + throw new NotSupportedError(); + } + /** + * Returns true if the body is not null and the body has been consumed. + * Otherwise, returns false. + * + * @see https://fetch.spec.whatwg.org/#dom-body-bodyused + * @readonly + * @returns {boolean} + */ + get bodyUsed() { + return util.isDisturbed(this); + } + /** + * @see https://fetch.spec.whatwg.org/#dom-body-body + * @readonly + * @returns {ReadableStream} + */ + get body() { + if (!this[kBody]) { + this[kBody] = ReadableStreamFrom(this); + if (this[kConsume]) { + this[kBody].getReader(); + assert(this[kBody].locked); + } + } + return this[kBody]; + } + /** + * Dumps the response body by reading `limit` number of bytes. + * @param {object} opts + * @param {number} [opts.limit = 131072] Number of bytes to read. + * @param {AbortSignal} [opts.signal] An AbortSignal to cancel the dump. + * @returns {Promise} + */ + dump(opts) { + const signal2 = opts?.signal; + if (signal2 != null && (typeof signal2 !== "object" || !("aborted" in signal2))) { + return Promise.reject(new InvalidArgumentError("signal must be an AbortSignal")); + } + const limit = opts?.limit && Number.isFinite(opts.limit) ? opts.limit : 128 * 1024; + if (signal2?.aborted) { + return Promise.reject(signal2.reason ?? new AbortError()); + } + if (this._readableState.closeEmitted) { + return Promise.resolve(null); + } + return new Promise((resolve, reject) => { + if (this[kContentLength] && this[kContentLength] > limit || this[kBytesRead] > limit) { + this.destroy(new AbortError()); + } + if (signal2) { + const onAbort = () => { + this.destroy(signal2.reason ?? new AbortError()); + }; + const abortListener = addAbortListener(signal2, onAbort); + this.on("close", function() { + abortListener[Symbol.dispose](); + if (signal2.aborted) { + reject(signal2.reason ?? new AbortError()); + } else { + resolve(null); + } + }); + } else { + this.on("close", resolve); + } + this.on("error", noop).on("data", () => { + if (this[kBytesRead] > limit) { + this.destroy(); + } + }).resume(); + }); + } + /** + * @param {BufferEncoding} encoding + * @returns {this} + */ + setEncoding(encoding) { + if (Buffer.isEncoding(encoding)) { + super.setEncoding(encoding); + } + return this; + } + }; + function isLocked(bodyReadable) { + return bodyReadable[kBody]?.locked === true || bodyReadable[kConsume] !== null; + } + function isUnusable(bodyReadable) { + return util.isDisturbed(bodyReadable) || isLocked(bodyReadable); + } + function consume(stream, type2) { + assert(!stream[kConsume]); + return new Promise((resolve, reject) => { + if (isUnusable(stream)) { + const rState = stream._readableState; + if (rState.destroyed && rState.closeEmitted === false) { + stream.on("error", reject).on("close", () => { + reject(new TypeError("unusable")); + }); + } else { + reject(rState.errored ?? new TypeError("unusable")); + } + } else { + queueMicrotask(() => { + stream[kConsume] = { + type: type2, + stream, + resolve, + reject, + length: 0, + body: [] + }; + stream.on("error", function(err) { + consumeFinish(this[kConsume], err); + }).on("close", function() { + if (this[kConsume].body !== null) { + consumeFinish(this[kConsume], new RequestAbortedError()); + } + }); + consumeStart(stream[kConsume]); + }); + } + }); + } + function consumeStart(consume2) { + if (consume2.body === null) { + return; + } + const { _readableState: state2 } = consume2.stream; + if (state2.bufferIndex) { + const start2 = state2.bufferIndex; + const end2 = state2.buffer.length; + for (let n = start2; n < end2; n++) { + consumePush(consume2, state2.buffer[n]); + } + } else { + for (const chunk of state2.buffer) { + consumePush(consume2, chunk); + } + } + const decoder = state2.decoder; + if (decoder != null && decoder.lastNeed > 0) { + consumePush(consume2, Buffer.from(decoder.lastChar.subarray(0, decoder.lastTotal - decoder.lastNeed))); + } + if (state2.endEmitted) { + consumeEnd(consume2, state2.encoding); + return; + } + consume2.stream.on("end", function() { + consumeEnd(this[kConsume], this._readableState.encoding); + }); + consume2.stream.resume(); + while (consume2.stream.read() != null) { + } + } + function chunksDecode(chunks, length2, encoding) { + if (chunks.length === 0 || length2 === 0) { + return ""; + } + const buffer2 = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks, length2); + const bufferLength = buffer2.length; + const start2 = bufferLength > 2 && buffer2[0] === 239 && buffer2[1] === 187 && buffer2[2] === 191 ? 3 : 0; + if (!encoding || encoding === "utf8" || encoding === "utf-8") { + return buffer2.utf8Slice(start2, bufferLength); + } else { + return buffer2.subarray(start2, bufferLength).toString(encoding); + } + } + function chunksConcat(chunks, length2) { + if (chunks.length === 0 || length2 === 0) { + return new Uint8Array(0); + } + if (chunks.length === 1) { + return new Uint8Array(chunks[0]); + } + const buffer2 = new Uint8Array(Buffer.allocUnsafeSlow(length2).buffer); + let offset2 = 0; + for (let i = 0; i < chunks.length; ++i) { + const chunk = chunks[i]; + buffer2.set(chunk, offset2); + offset2 += chunk.length; + } + return buffer2; + } + function consumeEnd(consume2, encoding) { + const { type: type2, body: body2, resolve, stream, length: length2 } = consume2; + try { + if (type2 === "text") { + resolve(chunksDecode(body2, length2, encoding)); + } else if (type2 === "json") { + resolve(JSON.parse(chunksDecode(body2, length2, encoding))); + } else if (type2 === "arrayBuffer") { + resolve(chunksConcat(body2, length2).buffer); + } else if (type2 === "blob") { + resolve(new Blob(body2, { type: stream[kContentType] })); + } else if (type2 === "bytes") { + resolve(chunksConcat(body2, length2)); + } + consumeFinish(consume2); + } catch (err) { + stream.destroy(err); + } + } + function consumePush(consume2, chunk) { + if (consume2.body === null) { + return; + } + if (typeof chunk === "string") { + chunk = Buffer.from(chunk, consume2.stream._readableState.encoding); + } + consume2.length += chunk.length; + consume2.body.push(chunk); + } + function consumeFinish(consume2, err) { + if (consume2.body === null) { + return; + } + if (err) { + consume2.reject(err); + } else { + consume2.resolve(); + } + consume2.type = null; + consume2.stream = null; + consume2.resolve = null; + consume2.reject = null; + consume2.length = 0; + consume2.body = null; + } + module2.exports = { + Readable: BodyReadable, + chunksDecode + }; + } +}); + +// node_modules/undici/lib/api/api-request.js +var require_api_request = __commonJS({ + "node_modules/undici/lib/api/api-request.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { AsyncResource } = require("node:async_hooks"); + var { Readable: Readable2 } = require_readable(); + var { InvalidArgumentError, RequestAbortedError } = require_errors2(); + var util = require_util(); + function noop() { + } + var RequestHandler = class extends AsyncResource { + constructor(opts, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + const { signal: signal2, method: method2, opaque, body: body2, onInfo, responseHeaders, highWaterMark } = opts; + try { + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + if (highWaterMark != null && (!Number.isFinite(highWaterMark) || highWaterMark < 0)) { + throw new InvalidArgumentError("invalid highWaterMark"); + } + if (signal2 && typeof signal2.on !== "function" && typeof signal2.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + if (method2 === "CONNECT") { + throw new InvalidArgumentError("invalid method"); + } + if (onInfo && typeof onInfo !== "function") { + throw new InvalidArgumentError("invalid onInfo callback"); + } + super("UNDICI_REQUEST"); + } catch (err) { + if (util.isStream(body2)) { + util.destroy(body2.on("error", noop), err); + } + throw err; + } + this.method = method2; + this.responseHeaders = responseHeaders || null; + this.opaque = opaque || null; + this.callback = callback; + this.res = null; + this.abort = null; + this.body = body2; + this.trailers = {}; + this.context = null; + this.controller = null; + this.onInfo = onInfo || null; + this.highWaterMark = highWaterMark; + this.reason = null; + this.removeAbortListener = null; + if (signal2?.aborted) { + this.reason = signal2.reason ?? new RequestAbortedError(); + } else if (signal2) { + this.removeAbortListener = util.addAbortListener(signal2, () => { + this.reason = signal2.reason ?? new RequestAbortedError(); + if (this.res) { + const res = this.res; + this.res = null; + util.destroy(res.on("error", noop), this.reason); + } else if (this.abort) { + this.abort(this.reason); + } + }); + } + } + onRequestStart(controller, context2) { + if (this.reason) { + controller.abort(this.reason); + return; + } + assert(this.callback); + this.controller = controller; + this.abort = (reason2) => controller.abort(reason2); + this.context = context2; + } + onResponseStart(controller, statusCode, headers2, statusText) { + const { callback, opaque, context: context2, responseHeaders, highWaterMark } = this; + const rawHeaders = controller?.rawHeaders; + const responseHeaderData = responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : headers2; + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers: responseHeaderData }); + } + return; + } + const parsedHeaders = headers2; + const contentType2 = parsedHeaders?.["content-type"]; + const contentLength2 = parsedHeaders?.["content-length"]; + const res = new Readable2({ + resume: () => controller.resume(), + abort: (reason2) => controller.abort(reason2), + contentType: contentType2, + contentLength: this.method !== "HEAD" && contentLength2 ? Number(contentLength2) : null, + highWaterMark + }); + if (this.removeAbortListener) { + res.on("close", this.removeAbortListener); + this.removeAbortListener = null; + } + this.callback = null; + this.res = res; + if (callback !== null) { + try { + this.runInAsyncScope(callback, null, null, { + statusCode, + statusText, + headers: responseHeaderData, + trailers: this.trailers, + opaque, + body: res, + context: context2 + }); + } catch (err) { + this.res = null; + util.destroy(res.on("error", noop), err); + queueMicrotask(() => { + throw err; + }); + } + } + } + onResponseData(controller, chunk) { + if (!this.res) { + return; + } + if (this.res.push(chunk) === false) { + controller.pause(); + } + } + onResponseEnd(_controller, trailers) { + if (trailers && typeof trailers === "object") { + for (const key of Object.keys(trailers)) { + if (key === "__proto__") { + Object.defineProperty(this.trailers, key, { + value: trailers[key], + enumerable: true, + configurable: true, + writable: true + }); + } else { + this.trailers[key] = trailers[key]; + } + } + } + this.res?.push(null); + } + onResponseError(_controller, err) { + const { res, callback, body: body2, opaque } = this; + if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); + } + if (res) { + this.res = null; + queueMicrotask(() => { + util.destroy(res.on("error", noop), err); + }); + } + if (body2) { + this.body = null; + if (util.isStream(body2)) { + body2.on("error", noop); + util.destroy(body2, err); + } + } + if (this.removeAbortListener) { + this.removeAbortListener(); + this.removeAbortListener = null; + } + } + }; + function request(opts, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + request.call(this, opts, (err, data2) => { + return err ? reject(err) : resolve(data2); + }); + }); + } + try { + const handler = new RequestHandler(opts, callback); + this.dispatch(opts, handler); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts?.opaque; + queueMicrotask(() => callback(err, { opaque })); + } + } + module2.exports = request; + module2.exports.RequestHandler = RequestHandler; + } +}); + +// node_modules/undici/lib/api/abort-signal.js +var require_abort_signal = __commonJS({ + "node_modules/undici/lib/api/abort-signal.js"(exports2, module2) { + "use strict"; + var { addAbortListener } = require_util(); + var { RequestAbortedError } = require_errors2(); + var kListener = /* @__PURE__ */ Symbol("kListener"); + var kSignal = /* @__PURE__ */ Symbol("kSignal"); + function abort2(self2) { + if (self2.abort) { + self2.abort(self2[kSignal]?.reason); + } else { + self2.reason = self2[kSignal]?.reason ?? new RequestAbortedError(); + } + removeSignal(self2); + } + function addSignal(self2, signal2) { + self2.reason = null; + self2[kSignal] = null; + self2[kListener] = null; + if (!signal2) { + return; + } + if (signal2.aborted) { + abort2(self2); + return; + } + self2[kSignal] = signal2; + self2[kListener] = () => { + abort2(self2); + }; + addAbortListener(self2[kSignal], self2[kListener]); + } + function removeSignal(self2) { + if (!self2[kSignal]) { + return; + } + if ("removeEventListener" in self2[kSignal]) { + self2[kSignal].removeEventListener("abort", self2[kListener]); + } else { + self2[kSignal].removeListener("abort", self2[kListener]); + } + self2[kSignal] = null; + self2[kListener] = null; + } + module2.exports = { + addSignal, + removeSignal + }; + } +}); + +// node_modules/undici/lib/api/api-stream.js +var require_api_stream = __commonJS({ + "node_modules/undici/lib/api/api-stream.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { AsyncResource } = require("node:async_hooks"); + var { InvalidArgumentError, InvalidReturnValueError } = require_errors2(); + var util = require_util(); + var { addSignal, removeSignal } = require_abort_signal(); + function noop() { + } + function getWritableError(stream2) { + return stream2.errored ?? stream2.writableErrored ?? stream2._writableState?.errored; + } + function createPrematureCloseError() { + const err = new Error("Premature close"); + err.code = "ERR_STREAM_PREMATURE_CLOSE"; + return err; + } + function trackWritableLifecycle(stream2, callback) { + let done = false; + const cleanup = () => { + stream2.removeListener("close", onClose); + stream2.removeListener("error", onError); + stream2.removeListener("finish", onFinish); + }; + const finish = (err, fromErrorEvent = false) => { + if (done) { + return; + } + done = true; + cleanup(); + callback(err, fromErrorEvent); + }; + const onClose = () => { + const err = getWritableError(stream2); + finish(err ?? (!stream2.writableFinished ? createPrematureCloseError() : void 0)); + }; + const onError = (err) => finish(err, true); + const onFinish = () => finish(); + stream2.on("close", onClose); + stream2.on("error", onError); + stream2.on("finish", onFinish); + if (stream2.closed) { + process.nextTick(onClose); + } else if (stream2.writableFinished) { + process.nextTick(onFinish); + } + } + var StreamHandler = class extends AsyncResource { + constructor(opts, factory, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + const { signal: signal2, method: method2, opaque, body: body2, onInfo, responseHeaders } = opts; + try { + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + if (typeof factory !== "function") { + throw new InvalidArgumentError("invalid factory"); + } + if (signal2 && typeof signal2.on !== "function" && typeof signal2.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + if (method2 === "CONNECT") { + throw new InvalidArgumentError("invalid method"); + } + if (onInfo && typeof onInfo !== "function") { + throw new InvalidArgumentError("invalid onInfo callback"); + } + super("UNDICI_STREAM"); + } catch (err) { + if (util.isStream(body2)) { + util.destroy(body2.on("error", noop), err); + } + throw err; + } + this.responseHeaders = responseHeaders || null; + this.opaque = opaque || null; + this.factory = factory; + this.callback = callback; + this.res = null; + this.abort = null; + this.context = null; + this.controller = null; + this.trailers = null; + this.body = body2; + this.onInfo = onInfo || null; + if (util.isStream(body2)) { + body2.on("error", (err) => { + this.onResponseError(this.controller, err); + }); + } + addSignal(this, signal2); + } + onRequestStart(controller, context2) { + if (this.reason) { + controller.abort(this.reason); + return; + } + assert(this.callback); + this.controller = controller; + this.abort = (reason2) => controller.abort(reason2); + this.context = context2; + } + onResponseStart(controller, statusCode, headers2, _statusMessage) { + const { factory, opaque, context: context2, responseHeaders } = this; + const rawHeaders = controller?.rawHeaders; + const responseHeaderData = responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : headers2; + if (statusCode < 200) { + if (this.onInfo) { + this.onInfo({ statusCode, headers: responseHeaderData }); + } + return; + } + this.factory = null; + if (factory === null) { + return; + } + const res = this.runInAsyncScope(factory, null, { + statusCode, + headers: responseHeaderData, + opaque, + context: context2 + }); + if (!res || typeof res.write !== "function" || typeof res.end !== "function" || typeof res.on !== "function") { + throw new InvalidReturnValueError("expected Writable"); + } + trackWritableLifecycle(res, (err, fromErrorEvent) => { + const { callback, res: res2, opaque: opaque2, trailers, abort: abort2 } = this; + this.res = null; + if (err || !res2?.readable) { + util.destroy(res2, fromErrorEvent ? void 0 : err); + } + this.callback = null; + this.runInAsyncScope(callback, null, err || null, { opaque: opaque2, trailers }); + if (err) { + abort2(err); + } + }); + res.on("drain", () => controller.resume()); + this.res = res; + const needDrain = res.writableNeedDrain !== void 0 ? res.writableNeedDrain : res._writableState?.needDrain; + if (needDrain === true) { + controller.pause(); + } + } + onResponseData(controller, chunk) { + const { res } = this; + if (!res) { + return; + } + if (res.write(chunk) === false) { + controller.pause(); + } + } + onResponseEnd(_controller, trailers) { + const { res } = this; + removeSignal(this); + if (!res) { + return; + } + if (trailers && typeof trailers === "object") { + this.trailers = trailers; + } + res.end(); + } + onResponseError(_controller, err) { + const { res, callback, opaque, body: body2 } = this; + removeSignal(this); + this.factory = null; + if (res) { + this.res = null; + util.destroy(res, err); + } else if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); + } + if (body2) { + this.body = null; + util.destroy(body2, err); + } + } + }; + function stream(opts, factory, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + stream.call(this, opts, factory, (err, data2) => { + return err ? reject(err) : resolve(data2); + }); + }); + } + try { + const handler = new StreamHandler(opts, factory, callback); + this.dispatch(opts, handler); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts?.opaque; + queueMicrotask(() => callback(err, { opaque })); + } + } + module2.exports = stream; + } +}); + +// node_modules/undici/lib/api/api-pipeline.js +var require_api_pipeline = __commonJS({ + "node_modules/undici/lib/api/api-pipeline.js"(exports2, module2) { + "use strict"; + var { + Readable: Readable2, + Duplex, + PassThrough + } = require("node:stream"); + var assert = require("node:assert"); + var { AsyncResource } = require("node:async_hooks"); + var { + InvalidArgumentError, + InvalidReturnValueError, + RequestAbortedError + } = require_errors2(); + var util = require_util(); + var { kBodyUsed } = require_symbols(); + var { addSignal, removeSignal } = require_abort_signal(); + function noop() { + } + var kResume = /* @__PURE__ */ Symbol("resume"); + var PipelineRequest = class extends Readable2 { + constructor() { + super({ autoDestroy: true }); + this[kResume] = null; + this[kBodyUsed] = true; + } + _read() { + const { [kResume]: resume } = this; + if (resume) { + this[kResume] = null; + resume(); + } + } + _destroy(err, callback) { + this._read(); + callback(err); + } + }; + var PipelineResponse = class extends Readable2 { + constructor(resume) { + super({ autoDestroy: true }); + this[kResume] = resume; + } + _read() { + this[kResume](); + } + _destroy(err, callback) { + if (!err && !this._readableState.endEmitted) { + err = new RequestAbortedError(); + } + callback(err); + } + }; + var PipelineHandler = class extends AsyncResource { + constructor(opts, handler) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (typeof handler !== "function") { + throw new InvalidArgumentError("invalid handler"); + } + const { signal: signal2, method: method2, opaque, onInfo, responseHeaders } = opts; + if (signal2 && typeof signal2.on !== "function" && typeof signal2.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + if (method2 === "CONNECT") { + throw new InvalidArgumentError("invalid method"); + } + if (onInfo && typeof onInfo !== "function") { + throw new InvalidArgumentError("invalid onInfo callback"); + } + super("UNDICI_PIPELINE"); + this.opaque = opaque || null; + this.responseHeaders = responseHeaders || null; + this.handler = handler; + this.abort = null; + this.context = null; + this.onInfo = onInfo || null; + this.req = new PipelineRequest().on("error", noop); + this.ret = new Duplex({ + readableObjectMode: opts.objectMode, + autoDestroy: true, + read: () => { + const { body: body2 } = this; + if (body2?.resume) { + body2.resume(); + } + }, + write: (chunk, encoding, callback) => { + const { req } = this; + if (req.push(chunk, encoding) || req._readableState.destroyed) { + callback(); + } else { + req[kResume] = callback; + } + }, + destroy: (err, callback) => { + const { body: body2, req, res, ret, abort: abort2 } = this; + if (!err && !ret._readableState.endEmitted) { + err = new RequestAbortedError(); + } + if (abort2 && err) { + abort2(); + } + util.destroy(body2, err); + util.destroy(req, err); + util.destroy(res, err); + removeSignal(this); + callback(err); + } + }).on("prefinish", () => { + const { req } = this; + req.push(null); + }); + this.res = null; + addSignal(this, signal2); + } + onRequestStart(controller, context2) { + const { res } = this; + if (this.reason) { + controller.abort(this.reason); + return; + } + assert(!res, "pipeline cannot be retried"); + this.abort = (reason2) => controller.abort(reason2); + this.context = context2; + } + onResponseStart(controller, statusCode, headers2, _statusMessage) { + const { opaque, handler, context: context2 } = this; + if (statusCode < 200) { + if (this.onInfo) { + const rawHeaders = controller?.rawHeaders; + const responseHeaders = this.responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : headers2; + this.onInfo({ statusCode, headers: responseHeaders }); + } + return; + } + this.res = new PipelineResponse(() => controller.resume()); + let body2; + try { + this.handler = null; + const rawHeaders = controller?.rawHeaders; + const responseHeaders = this.responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : headers2; + body2 = this.runInAsyncScope(handler, null, { + statusCode, + headers: responseHeaders, + opaque, + body: this.res, + context: context2 + }); + } catch (err) { + this.res.on("error", noop); + throw err; + } + if (!body2 || typeof body2.on !== "function") { + throw new InvalidReturnValueError("expected Readable"); + } + body2.on("data", (chunk) => { + const { ret, body: body3 } = this; + if (!ret.push(chunk) && body3.pause) { + body3.pause(); + } + }).on("error", (err) => { + const { ret } = this; + util.destroy(ret, err); + }).on("end", () => { + const { ret } = this; + ret.push(null); + }).on("close", () => { + const { ret } = this; + if (!ret._readableState.ended) { + util.destroy(ret, new RequestAbortedError()); + } + }); + this.body = body2; + } + onResponseData(controller, chunk) { + const { res } = this; + if (res.push(chunk) === false) { + controller.pause(); + } + } + onResponseEnd(_controller, _trailers) { + const { res } = this; + res.push(null); + } + onResponseError(_controller, err) { + const { ret } = this; + this.handler = null; + util.destroy(ret, err); + } + }; + function pipeline(opts, handler) { + try { + const pipelineHandler = new PipelineHandler(opts, handler); + this.dispatch({ ...opts, body: pipelineHandler.req }, pipelineHandler); + return pipelineHandler.ret; + } catch (err) { + return new PassThrough().destroy(err); + } + } + module2.exports = pipeline; + } +}); + +// node_modules/undici/lib/api/api-upgrade.js +var require_api_upgrade = __commonJS({ + "node_modules/undici/lib/api/api-upgrade.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError, SocketError } = require_errors2(); + var { AsyncResource } = require("node:async_hooks"); + var assert = require("node:assert"); + var util = require_util(); + var { kHTTP2Stream } = require_symbols(); + var { addSignal, removeSignal } = require_abort_signal(); + var UpgradeHandler = class extends AsyncResource { + constructor(opts, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + const { signal: signal2, opaque, responseHeaders } = opts; + if (signal2 && typeof signal2.on !== "function" && typeof signal2.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + super("UNDICI_UPGRADE"); + this.responseHeaders = responseHeaders || null; + this.opaque = opaque || null; + this.callback = callback; + this.abort = null; + this.context = null; + addSignal(this, signal2); + } + onRequestStart(controller, context2) { + if (this.reason) { + controller.abort(this.reason); + return; + } + assert(this.callback); + this.abort = (reason2) => controller.abort(reason2); + this.context = context2; + } + onResponseStart() { + throw new SocketError("bad upgrade", null); + } + onRequestUpgrade(controller, statusCode, headers2, socket) { + const expectedStatusCode = socket[kHTTP2Stream] === true ? 200 : 101; + if (statusCode !== expectedStatusCode) { + const socketInfo = socket[kHTTP2Stream] === true ? null : util.getSocketInfo(socket); + controller.abort(new SocketError("bad upgrade", socketInfo)); + return; + } + const { callback, opaque, context: context2 } = this; + removeSignal(this); + this.callback = null; + const rawHeaders = controller?.rawHeaders; + const responseHeaders = this.responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : headers2; + this.runInAsyncScope(callback, null, null, { + headers: responseHeaders, + socket, + opaque, + context: context2 + }); + } + onResponseError(_controller, err) { + const { callback, opaque } = this; + removeSignal(this); + if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); + } + } + }; + function upgrade(opts, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + upgrade.call(this, opts, (err, data2) => { + return err ? reject(err) : resolve(data2); + }); + }); + } + try { + const upgradeHandler = new UpgradeHandler(opts, callback); + const upgradeOpts = { + ...opts, + method: opts.method || "GET", + upgrade: opts.protocol || "Websocket" + }; + this.dispatch(upgradeOpts, upgradeHandler); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts?.opaque; + queueMicrotask(() => callback(err, { opaque })); + } + } + module2.exports = upgrade; + } +}); + +// node_modules/undici/lib/api/api-connect.js +var require_api_connect = __commonJS({ + "node_modules/undici/lib/api/api-connect.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { AsyncResource } = require("node:async_hooks"); + var { InvalidArgumentError, SocketError } = require_errors2(); + var util = require_util(); + var { addSignal, removeSignal } = require_abort_signal(); + var ConnectHandler = class extends AsyncResource { + constructor(opts, callback) { + if (!opts || typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (typeof callback !== "function") { + throw new InvalidArgumentError("invalid callback"); + } + const { signal: signal2, opaque, responseHeaders } = opts; + if (signal2 && typeof signal2.on !== "function" && typeof signal2.addEventListener !== "function") { + throw new InvalidArgumentError("signal must be an EventEmitter or EventTarget"); + } + super("UNDICI_CONNECT"); + this.opaque = opaque || null; + this.responseHeaders = responseHeaders || null; + this.callback = callback; + this.abort = null; + addSignal(this, signal2); + } + onRequestStart(controller, context2) { + if (this.reason) { + controller.abort(this.reason); + return; + } + assert(this.callback); + this.abort = (reason2) => controller.abort(reason2); + this.context = context2; + } + onResponseStart() { + throw new SocketError("bad connect", null); + } + onRequestUpgrade(controller, statusCode, headers2, socket) { + const { callback, opaque, context: context2 } = this; + removeSignal(this); + this.callback = null; + let responseHeaders = headers2; + const rawHeaders = controller?.rawHeaders; + if (responseHeaders != null) { + responseHeaders = this.responseHeaders === "raw" ? util.parseRawHeaders(rawHeaders) : headers2; + } + this.runInAsyncScope(callback, null, null, { + statusCode, + headers: responseHeaders, + socket, + opaque, + context: context2 + }); + } + onResponseError(_controller, err) { + const { callback, opaque } = this; + removeSignal(this); + if (callback) { + this.callback = null; + queueMicrotask(() => { + this.runInAsyncScope(callback, null, err, { opaque }); + }); + } + } + }; + function connect(opts, callback) { + if (callback === void 0) { + return new Promise((resolve, reject) => { + connect.call(this, opts, (err, data2) => { + return err ? reject(err) : resolve(data2); + }); + }); + } + try { + const connectHandler = new ConnectHandler(opts, callback); + const connectOptions = { ...opts, method: "CONNECT" }; + this.dispatch(connectOptions, connectHandler); + } catch (err) { + if (typeof callback !== "function") { + throw err; + } + const opaque = opts?.opaque; + queueMicrotask(() => callback(err, { opaque })); + } + } + module2.exports = connect; + } +}); + +// node_modules/undici/lib/api/index.js +var require_api = __commonJS({ + "node_modules/undici/lib/api/index.js"(exports2, module2) { + "use strict"; + module2.exports.request = require_api_request(); + module2.exports.stream = require_api_stream(); + module2.exports.pipeline = require_api_pipeline(); + module2.exports.upgrade = require_api_upgrade(); + module2.exports.connect = require_api_connect(); + } +}); + +// node_modules/undici/lib/mock/mock-errors.js +var require_mock_errors = __commonJS({ + "node_modules/undici/lib/mock/mock-errors.js"(exports2, module2) { + "use strict"; + var { UndiciError } = require_errors2(); + var kMockNotMatchedError = /* @__PURE__ */ Symbol.for("undici.error.UND_MOCK_ERR_MOCK_NOT_MATCHED"); + var MockNotMatchedError = class extends UndiciError { + constructor(message) { + super(message); + this.name = "MockNotMatchedError"; + this.message = message || "The request does not match any registered mock dispatches"; + this.code = "UND_MOCK_ERR_MOCK_NOT_MATCHED"; + } + static [Symbol.hasInstance](instance) { + return instance && instance[kMockNotMatchedError] === true; + } + get [kMockNotMatchedError]() { + return true; + } + }; + module2.exports = { + MockNotMatchedError + }; + } +}); + +// node_modules/undici/lib/mock/mock-symbols.js +var require_mock_symbols = __commonJS({ + "node_modules/undici/lib/mock/mock-symbols.js"(exports2, module2) { + "use strict"; + module2.exports = { + kAgent: /* @__PURE__ */ Symbol("agent"), + kOptions: /* @__PURE__ */ Symbol("options"), + kFactory: /* @__PURE__ */ Symbol("factory"), + kDispatches: /* @__PURE__ */ Symbol("dispatches"), + kDispatchKey: /* @__PURE__ */ Symbol("dispatch key"), + kDefaultHeaders: /* @__PURE__ */ Symbol("default headers"), + kDefaultTrailers: /* @__PURE__ */ Symbol("default trailers"), + kContentLength: /* @__PURE__ */ Symbol("content length"), + kMockAgent: /* @__PURE__ */ Symbol("mock agent"), + kMockAgentSet: /* @__PURE__ */ Symbol("mock agent set"), + kMockAgentGet: /* @__PURE__ */ Symbol("mock agent get"), + kMockDispatch: /* @__PURE__ */ Symbol("mock dispatch"), + kClose: /* @__PURE__ */ Symbol("close"), + kOriginalClose: /* @__PURE__ */ Symbol("original agent close"), + kOriginalDispatch: /* @__PURE__ */ Symbol("original dispatch"), + kOrigin: /* @__PURE__ */ Symbol("origin"), + kIsMockActive: /* @__PURE__ */ Symbol("is mock active"), + kNetConnect: /* @__PURE__ */ Symbol("net connect"), + kGetNetConnect: /* @__PURE__ */ Symbol("get net connect"), + kConnected: /* @__PURE__ */ Symbol("connected"), + kIgnoreTrailingSlash: /* @__PURE__ */ Symbol("ignore trailing slash"), + kMockAgentMockCallHistoryInstance: /* @__PURE__ */ Symbol("mock agent mock call history name"), + kMockAgentRegisterCallHistory: /* @__PURE__ */ Symbol("mock agent register mock call history"), + kMockAgentAddCallHistoryLog: /* @__PURE__ */ Symbol("mock agent add call history log"), + kMockAgentIsCallHistoryEnabled: /* @__PURE__ */ Symbol("mock agent is call history enabled"), + kMockAgentAcceptsNonStandardSearchParameters: /* @__PURE__ */ Symbol("mock agent accepts non standard search parameters"), + kMockCallHistoryAddLog: /* @__PURE__ */ Symbol("mock call history add log"), + kTotalDispatchCount: /* @__PURE__ */ Symbol("total dispatch count") + }; + } +}); + +// node_modules/undici/lib/mock/mock-utils.js +var require_mock_utils = __commonJS({ + "node_modules/undici/lib/mock/mock-utils.js"(exports2, module2) { + "use strict"; + var { MockNotMatchedError } = require_mock_errors(); + var { + kDispatches, + kMockAgent, + kOriginalDispatch, + kOrigin, + kGetNetConnect, + kTotalDispatchCount + } = require_mock_symbols(); + var { serializePathWithQuery, parseHeaders } = require_util(); + var { STATUS_CODES } = require("node:http"); + var { + types: { + isPromise + } + } = require("node:util"); + var { InvalidArgumentError } = require_errors2(); + var requestAborted = /* @__PURE__ */ Symbol("request aborted"); + function matchValue(match, value2) { + if (typeof match === "string") { + return match === value2; + } + if (match instanceof RegExp) { + return match.test(value2); + } + if (typeof match === "function") { + return match(value2) === true; + } + return false; + } + function lowerCaseEntries(headers2) { + return Object.fromEntries( + Object.entries(headers2).map(([headerName, headerValue]) => { + return [headerName.toLocaleLowerCase(), headerValue]; + }) + ); + } + function getHeaderByName(headers2, key) { + if (Array.isArray(headers2)) { + for (let i = 0; i < headers2.length; i += 2) { + if (headers2[i].toLocaleLowerCase() === key.toLocaleLowerCase()) { + return headers2[i + 1]; + } + } + return void 0; + } else if (typeof headers2.get === "function") { + return headers2.get(key); + } else { + return lowerCaseEntries(headers2)[key.toLocaleLowerCase()]; + } + } + function buildHeadersFromArray(headers2) { + const clone2 = headers2.slice(); + const entries2 = []; + for (let index = 0; index < clone2.length; index += 2) { + entries2.push([clone2[index], clone2[index + 1]]); + } + return Object.fromEntries(entries2); + } + function matchHeaders(mockDispatch2, headers2) { + if (typeof mockDispatch2.headers === "function") { + if (Array.isArray(headers2)) { + headers2 = buildHeadersFromArray(headers2); + } + return mockDispatch2.headers(headers2 ? lowerCaseEntries(headers2) : {}); + } + if (typeof mockDispatch2.headers === "undefined") { + return true; + } + if (typeof headers2 !== "object" || typeof mockDispatch2.headers !== "object") { + return false; + } + for (const [matchHeaderName, matchHeaderValue] of Object.entries(mockDispatch2.headers)) { + const headerValue = getHeaderByName(headers2, matchHeaderName); + if (!matchValue(matchHeaderValue, headerValue)) { + return false; + } + } + return true; + } + function normalizeSearchParams(query2) { + if (typeof query2 !== "string") { + return query2; + } + const originalQp = new URLSearchParams(query2); + const normalizedQp = new URLSearchParams(); + for (let [key, value2] of originalQp.entries()) { + key = key.replace("[]", ""); + const valueRepresentsString = /^(['"]).*\1$/.test(value2); + if (valueRepresentsString) { + normalizedQp.append(key, value2); + continue; + } + if (value2.includes(",")) { + const values2 = value2.split(","); + for (const v of values2) { + normalizedQp.append(key, v); + } + continue; + } + normalizedQp.append(key, value2); + } + return normalizedQp; + } + function safeUrl(path2) { + if (typeof path2 !== "string") { + return path2; + } + const pathSegments = path2.split("?", 3); + if (pathSegments.length !== 2) { + return path2; + } + const qp = new URLSearchParams(pathSegments.pop()); + qp.sort(); + return [...pathSegments, qp.toString()].join("?"); + } + function matchKey(mockDispatch2, { path: path2, method: method2, body: body2, headers: headers2 }) { + const pathMatch = matchValue(mockDispatch2.path, path2); + const methodMatch = matchValue(mockDispatch2.method, method2); + const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body2) : true; + const headersMatch = matchHeaders(mockDispatch2, headers2); + return pathMatch && methodMatch && bodyMatch && headersMatch; + } + function getResponseData(data2) { + if (Buffer.isBuffer(data2)) { + return data2; + } else if (data2 instanceof Uint8Array) { + return data2; + } else if (data2 instanceof ArrayBuffer) { + return data2; + } else if (ArrayBuffer.isView(data2)) { + return new Uint8Array(data2.buffer, data2.byteOffset, data2.byteLength); + } else if (typeof data2 === "object") { + return JSON.stringify(data2); + } else if (data2) { + return data2.toString(); + } else { + return ""; + } + } + function getMockDispatch(mockDispatches, key) { + const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path; + const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath; + const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath); + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path2, ignoreTrailingSlash }) => { + return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path2)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path2), resolvedPath); + }); + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`); + } + matchedMockDispatches = matchedMockDispatches.filter(({ method: method2 }) => matchValue(method2, key.method)); + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for method '${key.method}' on path '${resolvedPath}'`); + } + matchedMockDispatches = matchedMockDispatches.filter(({ body: body2 }) => typeof body2 !== "undefined" ? matchValue(body2, key.body) : true); + if (matchedMockDispatches.length === 0) { + throw new MockNotMatchedError(`Mock dispatch not matched for body '${key.body}' on path '${resolvedPath}'`); + } + matchedMockDispatches = matchedMockDispatches.filter((mockDispatch2) => matchHeaders(mockDispatch2, key.headers)); + if (matchedMockDispatches.length === 0) { + const headers2 = typeof key.headers === "object" ? JSON.stringify(key.headers) : key.headers; + throw new MockNotMatchedError(`Mock dispatch not matched for headers '${headers2}' on path '${resolvedPath}'`); + } + return matchedMockDispatches[0]; + } + function addMockDispatch(mockDispatches, key, data2, opts) { + const baseData = { timesInvoked: 0, times: 1, persist: false, consumed: false, ...opts }; + const replyData = typeof data2 === "function" ? { callback: data2 } : { ...data2 }; + const newMockDispatch = { ...baseData, ...key, pending: true, data: { error: null, ...replyData } }; + mockDispatches.push(newMockDispatch); + mockDispatches[kTotalDispatchCount] = (mockDispatches[kTotalDispatchCount] || 0) + 1; + return newMockDispatch; + } + function deleteMockDispatch(mockDispatches, key) { + const index = mockDispatches.findIndex((dispatch2) => { + if (!dispatch2.consumed) { + return false; + } + return matchKey(dispatch2, key); + }); + if (index !== -1) { + mockDispatches.splice(index, 1); + } + } + function removeTrailingSlash(path2) { + if (typeof path2 !== "string") { + return path2; + } + while (path2.endsWith("/")) { + path2 = path2.slice(0, -1); + } + if (path2.length === 0) { + path2 = "/"; + } + return path2; + } + function buildKey(opts) { + const { path: path2, method: method2, body: body2, headers: headers2, query: query2 } = opts; + return { + path: path2, + method: method2, + body: body2, + headers: headers2, + query: query2 + }; + } + function generateKeyValues(data2) { + const keys = Object.keys(data2); + const result3 = []; + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + const value2 = data2[key]; + const name2 = Buffer.from(`${key}`); + if (Array.isArray(value2)) { + for (let j = 0; j < value2.length; ++j) { + result3.push(name2, Buffer.from(`${value2[j]}`)); + } + } else { + result3.push(name2, Buffer.from(`${value2}`)); + } + } + return result3; + } + function getStatusText(statusCode) { + return STATUS_CODES[statusCode] || "unknown"; + } + async function getResponse(body2) { + const buffers = []; + for await (const data2 of body2) { + buffers.push(data2); + } + return Buffer.concat(buffers).toString("utf8"); + } + function mockDispatch(opts, handler) { + const key = buildKey(opts); + const mockDispatch2 = getMockDispatch(this[kDispatches], key); + const mockDispatches = this[kDispatches]; + mockDispatch2.timesInvoked++; + const { timesInvoked, times } = mockDispatch2; + mockDispatch2.consumed = !mockDispatch2.persist && timesInvoked >= times; + mockDispatch2.pending = timesInvoked < times; + const hasBodyHooks = typeof handler.onBodySent === "function" || typeof handler.onRequestSent === "function"; + if (mockDispatch2.data.callback && (!hasBodyHooks || opts.body == null)) { + const { callback, ...responseDefaults } = mockDispatch2.data; + const callbackResult = callback(opts); + if (isPromise(callbackResult)) { + callbackResult.then( + (resolvedData) => { + if (resolvedData == null || typeof resolvedData !== "object") { + handler.onResponseError(null, new InvalidArgumentError("reply options callback must return an object")); + return; + } + mockDispatch2.data = { ...responseDefaults, ...resolvedData }; + dispatchMockReply(mockDispatches, mockDispatch2, key, opts, handler); + }, + (error2) => { + handler.onResponseError(null, error2); + } + ); + return true; + } + if (callbackResult == null || typeof callbackResult !== "object") { + throw new InvalidArgumentError("reply options callback must return an object"); + } + mockDispatch2.data = { ...responseDefaults, ...callbackResult }; + } + return dispatchMockReply(mockDispatches, mockDispatch2, key, opts, handler); + } + function dispatchMockReply(mockDispatches, mockDispatch2, key, opts, handler) { + const { data: response, delay } = mockDispatch2; + if (response.error !== null) { + deleteMockDispatch(mockDispatches, key); + handler.onResponseError(null, response.error); + return true; + } + let aborted2 = false; + let timer = null; + const controller = { + paused: false, + rawHeaders: null, + rawTrailers: null, + pause() { + this.paused = true; + }, + resume() { + this.paused = false; + }, + abort: (reason2) => { + if (aborted2) { + return; + } + aborted2 = true; + if (timer !== null) { + clearTimeout(timer); + timer = null; + } + handler.onResponseError?.(controller, reason2); + } + }; + let replyOpts = opts; + const dispatches = mockDispatches; + handler.onRequestStart?.(controller, null); + if (aborted2) { + return true; + } + const requestBody = dispatchRequestBody(opts.body, handler, controller, () => aborted2); + if (isPromise(requestBody)) { + requestBody.then((body2) => { + if (body2 === requestAborted) { + return; + } + if (body2 !== opts.body) { + replyOpts = { ...opts, body: body2 }; + } + sendReply(); + }, (error2) => controller.abort(error2)); + return true; + } + if (requestBody === requestAborted) { + return true; + } + if (requestBody !== opts.body) { + replyOpts = { ...opts, body: requestBody }; + } + sendReply(); + function sendReply() { + if (response.callback) { + const { callback, ...responseDefaults } = response; + let callbackResult; + try { + callbackResult = callback(replyOpts); + } catch (err) { + deleteMockDispatch(mockDispatches, key); + handler.onResponseError(null, err); + return; + } + if (isPromise(callbackResult)) { + callbackResult.then( + (resolvedData) => { + if (resolvedData == null || typeof resolvedData !== "object") { + handler.onResponseError(null, new InvalidArgumentError("reply options callback must return an object")); + return; + } + mockDispatch2.data = { ...responseDefaults, ...resolvedData }; + handleReply(dispatches, mockDispatch2.data); + }, + (err) => { + handler.onResponseError(null, err); + } + ); + return; + } + if (callbackResult == null || typeof callbackResult !== "object") { + throw new InvalidArgumentError("reply options callback must return an object"); + } + mockDispatch2.data = { ...responseDefaults, ...callbackResult }; + handleReply(dispatches, mockDispatch2.data); + return; + } + if (typeof delay === "number" && delay > 0) { + timer = setTimeout(() => { + timer = null; + handleReply(dispatches); + }, delay); + } else { + handleReply(dispatches); + } + } + function handleReply(mockDispatches2, _response = response) { + if (aborted2) { + return; + } + const { statusCode, data: data2, headers: headers2, trailers } = _response; + const optsHeaders = Array.isArray(opts.headers) ? buildHeadersFromArray(opts.headers) : opts.headers; + const body2 = typeof data2 === "function" ? data2({ ...replyOpts, headers: optsHeaders }) : data2; + if (isPromise(body2)) { + return body2.then((newData) => handleReply(mockDispatches2, { ..._response, data: newData })); + } + if (aborted2) { + return; + } + const responseData = getResponseData(body2); + const responseHeaders = generateKeyValues(headers2 ?? {}); + const responseTrailers = generateKeyValues(trailers ?? {}); + controller.rawHeaders = responseHeaders; + controller.rawTrailers = responseTrailers; + handler.onResponseStart?.(controller, statusCode, parseHeaders(responseHeaders), getStatusText(statusCode)); + handler.onResponseData?.(controller, Buffer.from(responseData)); + handler.onResponseEnd?.(controller, parseHeaders(responseTrailers)); + deleteMockDispatch(mockDispatches2, key); + } + return true; + } + function dispatchRequestBody(body2, handler, controller, isAborted) { + if (typeof handler.onBodySent !== "function" && typeof handler.onRequestSent !== "function") { + return body2; + } + if (body2 == null) { + return callOnRequestSent(handler, controller, isAborted) ? body2 : requestAborted; + } + if (body2 && typeof body2[Symbol.asyncIterator] === "function") { + return dispatchAsyncIterableBody(body2, handler, controller, isAborted); + } + if (isIterableBody(body2)) { + const chunks = []; + for (const chunk of body2) { + if (isAborted()) { + return requestAborted; + } + chunks.push(chunk); + if (!callOnBodySent(handler, controller, chunk) || isAborted()) { + return requestAborted; + } + } + return callOnRequestSent(handler, controller, isAborted) ? chunks : requestAborted; + } + if (isAborted()) { + return requestAborted; + } + if (!callOnBodySent(handler, controller, body2)) { + return requestAborted; + } + return callOnRequestSent(handler, controller, isAborted) ? body2 : requestAborted; + } + async function dispatchAsyncIterableBody(body2, handler, controller, isAborted) { + const chunks = []; + for await (const chunk of body2) { + if (isAborted()) { + return requestAborted; + } + chunks.push(chunk); + if (!callOnBodySent(handler, controller, chunk) || isAborted()) { + return requestAborted; + } + } + if (!callOnRequestSent(handler, controller, isAborted)) { + return requestAborted; + } + return { + async *[Symbol.asyncIterator]() { + yield* chunks; + } + }; + } + function callOnBodySent(handler, controller, chunk) { + try { + handler.onBodySent?.(chunk); + return true; + } catch (error2) { + controller.abort(error2); + return false; + } + } + function callOnRequestSent(handler, controller, isAborted) { + try { + handler.onRequestSent?.(); + return !isAborted(); + } catch (error2) { + controller.abort(error2); + return false; + } + } + function isIterableBody(body2) { + return typeof body2 !== "string" && !Buffer.isBuffer(body2) && !ArrayBuffer.isView(body2) && typeof body2[Symbol.iterator] === "function"; + } + function buildMockDispatch() { + const agent = this[kMockAgent]; + const origin = this[kOrigin]; + const originalDispatch = this[kOriginalDispatch]; + return function dispatch2(opts, handler) { + if (agent.isMockActive) { + try { + mockDispatch.call(this, opts, handler); + } catch (error2) { + if (error2.code === "UND_MOCK_ERR_MOCK_NOT_MATCHED") { + const netConnect = agent[kGetNetConnect](); + const totalInterceptsCount = this[kDispatches][kTotalDispatchCount] || this[kDispatches].length; + const pendingInterceptsCount = this[kDispatches].filter(({ consumed }) => !consumed).length; + const interceptsMessage = `, ${pendingInterceptsCount} interceptor(s) remaining out of ${totalInterceptsCount} defined`; + if (netConnect === false) { + throw new MockNotMatchedError(`${error2.message}: subsequent request to origin ${origin} was not allowed (net.connect disabled)${interceptsMessage}`); + } + if (checkNetConnect(netConnect, origin)) { + originalDispatch.call(this, "__mockAgentBodyForDispatch" in opts ? { ...opts, body: opts.__mockAgentBodyForDispatch } : opts, handler); + } else { + throw new MockNotMatchedError(`${error2.message}: subsequent request to origin ${origin} was not allowed (net.connect is not enabled for this origin)${interceptsMessage}`); + } + } else { + throw error2; + } + } + } else { + originalDispatch.call(this, opts, handler); + } + }; + } + function checkNetConnect(netConnect, origin) { + const url2 = new URL(origin); + if (netConnect === true) { + return true; + } else if (Array.isArray(netConnect) && netConnect.some((matcher) => matchValue(matcher, url2.host))) { + return true; + } + return false; + } + function normalizeOrigin(origin) { + if (typeof origin !== "string" && !(origin instanceof URL)) { + return origin; + } + if (origin instanceof URL) { + return origin.origin; + } + return origin.toLowerCase(); + } + function buildAndValidateMockOptions(opts) { + const { agent, ...mockOptions } = opts; + if ("enableCallHistory" in mockOptions && typeof mockOptions.enableCallHistory !== "boolean") { + throw new InvalidArgumentError("options.enableCallHistory must to be a boolean"); + } + if ("acceptNonStandardSearchParameters" in mockOptions && typeof mockOptions.acceptNonStandardSearchParameters !== "boolean") { + throw new InvalidArgumentError("options.acceptNonStandardSearchParameters must to be a boolean"); + } + if ("ignoreTrailingSlash" in mockOptions && typeof mockOptions.ignoreTrailingSlash !== "boolean") { + throw new InvalidArgumentError("options.ignoreTrailingSlash must to be a boolean"); + } + return mockOptions; + } + module2.exports = { + getResponseData, + getMockDispatch, + addMockDispatch, + deleteMockDispatch, + buildKey, + generateKeyValues, + matchValue, + getResponse, + getStatusText, + mockDispatch, + buildMockDispatch, + checkNetConnect, + buildAndValidateMockOptions, + getHeaderByName, + buildHeadersFromArray, + normalizeSearchParams, + normalizeOrigin + }; + } +}); + +// node_modules/undici/lib/mock/mock-interceptor.js +var require_mock_interceptor = __commonJS({ + "node_modules/undici/lib/mock/mock-interceptor.js"(exports2, module2) { + "use strict"; + var { getResponseData, buildKey, addMockDispatch } = require_mock_utils(); + var { + kDispatches, + kDispatchKey, + kDefaultHeaders, + kDefaultTrailers, + kContentLength, + kMockDispatch, + kIgnoreTrailingSlash + } = require_mock_symbols(); + var { InvalidArgumentError } = require_errors2(); + var { serializePathWithQuery } = require_util(); + var { + types: { + isPromise + } + } = require("node:util"); + var MockScope = class { + constructor(mockDispatch) { + this[kMockDispatch] = mockDispatch; + } + /** + * Delay a reply by a set amount in ms. + */ + delay(waitInMs) { + if (typeof waitInMs !== "number" || !Number.isInteger(waitInMs) || waitInMs <= 0) { + throw new InvalidArgumentError("waitInMs must be a valid integer > 0"); + } + this[kMockDispatch].delay = waitInMs; + return this; + } + /** + * For a defined reply, never mark as consumed. + */ + persist() { + this[kMockDispatch].persist = true; + return this; + } + /** + * Allow one to define a reply for a set amount of matching requests. + */ + times(repeatTimes) { + if (typeof repeatTimes !== "number" || !Number.isInteger(repeatTimes) || repeatTimes <= 0) { + throw new InvalidArgumentError("repeatTimes must be a valid integer > 0"); + } + this[kMockDispatch].times = repeatTimes; + return this; + } + }; + var MockInterceptor = class { + constructor(opts, mockDispatches) { + if (typeof opts !== "object") { + throw new InvalidArgumentError("opts must be an object"); + } + if (typeof opts.path === "undefined") { + throw new InvalidArgumentError("opts.path must be defined"); + } + if (typeof opts.method === "undefined") { + opts.method = "GET"; + } + if (typeof opts.path === "string") { + if (opts.query) { + opts.path = serializePathWithQuery(opts.path, opts.query); + } else { + const parsedURL = new URL(opts.path, "data://"); + opts.path = parsedURL.pathname + parsedURL.search; + } + } + if (typeof opts.method === "string") { + opts.method = opts.method.toUpperCase(); + } + this[kDispatchKey] = buildKey(opts); + this[kDispatches] = mockDispatches; + this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false; + this[kDefaultHeaders] = {}; + this[kDefaultTrailers] = {}; + this[kContentLength] = false; + } + createMockScopeDispatchData({ statusCode, data: data2, responseOptions }) { + const responseData = getResponseData(data2); + const contentLength2 = this[kContentLength] ? { "content-length": responseData.length } : {}; + const headers2 = { ...this[kDefaultHeaders], ...contentLength2, ...responseOptions.headers }; + const trailers = { ...this[kDefaultTrailers], ...responseOptions.trailers }; + return { statusCode, data: data2, headers: headers2, trailers }; + } + validateReplyParameters(replyParameters) { + if (typeof replyParameters.statusCode === "undefined") { + throw new InvalidArgumentError("statusCode must be defined"); + } + if (typeof replyParameters.responseOptions !== "object" || replyParameters.responseOptions === null) { + throw new InvalidArgumentError("responseOptions must be an object"); + } + } + /** + * Mock an undici request with a defined reply. + */ + reply(replyOptionsCallbackOrStatusCode) { + if (typeof replyOptionsCallbackOrStatusCode === "function") { + const resolveReplyCallbackData = (resolvedData) => { + if (typeof resolvedData !== "object" || resolvedData === null) { + throw new InvalidArgumentError("reply options callback must return an object"); + } + const replyParameters2 = { data: "", responseOptions: {}, ...resolvedData }; + this.validateReplyParameters(replyParameters2); + return { + ...this.createMockScopeDispatchData(replyParameters2) + }; + }; + const wrappedDefaultsCallback = (opts) => { + const resolvedData = replyOptionsCallbackOrStatusCode(opts); + if (isPromise(resolvedData)) { + return resolvedData.then(resolveReplyCallbackData); + } + return resolveReplyCallbackData(resolvedData); + }; + const newMockDispatch2 = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }); + return new MockScope(newMockDispatch2); + } + const replyParameters = { + statusCode: replyOptionsCallbackOrStatusCode, + data: arguments[1] === void 0 ? "" : arguments[1], + responseOptions: arguments[2] === void 0 ? {} : arguments[2] + }; + this.validateReplyParameters(replyParameters); + const dispatchData = this.createMockScopeDispatchData(replyParameters); + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], dispatchData, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }); + return new MockScope(newMockDispatch); + } + /** + * Mock an undici request with a defined error. + */ + replyWithError(error2) { + if (typeof error2 === "undefined") { + throw new InvalidArgumentError("error must be defined"); + } + const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], { error: error2 }, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] }); + return new MockScope(newMockDispatch); + } + /** + * Set default reply headers on the interceptor for subsequent replies + */ + defaultReplyHeaders(headers2) { + if (typeof headers2 === "undefined") { + throw new InvalidArgumentError("headers must be defined"); + } + this[kDefaultHeaders] = headers2; + return this; + } + /** + * Set default reply trailers on the interceptor for subsequent replies + */ + defaultReplyTrailers(trailers) { + if (typeof trailers === "undefined") { + throw new InvalidArgumentError("trailers must be defined"); + } + this[kDefaultTrailers] = trailers; + return this; + } + /** + * Set reply content length header for replies on the interceptor + */ + replyContentLength() { + this[kContentLength] = true; + return this; + } + }; + module2.exports.MockInterceptor = MockInterceptor; + module2.exports.MockScope = MockScope; + } +}); + +// node_modules/undici/lib/mock/mock-client.js +var require_mock_client = __commonJS({ + "node_modules/undici/lib/mock/mock-client.js"(exports2, module2) { + "use strict"; + var { promisify } = require("node:util"); + var Client = require_client(); + var { buildMockDispatch } = require_mock_utils(); + var { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected, + kIgnoreTrailingSlash + } = require_mock_symbols(); + var { MockInterceptor } = require_mock_interceptor(); + var Symbols = require_symbols(); + var { InvalidArgumentError } = require_errors2(); + var MockClient = class extends Client { + constructor(origin, opts) { + if (!opts || !opts.agent || typeof opts.agent.dispatch !== "function") { + throw new InvalidArgumentError("Argument opts.agent must implement Agent"); + } + super(origin, opts); + this[kMockAgent] = opts.agent; + this[kOrigin] = origin; + this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false; + this[kDispatches] = []; + this[kConnected] = 1; + this[kOriginalDispatch] = this.dispatch; + this[kOriginalClose] = this.close.bind(this); + this.dispatch = buildMockDispatch.call(this); + this.close = this[kClose]; + } + get [Symbols.kConnected]() { + return this[kConnected]; + } + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept(opts) { + return new MockInterceptor( + opts && { ignoreTrailingSlash: this[kIgnoreTrailingSlash], ...opts }, + this[kDispatches] + ); + } + cleanMocks() { + this[kDispatches] = []; + } + async [kClose]() { + await promisify(this[kOriginalClose])(); + this[kConnected] = 0; + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]); + } + }; + module2.exports = MockClient; + } +}); + +// node_modules/undici/lib/mock/mock-call-history.js +var require_mock_call_history = __commonJS({ + "node_modules/undici/lib/mock/mock-call-history.js"(exports2, module2) { + "use strict"; + var { kMockCallHistoryAddLog } = require_mock_symbols(); + var { InvalidArgumentError } = require_errors2(); + function handleFilterCallsWithOptions(criteria, options2, handler, store, allLogs) { + switch (options2.operator) { + case "OR": + store.push(...handler(criteria, allLogs)); + return store; + case "AND": + return handler(criteria, store); + default: + throw new InvalidArgumentError("options.operator must to be a case insensitive string equal to 'OR' or 'AND'"); + } + } + function buildAndValidateFilterCallsOptions(options2 = {}) { + const finalOptions = {}; + if ("operator" in options2) { + if (typeof options2.operator !== "string" || options2.operator.toUpperCase() !== "OR" && options2.operator.toUpperCase() !== "AND") { + throw new InvalidArgumentError("options.operator must to be a case insensitive string equal to 'OR' or 'AND'"); + } + return { + ...finalOptions, + operator: options2.operator.toUpperCase() + }; + } + return finalOptions; + } + function makeFilterCalls(parameterName) { + return (parameterValue, logs = this.logs) => { + if (typeof parameterValue === "string" || parameterValue == null) { + return logs.filter((log) => { + return log[parameterName] === parameterValue; + }); + } + if (parameterValue instanceof RegExp) { + return logs.filter((log) => { + return parameterValue.test(log[parameterName]); + }); + } + throw new InvalidArgumentError(`${parameterName} parameter should be one of string, regexp, undefined or null`); + }; + } + function computeUrlWithMaybeSearchParameters(requestInit) { + try { + const url2 = new URL(requestInit.path, requestInit.origin); + if (url2.search.length !== 0) { + return url2; + } + url2.search = new URLSearchParams(requestInit.query).toString(); + return url2; + } catch (error2) { + throw new InvalidArgumentError("An error occurred when computing MockCallHistoryLog.url", { cause: error2 }); + } + } + var MockCallHistoryLog = class { + constructor(requestInit = {}) { + this.body = requestInit.body; + this.headers = requestInit.headers; + this.method = requestInit.method; + const url2 = computeUrlWithMaybeSearchParameters(requestInit); + this.fullUrl = url2.toString(); + this.origin = url2.origin; + this.path = url2.pathname; + this.searchParams = Object.fromEntries(url2.searchParams); + this.protocol = url2.protocol; + this.host = url2.host; + this.port = url2.port; + this.hash = url2.hash; + } + toMap() { + return /* @__PURE__ */ new Map( + [ + ["protocol", this.protocol], + ["host", this.host], + ["port", this.port], + ["origin", this.origin], + ["path", this.path], + ["hash", this.hash], + ["searchParams", this.searchParams], + ["fullUrl", this.fullUrl], + ["method", this.method], + ["body", this.body], + ["headers", this.headers] + ] + ); + } + toString() { + const options2 = { betweenKeyValueSeparator: "->", betweenPairSeparator: "|" }; + let result3 = ""; + this.toMap().forEach((value2, key) => { + if (typeof value2 === "string" || value2 === void 0 || value2 === null) { + result3 = `${result3}${key}${options2.betweenKeyValueSeparator}${value2}${options2.betweenPairSeparator}`; + } + if (typeof value2 === "object" && value2 !== null || Array.isArray(value2)) { + result3 = `${result3}${key}${options2.betweenKeyValueSeparator}${JSON.stringify(value2)}${options2.betweenPairSeparator}`; + } + }); + return result3.slice(0, -1); + } + }; + var MockCallHistory = class { + logs = []; + calls() { + return this.logs; + } + firstCall() { + return this.logs.at(0); + } + lastCall() { + return this.logs.at(-1); + } + nthCall(number) { + if (typeof number !== "number") { + throw new InvalidArgumentError("nthCall must be called with a number"); + } + if (!Number.isInteger(number)) { + throw new InvalidArgumentError("nthCall must be called with an integer"); + } + if (Math.sign(number) !== 1) { + throw new InvalidArgumentError("nthCall must be called with a positive value. use firstCall or lastCall instead"); + } + return this.logs.at(number - 1); + } + filterCalls(criteria, options2) { + if (this.logs.length === 0) { + return this.logs; + } + if (typeof criteria === "function") { + return this.logs.filter(criteria); + } + if (criteria instanceof RegExp) { + return this.logs.filter((log) => { + return criteria.test(log.toString()); + }); + } + if (typeof criteria === "object" && criteria !== null) { + if (Object.keys(criteria).length === 0) { + return this.logs; + } + const finalOptions = { operator: "OR", ...buildAndValidateFilterCallsOptions(options2) }; + let maybeDuplicatedLogsFiltered = finalOptions.operator === "AND" ? this.logs : []; + if ("protocol" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered, this.logs); + } + if ("host" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered, this.logs); + } + if ("port" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered, this.logs); + } + if ("origin" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered, this.logs); + } + if ("path" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered, this.logs); + } + if ("hash" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered, this.logs); + } + if ("fullUrl" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered, this.logs); + } + if ("method" in criteria) { + maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered, this.logs); + } + const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)]; + return uniqLogsFiltered; + } + throw new InvalidArgumentError("criteria parameter should be one of function, regexp, or object"); + } + filterCallsByProtocol = makeFilterCalls.call(this, "protocol"); + filterCallsByHost = makeFilterCalls.call(this, "host"); + filterCallsByPort = makeFilterCalls.call(this, "port"); + filterCallsByOrigin = makeFilterCalls.call(this, "origin"); + filterCallsByPath = makeFilterCalls.call(this, "path"); + filterCallsByHash = makeFilterCalls.call(this, "hash"); + filterCallsByFullUrl = makeFilterCalls.call(this, "fullUrl"); + filterCallsByMethod = makeFilterCalls.call(this, "method"); + clear() { + this.logs = []; + } + [kMockCallHistoryAddLog](requestInit) { + const log = new MockCallHistoryLog(requestInit); + this.logs.push(log); + return log; + } + *[Symbol.iterator]() { + for (const log of this.calls()) { + yield log; + } + } + }; + module2.exports.MockCallHistory = MockCallHistory; + module2.exports.MockCallHistoryLog = MockCallHistoryLog; + } +}); + +// node_modules/undici/lib/mock/mock-pool.js +var require_mock_pool = __commonJS({ + "node_modules/undici/lib/mock/mock-pool.js"(exports2, module2) { + "use strict"; + var { promisify } = require("node:util"); + var Pool = require_pool(); + var { buildMockDispatch } = require_mock_utils(); + var { + kDispatches, + kMockAgent, + kClose, + kOriginalClose, + kOrigin, + kOriginalDispatch, + kConnected, + kIgnoreTrailingSlash + } = require_mock_symbols(); + var { MockInterceptor } = require_mock_interceptor(); + var Symbols = require_symbols(); + var { InvalidArgumentError } = require_errors2(); + var MockPool = class extends Pool { + constructor(origin, opts) { + if (!opts || !opts.agent || typeof opts.agent.dispatch !== "function") { + throw new InvalidArgumentError("Argument opts.agent must implement Agent"); + } + super(origin, opts); + this[kMockAgent] = opts.agent; + this[kOrigin] = origin; + this[kIgnoreTrailingSlash] = opts.ignoreTrailingSlash ?? false; + this[kDispatches] = []; + this[kConnected] = 1; + this[kOriginalDispatch] = this.dispatch; + this[kOriginalClose] = this.close.bind(this); + this.dispatch = buildMockDispatch.call(this); + this.close = this[kClose]; + } + get [Symbols.kConnected]() { + return this[kConnected]; + } + /** + * Sets up the base interceptor for mocking replies from undici. + */ + intercept(opts) { + return new MockInterceptor( + opts && { ignoreTrailingSlash: this[kIgnoreTrailingSlash], ...opts }, + this[kDispatches] + ); + } + cleanMocks() { + this[kDispatches] = []; + } + async [kClose]() { + await promisify(this[kOriginalClose])(); + this[kConnected] = 0; + this[kMockAgent][Symbols.kClients].delete(this[kOrigin]); + } + }; + module2.exports = MockPool; + } +}); + +// node_modules/undici/lib/mock/pending-interceptors-formatter.js +var require_pending_interceptors_formatter = __commonJS({ + "node_modules/undici/lib/mock/pending-interceptors-formatter.js"(exports2, module2) { + "use strict"; + var { Transform } = require("node:stream"); + var { Console } = require("node:console"); + var PERSISTENT = process.versions.icu ? "\u2705" : "Y "; + var NOT_PERSISTENT = process.versions.icu ? "\u274C" : "N "; + module2.exports = class PendingInterceptorsFormatter { + constructor({ disableColors } = {}) { + this.transform = new Transform({ + transform(chunk, _enc, cb) { + cb(null, chunk); + } + }); + this.logger = new Console({ + stdout: this.transform, + inspectOptions: { + colors: !disableColors && !process.env.CI + } + }); + } + format(pendingInterceptors) { + const withPrettyHeaders = pendingInterceptors.map( + ({ method: method2, path: path2, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + Method: method2, + Origin: origin, + Path: path2, + "Status code": statusCode, + Persistent: persist ? PERSISTENT : NOT_PERSISTENT, + Invocations: timesInvoked, + Remaining: persist ? Infinity : times - timesInvoked + }) + ); + this.logger.table(withPrettyHeaders); + return this.transform.read().toString(); + } + }; + } +}); + +// node_modules/undici/lib/mock/mock-agent.js +var require_mock_agent = __commonJS({ + "node_modules/undici/lib/mock/mock-agent.js"(exports2, module2) { + "use strict"; + var { kClients } = require_symbols(); + var Agent = require_agent(); + var { + kAgent, + kMockAgentSet, + kMockAgentGet, + kDispatches, + kIsMockActive, + kNetConnect, + kGetNetConnect, + kOptions, + kFactory, + kMockAgentRegisterCallHistory, + kMockAgentIsCallHistoryEnabled, + kMockAgentAddCallHistoryLog, + kMockAgentMockCallHistoryInstance, + kMockAgentAcceptsNonStandardSearchParameters, + kMockCallHistoryAddLog, + kIgnoreTrailingSlash + } = require_mock_symbols(); + var MockClient = require_mock_client(); + var MockPool = require_mock_pool(); + var { matchValue, normalizeSearchParams, buildAndValidateMockOptions, normalizeOrigin } = require_mock_utils(); + var { InvalidArgumentError, UndiciError } = require_errors2(); + var Dispatcher = require_dispatcher(); + var PendingInterceptorsFormatter = require_pending_interceptors_formatter(); + var { MockCallHistory } = require_mock_call_history(); + var MockAgent = class extends Dispatcher { + constructor(opts = {}) { + super(opts); + const mockOptions = buildAndValidateMockOptions(opts); + this[kNetConnect] = true; + this[kIsMockActive] = true; + this[kMockAgentIsCallHistoryEnabled] = mockOptions.enableCallHistory ?? false; + this[kMockAgentAcceptsNonStandardSearchParameters] = mockOptions.acceptNonStandardSearchParameters ?? false; + this[kIgnoreTrailingSlash] = mockOptions.ignoreTrailingSlash ?? false; + if (opts?.agent && typeof opts.agent.dispatch !== "function") { + throw new InvalidArgumentError("Argument opts.agent must implement Agent"); + } + const agent = opts?.agent ? opts.agent : new Agent(opts); + this[kAgent] = agent; + this[kClients] = agent[kClients]; + this[kOptions] = mockOptions; + if (this[kMockAgentIsCallHistoryEnabled]) { + this[kMockAgentRegisterCallHistory](); + } + } + get(origin) { + const normalizedOrigin = normalizeOrigin(origin); + const originKey = this[kIgnoreTrailingSlash] ? normalizedOrigin.replace(/\/$/, "") : normalizedOrigin; + let dispatcher = this[kMockAgentGet](originKey); + if (!dispatcher) { + dispatcher = this[kFactory](originKey); + this[kMockAgentSet](originKey, dispatcher); + } + return dispatcher; + } + dispatch(opts, handler) { + opts.origin = normalizeOrigin(opts.origin); + this.get(opts.origin); + this[kMockAgentAddCallHistoryLog](opts); + const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters]; + const dispatchOpts = { ...opts }; + if (acceptNonStandardSearchParameters && dispatchOpts.path) { + const [path2, searchParams] = dispatchOpts.path.split("?"); + const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters); + dispatchOpts.path = `${path2}?${normalizedSearchParams}`; + } + return this[kAgent].dispatch(dispatchOpts, handler); + } + async close() { + this.clearCallHistory(); + await this[kAgent].close(); + this[kClients].clear(); + } + deactivate() { + this[kIsMockActive] = false; + } + activate() { + this[kIsMockActive] = true; + } + enableNetConnect(matcher) { + if (typeof matcher === "string" || typeof matcher === "function" || matcher instanceof RegExp) { + if (Array.isArray(this[kNetConnect])) { + this[kNetConnect].push(matcher); + } else { + this[kNetConnect] = [matcher]; + } + } else if (typeof matcher === "undefined") { + this[kNetConnect] = true; + } else { + throw new InvalidArgumentError("Unsupported matcher. Must be one of String|Function|RegExp."); + } + } + disableNetConnect() { + this[kNetConnect] = false; + } + enableCallHistory() { + this[kMockAgentIsCallHistoryEnabled] = true; + return this; + } + disableCallHistory() { + this[kMockAgentIsCallHistoryEnabled] = false; + return this; + } + getCallHistory() { + return this[kMockAgentMockCallHistoryInstance]; + } + clearCallHistory() { + if (this[kMockAgentMockCallHistoryInstance] !== void 0) { + this[kMockAgentMockCallHistoryInstance].clear(); + } + } + // This is required to bypass issues caused by using global symbols - see: + // https://github.com/nodejs/undici/issues/1447 + get isMockActive() { + return this[kIsMockActive]; + } + [kMockAgentRegisterCallHistory]() { + if (this[kMockAgentMockCallHistoryInstance] === void 0) { + this[kMockAgentMockCallHistoryInstance] = new MockCallHistory(); + } + } + [kMockAgentAddCallHistoryLog](opts) { + if (this[kMockAgentIsCallHistoryEnabled]) { + this[kMockAgentRegisterCallHistory](); + this[kMockAgentMockCallHistoryInstance][kMockCallHistoryAddLog](opts); + } + } + [kMockAgentSet](origin, dispatcher) { + this[kClients].set(origin, dispatcher); + } + [kFactory](origin) { + const mockOptions = Object.assign({ agent: this }, this[kOptions]); + return this[kOptions] && this[kOptions].connections === 1 ? new MockClient(origin, mockOptions) : new MockPool(origin, mockOptions); + } + [kMockAgentGet](origin) { + const dispatcher = this[kClients].get(origin); + if (dispatcher) { + return dispatcher; + } + if (typeof origin !== "string") { + const dispatcher2 = this[kFactory]("http://localhost:9999"); + this[kMockAgentSet](origin, dispatcher2); + return dispatcher2; + } + for (const [keyMatcher, nonExplicitDispatcher] of Array.from(this[kClients])) { + if (nonExplicitDispatcher && typeof keyMatcher !== "string" && matchValue(keyMatcher, origin)) { + const dispatcher2 = this[kFactory](origin); + this[kMockAgentSet](origin, dispatcher2); + dispatcher2[kDispatches] = nonExplicitDispatcher[kDispatches]; + return dispatcher2; + } + } + } + [kGetNetConnect]() { + return this[kNetConnect]; + } + pendingInterceptors() { + const mockAgentClients = this[kClients]; + return Array.from(mockAgentClients.entries()).flatMap(([origin, dispatcher]) => dispatcher[kDispatches].map((dispatch2) => ({ ...dispatch2, origin }))).filter(({ pending }) => pending); + } + assertNoPendingInterceptors({ pendingInterceptorsFormatter = new PendingInterceptorsFormatter() } = {}) { + const pending = this.pendingInterceptors(); + if (pending.length === 0) { + return; + } + throw new UndiciError( + pending.length === 1 ? `1 interceptor is pending: + +${pendingInterceptorsFormatter.format(pending)}`.trim() : `${pending.length} interceptors are pending: + +${pendingInterceptorsFormatter.format(pending)}`.trim() + ); + } + }; + module2.exports = MockAgent; + } +}); + +// node_modules/undici/lib/mock/snapshot-utils.js +var require_snapshot_utils = __commonJS({ + "node_modules/undici/lib/mock/snapshot-utils.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError } = require_errors2(); + var { runtimeFeatures } = require_runtime_features(); + function createHeaderFilters(matchOptions = {}) { + const { ignoreHeaders = [], excludeHeaders = [], matchHeaders = [], caseSensitive = false } = matchOptions; + return { + ignore: new Set(ignoreHeaders.map((header) => caseSensitive ? header : header.toLowerCase())), + exclude: new Set(excludeHeaders.map((header) => caseSensitive ? header : header.toLowerCase())), + match: new Set(matchHeaders.map((header) => caseSensitive ? header : header.toLowerCase())) + }; + } + var crypto3 = runtimeFeatures.has("crypto") ? require("node:crypto") : null; + var hashId = crypto3?.hash ? (value2) => crypto3.hash("sha256", value2, "base64url") : (value2) => Buffer.from(value2).toString("base64url"); + function isUndiciHeaders(headers2) { + return Array.isArray(headers2) && (headers2.length & 1) === 0; + } + function isUrlExcludedFactory(excludePatterns = []) { + if (excludePatterns.length === 0) { + return () => false; + } + return function isUrlExcluded(url2) { + let urlLowerCased; + for (const pattern of excludePatterns) { + if (typeof pattern === "string") { + if (!urlLowerCased) { + urlLowerCased = url2.toLowerCase(); + } + if (urlLowerCased.includes(pattern.toLowerCase())) { + return true; + } + } else if (pattern instanceof RegExp) { + if (pattern.test(url2)) { + return true; + } + } + } + return false; + }; + } + function normalizeHeaders(headers2) { + const normalizedHeaders = {}; + if (!headers2) return normalizedHeaders; + if (isUndiciHeaders(headers2)) { + for (let i = 0; i < headers2.length; i += 2) { + const key = headers2[i]; + const value2 = headers2[i + 1]; + if (key && value2 !== void 0) { + const keyStr = Buffer.isBuffer(key) ? key.toString() : key; + const valueStr = Buffer.isBuffer(value2) ? value2.toString() : value2; + normalizedHeaders[keyStr.toLowerCase()] = valueStr; + } + } + return normalizedHeaders; + } + if (headers2 && typeof headers2 === "object") { + for (const [key, value2] of Object.entries(headers2)) { + if (key && typeof key === "string") { + normalizedHeaders[key.toLowerCase()] = Array.isArray(value2) ? value2.join(", ") : String(value2); + } + } + } + return normalizedHeaders; + } + var validSnapshotModes = ( + /** @type {const} */ + ["record", "playback", "update"] + ); + function validateSnapshotMode(mode2) { + if (!validSnapshotModes.includes(mode2)) { + throw new InvalidArgumentError(`Invalid snapshot mode: ${mode2}. Must be one of: ${validSnapshotModes.join(", ")}`); + } + } + module2.exports = { + createHeaderFilters, + hashId, + isUndiciHeaders, + normalizeHeaders, + isUrlExcludedFactory, + validateSnapshotMode + }; + } +}); + +// node_modules/undici/lib/mock/snapshot-recorder.js +var require_snapshot_recorder = __commonJS({ + "node_modules/undici/lib/mock/snapshot-recorder.js"(exports2, module2) { + "use strict"; + var { writeFile, readFile, mkdir } = require("node:fs/promises"); + var { dirname: dirname2, resolve } = require("node:path"); + var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = require("node:timers"); + var { InvalidArgumentError, UndiciError } = require_errors2(); + var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils(); + function normalizeUrlForMatching(url2, matchQuery, normalizeQuery) { + if (matchQuery === false) return `${url2.origin}${url2.pathname}`; + if (normalizeQuery) { + const normalized = String(normalizeQuery(url2.searchParams) ?? ""); + return normalized ? `${url2.origin}${url2.pathname}?${normalized}` : `${url2.origin}${url2.pathname}`; + } + return url2.toString(); + } + function normalizeBodyForMatching(body2, matchBody, normalizeBody) { + if (matchBody === false) return ""; + if (normalizeBody) return String(normalizeBody(body2) ?? ""); + return body2 ? String(body2) : ""; + } + function formatRequestKey(opts, headerFilters, matchOptions = {}) { + const url2 = new URL(opts.path, opts.origin); + const normalized = opts._normalizedHeaders || normalizeHeaders(opts.headers); + if (!opts._normalizedHeaders) { + opts._normalizedHeaders = normalized; + } + return { + method: opts.method || "GET", + url: normalizeUrlForMatching(url2, matchOptions.matchQuery, matchOptions.normalizeQuery), + headers: filterHeadersForMatching(normalized, headerFilters, matchOptions), + body: normalizeBodyForMatching(opts.body, matchOptions.matchBody, matchOptions.normalizeBody) + }; + } + function filterHeadersForMatching(headers2, headerFilters, matchOptions = {}) { + if (!headers2 || typeof headers2 !== "object") return {}; + const { + caseSensitive = false + } = matchOptions; + const filtered = {}; + const { ignore, exclude, match } = headerFilters; + for (const [key, value2] of Object.entries(headers2)) { + const headerKey = caseSensitive ? key : key.toLowerCase(); + if (exclude.has(headerKey)) continue; + if (ignore.has(headerKey)) continue; + if (match.size !== 0) { + if (!match.has(headerKey)) continue; + } + filtered[headerKey] = value2; + } + return filtered; + } + function filterHeadersForStorage(headers2, headerFilters, matchOptions = {}) { + if (!headers2 || typeof headers2 !== "object") return {}; + const { + caseSensitive = false + } = matchOptions; + const filtered = {}; + const { exclude: excludeSet } = headerFilters; + for (const [key, value2] of Object.entries(headers2)) { + const headerKey = caseSensitive ? key : key.toLowerCase(); + if (excludeSet.has(headerKey)) continue; + filtered[headerKey] = value2; + } + return filtered; + } + function createRequestHash(formattedRequest) { + const parts = [ + formattedRequest.method, + formattedRequest.url + ]; + if (formattedRequest.headers && typeof formattedRequest.headers === "object") { + const headerKeys = Object.keys(formattedRequest.headers).sort(); + for (const key of headerKeys) { + const values2 = Array.isArray(formattedRequest.headers[key]) ? formattedRequest.headers[key] : [formattedRequest.headers[key]]; + parts.push(key); + for (const value2 of values2.sort()) { + parts.push(String(value2)); + } + } + } + parts.push(formattedRequest.body); + const content2 = parts.join("|"); + return hashId(content2); + } + var SnapshotRecorder = class { + /** @type {NodeJS.Timeout | null} */ + #flushTimeout; + /** @type {import('./snapshot-utils').IsUrlExcluded} */ + #isUrlExcluded; + /** @type {Map} */ + #snapshots = /* @__PURE__ */ new Map(); + /** @type {string|undefined} */ + #snapshotPath; + /** @type {number} */ + #maxSnapshots = Infinity; + /** @type {boolean} */ + #autoFlush = false; + /** @type {import('./snapshot-utils').HeaderFilters} */ + #headerFilters; + /** + * Creates a new SnapshotRecorder instance + * @param {SnapshotRecorderOptions&SnapshotRecorderMatchOptions} [options={}] - Configuration options for the recorder + */ + constructor(options2 = {}) { + this.#snapshotPath = options2.snapshotPath; + this.#maxSnapshots = options2.maxSnapshots || Infinity; + this.#autoFlush = options2.autoFlush || false; + this.flushInterval = options2.flushInterval || 3e4; + this._flushTimer = null; + this.matchOptions = { + matchHeaders: options2.matchHeaders || [], + // empty means match all headers + ignoreHeaders: options2.ignoreHeaders || [], + excludeHeaders: options2.excludeHeaders || [], + matchBody: options2.matchBody !== false, + // default: true + normalizeBody: options2.normalizeBody || void 0, + matchQuery: options2.matchQuery !== false, + // default: true + normalizeQuery: options2.normalizeQuery || void 0, + caseSensitive: options2.caseSensitive || false + }; + this.#headerFilters = createHeaderFilters(this.matchOptions); + this.shouldRecord = options2.shouldRecord || (() => true); + this.shouldPlayback = options2.shouldPlayback || (() => true); + this.#isUrlExcluded = isUrlExcludedFactory(options2.excludeUrls); + if (this.#autoFlush && this.#snapshotPath) { + this.#startAutoFlush(); + } + } + /** + * Records a request-response interaction + * @param {SnapshotRequestOptions} requestOpts - Request options + * @param {SnapshotEntryResponse} response - Response data to record + * @return {Promise} - Resolves when the recording is complete + */ + async record(requestOpts, response) { + if (!this.shouldRecord(requestOpts)) { + return; + } + if (this.isUrlExcluded(requestOpts)) { + return; + } + const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions); + const hash = createRequestHash(request); + const normalizedHeaders = normalizeHeaders(response.headers); + const responseData = { + statusCode: response.statusCode, + headers: filterHeadersForStorage(normalizedHeaders, this.#headerFilters, this.matchOptions), + body: Buffer.isBuffer(response.body) ? response.body.toString("base64") : Buffer.from(String(response.body || "")).toString("base64"), + trailers: response.trailers + }; + if (this.#snapshots.size >= this.#maxSnapshots && !this.#snapshots.has(hash)) { + const oldestKey = this.#snapshots.keys().next().value; + this.#snapshots.delete(oldestKey); + } + const existingSnapshot = this.#snapshots.get(hash); + if (existingSnapshot && existingSnapshot.responses) { + existingSnapshot.responses.push(responseData); + existingSnapshot.timestamp = (/* @__PURE__ */ new Date()).toISOString(); + } else { + this.#snapshots.set(hash, { + request, + responses: [responseData], + // Always store as array for consistency + callCount: 0, + timestamp: (/* @__PURE__ */ new Date()).toISOString() + }); + } + if (this.#autoFlush && this.#snapshotPath) { + this.#scheduleFlush(); + } + } + /** + * Checks if a URL should be excluded from recording/playback + * @param {SnapshotRequestOptions} requestOpts - Request options to check + * @returns {boolean} - True if URL is excluded + */ + isUrlExcluded(requestOpts) { + const url2 = new URL(requestOpts.path, requestOpts.origin).toString(); + return this.#isUrlExcluded(url2); + } + /** + * Finds a matching snapshot for the given request + * Returns the appropriate response based on call count for sequential responses + * + * @param {SnapshotRequestOptions} requestOpts - Request options to match + * @returns {SnapshotEntry&Record<'response', SnapshotEntryResponse>|undefined} - Matching snapshot response or undefined if not found + */ + findSnapshot(requestOpts) { + if (!this.shouldPlayback(requestOpts)) { + return void 0; + } + if (this.isUrlExcluded(requestOpts)) { + return void 0; + } + const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions); + const hash = createRequestHash(request); + const snapshot = this.#snapshots.get(hash); + if (!snapshot) return void 0; + const currentCallCount = snapshot.callCount || 0; + const responseIndex = Math.min(currentCallCount, snapshot.responses.length - 1); + snapshot.callCount = currentCallCount + 1; + return { + ...snapshot, + response: snapshot.responses[responseIndex] + }; + } + /** + * Loads snapshots from file + * @param {string} [filePath] - Optional file path to load snapshots from + * @return {Promise} - Resolves when snapshots are loaded + */ + async loadSnapshots(filePath) { + const path2 = filePath || this.#snapshotPath; + if (!path2) { + throw new InvalidArgumentError("Snapshot path is required"); + } + try { + const data2 = await readFile(resolve(path2), "utf8"); + const parsed = JSON.parse(data2); + if (Array.isArray(parsed)) { + this.#snapshots.clear(); + for (const { hash, snapshot } of parsed) { + this.#snapshots.set(hash, snapshot); + } + } else { + this.#snapshots = new Map(Object.entries(parsed)); + } + } catch (error2) { + if (error2.code === "ENOENT") { + this.#snapshots.clear(); + } else { + throw new UndiciError(`Failed to load snapshots from ${path2}`, { cause: error2 }); + } + } + } + /** + * Saves snapshots to file + * + * @param {string} [filePath] - Optional file path to save snapshots + * @returns {Promise} - Resolves when snapshots are saved + */ + async saveSnapshots(filePath) { + const path2 = filePath || this.#snapshotPath; + if (!path2) { + throw new InvalidArgumentError("Snapshot path is required"); + } + const resolvedPath = resolve(path2); + await mkdir(dirname2(resolvedPath), { recursive: true }); + const data2 = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({ + hash, + snapshot + })); + await writeFile(resolvedPath, JSON.stringify(data2, null, 2), { flush: true }); + } + /** + * Clears all recorded snapshots + * @returns {void} + */ + clear() { + this.#snapshots.clear(); + } + /** + * Gets all recorded snapshots + * @return {Array} - Array of all recorded snapshots + */ + getSnapshots() { + return Array.from(this.#snapshots.values()); + } + /** + * Gets snapshot count + * @return {number} - Number of recorded snapshots + */ + size() { + return this.#snapshots.size; + } + /** + * Resets call counts for all snapshots (useful for test cleanup) + * @returns {void} + */ + resetCallCounts() { + for (const snapshot of this.#snapshots.values()) { + snapshot.callCount = 0; + } + } + /** + * Deletes a specific snapshot by request options + * @param {SnapshotRequestOptions} requestOpts - Request options to match + * @returns {boolean} - True if snapshot was deleted, false if not found + */ + deleteSnapshot(requestOpts) { + const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions); + const hash = createRequestHash(request); + return this.#snapshots.delete(hash); + } + /** + * Gets information about a specific snapshot + * @param {SnapshotRequestOptions} requestOpts - Request options to match + * @returns {SnapshotInfo|null} - Snapshot information or null if not found + */ + getSnapshotInfo(requestOpts) { + const request = formatRequestKey(requestOpts, this.#headerFilters, this.matchOptions); + const hash = createRequestHash(request); + const snapshot = this.#snapshots.get(hash); + if (!snapshot) return null; + return { + hash, + request: snapshot.request, + responseCount: snapshot.responses ? snapshot.responses.length : snapshot.response ? 1 : 0, + // .response for legacy snapshots + callCount: snapshot.callCount || 0, + timestamp: snapshot.timestamp + }; + } + /** + * Replaces all snapshots with new data (full replacement) + * @param {Array<{hash: string; snapshot: SnapshotEntry}>|Record} snapshotData - New snapshot data to replace existing ones + * @returns {void} + */ + replaceSnapshots(snapshotData) { + this.#snapshots.clear(); + if (Array.isArray(snapshotData)) { + for (const { hash, snapshot } of snapshotData) { + this.#snapshots.set(hash, snapshot); + } + } else if (snapshotData && typeof snapshotData === "object") { + this.#snapshots = new Map(Object.entries(snapshotData)); + } + } + /** + * Starts the auto-flush timer + * @returns {void} + */ + #startAutoFlush() { + return this.#scheduleFlush(); + } + /** + * Stops the auto-flush timer + * @returns {void} + */ + #stopAutoFlush() { + if (this.#flushTimeout) { + clearTimeout2(this.#flushTimeout); + this.saveSnapshots().catch(() => { + }); + this.#flushTimeout = null; + } + } + /** + * Schedules a flush (debounced to avoid excessive writes) + */ + #scheduleFlush() { + this.#flushTimeout = setTimeout2(() => { + this.saveSnapshots().catch(() => { + }); + if (this.#autoFlush) { + this.#flushTimeout?.refresh(); + } else { + this.#flushTimeout = null; + } + }, 1e3); + } + /** + * Cleanup method to stop timers + * @returns {void} + */ + destroy() { + this.#stopAutoFlush(); + if (this.#flushTimeout) { + clearTimeout2(this.#flushTimeout); + this.#flushTimeout = null; + } + } + /** + * Async close method that saves all recordings and performs cleanup + * @returns {Promise} + */ + async close() { + if (this.#snapshotPath && this.#snapshots.size !== 0) { + await this.saveSnapshots(); + } + this.destroy(); + } + }; + module2.exports = { SnapshotRecorder, formatRequestKey, createRequestHash, filterHeadersForMatching, filterHeadersForStorage, createHeaderFilters }; + } +}); + +// node_modules/undici/lib/mock/snapshot-agent.js +var require_snapshot_agent = __commonJS({ + "node_modules/undici/lib/mock/snapshot-agent.js"(exports2, module2) { + "use strict"; + var Agent = require_agent(); + var MockAgent = require_mock_agent(); + var { SnapshotRecorder } = require_snapshot_recorder(); + var { InvalidArgumentError, UndiciError } = require_errors2(); + var util = require_util(); + var { validateSnapshotMode } = require_snapshot_utils(); + var kSnapshotRecorder = /* @__PURE__ */ Symbol("kSnapshotRecorder"); + var kSnapshotMode = /* @__PURE__ */ Symbol("kSnapshotMode"); + var kSnapshotPath = /* @__PURE__ */ Symbol("kSnapshotPath"); + var kSnapshotLoaded = /* @__PURE__ */ Symbol("kSnapshotLoaded"); + var kRealAgent = /* @__PURE__ */ Symbol("kRealAgent"); + var warningEmitted = false; + var SnapshotAgent = class extends MockAgent { + constructor(opts = {}) { + if (!warningEmitted) { + process.emitWarning( + "SnapshotAgent is experimental and subject to change", + "ExperimentalWarning" + ); + warningEmitted = true; + } + const { + mode: mode2 = "record", + snapshotPath = null, + ...mockAgentOpts + } = opts; + super(mockAgentOpts); + validateSnapshotMode(mode2); + if ((mode2 === "playback" || mode2 === "update") && !snapshotPath) { + throw new InvalidArgumentError(`snapshotPath is required when mode is '${mode2}'`); + } + this[kSnapshotMode] = mode2; + this[kSnapshotPath] = snapshotPath; + this[kSnapshotRecorder] = new SnapshotRecorder({ + snapshotPath: this[kSnapshotPath], + mode: this[kSnapshotMode], + maxSnapshots: opts.maxSnapshots, + autoFlush: opts.autoFlush, + flushInterval: opts.flushInterval, + matchHeaders: opts.matchHeaders, + ignoreHeaders: opts.ignoreHeaders, + excludeHeaders: opts.excludeHeaders, + matchBody: opts.matchBody, + normalizeBody: opts.normalizeBody, + matchQuery: opts.matchQuery, + normalizeQuery: opts.normalizeQuery, + caseSensitive: opts.caseSensitive, + shouldRecord: opts.shouldRecord, + shouldPlayback: opts.shouldPlayback, + excludeUrls: opts.excludeUrls + }); + this[kSnapshotLoaded] = false; + if (this[kSnapshotMode] === "record" || this[kSnapshotMode] === "update" || this[kSnapshotMode] === "playback" && opts.excludeUrls && opts.excludeUrls.length > 0) { + this[kRealAgent] = new Agent(opts); + } + if ((this[kSnapshotMode] === "playback" || this[kSnapshotMode] === "update") && this[kSnapshotPath]) { + this.loadSnapshots().catch(() => { + }); + } + } + dispatch(opts, handler) { + const mode2 = this[kSnapshotMode]; + if (this[kSnapshotRecorder].isUrlExcluded(opts)) { + return this[kRealAgent].dispatch(opts, handler); + } + if (mode2 === "playback" || mode2 === "update") { + if (!this[kSnapshotLoaded]) { + return this.#asyncDispatch(opts, handler); + } + const snapshot = this[kSnapshotRecorder].findSnapshot(opts); + if (snapshot) { + return this.#replaySnapshot(snapshot, handler); + } else if (mode2 === "update") { + return this.#recordAndReplay(opts, handler); + } else { + const error2 = new UndiciError(`No snapshot found for ${opts.method || "GET"} ${opts.path}`); + if (handler.onResponseError) { + handler.onResponseError(null, error2); + return; + } + throw error2; + } + } else if (mode2 === "record") { + return this.#recordAndReplay(opts, handler); + } + } + /** + * Async version of dispatch for when we need to load snapshots first + */ + async #asyncDispatch(opts, handler) { + await this.loadSnapshots(); + return this.dispatch(opts, handler); + } + /** + * Records a real request and replays the response + */ + #recordAndReplay(opts, handler) { + const responseData = { + statusCode: null, + headers: {}, + trailers: {}, + body: [] + }; + const self2 = this; + const recordingHandler = { + onRequestStart(controller, context2) { + return handler.onRequestStart(controller, { ...context2, history: this.history }); + }, + onRequestUpgrade(controller, statusCode, headers2, socket) { + return handler.onRequestUpgrade(controller, statusCode, headers2, socket); + }, + onResponseStart(controller, statusCode, headers2, statusMessage) { + responseData.statusCode = statusCode; + responseData.headers = headers2; + return handler.onResponseStart(controller, statusCode, headers2, statusMessage); + }, + onResponseData(controller, chunk) { + responseData.body.push(chunk); + return handler.onResponseData(controller, chunk); + }, + onResponseEnd(controller, trailers) { + responseData.trailers = trailers; + const responseBody = Buffer.concat(responseData.body); + self2[kSnapshotRecorder].record(opts, { + statusCode: responseData.statusCode, + headers: responseData.headers, + body: responseBody, + trailers: responseData.trailers + }).then(() => handler.onResponseEnd(controller, trailers)).catch((error2) => handler.onResponseError(controller, error2)); + }, + onResponseError(controller, error2) { + return handler.onResponseError(controller, error2); + } + }; + const agent = this[kRealAgent]; + return agent.dispatch(opts, recordingHandler); + } + /** + * Replays a recorded response + * + * @param {Object} snapshot - The recorded snapshot to replay. + * @param {Object} handler - The handler to call with the response data. + * @returns {void} + */ + #replaySnapshot(snapshot, handler) { + try { + const { response } = snapshot; + const rawHeaders = response.headers ? util.toRawHeaders(response.headers) : []; + const rawTrailers = response.trailers ? util.toRawHeaders(response.trailers) : []; + const controller = { + rawHeaders, + rawTrailers, + pause() { + }, + resume() { + }, + abort(reason2) { + this.aborted = true; + this.reason = reason2; + }, + aborted: false, + paused: false + }; + handler.onRequestStart(controller); + handler.onResponseStart(controller, response.statusCode, response.headers, response.statusMessage); + const body2 = Buffer.from(response.body, "base64"); + handler.onResponseData(controller, body2); + handler.onResponseEnd(controller, response.trailers); + } catch (error2) { + handler.onResponseError?.(null, error2); + } + } + /** + * Loads snapshots from file + * + * @param {string} [filePath] - Optional file path to load snapshots from. + * @returns {Promise} - Resolves when snapshots are loaded. + */ + async loadSnapshots(filePath) { + await this[kSnapshotRecorder].loadSnapshots(filePath || this[kSnapshotPath]); + this[kSnapshotLoaded] = true; + if (this[kSnapshotMode] === "playback") { + this.#setupMockInterceptors(); + } + } + /** + * Saves snapshots to file + * + * @param {string} [filePath] - Optional file path to save snapshots to. + * @returns {Promise} - Resolves when snapshots are saved. + */ + async saveSnapshots(filePath) { + return this[kSnapshotRecorder].saveSnapshots(filePath || this[kSnapshotPath]); + } + /** + * Sets up MockAgent interceptors based on recorded snapshots. + * + * This method creates MockAgent interceptors for each recorded snapshot, + * allowing the SnapshotAgent to fall back to MockAgent's standard intercept + * mechanism in playback mode. Each interceptor is configured to persist + * (remain active for multiple requests) and responds with the recorded + * response data. + * + * Called automatically when loading snapshots in playback mode. + * + * @returns {void} + */ + #setupMockInterceptors() { + for (const snapshot of this[kSnapshotRecorder].getSnapshots()) { + const { request, responses, response } = snapshot; + const url2 = new URL(request.url); + const mockPool = this.get(url2.origin); + const responseData = responses ? responses[0] : response; + if (!responseData) continue; + mockPool.intercept({ + path: url2.pathname + url2.search, + method: request.method, + headers: request.headers, + body: request.body + }).reply(responseData.statusCode, responseData.body, { + headers: responseData.headers, + trailers: responseData.trailers + }).persist(); + } + } + /** + * Gets the snapshot recorder + * @return {SnapshotRecorder} - The snapshot recorder instance + */ + getRecorder() { + return this[kSnapshotRecorder]; + } + /** + * Gets the current mode + * @return {import('./snapshot-utils').SnapshotMode} - The current snapshot mode + */ + getMode() { + return this[kSnapshotMode]; + } + /** + * Clears all snapshots + * @returns {void} + */ + clearSnapshots() { + this[kSnapshotRecorder].clear(); + } + /** + * Resets call counts for all snapshots (useful for test cleanup) + * @returns {void} + */ + resetCallCounts() { + this[kSnapshotRecorder].resetCallCounts(); + } + /** + * Deletes a specific snapshot by request options + * @param {import('./snapshot-recorder').SnapshotRequestOptions} requestOpts - Request options to identify the snapshot + * @return {Promise} - Returns true if the snapshot was deleted, false if not found + */ + deleteSnapshot(requestOpts) { + return this[kSnapshotRecorder].deleteSnapshot(requestOpts); + } + /** + * Gets information about a specific snapshot + * @returns {import('./snapshot-recorder').SnapshotInfo|null} - Snapshot information or null if not found + */ + getSnapshotInfo(requestOpts) { + return this[kSnapshotRecorder].getSnapshotInfo(requestOpts); + } + /** + * Replaces all snapshots with new data (full replacement) + * @param {Array<{hash: string; snapshot: import('./snapshot-recorder').SnapshotEntryshotEntry}>|Record} snapshotData - New snapshot data to replace existing snapshots + * @returns {void} + */ + replaceSnapshots(snapshotData) { + this[kSnapshotRecorder].replaceSnapshots(snapshotData); + } + /** + * Closes the agent, saving snapshots and cleaning up resources. + * + * @returns {Promise} + */ + async close() { + if (this[kSnapshotMode] === "playback") { + this[kSnapshotRecorder].destroy(); + } else { + await this[kSnapshotRecorder].close(); + } + await this[kRealAgent]?.close(); + await super.close(); + } + }; + module2.exports = SnapshotAgent; + } +}); + +// node_modules/undici/lib/global.js +var require_global2 = __commonJS({ + "node_modules/undici/lib/global.js"(exports2, module2) { + "use strict"; + var globalDispatcher = /* @__PURE__ */ Symbol.for("undici.globalDispatcher.2"); + var legacyGlobalDispatcher = /* @__PURE__ */ Symbol.for("undici.globalDispatcher.1"); + var { InvalidArgumentError } = require_errors2(); + var Agent = require_agent(); + var Dispatcher1Wrapper = require_dispatcher1_wrapper(); + var fallbackDispatcher; + if (getGlobalDispatcher() === void 0) { + setGlobalDispatcher2(new Agent()); + } + function setGlobalDispatcher2(agent) { + if (!agent || typeof agent.dispatch !== "function") { + throw new InvalidArgumentError("Argument agent must implement Agent"); + } + try { + Object.defineProperty(globalThis, globalDispatcher, { + value: agent, + writable: true, + enumerable: false, + configurable: false + }); + } catch (err) { + if (err instanceof TypeError) { + fallbackDispatcher = agent; + return; + } + throw err; + } + try { + const legacyAgent = agent instanceof Dispatcher1Wrapper ? agent : new Dispatcher1Wrapper(agent); + Object.defineProperty(globalThis, legacyGlobalDispatcher, { + value: legacyAgent, + writable: true, + enumerable: false, + configurable: false + }); + } catch (err) { + if (!(err instanceof TypeError)) { + throw err; + } + } + } + function getGlobalDispatcher() { + return globalThis[globalDispatcher] ?? fallbackDispatcher; + } + var installedExports = ( + /** @type {const} */ + [ + "fetch", + "Headers", + "Response", + "Request", + "FormData", + "WebSocket", + "CloseEvent", + "ErrorEvent", + "MessageEvent", + "EventSource" + ] + ); + module2.exports = { + setGlobalDispatcher: setGlobalDispatcher2, + getGlobalDispatcher, + installedExports + }; + } +}); + +// node_modules/undici/lib/handler/decorator-handler.js +var require_decorator_handler = __commonJS({ + "node_modules/undici/lib/handler/decorator-handler.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + module2.exports = class DecoratorHandler { + #handler; + #onCompleteCalled = false; + #onErrorCalled = false; + #onResponseStartCalled = false; + constructor(handler) { + if (typeof handler !== "object" || handler === null) { + throw new TypeError("handler must be an object"); + } + this.#handler = handler; + } + onRequestStart(...args) { + this.#handler.onRequestStart?.(...args); + } + onRequestUpgrade(...args) { + assert(!this.#onCompleteCalled); + assert(!this.#onErrorCalled); + return this.#handler.onRequestUpgrade?.(...args); + } + onResponseStart(...args) { + assert(!this.#onCompleteCalled); + assert(!this.#onErrorCalled); + assert(!this.#onResponseStartCalled); + this.#onResponseStartCalled = true; + return this.#handler.onResponseStart?.(...args); + } + onResponseData(...args) { + assert(!this.#onCompleteCalled); + assert(!this.#onErrorCalled); + return this.#handler.onResponseData?.(...args); + } + onResponseEnd(...args) { + assert(!this.#onCompleteCalled); + assert(!this.#onErrorCalled); + this.#onCompleteCalled = true; + return this.#handler.onResponseEnd?.(...args); + } + onResponseError(...args) { + this.#onErrorCalled = true; + return this.#handler.onResponseError?.(...args); + } + /** + * @deprecated + */ + onBodySent() { + } + }; + } +}); + +// node_modules/undici/lib/handler/redirect-handler.js +var require_redirect_handler = __commonJS({ + "node_modules/undici/lib/handler/redirect-handler.js"(exports2, module2) { + "use strict"; + var util = require_util(); + var assert = require("node:assert"); + var { InvalidArgumentError } = require_errors2(); + var redirectableStatusCodes = [300, 301, 302, 303, 307, 308]; + var noop = () => { + }; + var RedirectHandler = class _RedirectHandler { + static buildDispatch(dispatcher, maxRedirections) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError("maxRedirections must be a positive number"); + } + const dispatch2 = dispatcher.dispatch.bind(dispatcher); + return (opts, originalHandler) => dispatch2(opts, new _RedirectHandler(dispatch2, maxRedirections, opts, originalHandler)); + } + constructor(dispatch2, maxRedirections, opts, handler) { + if (maxRedirections != null && (!Number.isInteger(maxRedirections) || maxRedirections < 0)) { + throw new InvalidArgumentError("maxRedirections must be a positive number"); + } + if (opts.throwOnMaxRedirect != null && typeof opts.throwOnMaxRedirect !== "boolean") { + throw new InvalidArgumentError("throwOnMaxRedirect must be a boolean"); + } + this.dispatch = dispatch2; + this.location = null; + const { maxRedirections: _, stripHeadersOnRedirect, stripHeadersOnCrossOriginRedirect, ...cleanOpts } = opts; + this.opts = cleanOpts; + this.opts.body = util.wrapRequestBody(this.opts.body); + this.stripHeadersOnRedirect = normalizeStripHeaders(stripHeadersOnRedirect, "stripHeadersOnRedirect"); + this.stripHeadersOnCrossOriginRedirect = normalizeStripHeaders(stripHeadersOnCrossOriginRedirect, "stripHeadersOnCrossOriginRedirect"); + this.maxRedirections = maxRedirections; + this.handler = handler; + this.history = []; + } + onRequestStart(controller, context2) { + this.handler.onRequestStart?.(controller, { ...context2, history: this.history }); + } + onRequestUpgrade(controller, statusCode, headers2, socket) { + this.handler.onRequestUpgrade?.(controller, statusCode, headers2, socket); + } + onResponseStart(controller, statusCode, headers2, statusMessage) { + if (this.opts.throwOnMaxRedirect && this.history.length >= this.maxRedirections) { + throw new Error("max redirects"); + } + let removeContentHeaders = statusCode === 303; + if ((statusCode === 301 || statusCode === 302) && this.opts.method === "POST") { + this.opts.method = "GET"; + if (util.isStream(this.opts.body)) { + util.destroy(this.opts.body.on("error", noop)); + } + this.opts.body = null; + removeContentHeaders = true; + } + if (statusCode === 303 && this.opts.method !== "HEAD") { + this.opts.method = "GET"; + if (util.isStream(this.opts.body)) { + util.destroy(this.opts.body.on("error", noop)); + } + this.opts.body = null; + } + this.location = this.history.length >= this.maxRedirections || util.isDisturbed(this.opts.body) || redirectableStatusCodes.indexOf(statusCode) === -1 ? null : headers2.location; + if (this.opts.origin) { + this.history.push(new URL(this.opts.path, this.opts.origin)); + } + if (!this.location) { + this.handler.onResponseStart?.(controller, statusCode, headers2, statusMessage); + return; + } + const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); + const path2 = search ? `${pathname}${search}` : pathname; + const redirectUrlString = `${origin}${path2}`; + for (const historyUrl of this.history) { + if (historyUrl.toString() === redirectUrlString) { + throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`); + } + } + this.opts.headers = cleanRequestHeaders(this.opts.headers, removeContentHeaders, this.opts.origin !== origin, this.stripHeadersOnRedirect, this.stripHeadersOnCrossOriginRedirect); + this.opts.path = path2; + this.opts.origin = origin; + this.opts.query = null; + } + onResponseData(controller, chunk) { + if (this.location) { + } else { + this.handler.onResponseData?.(controller, chunk); + } + } + onResponseEnd(controller, trailers) { + if (this.location) { + this.dispatch(this.opts, this); + } else { + this.handler.onResponseEnd(controller, trailers); + } + } + onResponseError(controller, error2) { + this.handler.onResponseError?.(controller, error2); + } + }; + function shouldRemoveHeader(header, removeContent, unknownOrigin, stripHeaders, stripHeadersOnCrossOrigin) { + const name2 = util.headerNameToString(header); + if (name2 === "host") { + return true; + } + if (stripHeaders?.has(name2) || unknownOrigin && stripHeadersOnCrossOrigin?.has(name2)) { + return true; + } + if (removeContent && name2.startsWith("content-")) { + return true; + } + if (unknownOrigin) { + return name2 === "authorization" || name2 === "cookie" || name2 === "proxy-authorization"; + } + return false; + } + function normalizeStripHeaders(headers2, optionName) { + if (headers2 == null) { + return null; + } + if (!Array.isArray(headers2)) { + throw new InvalidArgumentError(`${optionName} must be an array`); + } + const normalized = /* @__PURE__ */ new Set(); + for (const header of headers2) { + if (typeof header !== "string") { + throw new InvalidArgumentError(`${optionName} must contain header names`); + } + normalized.add(util.headerNameToString(header)); + } + return normalized; + } + function cleanRequestHeaders(headers2, removeContent, unknownOrigin, stripHeaders, stripHeadersOnCrossOrigin) { + const ret = []; + if (Array.isArray(headers2)) { + for (let i = 0; i < headers2.length; i += 2) { + if (!shouldRemoveHeader(headers2[i], removeContent, unknownOrigin, stripHeaders, stripHeadersOnCrossOrigin)) { + ret.push(headers2[i], headers2[i + 1]); + } + } + } else if (headers2 && typeof headers2 === "object") { + const entries2 = util.hasSafeIterator(headers2) ? headers2 : Object.entries(headers2); + for (const [key, value2] of entries2) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin, stripHeaders, stripHeadersOnCrossOrigin)) { + ret.push(key, value2); + } + } + } else { + assert(headers2 == null, "headers must be an object or an array"); + } + return ret; + } + module2.exports = RedirectHandler; + } +}); + +// node_modules/undici/lib/interceptor/redirect.js +var require_redirect = __commonJS({ + "node_modules/undici/lib/interceptor/redirect.js"(exports2, module2) { + "use strict"; + var RedirectHandler = require_redirect_handler(); + function createRedirectInterceptor({ maxRedirections: defaultMaxRedirections, throwOnMaxRedirect: defaultThrowOnMaxRedirect, stripHeadersOnRedirect: defaultStripHeadersOnRedirect, stripHeadersOnCrossOriginRedirect: defaultStripHeadersOnCrossOriginRedirect } = {}) { + return (dispatch2) => { + return function Intercept(opts, handler) { + const { maxRedirections = defaultMaxRedirections, throwOnMaxRedirect = defaultThrowOnMaxRedirect, stripHeadersOnRedirect = defaultStripHeadersOnRedirect, stripHeadersOnCrossOriginRedirect = defaultStripHeadersOnCrossOriginRedirect, ...rest } = opts; + if (maxRedirections == null || maxRedirections === 0) { + return dispatch2(opts, handler); + } + const dispatchOpts = { ...rest, throwOnMaxRedirect, stripHeadersOnRedirect, stripHeadersOnCrossOriginRedirect }; + const redirectHandler = new RedirectHandler(dispatch2, maxRedirections, dispatchOpts, handler); + return dispatch2(dispatchOpts, redirectHandler); + }; + }; + } + module2.exports = createRedirectInterceptor; + } +}); + +// node_modules/undici/lib/interceptor/response-error.js +var require_response_error = __commonJS({ + "node_modules/undici/lib/interceptor/response-error.js"(exports2, module2) { + "use strict"; + var DecoratorHandler = require_decorator_handler(); + var { ResponseError } = require_errors2(); + var ResponseErrorHandler = class extends DecoratorHandler { + #statusCode; + #contentType; + #decoder; + #headers; + #body; + constructor(_opts, { handler }) { + super(handler); + } + #checkContentType(contentType2) { + return (this.#contentType ?? "").indexOf(contentType2) === 0; + } + onRequestStart(controller, context2) { + this.#statusCode = 0; + this.#contentType = null; + this.#decoder = null; + this.#headers = null; + this.#body = ""; + return super.onRequestStart(controller, context2); + } + onResponseStart(controller, statusCode, headers2, statusMessage) { + this.#statusCode = statusCode; + this.#headers = headers2; + this.#contentType = headers2["content-type"]; + if (this.#statusCode < 400) { + return super.onResponseStart(controller, statusCode, headers2, statusMessage); + } + if (this.#checkContentType("application/json") || this.#checkContentType("text/plain")) { + this.#decoder = new TextDecoder("utf-8"); + } + } + onResponseData(controller, chunk) { + if (this.#statusCode < 400) { + return super.onResponseData(controller, chunk); + } + this.#body += this.#decoder?.decode(chunk, { stream: true }) ?? ""; + } + onResponseEnd(controller, trailers) { + if (this.#statusCode >= 400) { + this.#body += this.#decoder?.decode(void 0, { stream: false }) ?? ""; + if (this.#checkContentType("application/json")) { + try { + this.#body = JSON.parse(this.#body); + } catch { + } + } + let err; + const stackTraceLimit = Error.stackTraceLimit; + Error.stackTraceLimit = 0; + try { + err = new ResponseError("Response Error", this.#statusCode, { + body: this.#body, + headers: this.#headers + }); + } finally { + Error.stackTraceLimit = stackTraceLimit; + } + super.onResponseError(controller, err); + } else { + super.onResponseEnd(controller, trailers); + } + } + onResponseError(controller, err) { + super.onResponseError(controller, err); + } + }; + module2.exports = () => { + return (dispatch2) => { + return function Intercept(opts, handler) { + return dispatch2(opts, new ResponseErrorHandler(opts, { handler })); + }; + }; + }; + } +}); + +// node_modules/undici/lib/interceptor/retry.js +var require_retry = __commonJS({ + "node_modules/undici/lib/interceptor/retry.js"(exports2, module2) { + "use strict"; + var RetryHandler = require_retry_handler(); + module2.exports = (globalOpts) => { + return (dispatch2) => { + return function retryInterceptor(opts, handler) { + return dispatch2( + opts, + new RetryHandler( + { ...opts, retryOptions: { ...globalOpts, ...opts.retryOptions } }, + { + handler, + dispatch: dispatch2 + } + ) + ); + }; + }; + }; + } +}); + +// node_modules/undici/lib/interceptor/dump.js +var require_dump = __commonJS({ + "node_modules/undici/lib/interceptor/dump.js"(exports2, module2) { + "use strict"; + var { InvalidArgumentError, RequestAbortedError } = require_errors2(); + var DecoratorHandler = require_decorator_handler(); + var DumpHandler = class extends DecoratorHandler { + #maxSize = 1024 * 1024; + #dumped = false; + #size = 0; + #controller = null; + aborted = false; + reason = false; + constructor({ maxSize, signal: signal2 }, handler) { + if (maxSize != null && (!Number.isFinite(maxSize) || maxSize < 1)) { + throw new InvalidArgumentError("maxSize must be a number greater than 0"); + } + super(handler); + this.#maxSize = maxSize ?? this.#maxSize; + } + #abort(reason2) { + this.aborted = true; + this.reason = reason2; + } + onRequestStart(controller, context2) { + controller.abort = this.#abort.bind(this); + this.#controller = controller; + return super.onRequestStart(controller, context2); + } + onResponseStart(controller, statusCode, headers2, statusMessage) { + const contentLength2 = headers2["content-length"]; + if (contentLength2 != null && contentLength2 > this.#maxSize) { + throw new RequestAbortedError( + `Response size (${contentLength2}) larger than maxSize (${this.#maxSize})` + ); + } + if (this.aborted === true) { + return true; + } + return super.onResponseStart(controller, statusCode, headers2, statusMessage); + } + onResponseError(controller, err) { + if (this.#dumped) { + return; + } + err = this.#controller?.reason ?? err; + super.onResponseError(controller, err); + } + onResponseData(controller, chunk) { + this.#size = this.#size + chunk.length; + if (this.#size >= this.#maxSize) { + this.#dumped = true; + if (this.aborted === true) { + super.onResponseError(controller, this.reason); + } else { + super.onResponseEnd(controller, {}); + } + } + return true; + } + onResponseEnd(controller, trailers) { + if (this.#dumped) { + return; + } + if (this.#controller.aborted === true) { + super.onResponseError(controller, this.reason); + return; + } + super.onResponseEnd(controller, trailers); + } + }; + function createDumpInterceptor({ maxSize: defaultMaxSize } = { + maxSize: 1024 * 1024 + }) { + return (dispatch2) => { + return function Intercept(opts, handler) { + const { dumpMaxSize = defaultMaxSize } = opts; + const dumpHandler = new DumpHandler({ maxSize: dumpMaxSize, signal: opts.signal }, handler); + return dispatch2(opts, dumpHandler); + }; + }; + } + module2.exports = createDumpInterceptor; + } +}); + +// node_modules/undici/lib/interceptor/dns.js +var require_dns = __commonJS({ + "node_modules/undici/lib/interceptor/dns.js"(exports2, module2) { + "use strict"; + var { isIP: isIP2 } = require("node:net"); + var { lookup } = require("node:dns"); + var DecoratorHandler = require_decorator_handler(); + var { InvalidArgumentError, InformationalError } = require_errors2(); + var maxInt = Math.pow(2, 31) - 1; + function hasSafeIterator(headers2) { + const prototype = Object.getPrototypeOf(headers2); + const ownIterator = Object.hasOwn(headers2, Symbol.iterator); + return ownIterator || prototype != null && prototype !== Object.prototype && typeof headers2[Symbol.iterator] === "function"; + } + function isHostHeader(key) { + return typeof key === "string" && key.toLowerCase() === "host"; + } + function normalizeHeaders(headers2) { + if (headers2 == null) { + return null; + } + if (Array.isArray(headers2)) { + if (headers2.length === 0 || !Array.isArray(headers2[0])) { + return headers2; + } + const normalized = []; + for (const header of headers2) { + if (Array.isArray(header) && header.length === 2) { + normalized.push(header[0], header[1]); + } else { + normalized.push(header); + } + } + return normalized; + } + if (typeof headers2 === "object" && hasSafeIterator(headers2)) { + const normalized = []; + for (const header of headers2) { + if (Array.isArray(header) && header.length === 2) { + normalized.push(header[0], header[1]); + } else { + normalized.push(header); + } + } + return normalized; + } + return headers2; + } + function hasHostHeader(headers2) { + if (headers2 == null) { + return false; + } + if (Array.isArray(headers2)) { + if (headers2.length === 0) { + return false; + } + for (let i = 0; i < headers2.length; i += 2) { + if (isHostHeader(headers2[i])) { + return true; + } + } + return false; + } + if (typeof headers2 === "object") { + for (const key in headers2) { + if (isHostHeader(key)) { + return true; + } + } + } + return false; + } + function withHostHeader(host2, headers2) { + const normalizedHeaders = normalizeHeaders(headers2); + if (hasHostHeader(normalizedHeaders)) { + return normalizedHeaders; + } + if (Array.isArray(normalizedHeaders)) { + return ["host", host2, ...normalizedHeaders]; + } + if (normalizedHeaders && typeof normalizedHeaders === "object") { + return { + host: host2, + ...normalizedHeaders + }; + } + return { host: host2 }; + } + var DNSStorage = class { + #maxItems = 0; + #records = /* @__PURE__ */ new Map(); + constructor(opts) { + this.#maxItems = opts.maxItems; + } + get size() { + return this.#records.size; + } + get(hostname) { + return this.#records.get(hostname) ?? null; + } + set(hostname, records) { + this.#records.set(hostname, records); + } + delete(hostname) { + this.#records.delete(hostname); + } + // Delegate to storage decide can we do more lookups or not + full() { + return this.size >= this.#maxItems; + } + }; + var DNSInstance = class { + #maxTTL = 0; + #maxItems = 0; + dualStack = true; + affinity = null; + lookup = null; + pick = null; + storage = null; + constructor(opts) { + this.#maxTTL = opts.maxTTL; + this.#maxItems = opts.maxItems; + this.dualStack = opts.dualStack; + this.affinity = opts.affinity; + this.lookup = opts.lookup ?? this.#defaultLookup; + this.pick = opts.pick ?? this.#defaultPick; + this.storage = opts.storage ?? new DNSStorage(opts); + } + runLookup(origin, opts, cb) { + const ips = this.storage.get(origin.hostname); + if (ips == null && this.storage.full()) { + cb(null, origin); + return; + } + const newOpts = { + affinity: this.affinity, + dualStack: this.dualStack, + lookup: this.lookup, + pick: this.pick, + ...opts.dns, + maxTTL: this.#maxTTL, + maxItems: this.#maxItems + }; + if (ips == null) { + this.lookup(origin, newOpts, (err, addresses) => { + if (err || addresses == null || addresses.length === 0) { + cb(err ?? new InformationalError("No DNS entries found")); + return; + } + this.setRecords(origin, addresses); + const records = this.storage.get(origin.hostname); + const ip = this.pick( + origin, + records, + newOpts.affinity + ); + let port; + if (typeof ip.port === "number") { + port = `:${ip.port}`; + } else if (origin.port !== "") { + port = `:${origin.port}`; + } else { + port = ""; + } + cb( + null, + new URL(`${origin.protocol}//${ip.family === 6 ? `[${ip.address}]` : ip.address}${port}`) + ); + }); + } else { + const ip = this.pick( + origin, + ips, + newOpts.affinity + ); + if (ip == null) { + this.storage.delete(origin.hostname); + this.runLookup(origin, opts, cb); + return; + } + let port; + if (typeof ip.port === "number") { + port = `:${ip.port}`; + } else if (origin.port !== "") { + port = `:${origin.port}`; + } else { + port = ""; + } + cb( + null, + new URL(`${origin.protocol}//${ip.family === 6 ? `[${ip.address}]` : ip.address}${port}`) + ); + } + } + #defaultLookup(origin, opts, cb) { + lookup( + origin.hostname, + { + all: true, + family: this.dualStack === false ? this.affinity : 0, + order: "ipv4first" + }, + (err, addresses) => { + if (err) { + return cb(err); + } + const results = /* @__PURE__ */ new Map(); + for (const addr of addresses) { + results.set(`${addr.address}:${addr.family}`, addr); + } + cb(null, results.values()); + } + ); + } + #defaultPick(origin, hostnameRecords, affinity) { + let ip = null; + const { records, offset: offset2 } = hostnameRecords; + let family; + if (this.dualStack) { + if (affinity == null) { + if (offset2 == null || offset2 === maxInt) { + hostnameRecords.offset = 0; + affinity = 4; + } else { + hostnameRecords.offset++; + affinity = (hostnameRecords.offset & 1) === 1 ? 6 : 4; + } + } + if (records[affinity] != null && records[affinity].ips.length > 0) { + family = records[affinity]; + } else { + family = records[affinity === 4 ? 6 : 4]; + } + } else { + family = records[affinity]; + } + if (family == null || family.ips.length === 0) { + return ip; + } + if (family.offset == null || family.offset === maxInt) { + family.offset = 0; + } else { + family.offset++; + } + const position = family.offset % family.ips.length; + ip = family.ips[position] ?? null; + if (ip == null) { + return ip; + } + if (Date.now() - ip.timestamp > ip.ttl) { + family.ips.splice(position, 1); + return this.pick(origin, hostnameRecords, affinity); + } + return ip; + } + pickFamily(origin, ipFamily) { + const records = this.storage.get(origin.hostname)?.records; + if (!records) { + return null; + } + const family = records[ipFamily]; + if (!family) { + return null; + } + if (family.offset == null || family.offset === maxInt) { + family.offset = 0; + } else { + family.offset++; + } + const position = family.offset % family.ips.length; + const ip = family.ips[position] ?? null; + if (ip == null) { + return ip; + } + if (Date.now() - ip.timestamp > ip.ttl) { + family.ips.splice(position, 1); + } + return ip; + } + setRecords(origin, addresses) { + const timestamp = Date.now(); + const records = { records: { 4: null, 6: null } }; + let minTTL = this.#maxTTL; + for (const record of addresses) { + record.timestamp = timestamp; + if (typeof record.ttl === "number") { + record.ttl = Math.min(record.ttl, this.#maxTTL); + minTTL = Math.min(minTTL, record.ttl); + } else { + record.ttl = this.#maxTTL; + } + const familyRecords = records.records[record.family] ?? { ips: [] }; + familyRecords.ips.push(record); + records.records[record.family] = familyRecords; + } + this.storage.set(origin.hostname, records, { ttl: minTTL }); + } + deleteRecords(origin) { + this.storage.delete(origin.hostname); + } + getHandler(meta, opts) { + return new DNSDispatchHandler(this, meta, opts); + } + }; + var DNSDispatchHandler = class extends DecoratorHandler { + #state = null; + #opts = null; + #dispatch = null; + #origin = null; + #controller = null; + #newOrigin = null; + #firstTry = true; + constructor(state2, { origin, handler, dispatch: dispatch2, newOrigin }, opts) { + super(handler); + this.#origin = origin; + this.#newOrigin = newOrigin; + this.#opts = { ...opts }; + this.#state = state2; + this.#dispatch = dispatch2; + } + onResponseError(controller, err) { + switch (err.code) { + case "ETIMEDOUT": + case "ECONNREFUSED": { + if (this.#state.dualStack) { + if (!this.#firstTry) { + super.onResponseError(controller, err); + return; + } + this.#firstTry = false; + const otherFamily = this.#newOrigin.hostname[0] === "[" ? 4 : 6; + const ip = this.#state.pickFamily(this.#origin, otherFamily); + if (ip == null) { + super.onResponseError(controller, err); + return; + } + let port; + if (typeof ip.port === "number") { + port = `:${ip.port}`; + } else if (this.#origin.port !== "") { + port = `:${this.#origin.port}`; + } else { + port = ""; + } + const dispatchOpts = { + ...this.#opts, + origin: `${this.#origin.protocol}//${ip.family === 6 ? `[${ip.address}]` : ip.address}${port}`, + headers: withHostHeader(this.#origin.host, this.#opts.headers) + }; + this.#dispatch(dispatchOpts, this); + return; + } + super.onResponseError(controller, err); + break; + } + case "ENOTFOUND": + this.#state.deleteRecords(this.#origin); + super.onResponseError(controller, err); + break; + default: + super.onResponseError(controller, err); + break; + } + } + }; + module2.exports = (interceptorOpts) => { + if (interceptorOpts?.maxTTL != null && (typeof interceptorOpts?.maxTTL !== "number" || interceptorOpts?.maxTTL < 0)) { + throw new InvalidArgumentError("Invalid maxTTL. Must be a positive number"); + } + if (interceptorOpts?.maxItems != null && (typeof interceptorOpts?.maxItems !== "number" || interceptorOpts?.maxItems < 1)) { + throw new InvalidArgumentError( + "Invalid maxItems. Must be a positive number and greater than zero" + ); + } + if (interceptorOpts?.affinity != null && interceptorOpts?.affinity !== 4 && interceptorOpts?.affinity !== 6) { + throw new InvalidArgumentError("Invalid affinity. Must be either 4 or 6"); + } + if (interceptorOpts?.dualStack != null && typeof interceptorOpts?.dualStack !== "boolean") { + throw new InvalidArgumentError("Invalid dualStack. Must be a boolean"); + } + if (interceptorOpts?.lookup != null && typeof interceptorOpts?.lookup !== "function") { + throw new InvalidArgumentError("Invalid lookup. Must be a function"); + } + if (interceptorOpts?.pick != null && typeof interceptorOpts?.pick !== "function") { + throw new InvalidArgumentError("Invalid pick. Must be a function"); + } + if (interceptorOpts?.storage != null && (typeof interceptorOpts?.storage?.get !== "function" || typeof interceptorOpts?.storage?.set !== "function" || typeof interceptorOpts?.storage?.full !== "function" || typeof interceptorOpts?.storage?.delete !== "function")) { + throw new InvalidArgumentError("Invalid storage. Must be a object with methods: { get, set, full, delete }"); + } + const dualStack = interceptorOpts?.dualStack ?? true; + let affinity; + if (dualStack) { + affinity = interceptorOpts?.affinity ?? null; + } else { + affinity = interceptorOpts?.affinity ?? 4; + } + const opts = { + maxTTL: interceptorOpts?.maxTTL ?? 1e4, + // Expressed in ms + lookup: interceptorOpts?.lookup ?? null, + pick: interceptorOpts?.pick ?? null, + dualStack, + affinity, + maxItems: interceptorOpts?.maxItems ?? Infinity, + storage: interceptorOpts?.storage + }; + const instance = new DNSInstance(opts); + return (dispatch2) => { + return function dnsInterceptor(origDispatchOpts, handler) { + if (origDispatchOpts.origin == null) { + return dispatch2(origDispatchOpts, handler); + } + const origin = origDispatchOpts.origin.constructor === URL ? origDispatchOpts.origin : new URL(origDispatchOpts.origin); + if (isIP2(origin.hostname) !== 0) { + return dispatch2(origDispatchOpts, handler); + } + instance.runLookup(origin, origDispatchOpts, (err, newOrigin) => { + if (err) { + return handler.onResponseError(null, err); + } + const dispatchOpts = { + ...origDispatchOpts, + servername: origin.hostname, + // For SNI on TLS + origin: newOrigin.origin, + headers: withHostHeader(origin.host, origDispatchOpts.headers) + }; + dispatch2( + dispatchOpts, + instance.getHandler( + { origin, dispatch: dispatch2, handler, newOrigin }, + origDispatchOpts + ) + ); + }); + return true; + }; + }; + }; + } +}); + +// node_modules/undici/lib/util/cache.js +var require_cache = __commonJS({ + "node_modules/undici/lib/util/cache.js"(exports2, module2) { + "use strict"; + var { + safeHTTPMethods, + pathHasQueryOrFragment, + hasSafeIterator, + isValidHTTPToken + } = require_util(); + var { serializePathWithQuery } = require_util(); + var MAX_DELTA_SECONDS = 2147483647; + var RESTRICTIVE_DIRECTIVE_NAMES = ["no-store", "private", "no-cache"]; + var kInvalidCacheControlDirectives = /* @__PURE__ */ Symbol("invalid cache-control directives"); + function trimOWS(value2) { + return value2.replace(/^[\t ]+|[\t ]+$/g, ""); + } + function arrayIncludes(array, value2) { + for (let i = 0; i < array.length; i++) { + if (array[i] === value2) { + return true; + } + } + return false; + } + function trimOWSStart(value2) { + return value2.replace(/^[\t ]+/, ""); + } + function trimOWSEnd(value2) { + return value2.replace(/[\t ]+$/, ""); + } + function findUnescapedQuote(value2, start2) { + let escaped = false; + for (let i = start2; i < value2.length; i++) { + if (escaped) { + escaped = false; + } else if (value2[i] === "\\") { + escaped = true; + } else if (value2[i] === '"') { + return i; + } + } + return -1; + } + function splitCacheControlHeaderValue(value2) { + const directives = []; + let start2 = 0; + let quoteStart = -1; + let inQuote = false; + let escaped = false; + for (let i = 0; i < value2.length; i++) { + if (inQuote) { + if (escaped) { + escaped = false; + } else if (value2[i] === "\\") { + escaped = true; + } else if (value2[i] === '"') { + inQuote = false; + quoteStart = -1; + } + } else if (value2[i] === '"') { + inQuote = true; + quoteStart = i; + } else if (value2[i] === ",") { + directives.push({ value: value2.substring(start2, i), fromMalformedQuote: false }); + start2 = i + 1; + } + } + if (!inQuote) { + directives.push({ value: value2.substring(start2), fromMalformedQuote: false }); + return directives; + } + const tail = value2.substring(start2); + const quoteOffset = quoteStart - start2; + let tailStart = 0; + for (let i = 0; i < tail.length; i++) { + if (tail[i] === ",") { + directives.push({ + value: tail.substring(tailStart, i), + fromMalformedQuote: tailStart > quoteOffset + }); + tailStart = i + 1; + } + } + directives.push({ + value: tail.substring(tailStart), + fromMalformedQuote: tailStart > quoteOffset + }); + return directives; + } + function markInvalidCacheControlDirective(directives, key) { + let invalidDirectives = directives[kInvalidCacheControlDirectives]; + if (invalidDirectives === void 0) { + invalidDirectives = /* @__PURE__ */ new Set(); + Object.defineProperty(directives, kInvalidCacheControlDirectives, { + value: invalidDirectives + }); + } + invalidDirectives.add(key); + } + function hasInvalidCacheControlDirective(directives, key) { + return directives[kInvalidCacheControlDirectives]?.has(key) === true; + } + function getMalformedRestrictiveDirectiveName(key) { + for (const directiveName of RESTRICTIVE_DIRECTIVE_NAMES) { + if (key.startsWith(directiveName) && key.length > directiveName.length && !isValidHTTPToken(key[directiveName.length])) { + return directiveName; + } + } + let tokenOnlyKey = ""; + let hasInvalidTokenChar = false; + for (let i = 0; i < key.length; i++) { + if (isValidHTTPToken(key[i])) { + tokenOnlyKey += key[i]; + } else { + hasInvalidTokenChar = true; + } + } + if (hasInvalidTokenChar && arrayIncludes(RESTRICTIVE_DIRECTIVE_NAMES, tokenOnlyKey)) { + return tokenOnlyKey; + } + } + function makeCacheKey(opts) { + const origin = opts.origin ? opts.origin.toString() : ""; + let fullPath = opts.path || "/"; + if (opts.query && !pathHasQueryOrFragment(fullPath)) { + fullPath = serializePathWithQuery(fullPath, opts.query); + } + return { + origin, + method: opts.method, + path: fullPath, + headers: opts.headers + }; + } + function appendHeader(headers2, key, val) { + const headerName = key.toLowerCase(); + const current = headers2[headerName]; + const values2 = Array.isArray(val) ? val : [val]; + if (current === void 0) { + headers2[headerName] = Array.isArray(val) ? val.slice() : val; + } else if (Array.isArray(current)) { + current.push(...values2); + } else { + headers2[headerName] = [current, ...values2]; + } + } + function normalizeHeaders(opts) { + let headers2; + if (opts.headers == null) { + headers2 = {}; + } else if (typeof opts.headers === "object") { + headers2 = {}; + if (hasSafeIterator(opts.headers)) { + if (Array.isArray(opts.headers)) { + const first = opts.headers[0]; + if (Array.isArray(first)) { + for (const x3 of opts.headers) { + if (!Array.isArray(x3)) { + throw new Error("opts.headers is not a valid header map"); + } + const [key, val] = x3; + if (typeof key !== "string" || typeof val !== "string") { + throw new Error("opts.headers is not a valid header map"); + } + appendHeader(headers2, key, val); + } + } else { + const len = opts.headers.length; + if (len % 2 !== 0) { + throw new Error("opts.headers is not a valid header map"); + } + for (let i = 0; i < len; i += 2) { + const key = opts.headers[i]; + const val = opts.headers[i + 1]; + if (typeof key !== "string" || typeof val !== "string" && !Array.isArray(val)) { + throw new Error("opts.headers is not a valid header map"); + } + if (typeof val === "string") { + appendHeader(headers2, key, val); + } else { + const mapped = []; + for (let j = 0; j < val.length; j++) { + const v = val[j]; + mapped.push(typeof v === "string" ? v : v.toString("latin1")); + } + appendHeader(headers2, key, mapped); + } + } + } + } else { + for (const x3 of opts.headers) { + if (!Array.isArray(x3)) { + throw new Error("opts.headers is not a valid header map"); + } + const [key, val] = x3; + if (typeof key !== "string" || typeof val !== "string") { + throw new Error("opts.headers is not a valid header map"); + } + appendHeader(headers2, key, val); + } + } + } else { + for (const key of Object.keys(opts.headers)) { + appendHeader(headers2, key, opts.headers[key]); + } + } + } else { + throw new Error("opts.headers is not an object"); + } + return headers2; + } + function assertCacheKey(key) { + if (typeof key !== "object") { + throw new TypeError(`expected key to be object, got ${typeof key}`); + } + for (const property of ["origin", "method", "path"]) { + if (typeof key[property] !== "string") { + throw new TypeError(`expected key.${property} to be string, got ${typeof key[property]}`); + } + } + if (key.headers !== void 0 && typeof key.headers !== "object") { + throw new TypeError(`expected headers to be object, got ${typeof key}`); + } + } + function assertCacheValue(value2) { + if (typeof value2 !== "object") { + throw new TypeError(`expected value to be object, got ${typeof value2}`); + } + for (const property of ["statusCode", "cachedAt", "staleAt", "deleteAt"]) { + if (typeof value2[property] !== "number") { + throw new TypeError(`expected value.${property} to be number, got ${typeof value2[property]}`); + } + } + if (typeof value2.statusMessage !== "string") { + throw new TypeError(`expected value.statusMessage to be string, got ${typeof value2.statusMessage}`); + } + if (value2.headers != null && typeof value2.headers !== "object") { + throw new TypeError(`expected value.rawHeaders to be object, got ${typeof value2.headers}`); + } + if (value2.vary !== void 0 && typeof value2.vary !== "object") { + throw new TypeError(`expected value.vary to be object, got ${typeof value2.vary}`); + } + if (value2.etag !== void 0 && typeof value2.etag !== "string") { + throw new TypeError(`expected value.etag to be string, got ${typeof value2.etag}`); + } + } + function parseCacheControlHeader(header) { + const output = {}; + const invalidNumericDirectives = /* @__PURE__ */ new Set(); + const invalidNoArgumentDirectives = /* @__PURE__ */ new Set(); + const directives = splitCacheControlHeaderValue(Array.isArray(header) ? header.join(",") : header); + for (let i = 0; i < directives.length; i++) { + const directiveRecord = directives[i]; + const directive = directiveRecord.value.toLowerCase(); + const fromMalformedQuote = directiveRecord.fromMalformedQuote; + const keyValueDelimiter = directive.indexOf("="); + let key; + let value2; + let keyHasTrailingWhitespace = false; + let valueHasLeadingWhitespace = false; + if (keyValueDelimiter !== -1) { + const rawKey = directive.substring(0, keyValueDelimiter); + const rawValue = directive.substring(keyValueDelimiter + 1); + keyHasTrailingWhitespace = trimOWSEnd(rawKey) !== rawKey; + valueHasLeadingWhitespace = trimOWSStart(rawValue) !== rawValue; + key = trimOWS(rawKey); + value2 = trimOWSStart(rawValue); + } else { + key = trimOWS(directive); + } + const malformedRestrictiveDirectiveName = getMalformedRestrictiveDirectiveName(key); + if (malformedRestrictiveDirectiveName !== void 0) { + output[malformedRestrictiveDirectiveName] = true; + continue; + } + switch (key) { + case "min-fresh": + case "max-stale": + case "max-age": + case "s-maxage": + case "stale-while-revalidate": + case "stale-if-error": { + if (fromMalformedQuote || invalidNumericDirectives.has(key)) { + continue; + } + if (value2 === void 0 || keyHasTrailingWhitespace || valueHasLeadingWhitespace) { + delete output[key]; + invalidNumericDirectives.add(key); + markInvalidCacheControlDirective(output, key); + continue; + } + if (value2.length >= 2 && value2[0] === '"' && value2[value2.length - 1] === '"') { + value2 = value2.substring(1, value2.length - 1); + } + if (!/^[0-9]+$/.test(value2)) { + delete output[key]; + invalidNumericDirectives.add(key); + markInvalidCacheControlDirective(output, key); + continue; + } + const parsedValue = Math.min(parseInt(value2, 10), MAX_DELTA_SECONDS); + if (key === "min-fresh") { + if (!(key in output) || output[key] < parsedValue) { + output[key] = parsedValue; + } + } else if (!(key in output) || output[key] > parsedValue) { + output[key] = parsedValue; + } + break; + } + case "private": + case "no-cache": { + if (fromMalformedQuote) { + output[key] = true; + break; + } + if (value2 !== void 0 && value2.length === 0) { + output[key] = true; + break; + } + if (value2) { + if (value2[0] === '"') { + value2 = trimOWSEnd(value2); + let fieldList = ""; + let lastQuotedPart = i; + let foundEndingQuote = false; + const closingQuote = findUnescapedQuote(value2, 1); + if (closingQuote !== -1) { + fieldList = value2.substring(1, closingQuote); + foundEndingQuote = true; + } else { + const fieldListParts = [value2.substring(1)]; + for (let j = i + 1; j < directives.length; j++) { + const nextPart = trimOWS(directives[j].value); + const closingQuote2 = findUnescapedQuote(nextPart, 0); + lastQuotedPart = j; + if (closingQuote2 !== -1) { + fieldListParts.push(nextPart.substring(0, closingQuote2)); + foundEndingQuote = true; + break; + } + fieldListParts.push(nextPart); + } + fieldList = fieldListParts.join(","); + } + if (!foundEndingQuote) { + output[key] = true; + break; + } + i = lastQuotedPart; + const headers2 = fieldList.split(","); + let validFieldNames = true; + for (let j = 0; j < headers2.length; j++) { + headers2[j] = trimOWS(headers2[j]); + if (!isValidHTTPToken(headers2[j])) { + validFieldNames = false; + } + } + if (!validFieldNames) { + output[key] = true; + } else if (output[key] !== true) { + if (key in output) { + output[key] = output[key].concat(headers2); + } else { + output[key] = headers2; + } + } + } else { + const fieldName = trimOWS(value2); + if (!isValidHTTPToken(fieldName)) { + output[key] = true; + } else if (output[key] !== true) { + if (key in output) { + output[key] = output[key].concat(fieldName); + } else { + output[key] = [fieldName]; + } + } + } + break; + } + } + // eslint-disable-next-line no-fallthrough + case "public": + case "must-revalidate": + case "proxy-revalidate": + case "immutable": + case "no-transform": + case "must-understand": + case "only-if-cached": + if (fromMalformedQuote || invalidNoArgumentDirectives.has(key)) { + continue; + } + if (value2 !== void 0) { + delete output[key]; + invalidNoArgumentDirectives.add(key); + continue; + } + output[key] = true; + break; + case "no-store": + output[key] = true; + break; + default: + continue; + } + } + return output; + } + function splitVaryHeader(varyHeader) { + const values2 = Array.isArray(varyHeader) ? varyHeader : [varyHeader]; + const output = []; + for (let i = 0; i < values2.length; i++) { + const parts = values2[i].split(","); + for (let j = 0; j < parts.length; j++) { + output.push(parts[j]); + } + } + return output; + } + function hasVaryStar(varyHeader) { + const values2 = splitVaryHeader(varyHeader); + for (let i = 0; i < values2.length; i++) { + if (trimOWS(values2[i]).indexOf("*") !== -1) { + return true; + } + } + return false; + } + function parseVaryHeader(varyHeader, headers2) { + if (hasVaryStar(varyHeader)) { + return headers2; + } + const output = ( + /** @type {Record} */ + {} + ); + const varyingHeaders = splitVaryHeader(varyHeader); + for (const header of varyingHeaders) { + const trimmedHeader = trimOWS(header).toLowerCase(); + if (trimmedHeader.length === 0) { + continue; + } + if (!isValidHTTPToken(trimmedHeader)) { + return void 0; + } + const headerValue = headers2[trimmedHeader]; + output[trimmedHeader] = Array.isArray(headerValue) ? headerValue.slice() : headerValue ?? null; + } + return output; + } + function isInvalidOrWildcardVaryHeader(varyHeader) { + return hasVaryStar(varyHeader) || parseVaryHeader(varyHeader, {}) === void 0; + } + function isEtagUsable(etag) { + if (etag.length <= 2) { + return false; + } + if (etag[0] === '"' && etag[etag.length - 1] === '"') { + return !(etag[1] === '"' || etag.startsWith('"W/')); + } + if (etag.startsWith('W/"') && etag[etag.length - 1] === '"') { + return etag.length !== 4; + } + return false; + } + function assertCacheStore(store, name2 = "CacheStore") { + if (typeof store !== "object" || store === null) { + throw new TypeError(`expected type of ${name2} to be a CacheStore, got ${store === null ? "null" : typeof store}`); + } + for (const fn of ["get", "createWriteStream", "delete"]) { + if (typeof store[fn] !== "function") { + throw new TypeError(`${name2} needs to have a \`${fn}()\` function`); + } + } + } + function assertCacheMethods(methods, name2 = "CacheMethods") { + if (!Array.isArray(methods)) { + throw new TypeError(`expected type of ${name2} needs to be an array, got ${methods === null ? "null" : typeof methods}`); + } + if (methods.length === 0) { + throw new TypeError(`${name2} needs to have at least one method`); + } + for (const method2 of methods) { + if (!arrayIncludes(safeHTTPMethods, method2)) { + throw new TypeError(`element of ${name2}-array needs to be one of following values: ${safeHTTPMethods.join(", ")}, got ${method2}`); + } + } + } + function makeDeduplicationKey(cacheKey, excludeHeaders) { + const headers2 = {}; + if (cacheKey.headers) { + const sortedHeaders = Object.keys(cacheKey.headers).sort(); + for (const header of sortedHeaders) { + if (excludeHeaders?.has(header.toLowerCase())) { + continue; + } + headers2[header] = cacheKey.headers[header]; + } + } + return JSON.stringify([cacheKey.origin, cacheKey.method, cacheKey.path, headers2]); + } + module2.exports = { + makeCacheKey, + normalizeHeaders, + assertCacheKey, + assertCacheValue, + parseCacheControlHeader, + hasInvalidCacheControlDirective, + parseVaryHeader, + hasVaryStar, + isInvalidOrWildcardVaryHeader, + isEtagUsable, + assertCacheMethods, + assertCacheStore, + makeDeduplicationKey + }; + } +}); + +// node_modules/undici/lib/util/date.js +var require_date = __commonJS({ + "node_modules/undici/lib/util/date.js"(exports2, module2) { + "use strict"; + function parseHttpDate(date) { + switch (date[3]) { + case ",": + return parseImfDate(date); + case " ": + return parseAscTimeDate(date); + default: + return parseRfc850Date(date); + } + } + function makeDate(year, monthIdx, day, hour, minute, second, weekday) { + const result3 = new Date(Date.UTC(year, monthIdx, day, hour, minute, second)); + if (year >= 0 && year <= 99) { + result3.setUTCFullYear(year); + } + return result3.getUTCFullYear() === year && result3.getUTCMonth() === monthIdx && result3.getUTCDate() === day && result3.getUTCHours() === hour && result3.getUTCMinutes() === minute && result3.getUTCSeconds() === second && result3.getUTCDay() === weekday ? result3 : void 0; + } + function parseImfDate(date) { + if (date.length !== 29 || date[4] !== " " || date[7] !== " " || date[11] !== " " || date[16] !== " " || date[19] !== ":" || date[22] !== ":" || date[25] !== " " || date[26] !== "G" || date[27] !== "M" || date[28] !== "T") { + return void 0; + } + let weekday = -1; + if (date[0] === "S" && date[1] === "u" && date[2] === "n") { + weekday = 0; + } else if (date[0] === "M" && date[1] === "o" && date[2] === "n") { + weekday = 1; + } else if (date[0] === "T" && date[1] === "u" && date[2] === "e") { + weekday = 2; + } else if (date[0] === "W" && date[1] === "e" && date[2] === "d") { + weekday = 3; + } else if (date[0] === "T" && date[1] === "h" && date[2] === "u") { + weekday = 4; + } else if (date[0] === "F" && date[1] === "r" && date[2] === "i") { + weekday = 5; + } else if (date[0] === "S" && date[1] === "a" && date[2] === "t") { + weekday = 6; + } else { + return void 0; + } + let day = 0; + if (date[5] === "0") { + const code = date.charCodeAt(6); + if (code < 49 || code > 57) { + return void 0; + } + day = code - 48; + } else { + const code1 = date.charCodeAt(5); + if (code1 < 49 || code1 > 51) { + return void 0; + } + const code2 = date.charCodeAt(6); + if (code2 < 48 || code2 > 57) { + return void 0; + } + day = (code1 - 48) * 10 + (code2 - 48); + } + let monthIdx = -1; + if (date[8] === "J" && date[9] === "a" && date[10] === "n") { + monthIdx = 0; + } else if (date[8] === "F" && date[9] === "e" && date[10] === "b") { + monthIdx = 1; + } else if (date[8] === "M" && date[9] === "a") { + if (date[10] === "r") { + monthIdx = 2; + } else if (date[10] === "y") { + monthIdx = 4; + } else { + return void 0; + } + } else if (date[8] === "J") { + if (date[9] === "a" && date[10] === "n") { + monthIdx = 0; + } else if (date[9] === "u") { + if (date[10] === "n") { + monthIdx = 5; + } else if (date[10] === "l") { + monthIdx = 6; + } else { + return void 0; + } + } else { + return void 0; + } + } else if (date[8] === "A") { + if (date[9] === "p" && date[10] === "r") { + monthIdx = 3; + } else if (date[9] === "u" && date[10] === "g") { + monthIdx = 7; + } else { + return void 0; + } + } else if (date[8] === "S" && date[9] === "e" && date[10] === "p") { + monthIdx = 8; + } else if (date[8] === "O" && date[9] === "c" && date[10] === "t") { + monthIdx = 9; + } else if (date[8] === "N" && date[9] === "o" && date[10] === "v") { + monthIdx = 10; + } else if (date[8] === "D" && date[9] === "e" && date[10] === "c") { + monthIdx = 11; + } else { + return void 0; + } + const yearDigit1 = date.charCodeAt(12); + if (yearDigit1 < 48 || yearDigit1 > 57) { + return void 0; + } + const yearDigit2 = date.charCodeAt(13); + if (yearDigit2 < 48 || yearDigit2 > 57) { + return void 0; + } + const yearDigit3 = date.charCodeAt(14); + if (yearDigit3 < 48 || yearDigit3 > 57) { + return void 0; + } + const yearDigit4 = date.charCodeAt(15); + if (yearDigit4 < 48 || yearDigit4 > 57) { + return void 0; + } + const year = (yearDigit1 - 48) * 1e3 + (yearDigit2 - 48) * 100 + (yearDigit3 - 48) * 10 + (yearDigit4 - 48); + let hour = 0; + if (date[17] === "0") { + const code = date.charCodeAt(18); + if (code < 48 || code > 57) { + return void 0; + } + hour = code - 48; + } else { + const code1 = date.charCodeAt(17); + if (code1 < 48 || code1 > 50) { + return void 0; + } + const code2 = date.charCodeAt(18); + if (code2 < 48 || code2 > 57) { + return void 0; + } + if (code1 === 50 && code2 > 51) { + return void 0; + } + hour = (code1 - 48) * 10 + (code2 - 48); + } + let minute = 0; + if (date[20] === "0") { + const code = date.charCodeAt(21); + if (code < 48 || code > 57) { + return void 0; + } + minute = code - 48; + } else { + const code1 = date.charCodeAt(20); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(21); + if (code2 < 48 || code2 > 57) { + return void 0; + } + minute = (code1 - 48) * 10 + (code2 - 48); + } + let second = 0; + if (date[23] === "0") { + const code = date.charCodeAt(24); + if (code < 48 || code > 57) { + return void 0; + } + second = code - 48; + } else { + const code1 = date.charCodeAt(23); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(24); + if (code2 < 48 || code2 > 57) { + return void 0; + } + second = (code1 - 48) * 10 + (code2 - 48); + } + return makeDate(year, monthIdx, day, hour, minute, second, weekday); + } + function parseAscTimeDate(date) { + if (date.length !== 24 || date[7] !== " " || date[10] !== " " || date[19] !== " ") { + return void 0; + } + let weekday = -1; + if (date[0] === "S" && date[1] === "u" && date[2] === "n") { + weekday = 0; + } else if (date[0] === "M" && date[1] === "o" && date[2] === "n") { + weekday = 1; + } else if (date[0] === "T" && date[1] === "u" && date[2] === "e") { + weekday = 2; + } else if (date[0] === "W" && date[1] === "e" && date[2] === "d") { + weekday = 3; + } else if (date[0] === "T" && date[1] === "h" && date[2] === "u") { + weekday = 4; + } else if (date[0] === "F" && date[1] === "r" && date[2] === "i") { + weekday = 5; + } else if (date[0] === "S" && date[1] === "a" && date[2] === "t") { + weekday = 6; + } else { + return void 0; + } + let monthIdx = -1; + if (date[4] === "J" && date[5] === "a" && date[6] === "n") { + monthIdx = 0; + } else if (date[4] === "F" && date[5] === "e" && date[6] === "b") { + monthIdx = 1; + } else if (date[4] === "M" && date[5] === "a") { + if (date[6] === "r") { + monthIdx = 2; + } else if (date[6] === "y") { + monthIdx = 4; + } else { + return void 0; + } + } else if (date[4] === "J") { + if (date[5] === "a" && date[6] === "n") { + monthIdx = 0; + } else if (date[5] === "u") { + if (date[6] === "n") { + monthIdx = 5; + } else if (date[6] === "l") { + monthIdx = 6; + } else { + return void 0; + } + } else { + return void 0; + } + } else if (date[4] === "A") { + if (date[5] === "p" && date[6] === "r") { + monthIdx = 3; + } else if (date[5] === "u" && date[6] === "g") { + monthIdx = 7; + } else { + return void 0; + } + } else if (date[4] === "S" && date[5] === "e" && date[6] === "p") { + monthIdx = 8; + } else if (date[4] === "O" && date[5] === "c" && date[6] === "t") { + monthIdx = 9; + } else if (date[4] === "N" && date[5] === "o" && date[6] === "v") { + monthIdx = 10; + } else if (date[4] === "D" && date[5] === "e" && date[6] === "c") { + monthIdx = 11; + } else { + return void 0; + } + let day = 0; + if (date[8] === " ") { + const code = date.charCodeAt(9); + if (code < 49 || code > 57) { + return void 0; + } + day = code - 48; + } else { + const code1 = date.charCodeAt(8); + if (code1 < 49 || code1 > 51) { + return void 0; + } + const code2 = date.charCodeAt(9); + if (code2 < 48 || code2 > 57) { + return void 0; + } + day = (code1 - 48) * 10 + (code2 - 48); + } + let hour = 0; + if (date[11] === "0") { + const code = date.charCodeAt(12); + if (code < 48 || code > 57) { + return void 0; + } + hour = code - 48; + } else { + const code1 = date.charCodeAt(11); + if (code1 < 48 || code1 > 50) { + return void 0; + } + const code2 = date.charCodeAt(12); + if (code2 < 48 || code2 > 57) { + return void 0; + } + if (code1 === 50 && code2 > 51) { + return void 0; + } + hour = (code1 - 48) * 10 + (code2 - 48); + } + let minute = 0; + if (date[14] === "0") { + const code = date.charCodeAt(15); + if (code < 48 || code > 57) { + return void 0; + } + minute = code - 48; + } else { + const code1 = date.charCodeAt(14); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(15); + if (code2 < 48 || code2 > 57) { + return void 0; + } + minute = (code1 - 48) * 10 + (code2 - 48); + } + let second = 0; + if (date[17] === "0") { + const code = date.charCodeAt(18); + if (code < 48 || code > 57) { + return void 0; + } + second = code - 48; + } else { + const code1 = date.charCodeAt(17); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(18); + if (code2 < 48 || code2 > 57) { + return void 0; + } + second = (code1 - 48) * 10 + (code2 - 48); + } + const yearDigit1 = date.charCodeAt(20); + if (yearDigit1 < 48 || yearDigit1 > 57) { + return void 0; + } + const yearDigit2 = date.charCodeAt(21); + if (yearDigit2 < 48 || yearDigit2 > 57) { + return void 0; + } + const yearDigit3 = date.charCodeAt(22); + if (yearDigit3 < 48 || yearDigit3 > 57) { + return void 0; + } + const yearDigit4 = date.charCodeAt(23); + if (yearDigit4 < 48 || yearDigit4 > 57) { + return void 0; + } + const year = (yearDigit1 - 48) * 1e3 + (yearDigit2 - 48) * 100 + (yearDigit3 - 48) * 10 + (yearDigit4 - 48); + return makeDate(year, monthIdx, day, hour, minute, second, weekday); + } + function parseRfc850Date(date) { + let commaIndex = -1; + let weekday = -1; + if (date[0] === "S") { + if (date[1] === "u" && date[2] === "n" && date[3] === "d" && date[4] === "a" && date[5] === "y") { + weekday = 0; + commaIndex = 6; + } else if (date[1] === "a" && date[2] === "t" && date[3] === "u" && date[4] === "r" && date[5] === "d" && date[6] === "a" && date[7] === "y") { + weekday = 6; + commaIndex = 8; + } + } else if (date[0] === "M" && date[1] === "o" && date[2] === "n" && date[3] === "d" && date[4] === "a" && date[5] === "y") { + weekday = 1; + commaIndex = 6; + } else if (date[0] === "T") { + if (date[1] === "u" && date[2] === "e" && date[3] === "s" && date[4] === "d" && date[5] === "a" && date[6] === "y") { + weekday = 2; + commaIndex = 7; + } else if (date[1] === "h" && date[2] === "u" && date[3] === "r" && date[4] === "s" && date[5] === "d" && date[6] === "a" && date[7] === "y") { + weekday = 4; + commaIndex = 8; + } + } else if (date[0] === "W" && date[1] === "e" && date[2] === "d" && date[3] === "n" && date[4] === "e" && date[5] === "s" && date[6] === "d" && date[7] === "a" && date[8] === "y") { + weekday = 3; + commaIndex = 9; + } else if (date[0] === "F" && date[1] === "r" && date[2] === "i" && date[3] === "d" && date[4] === "a" && date[5] === "y") { + weekday = 5; + commaIndex = 6; + } else { + return void 0; + } + if (date[commaIndex] !== "," || date.length - commaIndex - 1 !== 23 || date[commaIndex + 1] !== " " || date[commaIndex + 4] !== "-" || date[commaIndex + 8] !== "-" || date[commaIndex + 11] !== " " || date[commaIndex + 14] !== ":" || date[commaIndex + 17] !== ":" || date[commaIndex + 20] !== " " || date[commaIndex + 21] !== "G" || date[commaIndex + 22] !== "M" || date[commaIndex + 23] !== "T") { + return void 0; + } + let day = 0; + if (date[commaIndex + 2] === "0") { + const code = date.charCodeAt(commaIndex + 3); + if (code < 49 || code > 57) { + return void 0; + } + day = code - 48; + } else { + const code1 = date.charCodeAt(commaIndex + 2); + if (code1 < 49 || code1 > 51) { + return void 0; + } + const code2 = date.charCodeAt(commaIndex + 3); + if (code2 < 48 || code2 > 57) { + return void 0; + } + day = (code1 - 48) * 10 + (code2 - 48); + } + let monthIdx = -1; + if (date[commaIndex + 5] === "J" && date[commaIndex + 6] === "a" && date[commaIndex + 7] === "n") { + monthIdx = 0; + } else if (date[commaIndex + 5] === "F" && date[commaIndex + 6] === "e" && date[commaIndex + 7] === "b") { + monthIdx = 1; + } else if (date[commaIndex + 5] === "M" && date[commaIndex + 6] === "a" && date[commaIndex + 7] === "r") { + monthIdx = 2; + } else if (date[commaIndex + 5] === "A" && date[commaIndex + 6] === "p" && date[commaIndex + 7] === "r") { + monthIdx = 3; + } else if (date[commaIndex + 5] === "M" && date[commaIndex + 6] === "a" && date[commaIndex + 7] === "y") { + monthIdx = 4; + } else if (date[commaIndex + 5] === "J" && date[commaIndex + 6] === "u" && date[commaIndex + 7] === "n") { + monthIdx = 5; + } else if (date[commaIndex + 5] === "J" && date[commaIndex + 6] === "u" && date[commaIndex + 7] === "l") { + monthIdx = 6; + } else if (date[commaIndex + 5] === "A" && date[commaIndex + 6] === "u" && date[commaIndex + 7] === "g") { + monthIdx = 7; + } else if (date[commaIndex + 5] === "S" && date[commaIndex + 6] === "e" && date[commaIndex + 7] === "p") { + monthIdx = 8; + } else if (date[commaIndex + 5] === "O" && date[commaIndex + 6] === "c" && date[commaIndex + 7] === "t") { + monthIdx = 9; + } else if (date[commaIndex + 5] === "N" && date[commaIndex + 6] === "o" && date[commaIndex + 7] === "v") { + monthIdx = 10; + } else if (date[commaIndex + 5] === "D" && date[commaIndex + 6] === "e" && date[commaIndex + 7] === "c") { + monthIdx = 11; + } else { + return void 0; + } + const yearDigit1 = date.charCodeAt(commaIndex + 9); + if (yearDigit1 < 48 || yearDigit1 > 57) { + return void 0; + } + const yearDigit2 = date.charCodeAt(commaIndex + 10); + if (yearDigit2 < 48 || yearDigit2 > 57) { + return void 0; + } + let year = (yearDigit1 - 48) * 10 + (yearDigit2 - 48); + year += year < 70 ? 2e3 : 1900; + let hour = 0; + if (date[commaIndex + 12] === "0") { + const code = date.charCodeAt(commaIndex + 13); + if (code < 48 || code > 57) { + return void 0; + } + hour = code - 48; + } else { + const code1 = date.charCodeAt(commaIndex + 12); + if (code1 < 48 || code1 > 50) { + return void 0; + } + const code2 = date.charCodeAt(commaIndex + 13); + if (code2 < 48 || code2 > 57) { + return void 0; + } + if (code1 === 50 && code2 > 51) { + return void 0; + } + hour = (code1 - 48) * 10 + (code2 - 48); + } + let minute = 0; + if (date[commaIndex + 15] === "0") { + const code = date.charCodeAt(commaIndex + 16); + if (code < 48 || code > 57) { + return void 0; + } + minute = code - 48; + } else { + const code1 = date.charCodeAt(commaIndex + 15); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(commaIndex + 16); + if (code2 < 48 || code2 > 57) { + return void 0; + } + minute = (code1 - 48) * 10 + (code2 - 48); + } + let second = 0; + if (date[commaIndex + 18] === "0") { + const code = date.charCodeAt(commaIndex + 19); + if (code < 48 || code > 57) { + return void 0; + } + second = code - 48; + } else { + const code1 = date.charCodeAt(commaIndex + 18); + if (code1 < 48 || code1 > 53) { + return void 0; + } + const code2 = date.charCodeAt(commaIndex + 19); + if (code2 < 48 || code2 > 57) { + return void 0; + } + second = (code1 - 48) * 10 + (code2 - 48); + } + return makeDate(year, monthIdx, day, hour, minute, second, weekday); + } + module2.exports = { + parseHttpDate + }; + } +}); + +// node_modules/undici/lib/handler/cache-handler.js +var require_cache_handler = __commonJS({ + "node_modules/undici/lib/handler/cache-handler.js"(exports2, module2) { + "use strict"; + var util = require_util(); + var { + parseCacheControlHeader, + hasInvalidCacheControlDirective, + parseVaryHeader, + hasVaryStar, + isInvalidOrWildcardVaryHeader, + isEtagUsable + } = require_cache(); + var { parseHttpDate } = require_date(); + function noop() { + } + var HEURISTICALLY_CACHEABLE_STATUS_CODES = [ + 200, + 203, + 204, + 206, + 300, + 301, + 308, + 404, + 405, + 410, + 414, + 501 + ]; + var NOT_UNDERSTOOD_STATUS_CODES = [ + 206 + ]; + var MAX_RESPONSE_AGE = 2147483647e3; + var REVALIDATION_ONLY_RETENTION = 864e5; + function trimOWS(value2) { + return value2.replace(/^[\t ]+|[\t ]+$/g, ""); + } + function arrayIncludes(array, value2) { + for (let i = 0; i < array.length; i++) { + if (array[i] === value2) { + return true; + } + } + return false; + } + function appendConnectionHeaderTokens(headersToRemove, connectionHeader) { + const values2 = Array.isArray(connectionHeader) ? connectionHeader : [connectionHeader]; + for (let i = 0; i < values2.length; i++) { + const tokens = values2[i].split(","); + for (let j = 0; j < tokens.length; j++) { + headersToRemove.push(trimOWS(tokens[j]).toLowerCase()); + } + } + } + function getSameOriginPath(cacheKey, location2) { + if (typeof location2 !== "string") { + return void 0; + } + let originUrl; + let requestUrl; + let locationUrl; + try { + originUrl = new URL(cacheKey.origin); + requestUrl = new URL(cacheKey.path, originUrl); + locationUrl = new URL(location2, requestUrl); + } catch { + return void 0; + } + if (locationUrl.origin !== originUrl.origin) { + return void 0; + } + return locationUrl.pathname + locationUrl.search; + } + function deleteCachedUri(store, cacheKey, path2) { + deleteCachedValue(store, { + ...cacheKey, + path: path2 + }); + for (let i = 0; i < util.safeHTTPMethods.length; i++) { + const method2 = util.safeHTTPMethods[i]; + if (method2 !== cacheKey.method) { + deleteCachedValue(store, { + ...cacheKey, + method: method2, + path: path2 + }); + } + } + } + function deleteLocationTargets(store, cacheKey, headerValue) { + if (headerValue === void 0) { + return; + } + const values2 = Array.isArray(headerValue) ? headerValue : [headerValue]; + for (let i = 0; i < values2.length; i++) { + const path2 = getSameOriginPath(cacheKey, values2[i]); + if (path2 !== void 0) { + deleteCachedUri(store, cacheKey, path2); + } + } + } + function invalidateUnsafeRequest(store, cacheKey, resHeaders) { + deleteCachedUri(store, cacheKey, cacheKey.path); + deleteLocationTargets(store, cacheKey, resHeaders.location); + deleteLocationTargets(store, cacheKey, resHeaders["content-location"]); + } + var CacheHandler = class { + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey} + */ + #cacheKey; + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions['type']} + */ + #cacheType; + /** + * @type {number | undefined} + */ + #cacheByDefault; + /** + * @type {import('../../types/cache-interceptor.d.ts').default.CacheStore} + */ + #store; + /** + * @type {import('../../types/dispatcher.d.ts').default.DispatchHandler} + */ + #handler; + /** + * @type {import('node:stream').Writable | undefined} + */ + #writeStream; + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} opts + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey + * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler + */ + constructor({ store, type: type2, cacheByDefault }, cacheKey, handler) { + this.#store = store; + this.#cacheType = type2; + this.#cacheByDefault = cacheByDefault; + this.#cacheKey = cacheKey; + this.#handler = handler; + } + onRequestStart(controller, context2) { + this.#writeStream?.destroy(); + this.#writeStream = void 0; + this.#handler.onRequestStart?.(controller, context2); + } + onRequestUpgrade(controller, statusCode, headers2, socket) { + this.#handler.onRequestUpgrade?.(controller, statusCode, headers2, socket); + } + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {number} statusCode + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders + * @param {string} statusMessage + */ + onResponseStart(controller, statusCode, resHeaders, statusMessage) { + const downstreamOnHeaders = () => this.#handler.onResponseStart?.( + controller, + statusCode, + resHeaders, + statusMessage + ); + const handler = this; + if (!arrayIncludes(util.safeHTTPMethods, this.#cacheKey.method) && statusCode >= 200 && statusCode <= 399) { + invalidateUnsafeRequest(this.#store, this.#cacheKey, resHeaders); + return downstreamOnHeaders(); + } + const cacheControlHeader = resHeaders["cache-control"]; + const heuristicallyCacheable = resHeaders["last-modified"] && arrayIncludes(HEURISTICALLY_CACHEABLE_STATUS_CODES, statusCode); + if (!cacheControlHeader && !resHeaders["expires"] && !heuristicallyCacheable && !this.#cacheByDefault) { + if (statusCode === 304 && resHeaders.vary && isInvalidOrWildcardVaryHeader(resHeaders.vary)) { + deleteCachedValue(this.#store, this.#cacheKey); + } + return downstreamOnHeaders(); + } + const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}; + if (!canCacheResponse(this.#cacheType, statusCode, resHeaders, cacheControlDirectives, this.#cacheKey.headers)) { + if (statusCode === 304 && (cacheControlHeader || revalidationResponseDisallowsCachedReuse(this.#cacheType, resHeaders, cacheControlDirectives))) { + deleteCachedValue(this.#store, this.#cacheKey); + } + return downstreamOnHeaders(); + } + const now = Date.now(); + const resAge = Object.hasOwn(resHeaders, "age") ? getAge(resHeaders.age) : void 0; + if (resAge !== void 0 && resAge >= MAX_RESPONSE_AGE) { + deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); + return downstreamOnHeaders(); + } + const resDate = Object.hasOwn(resHeaders, "date") ? getDate(resHeaders.date) : void 0; + if (resDate === null) { + deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); + return downstreamOnHeaders(); + } + const apparentAge = resDate ? Math.max(0, now - resDate.getTime()) : 0; + const currentAge = Math.max(apparentAge, resAge ?? 0); + const hasValidator = typeof resHeaders.etag === "string" && isEtagUsable(resHeaders.etag) || typeof resHeaders["last-modified"] === "string"; + const staleAt = determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives, hasValidator) ?? this.#cacheByDefault; + const revalidationOnly = staleAt === 0 && hasValidator; + if (staleAt === void 0 || currentAge >= staleAt && !revalidationOnly) { + if (cacheControlHeader || staleAt !== void 0) { + deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); + } + return downstreamOnHeaders(); + } + const baseTime = now - currentAge; + const absoluteStaleAt = staleAt + baseTime; + if (now >= absoluteStaleAt && !revalidationOnly) { + deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); + return downstreamOnHeaders(); + } + let varyDirectives; + if (this.#cacheKey.headers && resHeaders.vary) { + varyDirectives = parseVaryHeader(resHeaders.vary, this.#cacheKey.headers); + if (!varyDirectives) { + return downstreamOnHeaders(); + } + } + const cachedAt = baseTime; + const deleteAt = determineDeleteAt(baseTime, now, cacheControlDirectives, absoluteStaleAt); + const strippedHeaders = stripNecessaryHeaders(resHeaders, cacheControlDirectives); + const value2 = { + statusCode, + statusMessage, + headers: strippedHeaders, + vary: varyDirectives, + cacheControlDirectives, + cachedAt, + staleAt: absoluteStaleAt, + deleteAt + }; + if (statusCode === 304) { + const handle304 = (cachedValue) => { + if (!cachedValue) { + return downstreamOnHeaders(); + } + value2.statusCode = cachedValue.statusCode; + value2.statusMessage = cachedValue.statusMessage; + value2.etag = cachedValue.etag; + value2.vary = varyDirectives ?? cachedValue.vary; + value2.headers = { ...cachedValue.headers, ...strippedHeaders }; + downstreamOnHeaders(); + this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value2); + if (!this.#writeStream || !cachedValue?.body) { + return; + } + if (typeof cachedValue.body.values === "function") { + const bodyIterator = cachedValue.body.values(); + const streamCachedBody = () => { + for (const chunk of bodyIterator) { + const full = this.#writeStream.write(chunk) === false; + this.#handler.onResponseData?.(controller, chunk); + if (full) { + break; + } + } + }; + this.#writeStream.on("error", function() { + handler.#writeStream = void 0; + handler.#store.delete(handler.#cacheKey); + }).on("drain", () => { + streamCachedBody(); + }).on("close", function() { + if (handler.#writeStream === this) { + handler.#writeStream = void 0; + } + }); + streamCachedBody(); + } else if (typeof cachedValue.body.on === "function") { + cachedValue.body.on("data", (chunk) => { + this.#writeStream.write(chunk); + this.#handler.onResponseData?.(controller, chunk); + }).on("end", () => { + this.#writeStream.end(); + }).on("error", () => { + this.#writeStream = void 0; + this.#store.delete(this.#cacheKey); + }); + this.#writeStream.on("error", function() { + handler.#writeStream = void 0; + handler.#store.delete(handler.#cacheKey); + }).on("close", function() { + if (handler.#writeStream === this) { + handler.#writeStream = void 0; + } + }); + } + }; + const result3 = this.#store.get(this.#cacheKey); + if (result3 && typeof result3.then === "function") { + result3.then(handle304); + } else { + handle304(result3); + } + } else { + if (typeof resHeaders.etag === "string" && isEtagUsable(resHeaders.etag)) { + value2.etag = resHeaders.etag; + } + this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value2); + if (!this.#writeStream) { + return downstreamOnHeaders(); + } + this.#writeStream.on("drain", () => controller.resume()).on("error", function() { + handler.#writeStream = void 0; + handler.#store.delete(handler.#cacheKey); + }).on("close", function() { + if (handler.#writeStream === this) { + handler.#writeStream = void 0; + } + controller.resume(); + }); + downstreamOnHeaders(); + } + } + onResponseData(controller, chunk) { + if (this.#writeStream?.write(chunk) === false) { + controller.pause(); + } + this.#handler.onResponseData?.(controller, chunk); + } + onResponseEnd(controller, trailers) { + this.#writeStream?.end(); + this.#handler.onResponseEnd?.(controller, trailers); + } + onResponseError(controller, err) { + this.#writeStream?.destroy(err); + this.#writeStream = void 0; + this.#handler.onResponseError?.(controller, err); + } + }; + function deleteCachedValue(store, cacheKey) { + try { + store.delete(cacheKey)?.catch?.(noop); + } catch { + } + } + function deleteCachedValueIfNotModified(statusCode, store, cacheKey) { + if (statusCode === 304) { + deleteCachedValue(store, cacheKey); + } + } + function revalidationResponseDisallowsCachedReuse(cacheType, resHeaders, cacheControlDirectives) { + return cacheControlDirectives["no-store"] === true || cacheType === "shared" && cacheControlDirectives.private === true || (resHeaders.vary ? isInvalidOrWildcardVaryHeader(resHeaders.vary) : false); + } + function canCacheResponse(cacheType, statusCode, resHeaders, cacheControlDirectives, reqHeaders) { + if (statusCode < 200 || arrayIncludes(NOT_UNDERSTOOD_STATUS_CODES, statusCode)) { + return false; + } + if (!arrayIncludes(HEURISTICALLY_CACHEABLE_STATUS_CODES, statusCode) && !resHeaders["expires"] && !cacheControlDirectives.public && cacheControlDirectives["max-age"] === void 0 && // RFC 9111: a private response directive, if the cache is not shared + !(cacheControlDirectives.private && cacheType === "private") && !(cacheControlDirectives["s-maxage"] !== void 0 && cacheType === "shared")) { + return false; + } + if (cacheControlDirectives["no-store"]) { + return false; + } + if (cacheType === "shared" && cacheControlDirectives.private === true) { + return false; + } + if (resHeaders.vary && hasVaryStar(resHeaders.vary)) { + return false; + } + if (reqHeaders != null && Object.hasOwn(reqHeaders, "authorization")) { + if (!cacheControlDirectives.public && !cacheControlDirectives["s-maxage"] && !cacheControlDirectives["must-revalidate"]) { + return false; + } + if (typeof reqHeaders.authorization !== "string") { + return false; + } + if (Array.isArray(cacheControlDirectives["no-cache"]) && arrayIncludes(cacheControlDirectives["no-cache"], "authorization")) { + return false; + } + if (Array.isArray(cacheControlDirectives["private"]) && arrayIncludes(cacheControlDirectives["private"], "authorization")) { + return false; + } + } + return true; + } + function getDate(dateHeader) { + let dateValue = dateHeader; + if (Array.isArray(dateValue)) { + if (dateValue.length !== 1) { + return null; + } + dateValue = dateValue[0]; + } + if (typeof dateValue !== "string") { + return null; + } + return parseHttpDate(dateValue); + } + function getAge(ageHeader) { + let ageValue = ageHeader; + if (Array.isArray(ageValue)) { + if (ageValue.length !== 1) { + return MAX_RESPONSE_AGE; + } + ageValue = ageValue[0]; + } + if (typeof ageValue !== "string" || !/^[\t ]*[0-9]+[\t ]*$/.test(ageValue)) { + return MAX_RESPONSE_AGE; + } + const age = BigInt(ageValue.replace(/^[\t ]+|[\t ]+$/g, "")); + if (age >= BigInt(MAX_RESPONSE_AGE / 1e3)) { + return MAX_RESPONSE_AGE; + } + return Number(age) * 1e3; + } + function determineStaleAt(cacheType, now, age, resHeaders, responseDate, cacheControlDirectives, hasValidator) { + if (cacheType === "shared") { + if (hasInvalidCacheControlDirective(cacheControlDirectives, "s-maxage")) { + return 0; + } + const sMaxAge = cacheControlDirectives["s-maxage"]; + if (sMaxAge !== void 0) { + if (sMaxAge > 0) { + return sMaxAge * 1e3; + } + return 0; + } + } + if (hasInvalidCacheControlDirective(cacheControlDirectives, "max-age")) { + return 0; + } + const maxAge = cacheControlDirectives["max-age"]; + if (maxAge !== void 0) { + if (maxAge > 0) { + return maxAge * 1e3; + } + return 0; + } + if (Object.hasOwn(resHeaders, "expires")) { + if (typeof resHeaders.expires !== "string") { + return 0; + } + const expiresDate = parseHttpDate(resHeaders.expires); + if (!expiresDate) { + return 0; + } + if (now >= expiresDate.getTime()) { + return 0; + } + if (responseDate) { + if (responseDate >= expiresDate) { + return 0; + } + const freshnessLifetime = expiresDate.getTime() - responseDate.getTime(); + if (age !== void 0 && age >= freshnessLifetime) { + return 0; + } + return freshnessLifetime; + } + return expiresDate.getTime() - now; + } + if (typeof resHeaders["last-modified"] === "string") { + const lastModified = parseHttpDate(resHeaders["last-modified"]); + if (lastModified) { + if (lastModified.getTime() >= now) { + return void 0; + } + const responseAge = now - lastModified.getTime(); + return responseAge * 0.1; + } + } + if (cacheControlDirectives.immutable) { + return 31536e6; + } + if (cacheControlDirectives["no-cache"] === true && hasValidator) { + return 0; + } + return void 0; + } + function determineDeleteAt(baseTime, cachedAt, cacheControlDirectives, staleAt) { + let staleWhileRevalidate = -Infinity; + let staleIfError = -Infinity; + let immutable = -Infinity; + if (cacheControlDirectives["stale-while-revalidate"]) { + staleWhileRevalidate = staleAt + cacheControlDirectives["stale-while-revalidate"] * 1e3; + } + if (cacheControlDirectives["stale-if-error"]) { + staleIfError = staleAt + cacheControlDirectives["stale-if-error"] * 1e3; + } + if (cacheControlDirectives.immutable && staleWhileRevalidate === -Infinity && staleIfError === -Infinity) { + immutable = cachedAt + 31536e6; + } + if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity && immutable === -Infinity) { + const freshnessLifetime = staleAt - baseTime; + if (freshnessLifetime <= 0) { + return cachedAt + REVALIDATION_ONLY_RETENTION; + } + const datePrecisionPadding = Math.min(Math.max(cachedAt - baseTime, 0), 1e3); + return staleAt + freshnessLifetime + datePrecisionPadding; + } + return Math.max(staleAt, staleWhileRevalidate, staleIfError, immutable); + } + function stripNecessaryHeaders(resHeaders, cacheControlDirectives) { + const headersToRemove = [ + "connection", + "proxy-authenticate", + "proxy-authentication-info", + "proxy-authorization", + "proxy-connection", + "te", + "transfer-encoding", + "upgrade", + // We'll add age back when serving it + "age" + ]; + if (resHeaders["connection"]) { + appendConnectionHeaderTokens(headersToRemove, resHeaders["connection"]); + } + if (Array.isArray(cacheControlDirectives["no-cache"])) { + headersToRemove.push(...cacheControlDirectives["no-cache"]); + } + if (Array.isArray(cacheControlDirectives["private"])) { + headersToRemove.push(...cacheControlDirectives["private"]); + } + let strippedHeaders; + for (const headerName of headersToRemove) { + if (Object.hasOwn(resHeaders, headerName)) { + strippedHeaders ??= { ...resHeaders }; + delete strippedHeaders[headerName]; + } + } + return strippedHeaders ?? resHeaders; + } + module2.exports = CacheHandler; + } +}); + +// node_modules/undici/lib/cache/memory-cache-store.js +var require_memory_cache_store = __commonJS({ + "node_modules/undici/lib/cache/memory-cache-store.js"(exports2, module2) { + "use strict"; + var { Writable } = require("node:stream"); + var { EventEmitter } = require("node:events"); + var { assertCacheKey, assertCacheValue } = require_cache(); + var MemoryCacheStore = class extends EventEmitter { + #maxCount = 1024; + #maxSize = 104857600; + // 100MB + #maxEntrySize = 5242880; + // 5MB + #size = 0; + #count = 0; + #entries = /* @__PURE__ */ new Map(); + #hasEmittedMaxSizeEvent = false; + /** + * @param {import('../../types/cache-interceptor.d.ts').default.MemoryCacheStoreOpts | undefined} [opts] + */ + constructor(opts) { + super(); + if (opts) { + if (typeof opts !== "object") { + throw new TypeError("MemoryCacheStore options must be an object"); + } + if (opts.maxCount !== void 0) { + if (typeof opts.maxCount !== "number" || !Number.isInteger(opts.maxCount) || opts.maxCount < 0) { + throw new TypeError("MemoryCacheStore options.maxCount must be a non-negative integer"); + } + this.#maxCount = opts.maxCount; + } + if (opts.maxSize !== void 0) { + if (typeof opts.maxSize !== "number" || !Number.isInteger(opts.maxSize) || opts.maxSize < 0) { + throw new TypeError("MemoryCacheStore options.maxSize must be a non-negative integer"); + } + this.#maxSize = opts.maxSize; + } + if (opts.maxEntrySize !== void 0) { + if (typeof opts.maxEntrySize !== "number" || !Number.isInteger(opts.maxEntrySize) || opts.maxEntrySize < 0) { + throw new TypeError("MemoryCacheStore options.maxEntrySize must be a non-negative integer"); + } + this.#maxEntrySize = opts.maxEntrySize; + } + } + } + /** + * Get the current size of the cache in bytes + * @returns {number} The current size of the cache in bytes + */ + get size() { + return this.#size; + } + /** + * Check if the cache is full (either max size or max count reached) + * @returns {boolean} True if the cache is full, false otherwise + */ + isFull() { + return this.#size >= this.#maxSize || this.#count >= this.#maxCount; + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} req + * @returns {import('../../types/cache-interceptor.d.ts').default.GetResult | undefined} + */ + get(key) { + assertCacheKey(key); + const topLevelKey = `${key.origin}:${key.path}`; + const now = Date.now(); + const entries2 = this.#entries.get(topLevelKey); + const entry = entries2 ? findEntry(key, entries2, now) : null; + return entry == null ? void 0 : { + statusMessage: entry.statusMessage, + statusCode: entry.statusCode, + headers: entry.headers, + body: entry.body, + vary: entry.vary ? entry.vary : void 0, + etag: entry.etag, + cacheControlDirectives: entry.cacheControlDirectives, + cachedAt: entry.cachedAt, + staleAt: entry.staleAt, + deleteAt: entry.deleteAt + }; + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue} val + * @returns {Writable | undefined} + */ + createWriteStream(key, val) { + assertCacheKey(key); + assertCacheValue(val); + const topLevelKey = `${key.origin}:${key.path}`; + const store = this; + const entry = { ...key, ...val, body: [], size: 0 }; + return new Writable({ + write(chunk, encoding, callback) { + if (typeof chunk === "string") { + chunk = Buffer.from(chunk, encoding); + } + entry.size += chunk.byteLength; + if (entry.size > store.#maxEntrySize) { + this.destroy(); + } else { + entry.body.push(chunk); + } + callback(null); + }, + final(callback) { + let entries2 = store.#entries.get(topLevelKey); + if (!entries2) { + entries2 = []; + store.#entries.set(topLevelKey, entries2); + } + const previousEntry = findEntry(key, entries2, Date.now()); + if (previousEntry) { + const index = entries2.indexOf(previousEntry); + entries2.splice(index, 1, entry); + store.#size -= previousEntry.size; + } else { + entries2.push(entry); + store.#count += 1; + } + store.#size += entry.size; + if (store.#size > store.#maxSize || store.#count > store.#maxCount) { + if (!store.#hasEmittedMaxSizeEvent) { + store.emit("maxSizeExceeded", { + size: store.#size, + maxSize: store.#maxSize, + count: store.#count, + maxCount: store.#maxCount + }); + store.#hasEmittedMaxSizeEvent = true; + } + for (const [key2, entries3] of store.#entries) { + for (const entry2 of entries3.splice(0, entries3.length / 2)) { + store.#size -= entry2.size; + store.#count -= 1; + } + if (entries3.length === 0) { + store.#entries.delete(key2); + } + } + if (store.#size < store.#maxSize && store.#count < store.#maxCount) { + store.#hasEmittedMaxSizeEvent = false; + } + } + callback(null); + } + }); + } + /** + * @param {CacheKey} key + */ + delete(key) { + if (typeof key !== "object") { + throw new TypeError(`expected key to be object, got ${typeof key}`); + } + const topLevelKey = `${key.origin}:${key.path}`; + for (const entry of this.#entries.get(topLevelKey) ?? []) { + this.#size -= entry.size; + this.#count -= 1; + } + this.#entries.delete(topLevelKey); + } + }; + function findEntry(key, entries2, now) { + for (let i = 0; i < entries2.length; i++) { + const entry = entries2[i]; + if (entry.deleteAt > now && entry.method === key.method && varyMatches(key, entry)) { + return entry; + } + } + } + function varyMatches(key, entry) { + if (entry.vary == null) { + return true; + } + for (const headerName in entry.vary) { + if (Object.hasOwn(entry.vary, headerName) && !headerValueEquals(key.headers?.[headerName], entry.vary[headerName])) { + return false; + } + } + return true; + } + function headerValueEquals(lhs, rhs) { + if (lhs == null && rhs == null) { + return true; + } + if (lhs == null && rhs != null || lhs != null && rhs == null) { + return false; + } + if (Array.isArray(lhs) && Array.isArray(rhs)) { + if (lhs.length !== rhs.length) { + return false; + } + for (let i = 0; i < lhs.length; i++) { + if (lhs[i] !== rhs[i]) { + return false; + } + } + return true; + } + return lhs === rhs; + } + module2.exports = MemoryCacheStore; + } +}); + +// node_modules/undici/lib/handler/cache-revalidation-handler.js +var require_cache_revalidation_handler = __commonJS({ + "node_modules/undici/lib/handler/cache-revalidation-handler.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var CacheRevalidationHandler = class { + #successful = false; + /** + * @type {((success: boolean, context?: any, statusCode?: number, headers?: import('../../types/header.d.ts').IncomingHttpHeaders) => void) | null} + */ + #callback; + /** + * @type {(import('../../types/dispatcher.d.ts').default.DispatchHandler)} + */ + #handler; + #context; + /** + * @type {boolean} + */ + #allowErrorStatusCodes; + /** + * @param {(success: boolean, context?: any, statusCode?: number, headers?: import('../../types/header.d.ts').IncomingHttpHeaders) => void} callback Function to call if the cached value is valid + * @param {import('../../types/dispatcher.d.ts').default.DispatchHandlers} handler + * @param {boolean} allowErrorStatusCodes + */ + constructor(callback, handler, allowErrorStatusCodes) { + if (typeof callback !== "function") { + throw new TypeError("callback must be a function"); + } + this.#callback = callback; + this.#handler = handler; + this.#allowErrorStatusCodes = allowErrorStatusCodes; + } + onRequestStart(_, context2) { + this.#successful = false; + this.#context = context2; + } + onRequestUpgrade(controller, statusCode, headers2, socket) { + this.#handler.onRequestUpgrade?.(controller, statusCode, headers2, socket); + } + onResponseStart(controller, statusCode, headers2, statusMessage) { + assert(this.#callback != null); + this.#successful = statusCode === 304 || this.#allowErrorStatusCodes && statusCode >= 500 && statusCode <= 504; + this.#callback(this.#successful, this.#context, statusCode, headers2); + this.#callback = null; + if (this.#successful) { + return true; + } + this.#handler.onRequestStart?.(controller, this.#context); + this.#handler.onResponseStart?.( + controller, + statusCode, + headers2, + statusMessage + ); + } + onResponseData(controller, chunk) { + if (this.#successful) { + return; + } + return this.#handler.onResponseData?.(controller, chunk); + } + onResponseEnd(controller, trailers) { + if (this.#successful) { + return; + } + this.#handler.onResponseEnd?.(controller, trailers); + } + onResponseError(controller, err) { + if (this.#successful) { + return; + } + if (this.#callback) { + if (this.#allowErrorStatusCodes) { + this.#successful = true; + this.#callback(true, this.#context); + this.#callback = null; + return; + } + this.#callback(false); + this.#callback = null; + } + if (typeof this.#handler.onResponseError === "function") { + this.#handler.onResponseError(controller, err); + } else { + throw err; + } + } + }; + module2.exports = CacheRevalidationHandler; + } +}); + +// node_modules/undici/lib/interceptor/cache.js +var require_cache2 = __commonJS({ + "node_modules/undici/lib/interceptor/cache.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { Readable: Readable2 } = require("node:stream"); + var util = require_util(); + var CacheHandler = require_cache_handler(); + var MemoryCacheStore = require_memory_cache_store(); + var CacheRevalidationHandler = require_cache_revalidation_handler(); + var { assertCacheStore, assertCacheMethods, makeCacheKey, normalizeHeaders, parseCacheControlHeader, isInvalidOrWildcardVaryHeader } = require_cache(); + var { AbortError } = require_errors2(); + var { parseHttpDate } = require_date(); + function assertCacheOrigins(origins, name2) { + if (origins === void 0) return; + if (!Array.isArray(origins)) { + throw new TypeError(`expected ${name2} to be an array or undefined, got ${typeof origins}`); + } + for (let i = 0; i < origins.length; i++) { + const origin = origins[i]; + if (typeof origin !== "string" && !(origin instanceof RegExp)) { + throw new TypeError(`expected ${name2}[${i}] to be a string or RegExp, got ${typeof origin}`); + } + } + } + var nop = () => { + }; + function trimOWS(value2) { + return value2.replace(/^[\t ]+|[\t ]+$/g, ""); + } + function arrayIncludes(array, value2) { + for (let i = 0; i < array.length; i++) { + if (array[i] === value2) { + return true; + } + } + return false; + } + function hasPragmaNoCache(headers2) { + const pragma = headers2?.pragma; + if (!pragma) { + return false; + } + const values2 = Array.isArray(pragma) ? pragma : [pragma]; + for (let i = 0; i < values2.length; i++) { + const value2 = values2[i]; + if (typeof value2 !== "string") { + continue; + } + const directives = value2.split(","); + for (let j = 0; j < directives.length; j++) { + if (trimOWS(directives[j]).toLowerCase() === "no-cache") { + return true; + } + } + } + return false; + } + function needsRevalidation(result3, cacheControlDirectives, { headers: headers2 = {} }) { + if (cacheControlDirectives?.["no-cache"]) { + return true; + } + if (result3.cacheControlDirectives?.["no-cache"] && !Array.isArray(result3.cacheControlDirectives["no-cache"])) { + return true; + } + if (headers2["if-modified-since"] || headers2["if-none-match"]) { + return true; + } + return false; + } + function staleResponseRequiresRevalidation(result3, cacheType) { + return result3.cacheControlDirectives?.["must-revalidate"] === true || cacheType === "shared" && (result3.cacheControlDirectives?.["proxy-revalidate"] === true || // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.10 + // s-maxage implies proxy-revalidate for shared caches. + result3.cacheControlDirectives?.["s-maxage"] !== void 0); + } + function revalidationResponseDisallowsCachedReuse(cacheType, headers2) { + if (headers2.vary && isInvalidOrWildcardVaryHeader(headers2.vary)) { + return true; + } + const cacheControl = headers2["cache-control"]; + if (!cacheControl) { + return false; + } + const cacheControlDirectives = parseCacheControlHeader(cacheControl); + return cacheControlDirectives["no-store"] === true || cacheType === "shared" && cacheControlDirectives.private === true; + } + function revalidationResponseUpdatesCacheControl(headers2) { + return headers2["cache-control"] !== void 0; + } + function deleteCachedValue(store, cacheKey) { + try { + store.delete(cacheKey)?.catch?.(nop); + } catch { + } + } + function getUsableLastModified(headers2) { + const lastModified = headers2?.["last-modified"]; + if (typeof lastModified === "string" && parseHttpDate(lastModified)) { + return lastModified; + } + } + function makeRevalidationHeaders(opts, result3) { + const headers2 = { + ...opts.headers, + "if-modified-since": getUsableLastModified(result3.headers) ?? new Date(result3.cachedAt).toUTCString() + }; + if (result3.etag) { + headers2["if-none-match"] = result3.etag; + } + if (result3.vary) { + for (const key in result3.vary) { + if (result3.vary[key] != null) { + headers2[key] = result3.vary[key]; + } + } + } + return headers2; + } + function isStale(result3, cacheControlDirectives, cacheType) { + const now = Date.now(); + if (now > result3.staleAt) { + if (!staleResponseRequiresRevalidation(result3, cacheType) && cacheControlDirectives?.["max-stale"]) { + const gracePeriod = result3.staleAt + cacheControlDirectives["max-stale"] * 1e3; + return now > gracePeriod; + } + return true; + } + if (cacheControlDirectives?.["min-fresh"]) { + const timeLeftTillStale = result3.staleAt - now; + const threshold = cacheControlDirectives["min-fresh"] * 1e3; + return timeLeftTillStale <= threshold; + } + return false; + } + function withinStaleWhileRevalidateWindow(result3, cacheType) { + const staleWhileRevalidate = result3.cacheControlDirectives?.["stale-while-revalidate"]; + if (!staleWhileRevalidate || staleResponseRequiresRevalidation(result3, cacheType)) { + return false; + } + const now = Date.now(); + const staleWhileRevalidateExpiry = result3.staleAt + staleWhileRevalidate * 1e3; + return now <= staleWhileRevalidateExpiry; + } + function handleUncachedResponse(dispatch2, globalOpts, cacheKey, handler, opts, reqCacheControl) { + if (reqCacheControl?.["only-if-cached"]) { + let aborted2 = false; + const controller = { + paused: false, + rawHeaders: [], + rawTrailers: [], + pause() { + this.paused = true; + }, + resume() { + this.paused = false; + }, + abort: (reason2) => { + aborted2 = true; + handler.onResponseError?.(controller, reason2 ?? new AbortError()); + } + }; + try { + handler.onRequestStart?.(controller, null); + if (aborted2) { + return; + } + handler.onResponseStart?.(controller, 504, {}, "Gateway Timeout"); + if (aborted2) { + return; + } + handler.onResponseEnd?.(controller, {}); + } catch (err) { + if (typeof handler.onResponseError === "function") { + handler.onResponseError(controller, err); + } + } + return true; + } + return dispatch2(opts, new CacheHandler(globalOpts, cacheKey, handler)); + } + function sendCachedValue(handler, opts, result3, age, context2, isStale2) { + const stream = util.isStream(result3.body) ? result3.body : Readable2.from(result3.body ?? []); + assert(!stream.destroyed, "stream should not be destroyed"); + assert(!stream.readableDidRead, "stream should not be readableDidRead"); + const controller = { + rawHeaders: [], + rawTrailers: [], + resume() { + stream.resume(); + }, + pause() { + stream.pause(); + }, + get paused() { + return stream.isPaused(); + }, + get aborted() { + return stream.destroyed; + }, + get reason() { + return stream.errored; + }, + abort(reason2) { + stream.destroy(reason2 ?? new AbortError()); + } + }; + stream.on("error", function(err) { + if (!this.readableEnded) { + if (typeof handler.onResponseError === "function") { + handler.onResponseError(controller, err); + } else { + throw err; + } + } + }).on("close", function() { + if (!this.errored) { + handler.onResponseEnd?.(controller, {}); + } + }); + handler.onRequestStart?.(controller, context2); + if (stream.destroyed) { + return; + } + const headers2 = { ...result3.headers, age: String(age) }; + if (isStale2) { + headers2.warning = '110 - "response is stale"'; + } + controller.rawHeaders = util.toRawHeaders(headers2); + handler.onResponseStart?.(controller, result3.statusCode, headers2, result3.statusMessage); + if (opts.method === "HEAD") { + stream.destroy(); + } else { + stream.on("data", function(chunk) { + handler.onResponseData?.(controller, chunk); + }); + } + } + function handleResult(dispatch2, globalOpts, cacheKey, handler, opts, reqCacheControl, result3) { + if (!result3) { + return handleUncachedResponse(dispatch2, globalOpts, cacheKey, handler, opts, reqCacheControl); + } + const now = Date.now(); + if (now > result3.deleteAt) { + return dispatch2(opts, new CacheHandler(globalOpts, cacheKey, handler)); + } + const age = Math.round((now - result3.cachedAt) / 1e3); + const requestMaxAgeExpired = reqCacheControl?.["max-age"] !== void 0 && age >= reqCacheControl["max-age"]; + const stale = requestMaxAgeExpired || isStale(result3, reqCacheControl, globalOpts.type); + const revalidate = requestMaxAgeExpired || needsRevalidation(result3, reqCacheControl, opts); + if (stale || revalidate) { + if (util.isStream(opts.body) && util.bodyLength(opts.body) !== 0) { + return dispatch2(opts, new CacheHandler(globalOpts, cacheKey, handler)); + } + if (!revalidate && withinStaleWhileRevalidateWindow(result3, globalOpts.type)) { + sendCachedValue(handler, opts, result3, age, null, true); + queueMicrotask(() => { + const headers3 = makeRevalidationHeaders(opts, result3); + dispatch2( + { + ...opts, + headers: headers3 + }, + new CacheHandler(globalOpts, cacheKey, { + // Silent handler that just updates the cache + onRequestStart() { + }, + onRequestUpgrade() { + }, + onResponseStart() { + }, + onResponseData() { + }, + onResponseEnd() { + }, + onResponseError() { + } + }) + ); + }); + return true; + } + let withinStaleIfErrorThreshold = false; + if (!staleResponseRequiresRevalidation(result3, globalOpts.type)) { + const staleIfErrorExpiry = result3.cacheControlDirectives["stale-if-error"] ?? reqCacheControl?.["stale-if-error"]; + if (staleIfErrorExpiry) { + withinStaleIfErrorThreshold = now < result3.staleAt + staleIfErrorExpiry * 1e3; + } + } + const headers2 = makeRevalidationHeaders(opts, result3); + return dispatch2( + { + ...opts, + headers: headers2 + }, + new CacheRevalidationHandler( + (success, context2, statusCode, headers3) => { + if (success) { + if (statusCode === 304) { + if (revalidationResponseDisallowsCachedReuse(globalOpts.type, headers3)) { + if (util.isStream(result3.body)) { + result3.body.on("error", nop).destroy(); + } + deleteCachedValue(globalOpts.store, cacheKey); + return dispatch2(opts, new CacheHandler(globalOpts, cacheKey, handler)); + } + if (revalidationResponseUpdatesCacheControl(headers3)) { + deleteCachedValue(globalOpts.store, cacheKey); + } + } + sendCachedValue(handler, opts, result3, age, context2, stale); + } else if (util.isStream(result3.body)) { + result3.body.on("error", nop).destroy(); + } + }, + new CacheHandler(globalOpts, cacheKey, handler), + withinStaleIfErrorThreshold + ) + ); + } + if (util.isStream(opts.body)) { + opts.body.on("error", nop).destroy(); + } + sendCachedValue(handler, opts, result3, age, null, false); + } + module2.exports = (opts = {}) => { + const { + store = new MemoryCacheStore(), + methods = ["GET"], + cacheByDefault = void 0, + type: type2 = "shared", + origins = void 0 + } = opts; + if (typeof opts !== "object" || opts === null) { + throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? "null" : typeof opts}`); + } + assertCacheStore(store, "opts.store"); + assertCacheMethods(methods, "opts.methods"); + assertCacheOrigins(origins, "opts.origins"); + if (typeof cacheByDefault !== "undefined" && typeof cacheByDefault !== "number") { + throw new TypeError(`expected opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault}`); + } + if (typeof type2 !== "undefined" && type2 !== "shared" && type2 !== "private") { + throw new TypeError(`expected opts.type to be shared, private, or undefined, got ${typeof type2}`); + } + const globalOpts = { + store, + methods, + cacheByDefault, + type: type2 + }; + const safeMethodsToNotCache = []; + for (let i = 0; i < util.safeHTTPMethods.length; i++) { + const method2 = util.safeHTTPMethods[i]; + if (!arrayIncludes(methods, method2)) { + safeMethodsToNotCache.push(method2); + } + } + return (dispatch2) => { + return (opts2, handler) => { + if (arrayIncludes(safeMethodsToNotCache, opts2.method)) { + return dispatch2(opts2, handler); + } + if (origins !== void 0) { + if (!opts2.origin) { + return dispatch2(opts2, handler); + } + const requestOrigin = opts2.origin.toString().toLowerCase(); + let isAllowed = false; + for (let i = 0; i < origins.length; i++) { + const allowed = origins[i]; + if (typeof allowed === "string") { + if (allowed.toLowerCase() === requestOrigin) { + isAllowed = true; + break; + } + } else if (allowed.test(requestOrigin)) { + isAllowed = true; + break; + } + } + if (!isAllowed) { + return dispatch2(opts2, handler); + } + } + opts2 = { + ...opts2, + headers: normalizeHeaders(opts2) + }; + const reqCacheControl = opts2.headers?.["cache-control"] ? parseCacheControlHeader(opts2.headers["cache-control"]) : hasPragmaNoCache(opts2.headers) ? { "no-cache": true } : void 0; + if (reqCacheControl?.["no-store"]) { + return dispatch2(opts2, handler); + } + const cacheKey = makeCacheKey(opts2); + const result3 = store.get(cacheKey); + if (result3 && typeof result3.then === "function") { + return result3.then((result4) => handleResult( + dispatch2, + globalOpts, + cacheKey, + handler, + opts2, + reqCacheControl, + result4 + )); + } else { + return handleResult( + dispatch2, + globalOpts, + cacheKey, + handler, + opts2, + reqCacheControl, + result3 + ); + } + }; + }; + }; + } +}); + +// node_modules/undici/lib/interceptor/decompress.js +var require_decompress = __commonJS({ + "node_modules/undici/lib/interceptor/decompress.js"(exports2, module2) { + "use strict"; + var { createInflate, createGunzip, createBrotliDecompress, createZstdDecompress } = require("node:zlib"); + var { pipeline } = require("node:stream"); + var DecoratorHandler = require_decorator_handler(); + var supportedEncodings = { + gzip: createGunzip, + "x-gzip": createGunzip, + br: createBrotliDecompress, + deflate: createInflate, + compress: createInflate, + "x-compress": createInflate, + zstd: createZstdDecompress + }; + var defaultSkipStatusCodes = ( + /** @type {const} */ + [204, 304] + ); + var warningEmitted = ( + /** @type {boolean} */ + false + ); + var DecompressHandler = class extends DecoratorHandler { + /** @type {Transform[]} */ + #decompressors = []; + /** @type {Record | undefined} */ + #trailers; + /** @type {Readonly} */ + #skipStatusCodes; + /** @type {boolean} */ + #skipErrorResponses; + constructor(handler, { skipStatusCodes = defaultSkipStatusCodes, skipErrorResponses = true } = {}) { + super(handler); + this.#skipStatusCodes = skipStatusCodes; + this.#skipErrorResponses = skipErrorResponses; + } + /** + * Determines if decompression should be skipped based on encoding and status code + * @param {string} contentEncoding - Content-Encoding header value + * @param {number} statusCode - HTTP status code of the response + * @returns {boolean} - True if decompression should be skipped + */ + #shouldSkipDecompression(contentEncoding, statusCode) { + if (!contentEncoding || statusCode < 200) return true; + if (this.#skipStatusCodes.includes(statusCode)) return true; + if (this.#skipErrorResponses && statusCode >= 400) return true; + return false; + } + /** + * Creates a chain of decompressors for multiple content encodings + * + * @param {string} encodings - Comma-separated list of content encodings + * @returns {Array} - Array of decompressor streams + * @throws {Error} - If the number of content-encodings exceeds the maximum allowed + */ + #createDecompressionChain(encodings) { + const parts = encodings.split(","); + const maxContentEncodings = 5; + if (parts.length > maxContentEncodings) { + throw new Error(`too many content-encodings in response: ${parts.length}, maximum allowed is ${maxContentEncodings}`); + } + const decompressors = []; + for (let i = parts.length - 1; i >= 0; i--) { + const encoding = parts[i].trim(); + if (!encoding) continue; + if (!supportedEncodings[encoding]) { + decompressors.length = 0; + return decompressors; + } + decompressors.push(supportedEncodings[encoding]()); + } + return decompressors; + } + /** + * Sets up event handlers for a decompressor stream using readable events + * @param {DecompressorStream} decompressor - The decompressor stream + * @param {Controller} controller - The controller to coordinate with + * @returns {void} + */ + #setupDecompressorEvents(decompressor, controller) { + decompressor.on("readable", () => { + let chunk; + while ((chunk = decompressor.read()) !== null) { + const result3 = super.onResponseData(controller, chunk); + if (result3 === false) { + break; + } + } + }); + decompressor.on("error", (error2) => { + super.onResponseError(controller, error2); + }); + } + /** + * Sets up event handling for a single decompressor + * @param {Controller} controller - The controller to handle events + * @returns {void} + */ + #setupSingleDecompressor(controller) { + const decompressor = this.#decompressors[0]; + this.#setupDecompressorEvents(decompressor, controller); + decompressor.on("end", () => { + super.onResponseEnd(controller, this.#trailers); + }); + } + /** + * Sets up event handling for multiple chained decompressors using pipeline + * @param {Controller} controller - The controller to handle events + * @returns {void} + */ + #setupMultipleDecompressors(controller) { + const lastDecompressor = this.#decompressors[this.#decompressors.length - 1]; + this.#setupDecompressorEvents(lastDecompressor, controller); + pipeline(this.#decompressors, (err) => { + if (err) { + super.onResponseError(controller, err); + return; + } + super.onResponseEnd(controller, this.#trailers); + }); + } + /** + * Cleans up decompressor references to prevent memory leaks + * @returns {void} + */ + #cleanupDecompressors() { + this.#decompressors.length = 0; + } + /** + * @param {Controller} controller + * @param {number} statusCode + * @param {Record} headers + * @param {string} statusMessage + * @returns {void} + */ + onResponseStart(controller, statusCode, headers2, statusMessage) { + const contentEncoding = headers2["content-encoding"]; + if (this.#shouldSkipDecompression(contentEncoding, statusCode)) { + return super.onResponseStart(controller, statusCode, headers2, statusMessage); + } + const decompressors = this.#createDecompressionChain(contentEncoding.toLowerCase()); + if (decompressors.length === 0) { + this.#cleanupDecompressors(); + return super.onResponseStart(controller, statusCode, headers2, statusMessage); + } + this.#decompressors = decompressors; + const { "content-encoding": _, "content-length": __, ...newHeaders } = headers2; + if (controller?.rawHeaders) { + const rawHeaders = controller.rawHeaders; + if (Array.isArray(rawHeaders)) { + const filteredHeaders = []; + for (let i = 0; i < rawHeaders.length; i += 2) { + const headerName = rawHeaders[i]; + const name2 = Buffer.isBuffer(headerName) ? headerName.toString("latin1") : `${headerName}`; + const lowerName = name2.toLowerCase(); + if (lowerName === "content-encoding" || lowerName === "content-length") { + continue; + } + filteredHeaders.push(rawHeaders[i], rawHeaders[i + 1]); + } + controller.rawHeaders = filteredHeaders; + } else if (typeof rawHeaders === "object") { + for (const name2 of Object.keys(rawHeaders)) { + const lowerName = name2.toLowerCase(); + if (lowerName === "content-encoding" || lowerName === "content-length") { + delete rawHeaders[name2]; + } + } + } + } + if (this.#decompressors.length === 1) { + this.#setupSingleDecompressor(controller); + } else { + this.#setupMultipleDecompressors(controller); + } + return super.onResponseStart(controller, statusCode, newHeaders, statusMessage); + } + /** + * @param {Controller} controller + * @param {Buffer} chunk + * @returns {void} + */ + onResponseData(controller, chunk) { + if (this.#decompressors.length > 0) { + this.#decompressors[0].write(chunk); + return; + } + super.onResponseData(controller, chunk); + } + /** + * @param {Controller} controller + * @param {Record | undefined} trailers + * @returns {void} + */ + onResponseEnd(controller, trailers) { + if (this.#decompressors.length > 0) { + this.#trailers = trailers; + this.#decompressors[0].end(); + this.#cleanupDecompressors(); + return; + } + super.onResponseEnd(controller, trailers); + } + /** + * @param {Controller} controller + * @param {Error} err + * @returns {void} + */ + onResponseError(controller, err) { + if (this.#decompressors.length > 0) { + for (const decompressor of this.#decompressors) { + decompressor.destroy(err); + } + this.#cleanupDecompressors(); + } + super.onResponseError(controller, err); + } + }; + function createDecompressInterceptor(options2 = {}) { + if (!warningEmitted) { + process.emitWarning( + "DecompressInterceptor is experimental and subject to change", + "ExperimentalWarning" + ); + warningEmitted = true; + } + return (dispatch2) => { + return (opts, handler) => { + if (opts.method === "HEAD") { + return dispatch2(opts, handler); + } + const decompressHandler = new DecompressHandler(handler, options2); + return dispatch2(opts, decompressHandler); + }; + }; + } + module2.exports = createDecompressInterceptor; + } +}); + +// node_modules/undici/lib/handler/deduplication-handler.js +var require_deduplication_handler = __commonJS({ + "node_modules/undici/lib/handler/deduplication-handler.js"(exports2, module2) { + "use strict"; + var { RequestAbortedError } = require_errors2(); + var DEFAULT_MAX_BUFFER_SIZE = 5 * 1024 * 1024; + var DeduplicationHandler = class { + /** + * @type {DispatchHandler} + */ + #primaryHandler; + /** + * @type {WaitingHandler[]} + */ + #waitingHandlers = []; + /** + * @type {number} + */ + #maxBufferSize = DEFAULT_MAX_BUFFER_SIZE; + /** + * @type {number} + */ + #statusCode = 0; + /** + * @type {Record} + */ + #headers = {}; + /** + * @type {string} + */ + #statusMessage = ""; + /** + * @type {boolean} + */ + #aborted = false; + /** + * @type {boolean} + */ + #responseStarted = false; + /** + * @type {boolean} + */ + #responseDataStarted = false; + /** + * @type {boolean} + */ + #completed = false; + /** + * @type {import('../../types/dispatcher.d.ts').default.DispatchController | null} + */ + #controller = null; + /** + * @type {(() => void) | null} + */ + #onComplete = null; + /** + * @param {DispatchHandler} primaryHandler The primary handler + * @param {() => void} onComplete Callback when request completes + * @param {number} [maxBufferSize] Maximum paused buffer size per waiting handler + */ + constructor(primaryHandler, onComplete, maxBufferSize = DEFAULT_MAX_BUFFER_SIZE) { + this.#primaryHandler = primaryHandler; + this.#onComplete = onComplete; + this.#maxBufferSize = maxBufferSize; + } + /** + * Add a waiting handler that will receive response events. + * Returns false if deduplication can no longer safely attach this handler. + * + * @param {DispatchHandler} handler + * @returns {boolean} + */ + addWaitingHandler(handler) { + if (this.#completed || this.#responseDataStarted) { + return false; + } + const waitingHandler = this.#createWaitingHandler(handler); + const waitingController = waitingHandler.controller; + try { + handler.onRequestStart?.(waitingController, null); + if (waitingController.aborted) { + waitingHandler.done = true; + return true; + } + if (this.#responseStarted) { + handler.onResponseStart?.( + waitingController, + this.#statusCode, + this.#headers, + this.#statusMessage + ); + } + } catch { + waitingHandler.done = true; + return true; + } + if (!waitingController.aborted) { + this.#waitingHandlers.push(waitingHandler); + } + return true; + } + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {any} context + */ + onRequestStart(controller, context2) { + this.#controller = controller; + this.#primaryHandler.onRequestStart?.(controller, context2); + } + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {number} statusCode + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} headers + * @param {Socket} socket + */ + onRequestUpgrade(controller, statusCode, headers2, socket) { + this.#primaryHandler.onRequestUpgrade?.(controller, statusCode, headers2, socket); + } + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {number} statusCode + * @param {Record} headers + * @param {string} statusMessage + */ + onResponseStart(controller, statusCode, headers2, statusMessage) { + this.#responseStarted = true; + this.#statusCode = statusCode; + this.#headers = headers2; + this.#statusMessage = statusMessage; + this.#primaryHandler.onResponseStart?.(controller, statusCode, headers2, statusMessage); + for (const waitingHandler of this.#waitingHandlers) { + const { handler, controller: waitingController } = waitingHandler; + if (waitingHandler.done || waitingController.aborted) { + waitingHandler.done = true; + continue; + } + try { + handler.onResponseStart?.( + waitingController, + statusCode, + headers2, + statusMessage + ); + } catch { + } + if (waitingController.aborted) { + waitingHandler.done = true; + } + } + this.#pruneDoneWaitingHandlers(); + } + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {Buffer} chunk + */ + onResponseData(controller, chunk) { + if (this.#aborted || this.#completed) { + return; + } + this.#responseDataStarted = true; + this.#primaryHandler.onResponseData?.(controller, chunk); + for (const waitingHandler of this.#waitingHandlers) { + const { handler, controller: waitingController } = waitingHandler; + if (waitingHandler.done || waitingController.aborted) { + waitingHandler.done = true; + continue; + } + if (waitingController.paused) { + this.#bufferWaitingChunk(waitingHandler, chunk); + continue; + } + try { + handler.onResponseData?.(waitingController, chunk); + } catch { + } + if (waitingController.aborted) { + waitingHandler.done = true; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + } + } + this.#pruneDoneWaitingHandlers(); + } + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {object} trailers + */ + onResponseEnd(controller, trailers) { + if (this.#aborted || this.#completed) { + return; + } + this.#completed = true; + this.#primaryHandler.onResponseEnd?.(controller, trailers); + for (const waitingHandler of this.#waitingHandlers) { + if (waitingHandler.done || waitingHandler.controller.aborted) { + waitingHandler.done = true; + continue; + } + this.#flushWaitingHandler(waitingHandler); + if (waitingHandler.done || waitingHandler.controller.aborted) { + waitingHandler.done = true; + continue; + } + if (waitingHandler.controller.paused && waitingHandler.bufferedChunks.length > 0) { + waitingHandler.pendingTrailers = trailers; + continue; + } + try { + waitingHandler.handler.onResponseEnd?.(waitingHandler.controller, trailers); + } catch { + } + waitingHandler.done = true; + } + this.#pruneDoneWaitingHandlers(); + this.#onComplete?.(); + } + /** + * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller + * @param {Error} err + */ + onResponseError(controller, err) { + if (this.#completed) { + return; + } + this.#aborted = true; + this.#completed = true; + this.#primaryHandler.onResponseError?.(controller, err); + for (const waitingHandler of this.#waitingHandlers) { + this.#errorWaitingHandler(waitingHandler, err); + } + this.#waitingHandlers = []; + this.#onComplete?.(); + } + /** + * @param {DispatchHandler} handler + * @returns {WaitingHandler} + */ + #createWaitingHandler(handler) { + const waitingHandler = { + handler, + controller: null, + bufferedChunks: [], + bufferedBytes: 0, + pendingTrailers: null, + done: false + }; + const state2 = { + aborted: false, + paused: false, + reason: null + }; + waitingHandler.controller = { + resume: () => { + if (state2.aborted) { + return; + } + state2.paused = false; + this.#flushWaitingHandler(waitingHandler); + if (this.#completed && waitingHandler.pendingTrailers && waitingHandler.bufferedChunks.length === 0 && !state2.paused && !state2.aborted) { + try { + waitingHandler.handler.onResponseEnd?.(waitingHandler.controller, waitingHandler.pendingTrailers); + } catch { + } + waitingHandler.pendingTrailers = null; + waitingHandler.done = true; + } + this.#pruneDoneWaitingHandlers(); + }, + pause: () => { + if (!state2.aborted) { + state2.paused = true; + } + }, + get paused() { + return state2.paused; + }, + get aborted() { + return state2.aborted; + }, + get reason() { + return state2.reason; + }, + abort: (reason2) => { + state2.aborted = true; + state2.reason = reason2 ?? null; + waitingHandler.done = true; + waitingHandler.pendingTrailers = null; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + } + }; + return waitingHandler; + } + /** + * @param {WaitingHandler} waitingHandler + * @param {Buffer} chunk + */ + #bufferWaitingChunk(waitingHandler, chunk) { + if (waitingHandler.done || waitingHandler.controller.aborted) { + waitingHandler.done = true; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + return; + } + const bufferedChunk = Buffer.from(chunk); + waitingHandler.bufferedChunks.push(bufferedChunk); + waitingHandler.bufferedBytes += bufferedChunk.length; + if (waitingHandler.bufferedBytes > this.#maxBufferSize) { + const err = new RequestAbortedError(`Deduplicated waiting handler exceeded maxBufferSize (${this.#maxBufferSize} bytes) while paused`); + this.#errorWaitingHandler(waitingHandler, err); + } + } + /** + * @param {WaitingHandler} waitingHandler + */ + #flushWaitingHandler(waitingHandler) { + const { handler, controller } = waitingHandler; + while (!waitingHandler.done && !controller.aborted && !controller.paused && waitingHandler.bufferedChunks.length > 0) { + const bufferedChunk = waitingHandler.bufferedChunks.shift(); + waitingHandler.bufferedBytes -= bufferedChunk.length; + try { + handler.onResponseData?.(controller, bufferedChunk); + } catch { + } + if (controller.aborted) { + waitingHandler.done = true; + waitingHandler.pendingTrailers = null; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + break; + } + } + } + /** + * @param {WaitingHandler} waitingHandler + * @param {Error} err + */ + #errorWaitingHandler(waitingHandler, err) { + if (waitingHandler.done) { + return; + } + waitingHandler.done = true; + waitingHandler.pendingTrailers = null; + waitingHandler.bufferedChunks = []; + waitingHandler.bufferedBytes = 0; + try { + waitingHandler.controller.abort(err); + waitingHandler.handler.onResponseError?.(waitingHandler.controller, err); + } catch { + } + } + #pruneDoneWaitingHandlers() { + this.#waitingHandlers = this.#waitingHandlers.filter((waitingHandler) => waitingHandler.done === false); + } + }; + module2.exports = DeduplicationHandler; + } +}); + +// node_modules/undici/lib/interceptor/deduplicate.js +var require_deduplicate = __commonJS({ + "node_modules/undici/lib/interceptor/deduplicate.js"(exports2, module2) { + "use strict"; + var diagnosticsChannel = require("node:diagnostics_channel"); + var util = require_util(); + var DeduplicationHandler = require_deduplication_handler(); + var { normalizeHeaders, makeCacheKey, makeDeduplicationKey } = require_cache(); + var pendingRequestsChannel = diagnosticsChannel.channel("undici:request:pending-requests"); + module2.exports = (opts = {}) => { + const { + methods = ["GET"], + skipHeaderNames = [], + excludeHeaderNames = [], + maxBufferSize = 5 * 1024 * 1024 + } = opts; + if (typeof opts !== "object" || opts === null) { + throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? "null" : typeof opts}`); + } + if (!Array.isArray(methods)) { + throw new TypeError(`expected opts.methods to be an array, got ${typeof methods}`); + } + for (const method2 of methods) { + if (!util.safeHTTPMethods.includes(method2)) { + throw new TypeError(`expected opts.methods to only contain safe HTTP methods, got ${method2}`); + } + } + if (!Array.isArray(skipHeaderNames)) { + throw new TypeError(`expected opts.skipHeaderNames to be an array, got ${typeof skipHeaderNames}`); + } + if (!Array.isArray(excludeHeaderNames)) { + throw new TypeError(`expected opts.excludeHeaderNames to be an array, got ${typeof excludeHeaderNames}`); + } + if (!Number.isFinite(maxBufferSize) || maxBufferSize <= 0) { + throw new TypeError(`expected opts.maxBufferSize to be a positive finite number, got ${maxBufferSize}`); + } + const skipHeaderNamesSet = new Set(skipHeaderNames.map((name2) => name2.toLowerCase())); + const excludeHeaderNamesSet = new Set(excludeHeaderNames.map((name2) => name2.toLowerCase())); + const pendingRequests = /* @__PURE__ */ new Map(); + return (dispatch2) => { + return (opts2, handler) => { + if (opts2.upgrade || methods.includes(opts2.method) === false) { + return dispatch2(opts2, handler); + } + opts2 = { + ...opts2, + headers: normalizeHeaders(opts2) + }; + if (skipHeaderNamesSet.size > 0) { + for (const headerName of Object.keys(opts2.headers)) { + if (skipHeaderNamesSet.has(headerName.toLowerCase())) { + return dispatch2(opts2, handler); + } + } + } + const cacheKey = makeCacheKey(opts2); + const dedupeKey = makeDeduplicationKey(cacheKey, excludeHeaderNamesSet); + const pendingHandler = pendingRequests.get(dedupeKey); + if (pendingHandler) { + if (pendingHandler.addWaitingHandler(handler)) { + return true; + } + return dispatch2(opts2, handler); + } + const deduplicationHandler = new DeduplicationHandler( + handler, + () => { + pendingRequests.delete(dedupeKey); + if (pendingRequestsChannel.hasSubscribers) { + pendingRequestsChannel.publish({ size: pendingRequests.size, key: dedupeKey, type: "removed" }); + } + }, + maxBufferSize + ); + pendingRequests.set(dedupeKey, deduplicationHandler); + if (pendingRequestsChannel.hasSubscribers) { + pendingRequestsChannel.publish({ size: pendingRequests.size, key: dedupeKey, type: "added" }); + } + return dispatch2(opts2, deduplicationHandler); + }; + }; + }; + } +}); + +// node_modules/undici/lib/cache/sqlite-cache-store.js +var require_sqlite_cache_store = __commonJS({ + "node_modules/undici/lib/cache/sqlite-cache-store.js"(exports2, module2) { + "use strict"; + var { Writable } = require("node:stream"); + var { assertCacheKey, assertCacheValue } = require_cache(); + var DatabaseSync; + var VERSION2 = 3; + var MAX_ENTRY_SIZE = 2 * 1e3 * 1e3 * 1e3; + module2.exports = class SqliteCacheStore { + #maxEntrySize = MAX_ENTRY_SIZE; + #maxCount = Infinity; + /** + * @type {import('node:sqlite').DatabaseSync} + */ + #db; + /** + * @type {import('node:sqlite').StatementSync} + */ + #getValuesQuery; + /** + * @type {import('node:sqlite').StatementSync} + */ + #updateValueQuery; + /** + * @type {import('node:sqlite').StatementSync} + */ + #insertValueQuery; + /** + * @type {import('node:sqlite').StatementSync} + */ + #deleteExpiredValuesQuery; + /** + * @type {import('node:sqlite').StatementSync} + */ + #deleteByUrlQuery; + /** + * @type {import('node:sqlite').StatementSync} + */ + #countEntriesQuery; + /** + * @type {import('node:sqlite').StatementSync | null} + */ + #deleteOldValuesQuery; + /** + * @param {import('../../types/cache-interceptor.d.ts').default.SqliteCacheStoreOpts | undefined} opts + */ + constructor(opts) { + if (opts) { + if (typeof opts !== "object") { + throw new TypeError("SqliteCacheStore options must be an object"); + } + if (opts.maxEntrySize !== void 0) { + if (typeof opts.maxEntrySize !== "number" || !Number.isInteger(opts.maxEntrySize) || opts.maxEntrySize < 0) { + throw new TypeError("SqliteCacheStore options.maxEntrySize must be a non-negative integer"); + } + if (opts.maxEntrySize > MAX_ENTRY_SIZE) { + throw new TypeError("SqliteCacheStore options.maxEntrySize must be less than 2gb"); + } + this.#maxEntrySize = opts.maxEntrySize; + } + if (opts.maxCount !== void 0) { + if (typeof opts.maxCount !== "number" || !Number.isInteger(opts.maxCount) || opts.maxCount < 0) { + throw new TypeError("SqliteCacheStore options.maxCount must be a non-negative integer"); + } + this.#maxCount = opts.maxCount; + } + } + if (!DatabaseSync) { + DatabaseSync = require("node:sqlite").DatabaseSync; + } + this.#db = new DatabaseSync(opts?.location ?? ":memory:"); + this.#db.exec(` + PRAGMA journal_mode = WAL; + PRAGMA synchronous = NORMAL; + PRAGMA temp_store = memory; + PRAGMA optimize; + + CREATE TABLE IF NOT EXISTS cacheInterceptorV${VERSION2} ( + -- Data specific to us + id INTEGER PRIMARY KEY AUTOINCREMENT, + url TEXT NOT NULL, + method TEXT NOT NULL, + + -- Data returned to the interceptor + body BUF NULL, + deleteAt INTEGER NOT NULL, + statusCode INTEGER NOT NULL, + statusMessage TEXT NOT NULL, + headers TEXT NULL, + cacheControlDirectives TEXT NULL, + etag TEXT NULL, + vary TEXT NULL, + cachedAt INTEGER NOT NULL, + staleAt INTEGER NOT NULL + ); + + CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION2}_getValuesQuery ON cacheInterceptorV${VERSION2}(url, method, deleteAt); + CREATE INDEX IF NOT EXISTS idx_cacheInterceptorV${VERSION2}_deleteByUrlQuery ON cacheInterceptorV${VERSION2}(deleteAt); + `); + this.#getValuesQuery = this.#db.prepare(` + SELECT + id, + body, + deleteAt, + statusCode, + statusMessage, + headers, + etag, + cacheControlDirectives, + vary, + cachedAt, + staleAt + FROM cacheInterceptorV${VERSION2} + WHERE + url = ? + AND method = ? + ORDER BY + deleteAt ASC + `); + this.#updateValueQuery = this.#db.prepare(` + UPDATE cacheInterceptorV${VERSION2} SET + body = ?, + deleteAt = ?, + statusCode = ?, + statusMessage = ?, + headers = ?, + etag = ?, + cacheControlDirectives = ?, + vary = ?, + cachedAt = ?, + staleAt = ? + WHERE + id = ? + `); + this.#insertValueQuery = this.#db.prepare(` + INSERT INTO cacheInterceptorV${VERSION2} ( + url, + method, + body, + deleteAt, + statusCode, + statusMessage, + headers, + etag, + cacheControlDirectives, + vary, + cachedAt, + staleAt + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `); + this.#deleteByUrlQuery = this.#db.prepare( + `DELETE FROM cacheInterceptorV${VERSION2} WHERE url = ?` + ); + this.#countEntriesQuery = this.#db.prepare( + `SELECT COUNT(*) AS total FROM cacheInterceptorV${VERSION2}` + ); + this.#deleteExpiredValuesQuery = this.#db.prepare( + `DELETE FROM cacheInterceptorV${VERSION2} WHERE deleteAt <= ?` + ); + this.#deleteOldValuesQuery = this.#maxCount === Infinity ? null : this.#db.prepare(` + DELETE FROM cacheInterceptorV${VERSION2} + WHERE id IN ( + SELECT + id + FROM cacheInterceptorV${VERSION2} + ORDER BY cachedAt ASC + LIMIT ? + ) + `); + } + close() { + this.#db.close(); + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @returns {(import('../../types/cache-interceptor.d.ts').default.GetResult & { body?: Buffer }) | undefined} + */ + get(key) { + assertCacheKey(key); + const value2 = this.#findValue(key); + return value2 ? { + body: value2.body ? Buffer.from(value2.body.buffer, value2.body.byteOffset, value2.body.byteLength) : void 0, + statusCode: value2.statusCode, + statusMessage: value2.statusMessage, + headers: value2.headers ? JSON.parse(value2.headers) : void 0, + etag: value2.etag ? value2.etag : void 0, + vary: value2.vary ? JSON.parse(value2.vary) : void 0, + cacheControlDirectives: value2.cacheControlDirectives ? JSON.parse(value2.cacheControlDirectives) : void 0, + cachedAt: value2.cachedAt, + staleAt: value2.staleAt, + deleteAt: value2.deleteAt + } : void 0; + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue & { body: null | Buffer | Array}} value + */ + set(key, value2) { + assertCacheKey(key); + const url2 = this.#makeValueUrl(key); + const body2 = Array.isArray(value2.body) ? Buffer.concat(value2.body) : value2.body; + const size = body2?.byteLength; + if (size && size > this.#maxEntrySize) { + return; + } + const existingValue = this.#findValue(key, true); + if (existingValue) { + this.#updateValueQuery.run( + body2, + value2.deleteAt, + value2.statusCode, + value2.statusMessage, + value2.headers ? JSON.stringify(value2.headers) : null, + value2.etag ? value2.etag : null, + value2.cacheControlDirectives ? JSON.stringify(value2.cacheControlDirectives) : null, + value2.vary ? JSON.stringify(value2.vary) : null, + value2.cachedAt, + value2.staleAt, + existingValue.id + ); + } else { + this.#insertValueQuery.run( + url2, + key.method, + body2, + value2.deleteAt, + value2.statusCode, + value2.statusMessage, + value2.headers ? JSON.stringify(value2.headers) : null, + value2.etag ? value2.etag : null, + value2.cacheControlDirectives ? JSON.stringify(value2.cacheControlDirectives) : null, + value2.vary ? JSON.stringify(value2.vary) : null, + value2.cachedAt, + value2.staleAt + ); + this.#prune(); + } + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {import('../../types/cache-interceptor.d.ts').default.CacheValue} value + * @returns {Writable | undefined} + */ + createWriteStream(key, value2) { + assertCacheKey(key); + assertCacheValue(value2); + let size = 0; + const body2 = []; + const store = this; + return new Writable({ + decodeStrings: true, + write(chunk, encoding, callback) { + size += chunk.byteLength; + if (size <= store.#maxEntrySize) { + body2.push(chunk); + } else { + this.destroy(); + } + callback(); + }, + final(callback) { + store.set(key, { ...value2, body: body2 }); + callback(); + } + }); + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + */ + delete(key) { + if (typeof key !== "object") { + throw new TypeError(`expected key to be object, got ${typeof key}`); + } + this.#deleteByUrlQuery.run(this.#makeValueUrl(key)); + } + #prune() { + if (Number.isFinite(this.#maxCount) && this.size <= this.#maxCount) { + return 0; + } + { + const removed = this.#deleteExpiredValuesQuery.run(Date.now()).changes; + if (removed) { + return removed; + } + } + { + const removed = this.#deleteOldValuesQuery?.run(Math.max(Math.floor(this.#maxCount * 0.1), 1)).changes; + if (removed) { + return removed; + } + } + return 0; + } + /** + * Counts the number of rows in the cache + * @returns {Number} + */ + get size() { + const { total } = this.#countEntriesQuery.get(); + return total; + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @returns {string} + */ + #makeValueUrl(key) { + return `${key.origin}/${key.path}`; + } + /** + * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} key + * @param {boolean} [canBeExpired=false] + * @returns {SqliteStoreValue | undefined} + */ + #findValue(key, canBeExpired = false) { + const url2 = this.#makeValueUrl(key); + const { headers: headers2, method: method2 } = key; + const values2 = this.#getValuesQuery.all(url2, method2); + if (values2.length === 0) { + return void 0; + } + const now = Date.now(); + for (const value2 of values2) { + if (now >= value2.deleteAt && !canBeExpired) { + continue; + } + let matches = true; + if (value2.vary) { + const vary = JSON.parse(value2.vary); + for (const header in vary) { + if (!headerValueEquals(headers2[header], vary[header])) { + matches = false; + break; + } + } + } + if (matches) { + return value2; + } + } + return void 0; + } + }; + function headerValueEquals(lhs, rhs) { + if (lhs == null && rhs == null) { + return true; + } + if (lhs == null && rhs != null || lhs != null && rhs == null) { + return false; + } + if (Array.isArray(lhs) && Array.isArray(rhs)) { + if (lhs.length !== rhs.length) { + return false; + } + for (let i = 0; i < lhs.length; i++) { + if (lhs[i] !== rhs[i]) { + return false; + } + } + return true; + } + return lhs === rhs; + } + } +}); + +// node_modules/undici/lib/web/fetch/headers.js +var require_headers = __commonJS({ + "node_modules/undici/lib/web/fetch/headers.js"(exports2, module2) { + "use strict"; + var { kConstruct } = require_symbols(); + var { kEnumerableProperty } = require_util(); + var { + iteratorMixin, + isValidHeaderName, + isValidHeaderValue + } = require_util2(); + var { webidl } = require_webidl(); + var assert = require("node:assert"); + var util = require("node:util"); + function isHTTPWhiteSpaceCharCode(code) { + return code === 10 || code === 13 || code === 9 || code === 32; + } + function headerValueNormalize(potentialValue) { + let i = 0; + let j = potentialValue.length; + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(j - 1))) --j; + while (j > i && isHTTPWhiteSpaceCharCode(potentialValue.charCodeAt(i))) ++i; + return i === 0 && j === potentialValue.length ? potentialValue : potentialValue.substring(i, j); + } + function fill(headers2, object) { + if (Array.isArray(object)) { + for (let i = 0; i < object.length; ++i) { + const header = object[i]; + if (header.length !== 2) { + throw webidl.errors.exception({ + header: "Headers constructor", + message: `expected name/value pair to be length 2, found ${header.length}.` + }); + } + appendHeader(headers2, header[0], header[1]); + } + } else if (typeof object === "object" && object !== null) { + const keys = Object.keys(object); + for (let i = 0; i < keys.length; ++i) { + appendHeader(headers2, keys[i], object[keys[i]]); + } + } else { + throw webidl.errors.conversionFailed({ + prefix: "Headers constructor", + argument: "Argument 1", + types: ["sequence>", "record"] + }); + } + } + function appendHeader(headers2, name2, value2) { + value2 = headerValueNormalize(value2); + if (!isValidHeaderName(name2)) { + throw webidl.errors.invalidArgument({ + prefix: "Headers.append", + value: name2, + type: "header name" + }); + } else if (!isValidHeaderValue(value2)) { + throw webidl.errors.invalidArgument({ + prefix: "Headers.append", + value: value2, + type: "header value" + }); + } + if (getHeadersGuard(headers2) === "immutable") { + throw new TypeError("immutable"); + } + return getHeadersList(headers2).append(name2, value2, false); + } + function headersListSortAndCombine(target2) { + const headersList = getHeadersList(target2); + if (!headersList) { + return []; + } + if (headersList.sortedMap) { + return headersList.sortedMap; + } + const headers2 = []; + const names = headersList.toSortedArray(); + const cookies = headersList.cookies; + if (cookies === null || cookies.length === 1) { + return headersList.sortedMap = names; + } + for (let i = 0; i < names.length; ++i) { + const { 0: name2, 1: value2 } = names[i]; + if (name2 === "set-cookie") { + for (let j = 0; j < cookies.length; ++j) { + headers2.push([name2, cookies[j]]); + } + } else { + headers2.push([name2, value2]); + } + } + return headersList.sortedMap = headers2; + } + function compareHeaderName(a, b) { + return a[0] < b[0] ? -1 : 1; + } + var HeadersList = class _HeadersList { + /** @type {[string, string][]|null} */ + cookies = null; + sortedMap; + headersMap; + constructor(init) { + if (init instanceof _HeadersList) { + this.headersMap = new Map(init.headersMap); + this.sortedMap = init.sortedMap; + this.cookies = init.cookies === null ? null : [...init.cookies]; + } else { + this.headersMap = new Map(init); + this.sortedMap = null; + } + } + /** + * @see https://fetch.spec.whatwg.org/#header-list-contains + * @param {string} name + * @param {boolean} isLowerCase + */ + contains(name2, isLowerCase) { + return this.headersMap.has(isLowerCase ? name2 : name2.toLowerCase()); + } + clear() { + this.headersMap.clear(); + this.sortedMap = null; + this.cookies = null; + } + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-append + * @param {string} name + * @param {string} value + * @param {boolean} isLowerCase + */ + append(name2, value2, isLowerCase) { + this.sortedMap = null; + const lowercaseName = isLowerCase ? name2 : name2.toLowerCase(); + const exists = this.headersMap.get(lowercaseName); + if (exists) { + const delimiter = lowercaseName === "cookie" ? "; " : ", "; + this.headersMap.set(lowercaseName, { + name: exists.name, + value: `${exists.value}${delimiter}${value2}` + }); + } else { + this.headersMap.set(lowercaseName, { name: name2, value: value2 }); + } + if (lowercaseName === "set-cookie") { + (this.cookies ??= []).push(value2); + } + } + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-set + * @param {string} name + * @param {string} value + * @param {boolean} isLowerCase + */ + set(name2, value2, isLowerCase) { + this.sortedMap = null; + const lowercaseName = isLowerCase ? name2 : name2.toLowerCase(); + if (lowercaseName === "set-cookie") { + this.cookies = [value2]; + } + this.headersMap.set(lowercaseName, { name: name2, value: value2 }); + } + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-delete + * @param {string} name + * @param {boolean} isLowerCase + */ + delete(name2, isLowerCase) { + this.sortedMap = null; + if (!isLowerCase) name2 = name2.toLowerCase(); + if (name2 === "set-cookie") { + this.cookies = null; + } + this.headersMap.delete(name2); + } + /** + * @see https://fetch.spec.whatwg.org/#concept-header-list-get + * @param {string} name + * @param {boolean} isLowerCase + * @returns {string | null} + */ + get(name2, isLowerCase) { + return this.headersMap.get(isLowerCase ? name2 : name2.toLowerCase())?.value ?? null; + } + *[Symbol.iterator]() { + for (const { 0: name2, 1: { value: value2 } } of this.headersMap) { + yield [name2, value2]; + } + } + get entries() { + const headers2 = {}; + if (this.headersMap.size !== 0) { + for (const { name: name2, value: value2 } of this.headersMap.values()) { + headers2[name2] = value2; + } + } + return headers2; + } + rawValues() { + return this.headersMap.values(); + } + get entriesList() { + const headers2 = []; + if (this.headersMap.size !== 0) { + for (const { 0: lowerName, 1: { name: name2, value: value2 } } of this.headersMap) { + if (lowerName === "set-cookie") { + for (const cookie of this.cookies) { + headers2.push([name2, cookie]); + } + } else { + headers2.push([name2, value2]); + } + } + } + return headers2; + } + // https://fetch.spec.whatwg.org/#convert-header-names-to-a-sorted-lowercase-set + toSortedArray() { + const size = this.headersMap.size; + const array = new Array(size); + if (size <= 32) { + if (size === 0) { + return array; + } + const iterator = this.headersMap[Symbol.iterator](); + const firstValue = iterator.next().value; + array[0] = [firstValue[0], firstValue[1].value]; + assert(firstValue[1].value !== null); + for (let i = 1, j = 0, right = 0, left = 0, pivot = 0, x3, value2; i < size; ++i) { + value2 = iterator.next().value; + x3 = array[i] = [value2[0], value2[1].value]; + assert(x3[1] !== null); + left = 0; + right = i; + while (left < right) { + pivot = left + (right - left >> 1); + if (array[pivot][0] <= x3[0]) { + left = pivot + 1; + } else { + right = pivot; + } + } + if (i !== pivot) { + j = i; + while (j > left) { + array[j] = array[--j]; + } + array[left] = x3; + } + } + if (!iterator.next().done) { + throw new TypeError("Unreachable"); + } + return array; + } else { + let i = 0; + for (const { 0: name2, 1: { value: value2 } } of this.headersMap) { + array[i++] = [name2, value2]; + assert(value2 !== null); + } + return array.sort(compareHeaderName); + } + } + }; + var Headers3 = class _Headers { + #guard; + /** + * @type {HeadersList} + */ + #headersList; + /** + * @param {HeadersInit|Symbol} [init] + * @returns + */ + constructor(init = void 0) { + webidl.util.markAsUncloneable(this); + if (init === kConstruct) { + return; + } + this.#headersList = new HeadersList(); + this.#guard = "none"; + if (init !== void 0) { + init = webidl.converters.HeadersInit(init, "Headers constructor", "init"); + fill(this, init); + } + } + // https://fetch.spec.whatwg.org/#dom-headers-append + append(name2, value2) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 2, "Headers.append"); + const prefix2 = "Headers.append"; + name2 = webidl.converters.ByteString(name2, prefix2, "name"); + value2 = webidl.converters.ByteString(value2, prefix2, "value"); + return appendHeader(this, name2, value2); + } + // https://fetch.spec.whatwg.org/#dom-headers-delete + delete(name2) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 1, "Headers.delete"); + const prefix2 = "Headers.delete"; + name2 = webidl.converters.ByteString(name2, prefix2, "name"); + if (!isValidHeaderName(name2)) { + throw webidl.errors.invalidArgument({ + prefix: "Headers.delete", + value: name2, + type: "header name" + }); + } + if (this.#guard === "immutable") { + throw new TypeError("immutable"); + } + if (!this.#headersList.contains(name2, false)) { + return; + } + this.#headersList.delete(name2, false); + } + // https://fetch.spec.whatwg.org/#dom-headers-get + get(name2) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 1, "Headers.get"); + const prefix2 = "Headers.get"; + name2 = webidl.converters.ByteString(name2, prefix2, "name"); + if (!isValidHeaderName(name2)) { + throw webidl.errors.invalidArgument({ + prefix: prefix2, + value: name2, + type: "header name" + }); + } + return this.#headersList.get(name2, false); + } + // https://fetch.spec.whatwg.org/#dom-headers-has + has(name2) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 1, "Headers.has"); + const prefix2 = "Headers.has"; + name2 = webidl.converters.ByteString(name2, prefix2, "name"); + if (!isValidHeaderName(name2)) { + throw webidl.errors.invalidArgument({ + prefix: prefix2, + value: name2, + type: "header name" + }); + } + return this.#headersList.contains(name2, false); + } + // https://fetch.spec.whatwg.org/#dom-headers-set + set(name2, value2) { + webidl.brandCheck(this, _Headers); + webidl.argumentLengthCheck(arguments, 2, "Headers.set"); + const prefix2 = "Headers.set"; + name2 = webidl.converters.ByteString(name2, prefix2, "name"); + value2 = webidl.converters.ByteString(value2, prefix2, "value"); + value2 = headerValueNormalize(value2); + if (!isValidHeaderName(name2)) { + throw webidl.errors.invalidArgument({ + prefix: prefix2, + value: name2, + type: "header name" + }); + } else if (!isValidHeaderValue(value2)) { + throw webidl.errors.invalidArgument({ + prefix: prefix2, + value: value2, + type: "header value" + }); + } + if (this.#guard === "immutable") { + throw new TypeError("immutable"); + } + this.#headersList.set(name2, value2, false); + } + // https://fetch.spec.whatwg.org/#dom-headers-getsetcookie + getSetCookie() { + webidl.brandCheck(this, _Headers); + const list = this.#headersList.cookies; + if (list) { + return [...list]; + } + return []; + } + [util.inspect.custom](depth, options2) { + options2.depth ??= depth; + return `Headers ${util.formatWithOptions(options2, this.#headersList.entries)}`; + } + static getHeadersGuard(o) { + return o.#guard; + } + static setHeadersGuard(o, guard) { + o.#guard = guard; + } + /** + * @param {Headers} o + */ + static getHeadersList(o) { + return o.#headersList; + } + /** + * @param {Headers} target + * @param {HeadersList} list + */ + static setHeadersList(target2, list) { + target2.#headersList = list; + } + }; + var { getHeadersGuard, setHeadersGuard, getHeadersList, setHeadersList } = Headers3; + Reflect.deleteProperty(Headers3, "getHeadersGuard"); + Reflect.deleteProperty(Headers3, "setHeadersGuard"); + Reflect.deleteProperty(Headers3, "getHeadersList"); + Reflect.deleteProperty(Headers3, "setHeadersList"); + iteratorMixin("Headers", Headers3, headersListSortAndCombine, 0, 1); + Object.defineProperties(Headers3.prototype, { + append: kEnumerableProperty, + delete: kEnumerableProperty, + get: kEnumerableProperty, + has: kEnumerableProperty, + set: kEnumerableProperty, + getSetCookie: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "Headers", + configurable: true + }, + [util.inspect.custom]: { + enumerable: false + } + }); + webidl.converters.HeadersInit = function(V, prefix2, argument) { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT) { + const iterator = Reflect.get(V, Symbol.iterator); + if (!util.types.isProxy(V) && iterator === Headers3.prototype.entries) { + try { + return getHeadersList(V).entriesList; + } catch { + } + } + if (typeof iterator === "function") { + return webidl.converters["sequence>"](V, prefix2, argument, iterator.bind(V)); + } + return webidl.converters["record"](V, prefix2, argument); + } + throw webidl.errors.conversionFailed({ + prefix: "Headers constructor", + argument: "Argument 1", + types: ["sequence>", "record"] + }); + }; + module2.exports = { + fill, + // for test. + compareHeaderName, + Headers: Headers3, + HeadersList, + getHeadersGuard, + setHeadersGuard, + setHeadersList, + getHeadersList + }; + } +}); + +// node_modules/undici/lib/web/fetch/response.js +var require_response = __commonJS({ + "node_modules/undici/lib/web/fetch/response.js"(exports2, module2) { + "use strict"; + var { Headers: Headers3, HeadersList, fill, getHeadersGuard, setHeadersGuard, setHeadersList } = require_headers(); + var { extractBody, cloneBody, mixinBody, streamRegistry, bodyUnusable } = require_body(); + var util = require_util(); + var nodeUtil = require("node:util"); + var { kEnumerableProperty } = util; + var { + isValidReasonPhrase, + isCancelled, + isAborted, + isErrorLike, + environmentSettingsObject: relevantRealm + } = require_util2(); + var { + redirectStatusSet, + nullBodyStatus + } = require_constants4(); + var { webidl } = require_webidl(); + var { URLSerializer } = require_data_url(); + var { kConstruct } = require_symbols(); + var assert = require("node:assert"); + var { isomorphicEncode, serializeJavascriptValueToJSONString } = require_infra(); + var textEncoder = new TextEncoder("utf-8"); + var Response3 = class _Response { + /** @type {Headers} */ + #headers; + #state; + // Creates network error Response. + static error() { + const responseObject = fromInnerResponse(makeNetworkError(), "immutable"); + return responseObject; + } + // https://fetch.spec.whatwg.org/#dom-response-json + static json(data2, init = void 0) { + webidl.argumentLengthCheck(arguments, 1, "Response.json"); + init = webidl.converters.ResponseInit(init); + const bytes = textEncoder.encode( + serializeJavascriptValueToJSONString(data2) + ); + const body2 = extractBody(bytes); + const responseObject = fromInnerResponse(makeResponse({}), "response"); + initializeResponse(responseObject, init, { body: body2[0], type: "application/json" }); + return responseObject; + } + // Creates a redirect Response that redirects to url with status status. + static redirect(url2, status = 302) { + webidl.argumentLengthCheck(arguments, 1, "Response.redirect"); + url2 = webidl.converters.USVString(url2); + status = webidl.converters["unsigned short"](status); + let parsedURL; + try { + parsedURL = new URL(url2, relevantRealm.settingsObject.baseUrl); + } catch (err) { + throw new TypeError(`Failed to parse URL from ${url2}`, { cause: err }); + } + if (!redirectStatusSet.has(status)) { + throw new RangeError(`Invalid status code ${status}`); + } + const responseObject = fromInnerResponse(makeResponse({}), "immutable"); + responseObject.#state.status = status; + const value2 = isomorphicEncode(URLSerializer(parsedURL)); + responseObject.#state.headersList.append("location", value2, true); + return responseObject; + } + // https://fetch.spec.whatwg.org/#dom-response + constructor(body2 = null, init = void 0) { + webidl.util.markAsUncloneable(this); + if (body2 === kConstruct) { + return; + } + if (body2 !== null) { + body2 = webidl.converters.BodyInit(body2, "Response", "body"); + } + init = webidl.converters.ResponseInit(init); + this.#state = makeResponse({}); + this.#headers = new Headers3(kConstruct); + setHeadersGuard(this.#headers, "response"); + setHeadersList(this.#headers, this.#state.headersList); + let bodyWithType = null; + if (body2 != null) { + const [extractedBody, type2] = extractBody(body2); + bodyWithType = { body: extractedBody, type: type2 }; + } + initializeResponse(this, init, bodyWithType); + } + // Returns response’s type, e.g., "cors". + get type() { + webidl.brandCheck(this, _Response); + return this.#state.type; + } + // Returns response’s URL, if it has one; otherwise the empty string. + get url() { + webidl.brandCheck(this, _Response); + const urlList = this.#state.urlList; + const url2 = urlList[urlList.length - 1] ?? null; + if (url2 === null) { + return ""; + } + return URLSerializer(url2, true); + } + // Returns whether response was obtained through a redirect. + get redirected() { + webidl.brandCheck(this, _Response); + return this.#state.urlList.length > 1; + } + // Returns response’s status. + get status() { + webidl.brandCheck(this, _Response); + return this.#state.status; + } + // Returns whether response’s status is an ok status. + get ok() { + webidl.brandCheck(this, _Response); + return this.#state.status >= 200 && this.#state.status <= 299; + } + // Returns response’s status message. + get statusText() { + webidl.brandCheck(this, _Response); + return this.#state.statusText; + } + // Returns response’s headers as Headers. + get headers() { + webidl.brandCheck(this, _Response); + return this.#headers; + } + get body() { + webidl.brandCheck(this, _Response); + return this.#state.body ? this.#state.body.stream : null; + } + get bodyUsed() { + webidl.brandCheck(this, _Response); + return !!this.#state.body && util.isDisturbed(this.#state.body.stream); + } + // Returns a clone of response. + clone() { + webidl.brandCheck(this, _Response); + if (bodyUnusable(this.#state)) { + throw webidl.errors.exception({ + header: "Response.clone", + message: "Body has already been consumed." + }); + } + const clonedResponse = cloneResponse(this.#state); + if (this.#state.urlList.length !== 0 && this.#state.body?.stream) { + streamRegistry.register(this, new WeakRef(this.#state.body.stream)); + } + return fromInnerResponse(clonedResponse, getHeadersGuard(this.#headers)); + } + [nodeUtil.inspect.custom](depth, options2) { + if (options2.depth === null) { + options2.depth = 2; + } + options2.colors ??= true; + const properties = { + status: this.status, + statusText: this.statusText, + headers: this.headers, + body: this.body, + bodyUsed: this.bodyUsed, + ok: this.ok, + redirected: this.redirected, + type: this.type, + url: this.url + }; + return `Response ${nodeUtil.formatWithOptions(options2, properties)}`; + } + /** + * @param {Response} response + */ + static getResponseHeaders(response) { + return response.#headers; + } + /** + * @param {Response} response + * @param {Headers} newHeaders + */ + static setResponseHeaders(response, newHeaders) { + response.#headers = newHeaders; + } + /** + * @param {Response} response + */ + static getResponseState(response) { + return response.#state; + } + /** + * @param {Response} response + * @param {any} newState + */ + static setResponseState(response, newState) { + response.#state = newState; + } + }; + var { getResponseHeaders, setResponseHeaders, getResponseState, setResponseState } = Response3; + Reflect.deleteProperty(Response3, "getResponseHeaders"); + Reflect.deleteProperty(Response3, "setResponseHeaders"); + Reflect.deleteProperty(Response3, "getResponseState"); + Reflect.deleteProperty(Response3, "setResponseState"); + mixinBody(Response3, getResponseState); + Object.defineProperties(Response3.prototype, { + type: kEnumerableProperty, + url: kEnumerableProperty, + status: kEnumerableProperty, + ok: kEnumerableProperty, + redirected: kEnumerableProperty, + statusText: kEnumerableProperty, + headers: kEnumerableProperty, + clone: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "Response", + configurable: true + } + }); + Object.defineProperties(Response3, { + json: kEnumerableProperty, + redirect: kEnumerableProperty, + error: kEnumerableProperty + }); + function cloneResponse(response) { + if (response.internalResponse) { + return filterResponse( + cloneResponse(response.internalResponse), + response.type + ); + } + const newResponse = makeResponse({ ...response, body: null }); + if (response.body != null) { + newResponse.body = cloneBody(response.body); + } + return newResponse; + } + function makeResponse(init) { + return { + aborted: false, + rangeRequested: false, + timingAllowPassed: false, + requestIncludesCredentials: false, + type: "default", + status: 200, + timingInfo: null, + cacheState: "", + statusText: "", + ...init, + headersList: init?.headersList ? new HeadersList(init?.headersList) : new HeadersList(), + urlList: init?.urlList ? [...init.urlList] : [] + }; + } + function makeNetworkError(reason2) { + const isError = isErrorLike(reason2); + return makeResponse({ + type: "error", + status: 0, + error: isError ? reason2 : new Error(reason2 ? String(reason2) : reason2), + aborted: reason2 && reason2.name === "AbortError" + }); + } + function isNetworkError(response) { + return ( + // A network error is a response whose type is "error", + response.type === "error" && // status is 0 + response.status === 0 + ); + } + function makeFilteredResponse(response, state2) { + state2 = { + internalResponse: response, + ...state2 + }; + return new Proxy(response, { + get(target2, p) { + return p in state2 ? state2[p] : target2[p]; + }, + set(target2, p, value2) { + assert(!(p in state2)); + target2[p] = value2; + return true; + } + }); + } + function filterResponse(response, type2) { + if (type2 === "basic") { + return makeFilteredResponse(response, { + type: "basic", + headersList: response.headersList + }); + } else if (type2 === "cors") { + return makeFilteredResponse(response, { + type: "cors", + headersList: response.headersList + }); + } else if (type2 === "opaque") { + return makeFilteredResponse(response, { + type: "opaque", + urlList: [], + status: 0, + statusText: "", + body: null + }); + } else if (type2 === "opaqueredirect") { + return makeFilteredResponse(response, { + type: "opaqueredirect", + status: 0, + statusText: "", + headersList: [], + body: null + }); + } else { + assert(false); + } + } + function makeAppropriateNetworkError(fetchParams, err = null) { + assert(isCancelled(fetchParams)); + return isAborted(fetchParams) ? makeNetworkError(Object.assign(new DOMException("The operation was aborted.", "AbortError"), { cause: err })) : makeNetworkError(Object.assign(new DOMException("Request was cancelled."), { cause: err })); + } + function initializeResponse(response, init, body2) { + if (init.status !== null && (init.status < 200 || init.status > 599)) { + throw new RangeError('init["status"] must be in the range of 200 to 599, inclusive.'); + } + if ("statusText" in init && init.statusText != null) { + if (!isValidReasonPhrase(String(init.statusText))) { + throw new TypeError("Invalid statusText"); + } + } + if ("status" in init && init.status != null) { + getResponseState(response).status = init.status; + } + if ("statusText" in init && init.statusText != null) { + getResponseState(response).statusText = init.statusText; + } + if ("headers" in init && init.headers != null) { + fill(getResponseHeaders(response), init.headers); + } + if (body2) { + if (nullBodyStatus.includes(response.status)) { + throw webidl.errors.exception({ + header: "Response constructor", + message: `Invalid response status code ${response.status}` + }); + } + getResponseState(response).body = body2.body; + if (body2.type != null && !getResponseState(response).headersList.contains("content-type", true)) { + getResponseState(response).headersList.append("content-type", body2.type, true); + } + } + } + function fromInnerResponse(innerResponse, guard) { + const response = new Response3(kConstruct); + setResponseState(response, innerResponse); + const headers2 = new Headers3(kConstruct); + setResponseHeaders(response, headers2); + setHeadersList(headers2, innerResponse.headersList); + setHeadersGuard(headers2, guard); + if (innerResponse.urlList.length !== 0 && innerResponse.body?.stream) { + streamRegistry.register(response, new WeakRef(innerResponse.body.stream)); + } + return response; + } + webidl.converters.XMLHttpRequestBodyInit = function(V, prefix2, name2) { + if (typeof V === "string") { + return webidl.converters.USVString(V, prefix2, name2); + } + if (webidl.is.Blob(V)) { + return V; + } + if (webidl.is.BufferSource(V)) { + return V; + } + if (webidl.is.FormData(V)) { + return V; + } + if (webidl.is.URLSearchParams(V)) { + return V; + } + return webidl.converters.DOMString(V, prefix2, name2); + }; + webidl.converters.BodyInit = function(V, prefix2, argument) { + if (webidl.is.ReadableStream(V)) { + return V; + } + if (V?.[Symbol.asyncIterator]) { + return V; + } + return webidl.converters.XMLHttpRequestBodyInit(V, prefix2, argument); + }; + webidl.converters.ResponseInit = webidl.dictionaryConverter([ + { + key: "status", + converter: webidl.converters["unsigned short"], + defaultValue: () => 200 + }, + { + key: "statusText", + converter: webidl.converters.ByteString, + defaultValue: () => "" + }, + { + key: "headers", + converter: webidl.converters.HeadersInit + } + ]); + webidl.is.Response = webidl.util.MakeTypeAssertion(Response3); + module2.exports = { + isNetworkError, + makeNetworkError, + makeResponse, + makeAppropriateNetworkError, + filterResponse, + Response: Response3, + cloneResponse, + fromInnerResponse, + getResponseState + }; + } +}); + +// node_modules/undici/lib/web/fetch/request.js +var require_request2 = __commonJS({ + "node_modules/undici/lib/web/fetch/request.js"(exports2, module2) { + "use strict"; + var { extractBody, mixinBody, cloneBody, bodyUnusable } = require_body(); + var { Headers: Headers3, fill: fillHeaders, HeadersList, setHeadersGuard, getHeadersGuard, setHeadersList, getHeadersList } = require_headers(); + var util = require_util(); + var nodeUtil = require("node:util"); + var { + isValidHTTPToken, + sameOrigin, + environmentSettingsObject + } = require_util2(); + var { + forbiddenMethodsSet, + corsSafeListedMethodsSet, + referrerPolicy: referrerPolicy2, + requestRedirect, + requestMode, + requestCredentials, + requestCache, + requestDuplex + } = require_constants4(); + var { kEnumerableProperty, normalizedMethodRecordsBase, normalizedMethodRecords } = util; + var { webidl } = require_webidl(); + var { URLSerializer } = require_data_url(); + var { kConstruct } = require_symbols(); + var assert = require("node:assert"); + var { getMaxListeners, setMaxListeners, defaultMaxListeners } = require("node:events"); + var kAbortController = /* @__PURE__ */ Symbol("abortController"); + var requestFinalizer = new FinalizationRegistry(({ signal: signal2, abort: abort2 }) => { + signal2.removeEventListener("abort", abort2); + }); + var dependentControllerMap = /* @__PURE__ */ new WeakMap(); + var abortSignalHasEventHandlerLeakWarning; + try { + abortSignalHasEventHandlerLeakWarning = getMaxListeners(new AbortController().signal) > 0; + } catch { + abortSignalHasEventHandlerLeakWarning = false; + } + function buildAbort(acRef) { + return abort2; + function abort2() { + const ac = acRef.deref(); + if (ac !== void 0) { + requestFinalizer.unregister(abort2); + this.removeEventListener("abort", abort2); + ac.abort(this.reason); + const controllerList = dependentControllerMap.get(ac.signal); + if (controllerList !== void 0) { + if (controllerList.size !== 0) { + for (const ref of controllerList) { + const ctrl = ref.deref(); + if (ctrl !== void 0) { + ctrl.abort(this.reason); + } + } + controllerList.clear(); + } + dependentControllerMap.delete(ac.signal); + } + } + } + } + var patchMethodWarning = false; + var Request3 = class _Request { + /** @type {AbortSignal} */ + #signal; + /** @type {import('../../dispatcher/dispatcher')} */ + #dispatcher; + /** @type {Headers} */ + #headers; + #state; + /** + * Removes the `abort` listener that makes this request's signal follow the + * passed signal. `null` when no such listener was registered. + * @type {(() => void) | null} + */ + #abortCleanup = null; + // https://fetch.spec.whatwg.org/#dom-request + constructor(input, init = void 0) { + webidl.util.markAsUncloneable(this); + if (input === kConstruct) { + return; + } + const prefix2 = "Request constructor"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + input = webidl.converters.RequestInfo(input); + init = webidl.converters.RequestInit(init); + let request = null; + let fallbackMode = null; + const baseUrl = environmentSettingsObject.settingsObject.baseUrl; + let signal2 = null; + if (typeof input === "string") { + this.#dispatcher = init.dispatcher; + let parsedURL; + try { + parsedURL = new URL(input, baseUrl); + } catch (err) { + throw new TypeError("Failed to parse URL from " + input, { cause: err }); + } + if (parsedURL.username || parsedURL.password) { + throw new TypeError( + "Request cannot be constructed from a URL that includes credentials: " + input + ); + } + request = makeRequest({ urlList: [parsedURL] }); + fallbackMode = "cors"; + } else { + assert(webidl.is.Request(input)); + request = input.#state; + signal2 = input.#signal; + this.#dispatcher = init.dispatcher || input.#dispatcher; + } + const origin = environmentSettingsObject.settingsObject.origin; + let window2 = "client"; + if (request.window?.constructor?.name === "EnvironmentSettingsObject" && sameOrigin(request.window, origin)) { + window2 = request.window; + } + if (init.window != null) { + throw new TypeError(`'window' option '${window2}' must be null`); + } + if ("window" in init) { + window2 = "no-window"; + } + request = makeRequest({ + // URL request’s URL. + // undici implementation note: this is set as the first item in request's urlList in makeRequest + // method request’s method. + method: request.method, + // header list A copy of request’s header list. + // undici implementation note: headersList is cloned in makeRequest + headersList: request.headersList, + // unsafe-request flag Set. + unsafeRequest: request.unsafeRequest, + // client This’s relevant settings object. + client: environmentSettingsObject.settingsObject, + // window window. + window: window2, + // priority request’s priority. + priority: request.priority, + // origin request’s origin. The propagation of the origin is only significant for navigation requests + // being handled by a service worker. In this scenario a request can have an origin that is different + // from the current client. + origin: request.origin, + // referrer request’s referrer. + referrer: request.referrer, + // referrer policy request’s referrer policy. + referrerPolicy: request.referrerPolicy, + // mode request’s mode. + mode: request.mode, + // credentials mode request’s credentials mode. + credentials: request.credentials, + // cache mode request’s cache mode. + cache: request.cache, + // redirect mode request’s redirect mode. + redirect: request.redirect, + // integrity metadata request’s integrity metadata. + integrity: request.integrity, + // keepalive request’s keepalive. + keepalive: request.keepalive, + // reload-navigation flag request’s reload-navigation flag. + reloadNavigation: request.reloadNavigation, + // history-navigation flag request’s history-navigation flag. + historyNavigation: request.historyNavigation, + // URL list A clone of request’s URL list. + urlList: [...request.urlList] + }); + const initHasKey = Object.keys(init).length !== 0; + if (initHasKey) { + if (request.mode === "navigate") { + request.mode = "same-origin"; + } + request.reloadNavigation = false; + request.historyNavigation = false; + request.origin = "client"; + request.referrer = "client"; + request.referrerPolicy = ""; + request.url = request.urlList[request.urlList.length - 1]; + request.urlList = [request.url]; + } + if (init.referrer !== void 0) { + const referrer2 = init.referrer; + if (referrer2 === "") { + request.referrer = "no-referrer"; + } else { + let parsedReferrer; + try { + parsedReferrer = new URL(referrer2, baseUrl); + } catch (err) { + throw new TypeError(`Referrer "${referrer2}" is not a valid URL.`, { cause: err }); + } + if (parsedReferrer.protocol === "about:" && parsedReferrer.hostname === "client" || origin && !sameOrigin(parsedReferrer, environmentSettingsObject.settingsObject.baseUrl)) { + request.referrer = "client"; + } else { + request.referrer = parsedReferrer; + } + } + } + if (init.referrerPolicy !== void 0) { + request.referrerPolicy = init.referrerPolicy; + } + let mode2; + if (init.mode !== void 0) { + mode2 = init.mode; + } else { + mode2 = fallbackMode; + } + if (mode2 === "navigate") { + throw webidl.errors.exception({ + header: "Request constructor", + message: "invalid request mode navigate." + }); + } + if (mode2 != null) { + request.mode = mode2; + } + if (init.credentials !== void 0) { + request.credentials = init.credentials; + } + if (init.cache !== void 0) { + request.cache = init.cache; + } + if (request.cache === "only-if-cached" && request.mode !== "same-origin") { + throw new TypeError( + "'only-if-cached' can be set only with 'same-origin' mode" + ); + } + if (init.redirect !== void 0) { + request.redirect = init.redirect; + } + if (init.integrity != null) { + request.integrity = String(init.integrity); + } + if (init.keepalive !== void 0) { + request.keepalive = Boolean(init.keepalive); + } + if (init.method !== void 0) { + let method2 = init.method; + const mayBeNormalized = normalizedMethodRecords[method2]; + if (mayBeNormalized !== void 0) { + request.method = mayBeNormalized; + } else { + if (!isValidHTTPToken(method2)) { + throw new TypeError(`'${method2}' is not a valid HTTP method.`); + } + const upperCase = method2.toUpperCase(); + if (forbiddenMethodsSet.has(upperCase)) { + throw new TypeError(`'${method2}' HTTP method is unsupported.`); + } + method2 = normalizedMethodRecordsBase[upperCase] ?? method2; + request.method = method2; + } + if (!patchMethodWarning && request.method === "patch") { + process.emitWarning("Using `patch` is highly likely to result in a `405 Method Not Allowed`. `PATCH` is much more likely to succeed.", { + code: "UNDICI-FETCH-patch" + }); + patchMethodWarning = true; + } + } + if (init.signal !== void 0) { + signal2 = init.signal; + } + this.#state = request; + const ac = new AbortController(); + this.#signal = ac.signal; + if (signal2 != null) { + if (signal2.aborted) { + ac.abort(signal2.reason); + } else { + this[kAbortController] = ac; + const acRef = new WeakRef(ac); + const abort2 = buildAbort(acRef); + if (abortSignalHasEventHandlerLeakWarning && getMaxListeners(signal2) === defaultMaxListeners) { + setMaxListeners(1500, signal2); + } + const removeAbortListener = util.addAbortListener(signal2, abort2); + requestFinalizer.register(ac, { signal: signal2, abort: abort2 }, abort2); + this.#abortCleanup = () => { + requestFinalizer.unregister(abort2); + removeAbortListener(); + this.#abortCleanup = null; + }; + } + } + this.#headers = new Headers3(kConstruct); + setHeadersList(this.#headers, request.headersList); + setHeadersGuard(this.#headers, "request"); + if (mode2 === "no-cors") { + if (!corsSafeListedMethodsSet.has(request.method)) { + throw new TypeError( + `'${request.method} is unsupported in no-cors mode.` + ); + } + setHeadersGuard(this.#headers, "request-no-cors"); + } + if (initHasKey) { + const headersList = getHeadersList(this.#headers); + const headers2 = init.headers !== void 0 ? init.headers : new HeadersList(headersList); + headersList.clear(); + if (headers2 instanceof HeadersList) { + for (const { name: name2, value: value2 } of headers2.rawValues()) { + headersList.append(name2, value2, false); + } + headersList.cookies = headers2.cookies; + } else { + fillHeaders(this.#headers, headers2); + } + } + const inputBody = webidl.is.Request(input) ? input.#state.body : null; + if ((init.body != null || inputBody != null) && (request.method === "GET" || request.method === "HEAD")) { + throw new TypeError("Request with GET/HEAD method cannot have body."); + } + let initBody = null; + if (init.body != null) { + const [extractedBody, contentType2] = extractBody( + init.body, + request.keepalive + ); + initBody = extractedBody; + if (contentType2 && !getHeadersList(this.#headers).contains("content-type", true)) { + this.#headers.append("content-type", contentType2, true); + } + } + const inputOrInitBody = initBody ?? inputBody; + if (inputOrInitBody != null && inputOrInitBody.source == null) { + if (initBody != null && init.duplex == null) { + throw new TypeError("RequestInit: duplex option is required when sending a body."); + } + if (request.mode !== "same-origin" && request.mode !== "cors") { + throw new TypeError( + 'If request is made from ReadableStream, mode should be "same-origin" or "cors"' + ); + } + request.useCORSPreflightFlag = true; + } + let finalBody = inputOrInitBody; + if (initBody == null && inputBody != null) { + if (bodyUnusable(input.#state)) { + throw new TypeError( + "Cannot construct a Request with a Request object that has already been used." + ); + } + const identityTransform = new TransformStream(); + inputBody.stream.pipeThrough(identityTransform); + finalBody = { + source: inputBody.source, + length: inputBody.length, + stream: identityTransform.readable + }; + } + this.#state.body = finalBody; + } + // Returns request’s HTTP method, which is "GET" by default. + get method() { + webidl.brandCheck(this, _Request); + return this.#state.method; + } + // Returns the URL of request as a string. + get url() { + webidl.brandCheck(this, _Request); + return URLSerializer(this.#state.url); + } + // Returns a Headers object consisting of the headers associated with request. + // Note that headers added in the network layer by the user agent will not + // be accounted for in this object, e.g., the "Host" header. + get headers() { + webidl.brandCheck(this, _Request); + return this.#headers; + } + // Returns the kind of resource requested by request, e.g., "document" + // or "script". + get destination() { + webidl.brandCheck(this, _Request); + return this.#state.destination; + } + // Returns the referrer of request. Its value can be a same-origin URL if + // explicitly set in init, the empty string to indicate no referrer, and + // "about:client" when defaulting to the global’s default. This is used + // during fetching to determine the value of the `Referer` header of the + // request being made. + get referrer() { + webidl.brandCheck(this, _Request); + if (this.#state.referrer === "no-referrer") { + return ""; + } + if (this.#state.referrer === "client") { + return "about:client"; + } + return this.#state.referrer.toString(); + } + // Returns the referrer policy associated with request. + // This is used during fetching to compute the value of the request’s + // referrer. + get referrerPolicy() { + webidl.brandCheck(this, _Request); + return this.#state.referrerPolicy; + } + // Returns the mode associated with request, which is a string indicating + // whether the request will use CORS, or will be restricted to same-origin + // URLs. + get mode() { + webidl.brandCheck(this, _Request); + return this.#state.mode; + } + // Returns the credentials mode associated with request, + // which is a string indicating whether credentials will be sent with the + // request always, never, or only when sent to a same-origin URL. + get credentials() { + webidl.brandCheck(this, _Request); + return this.#state.credentials; + } + // Returns the cache mode associated with request, + // which is a string indicating how the request will + // interact with the browser’s cache when fetching. + get cache() { + webidl.brandCheck(this, _Request); + return this.#state.cache; + } + // Returns the redirect mode associated with request, + // which is a string indicating how redirects for the + // request will be handled during fetching. A request + // will follow redirects by default. + get redirect() { + webidl.brandCheck(this, _Request); + return this.#state.redirect; + } + // Returns request’s subresource integrity metadata, which is a + // cryptographic hash of the resource being fetched. Its value + // consists of multiple hashes separated by whitespace. [SRI] + get integrity() { + webidl.brandCheck(this, _Request); + return this.#state.integrity; + } + // Returns a boolean indicating whether or not request can outlive the + // global in which it was created. + get keepalive() { + webidl.brandCheck(this, _Request); + return this.#state.keepalive; + } + // Returns a boolean indicating whether or not request is for a reload + // navigation. + get isReloadNavigation() { + webidl.brandCheck(this, _Request); + return this.#state.reloadNavigation; + } + // Returns a boolean indicating whether or not request is for a history + // navigation (a.k.a. back-forward navigation). + get isHistoryNavigation() { + webidl.brandCheck(this, _Request); + return this.#state.historyNavigation; + } + // Returns the signal associated with request, which is an AbortSignal + // object indicating whether or not request has been aborted, and its + // abort event handler. + get signal() { + webidl.brandCheck(this, _Request); + return this.#signal; + } + get body() { + webidl.brandCheck(this, _Request); + return this.#state.body ? this.#state.body.stream : null; + } + get bodyUsed() { + webidl.brandCheck(this, _Request); + return !!this.#state.body && util.isDisturbed(this.#state.body.stream); + } + get duplex() { + webidl.brandCheck(this, _Request); + return "half"; + } + // Returns a clone of request. + clone() { + webidl.brandCheck(this, _Request); + if (bodyUnusable(this.#state)) { + throw new TypeError("unusable"); + } + const clonedRequest = cloneRequest(this.#state); + const ac = new AbortController(); + if (this.signal.aborted) { + ac.abort(this.signal.reason); + } else { + let list = dependentControllerMap.get(this.signal); + if (list === void 0) { + list = /* @__PURE__ */ new Set(); + dependentControllerMap.set(this.signal, list); + } + const acRef = new WeakRef(ac); + list.add(acRef); + util.addAbortListener( + ac.signal, + buildAbort(acRef) + ); + } + return fromInnerRequest(clonedRequest, this.#dispatcher, ac.signal, getHeadersGuard(this.#headers)); + } + [nodeUtil.inspect.custom](depth, options2) { + if (options2.depth === null) { + options2.depth = 2; + } + options2.colors ??= true; + const properties = { + method: this.method, + url: this.url, + headers: this.headers, + destination: this.destination, + referrer: this.referrer, + referrerPolicy: this.referrerPolicy, + mode: this.mode, + credentials: this.credentials, + cache: this.cache, + redirect: this.redirect, + integrity: this.integrity, + keepalive: this.keepalive, + isReloadNavigation: this.isReloadNavigation, + isHistoryNavigation: this.isHistoryNavigation, + signal: this.signal + }; + return `Request ${nodeUtil.formatWithOptions(options2, properties)}`; + } + /** + * @param {Request} request + * @param {AbortSignal} newSignal + */ + static setRequestSignal(request, newSignal) { + request.#signal = newSignal; + return request; + } + /** + * @param {Request} request + */ + static getRequestDispatcher(request) { + return request.#dispatcher; + } + /** + * @param {Request} request + * @param {import('../../dispatcher/dispatcher')} newDispatcher + */ + static setRequestDispatcher(request, newDispatcher) { + request.#dispatcher = newDispatcher; + } + /** + * @param {Request} request + * @param {Headers} newHeaders + */ + static setRequestHeaders(request, newHeaders) { + request.#headers = newHeaders; + } + /** + * @param {Request} request + */ + static getRequestState(request) { + return request.#state; + } + /** + * @param {Request} request + * @param {any} newState + */ + static setRequestState(request, newState) { + request.#state = newState; + } + /** + * Removes the `abort` listener that makes this request's signal follow the + * signal passed to its constructor, if any. Idempotent. + * @param {Request} request + */ + static removeRequestAbortListener(request) { + request.#abortCleanup?.(); + } + }; + var { setRequestSignal, getRequestDispatcher, setRequestDispatcher, setRequestHeaders, getRequestState, setRequestState, removeRequestAbortListener } = Request3; + Reflect.deleteProperty(Request3, "setRequestSignal"); + Reflect.deleteProperty(Request3, "getRequestDispatcher"); + Reflect.deleteProperty(Request3, "setRequestDispatcher"); + Reflect.deleteProperty(Request3, "setRequestHeaders"); + Reflect.deleteProperty(Request3, "getRequestState"); + Reflect.deleteProperty(Request3, "setRequestState"); + Reflect.deleteProperty(Request3, "removeRequestAbortListener"); + mixinBody(Request3, getRequestState); + function makeRequest(init) { + return { + method: init.method ?? "GET", + localURLsOnly: init.localURLsOnly ?? false, + unsafeRequest: init.unsafeRequest ?? false, + body: init.body ?? null, + client: init.client ?? null, + reservedClient: init.reservedClient ?? null, + replacesClientId: init.replacesClientId ?? "", + window: init.window ?? "client", + keepalive: init.keepalive ?? false, + serviceWorkers: init.serviceWorkers ?? "all", + initiator: init.initiator ?? "", + destination: init.destination ?? "", + priority: init.priority ?? null, + origin: init.origin ?? "client", + policyContainer: init.policyContainer ?? "client", + referrer: init.referrer ?? "client", + referrerPolicy: init.referrerPolicy ?? "", + mode: init.mode ?? "no-cors", + useCORSPreflightFlag: init.useCORSPreflightFlag ?? false, + // TODO: is this credentials mode? https://fetch.spec.whatwg.org/#concept-request-credentials-mode + credentials: init.credentials ?? "same-origin", + useCredentials: init.useCredentials ?? false, + cache: init.cache ?? "default", + redirect: init.redirect ?? "follow", + integrity: init.integrity ?? "", + cryptoGraphicsNonceMetadata: init.cryptoGraphicsNonceMetadata ?? "", + parserMetadata: init.parserMetadata ?? "", + reloadNavigation: init.reloadNavigation ?? false, + historyNavigation: init.historyNavigation ?? false, + userActivation: init.userActivation ?? false, + taintedOrigin: init.taintedOrigin ?? false, + redirectCount: init.redirectCount ?? 0, + responseTainting: init.responseTainting ?? "basic", + preventNoCacheCacheControlHeaderModification: init.preventNoCacheCacheControlHeaderModification ?? false, + done: init.done ?? false, + timingAllowFailed: init.timingAllowFailed ?? false, + useURLCredentials: init.useURLCredentials ?? void 0, + traversableForUserPrompts: init.traversableForUserPrompts ?? "client", + urlList: init.urlList, + url: init.urlList[0], + headersList: init.headersList ? new HeadersList(init.headersList) : new HeadersList() + }; + } + function cloneRequest(request) { + const newRequest = makeRequest({ ...request, body: null }); + if (request.body != null) { + newRequest.body = cloneBody(request.body); + } + return newRequest; + } + function fromInnerRequest(innerRequest, dispatcher, signal2, guard) { + const request = new Request3(kConstruct); + setRequestState(request, innerRequest); + setRequestDispatcher(request, dispatcher); + setRequestSignal(request, signal2); + const headers2 = new Headers3(kConstruct); + setRequestHeaders(request, headers2); + setHeadersList(headers2, innerRequest.headersList); + setHeadersGuard(headers2, guard); + return request; + } + Object.defineProperties(Request3.prototype, { + method: kEnumerableProperty, + url: kEnumerableProperty, + headers: kEnumerableProperty, + redirect: kEnumerableProperty, + clone: kEnumerableProperty, + signal: kEnumerableProperty, + duplex: kEnumerableProperty, + destination: kEnumerableProperty, + body: kEnumerableProperty, + bodyUsed: kEnumerableProperty, + isHistoryNavigation: kEnumerableProperty, + isReloadNavigation: kEnumerableProperty, + keepalive: kEnumerableProperty, + integrity: kEnumerableProperty, + cache: kEnumerableProperty, + credentials: kEnumerableProperty, + attribute: kEnumerableProperty, + referrerPolicy: kEnumerableProperty, + referrer: kEnumerableProperty, + mode: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "Request", + configurable: true + } + }); + webidl.is.Request = webidl.util.MakeTypeAssertion(Request3); + webidl.converters.RequestInfo = function(V) { + if (typeof V === "string") { + return webidl.converters.USVString(V); + } + if (webidl.is.Request(V)) { + return V; + } + return webidl.converters.USVString(V); + }; + webidl.converters.RequestInit = webidl.dictionaryConverter([ + { + key: "method", + converter: webidl.converters.ByteString + }, + { + key: "headers", + converter: webidl.converters.HeadersInit + }, + { + key: "body", + converter: webidl.nullableConverter( + webidl.converters.BodyInit + ) + }, + { + key: "referrer", + converter: webidl.converters.USVString + }, + { + key: "referrerPolicy", + converter: webidl.converters.DOMString, + // https://w3c.github.io/webappsec-referrer-policy/#referrer-policy + allowedValues: referrerPolicy2 + }, + { + key: "mode", + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#concept-request-mode + allowedValues: requestMode + }, + { + key: "credentials", + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcredentials + allowedValues: requestCredentials + }, + { + key: "cache", + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestcache + allowedValues: requestCache + }, + { + key: "redirect", + converter: webidl.converters.DOMString, + // https://fetch.spec.whatwg.org/#requestredirect + allowedValues: requestRedirect + }, + { + key: "integrity", + converter: webidl.converters.DOMString + }, + { + key: "keepalive", + converter: webidl.converters.boolean + }, + { + key: "signal", + converter: webidl.nullableConverter( + (signal2) => webidl.converters.AbortSignal( + signal2, + "RequestInit", + "signal" + ) + ) + }, + { + key: "window", + converter: webidl.converters.any + }, + { + key: "duplex", + converter: webidl.converters.DOMString, + allowedValues: requestDuplex + }, + { + key: "dispatcher", + // undici specific option + converter: webidl.converters.any + }, + { + key: "priority", + converter: webidl.converters.DOMString, + allowedValues: ["high", "low", "auto"], + defaultValue: () => "auto" + } + ]); + module2.exports = { + Request: Request3, + makeRequest, + fromInnerRequest, + cloneRequest, + getRequestDispatcher, + getRequestState, + removeRequestAbortListener + }; + } +}); + +// node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +var require_subresource_integrity = __commonJS({ + "node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { runtimeFeatures } = require_runtime_features(); + var validSRIHashAlgorithmTokenSet = /* @__PURE__ */ new Map([["sha256", 0], ["sha384", 1], ["sha512", 2]]); + var crypto3; + if (runtimeFeatures.has("crypto")) { + crypto3 = require("node:crypto"); + const cryptoHashes = crypto3.getHashes(); + if (cryptoHashes.length === 0) { + validSRIHashAlgorithmTokenSet.clear(); + } + for (const algorithm of validSRIHashAlgorithmTokenSet.keys()) { + if (cryptoHashes.includes(algorithm) === false) { + validSRIHashAlgorithmTokenSet.delete(algorithm); + } + } + } else { + validSRIHashAlgorithmTokenSet.clear(); + } + var getSRIHashAlgorithmIndex = ( + /** @type {GetSRIHashAlgorithmIndex} */ + Map.prototype.get.bind( + validSRIHashAlgorithmTokenSet + ) + ); + var isValidSRIHashAlgorithm = ( + /** @type {IsValidSRIHashAlgorithm} */ + Map.prototype.has.bind(validSRIHashAlgorithmTokenSet) + ); + var bytesMatch = runtimeFeatures.has("crypto") === false || validSRIHashAlgorithmTokenSet.size === 0 ? () => true : (bytes, metadataList) => { + const parsedMetadata = parseMetadata(metadataList); + if (parsedMetadata.length === 0) { + return true; + } + const metadata = getStrongestMetadata(parsedMetadata); + for (const item of metadata) { + const algorithm = item.alg; + const expectedValue = item.val; + const actualValue = applyAlgorithmToBytes(algorithm, bytes); + if (caseSensitiveMatch(actualValue, expectedValue)) { + return true; + } + } + return false; + }; + function getStrongestMetadata(metadataList) { + const result3 = []; + let strongest = null; + for (const item of metadataList) { + assert(isValidSRIHashAlgorithm(item.alg), "Invalid SRI hash algorithm token"); + if (result3.length === 0) { + result3.push(item); + strongest = item; + continue; + } + const currentAlgorithm = ( + /** @type {Metadata} */ + strongest.alg + ); + const currentAlgorithmIndex = getSRIHashAlgorithmIndex(currentAlgorithm); + const newAlgorithm = item.alg; + const newAlgorithmIndex = getSRIHashAlgorithmIndex(newAlgorithm); + if (newAlgorithmIndex < currentAlgorithmIndex) { + continue; + } else if (newAlgorithmIndex > currentAlgorithmIndex) { + strongest = item; + result3[0] = item; + result3.length = 1; + } else { + result3.push(item); + } + } + return result3; + } + function parseMetadata(metadata) { + const result3 = []; + for (const item of metadata.split(" ")) { + const expressionAndOptions = item.split("?", 1); + const algorithmExpression = expressionAndOptions[0]; + let base64Value = ""; + const algorithmAndValue = [algorithmExpression.slice(0, 6), algorithmExpression.slice(7)]; + const algorithm = algorithmAndValue[0]; + if (!isValidSRIHashAlgorithm(algorithm)) { + continue; + } + if (algorithmAndValue[1]) { + base64Value = algorithmAndValue[1]; + } + const metadata2 = { + alg: algorithm, + val: base64Value + }; + result3.push(metadata2); + } + return result3; + } + var applyAlgorithmToBytes = (algorithm, bytes) => { + return crypto3.hash(algorithm, bytes, "base64"); + }; + function caseSensitiveMatch(actualValue, expectedValue) { + let actualValueLength = actualValue.length; + if (actualValueLength !== 0 && actualValue[actualValueLength - 1] === "=") { + actualValueLength -= 1; + } + if (actualValueLength !== 0 && actualValue[actualValueLength - 1] === "=") { + actualValueLength -= 1; + } + let expectedValueLength = expectedValue.length; + if (expectedValueLength !== 0 && expectedValue[expectedValueLength - 1] === "=") { + expectedValueLength -= 1; + } + if (expectedValueLength !== 0 && expectedValue[expectedValueLength - 1] === "=") { + expectedValueLength -= 1; + } + if (actualValueLength !== expectedValueLength) { + return false; + } + for (let i = 0; i < actualValueLength; ++i) { + if (actualValue[i] === expectedValue[i] || actualValue[i] === "+" && expectedValue[i] === "-" || actualValue[i] === "/" && expectedValue[i] === "_") { + continue; + } + return false; + } + return true; + } + module2.exports = { + applyAlgorithmToBytes, + bytesMatch, + caseSensitiveMatch, + isValidSRIHashAlgorithm, + getStrongestMetadata, + parseMetadata + }; + } +}); + +// node_modules/undici/lib/web/fetch/index.js +var require_fetch = __commonJS({ + "node_modules/undici/lib/web/fetch/index.js"(exports2, module2) { + "use strict"; + var { + makeNetworkError, + makeAppropriateNetworkError, + filterResponse, + makeResponse, + fromInnerResponse, + getResponseState + } = require_response(); + var { HeadersList } = require_headers(); + var { Request: Request3, cloneRequest, getRequestDispatcher, getRequestState, removeRequestAbortListener } = require_request2(); + var zlib = require("node:zlib"); + var { + makePolicyContainer, + clonePolicyContainer, + requestBadPort, + TAOCheck, + appendRequestOriginHeader, + responseLocationURL, + requestCurrentURL, + setRequestReferrerPolicyOnRedirect, + tryUpgradeRequestToAPotentiallyTrustworthyURL, + createOpaqueTimingInfo, + appendFetchMetadata, + corsCheck, + crossOriginResourcePolicyCheck, + determineRequestsReferrer, + coarsenedSharedCurrentTime, + sameOrigin, + isCancelled, + isAborted, + isErrorLike, + fullyReadBody, + readableStreamClose, + urlIsLocal, + urlIsHttpHttpsScheme, + urlHasHttpsScheme, + clampAndCoarsenConnectionTimingInfo, + simpleRangeHeaderValue, + buildContentRange, + createInflate, + extractMimeType, + hasAuthenticationEntry, + includesCredentials, + isTraversableNavigable + } = require_util2(); + var assert = require("node:assert"); + var { safelyExtractBody, extractBody } = require_body(); + var { + redirectStatusSet, + nullBodyStatus, + safeMethodsSet, + requestBodyHeader, + subresourceSet + } = require_constants4(); + var EE = require("node:events"); + var { Readable: Readable2, pipeline, finished, isErrored, isReadable } = require("node:stream"); + var { addAbortListener, bufferToLowerCasedHeaderName } = require_util(); + var { dataURLProcessor, serializeAMimeType, minimizeSupportedMimeType } = require_data_url(); + var { getGlobalDispatcher } = require_global2(); + var { webidl } = require_webidl(); + var { STATUS_CODES } = require("node:http"); + var { bytesMatch } = require_subresource_integrity(); + var { isomorphicEncode } = require_infra(); + var GET_OR_HEAD = ["GET", "HEAD"]; + var defaultUserAgent = typeof __UNDICI_IS_NODE__ !== "undefined" || typeof esbuildDetection !== "undefined" ? "node" : "undici"; + var resolveObjectURL; + function appendHeadersListFromResponseHeaders(headersList, headers2, rawHeaders) { + if (Array.isArray(rawHeaders)) { + for (let i = 0; i < rawHeaders.length; i += 2) { + const nameStr = bufferToLowerCasedHeaderName(rawHeaders[i]); + const value2 = rawHeaders[i + 1]; + if (Array.isArray(value2) && !Buffer.isBuffer(value2)) { + for (const val of value2) { + headersList.append(nameStr, val.toString("latin1"), true); + } + } else { + headersList.append(nameStr, value2.toString("latin1"), true); + } + } + return; + } + for (const [name2, value2] of Object.entries(headers2 ?? {})) { + if (Array.isArray(value2)) { + for (const entry of value2) { + headersList.append(name2, `${entry}`, true); + } + } else { + headersList.append(name2, `${value2}`, true); + } + } + } + var Fetch2 = class extends EE { + constructor(dispatcher) { + super(); + this.dispatcher = dispatcher; + this.connection = null; + this.dump = false; + this.state = "ongoing"; + } + terminate(reason2) { + if (this.state !== "ongoing") { + return; + } + this.state = "terminated"; + this.connection?.destroy(reason2); + this.emit("terminated", reason2); + } + // https://fetch.spec.whatwg.org/#fetch-controller-abort + abort(error2) { + if (this.state !== "ongoing") { + return; + } + this.state = "aborted"; + if (!error2) { + error2 = new DOMException("The operation was aborted.", "AbortError"); + } + this.serializedAbortReason = error2; + this.connection?.destroy(error2); + this.emit("terminated", error2); + } + }; + function handleFetchDone(response) { + finalizeAndReportTiming(response, "fetch"); + } + function fetch2(input, init = void 0) { + webidl.argumentLengthCheck(arguments, 1, "globalThis.fetch"); + let p = Promise.withResolvers(); + let requestObject; + try { + requestObject = new Request3(input, init); + } catch (e) { + p.reject(e); + return p.promise; + } + const request = getRequestState(requestObject); + if (requestObject.signal.aborted) { + abortFetch(p, request, null, requestObject.signal.reason, null); + return p.promise; + } + const globalObject2 = request.client.globalObject; + if (globalObject2?.constructor?.name === "ServiceWorkerGlobalScope") { + request.serviceWorkers = "none"; + } + let responseObject = null; + let locallyAborted = false; + let controller = null; + const removeAbortListener = addAbortListener( + requestObject.signal, + () => { + locallyAborted = true; + assert(controller != null); + controller.abort(requestObject.signal.reason); + const realResponse = responseObject?.deref(); + abortFetch(p, request, realResponse, requestObject.signal.reason, controller.controller); + } + ); + const cleanupAbortListeners = () => { + removeAbortListener(); + removeRequestAbortListener(requestObject); + }; + const processResponse = (response) => { + if (locallyAborted) { + return; + } + if (response.aborted) { + abortFetch(p, request, responseObject, controller.serializedAbortReason, controller.controller); + cleanupAbortListeners(); + return; + } + if (response.type === "error") { + p.reject(new TypeError("fetch failed", { cause: response.error })); + cleanupAbortListeners(); + return; + } + responseObject = new WeakRef(fromInnerResponse(response, "immutable")); + p.resolve(responseObject.deref()); + p = null; + }; + controller = fetching({ + request, + processResponseEndOfBody: (response) => { + handleFetchDone(response); + cleanupAbortListeners(); + }, + processResponse, + dispatcher: getRequestDispatcher(requestObject), + // undici + // Keep requestObject alive to prevent its AbortController from being GC'd + // See https://github.com/nodejs/undici/issues/4627 + requestObject + }); + return p.promise; + } + function finalizeAndReportTiming(response, initiatorType = "other") { + if (response.type === "error" && response.aborted) { + return; + } + if (!response.urlList?.length) { + return; + } + const originalURL = response.urlList[0]; + let timingInfo = response.timingInfo; + let cacheState = response.cacheState; + if (!urlIsHttpHttpsScheme(originalURL)) { + return; + } + if (timingInfo === null) { + return; + } + if (!response.timingAllowPassed) { + timingInfo = createOpaqueTimingInfo({ + startTime: timingInfo.startTime + }); + cacheState = ""; + } + timingInfo.endTime = coarsenedSharedCurrentTime(); + response.timingInfo = timingInfo; + markResourceTiming( + timingInfo, + originalURL.href, + initiatorType, + globalThis, + cacheState, + "", + // bodyType + response.status + ); + } + var markResourceTiming = performance.markResourceTiming; + function abortFetch(p, request, responseObject, error2, controller) { + if (p) { + p.reject(error2); + } + if (request.body?.stream != null && isReadable(request.body.stream)) { + request.body.stream.cancel(error2).catch((err) => { + if (err.code === "ERR_INVALID_STATE") { + return; + } + throw err; + }); + } + if (responseObject == null) { + return; + } + const response = getResponseState(responseObject); + if (response.body?.stream != null && isReadable(response.body.stream)) { + controller.error(error2); + } + } + function fetching({ + request, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseEndOfBody, + processResponseConsumeBody, + useParallelQueue = false, + dispatcher = getGlobalDispatcher(), + // undici + requestObject = null + // Keep alive to prevent AbortController GC, see #4627 + }) { + assert(dispatcher); + let taskDestination = null; + let crossOriginIsolatedCapability = false; + if (request.client != null) { + taskDestination = request.client.globalObject; + crossOriginIsolatedCapability = request.client.crossOriginIsolatedCapability; + } + const currentTime2 = coarsenedSharedCurrentTime(crossOriginIsolatedCapability); + const timingInfo = createOpaqueTimingInfo({ + startTime: currentTime2 + }); + const fetchParams = { + controller: new Fetch2(dispatcher), + request, + timingInfo, + processRequestBodyChunkLength, + processRequestEndOfBody, + processResponse, + processResponseConsumeBody, + processResponseEndOfBody, + taskDestination, + crossOriginIsolatedCapability, + // Keep requestObject alive to prevent its AbortController from being GC'd + requestObject + }; + assert(!request.body || request.body.stream); + if (request.window === "client") { + request.window = request.client?.globalObject?.constructor?.name === "Window" ? request.client : "no-window"; + } + if (request.origin === "client") { + request.origin = request.client.origin; + } + if (request.policyContainer === "client") { + if (request.client != null) { + request.policyContainer = clonePolicyContainer( + request.client.policyContainer + ); + } else { + request.policyContainer = makePolicyContainer(); + } + } + if (!request.headersList.contains("accept", true)) { + const value2 = "*/*"; + request.headersList.append("accept", value2, true); + } + if (!request.headersList.contains("accept-language", true)) { + request.headersList.append("accept-language", "*", true); + } + if (request.priority === null) { + } + if (subresourceSet.has(request.destination)) { + } + mainFetch(fetchParams, false); + return fetchParams.controller; + } + async function mainFetch(fetchParams, recursive) { + try { + const request = fetchParams.request; + let response = null; + if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) { + response = makeNetworkError("local URLs only"); + } + tryUpgradeRequestToAPotentiallyTrustworthyURL(request); + if (requestBadPort(request) === "blocked") { + response = makeNetworkError("bad port"); + } + if (request.referrerPolicy === "") { + request.referrerPolicy = request.policyContainer.referrerPolicy; + } + if (request.referrer !== "no-referrer") { + request.referrer = determineRequestsReferrer(request); + } + if (response === null) { + const currentURL = requestCurrentURL(request); + if ( + // - request’s current URL’s origin is same origin with request’s origin, + // and request’s response tainting is "basic" + sameOrigin(currentURL, request.url) && request.responseTainting === "basic" || // request’s current URL’s scheme is "data" + currentURL.protocol === "data:" || // - request’s mode is "navigate" or "websocket" + (request.mode === "navigate" || request.mode === "websocket") + ) { + request.responseTainting = "basic"; + response = await schemeFetch(fetchParams); + } else if (request.mode === "same-origin") { + response = makeNetworkError('request mode cannot be "same-origin"'); + } else if (request.mode === "no-cors") { + if (request.redirect !== "follow") { + response = makeNetworkError( + 'redirect mode cannot be "follow" for "no-cors" request' + ); + } else { + request.responseTainting = "opaque"; + response = await schemeFetch(fetchParams); + } + } else if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) { + response = makeNetworkError("URL scheme must be a HTTP(S) scheme"); + } else { + request.responseTainting = "cors"; + response = await httpFetch(fetchParams); + } + } + if (recursive) { + return response; + } + if (response.status !== 0 && !response.internalResponse) { + if (request.responseTainting === "cors") { + } + if (request.responseTainting === "basic") { + response = filterResponse(response, "basic"); + } else if (request.responseTainting === "cors") { + response = filterResponse(response, "cors"); + } else if (request.responseTainting === "opaque") { + response = filterResponse(response, "opaque"); + } else { + assert(false); + } + } + let internalResponse = response.status === 0 ? response : response.internalResponse; + if (internalResponse.urlList.length === 0) { + internalResponse.urlList.push(...request.urlList); + } + if (!request.timingAllowFailed) { + response.timingAllowPassed = true; + } + if (response.type === "opaque" && internalResponse.status === 206 && internalResponse.rangeRequested && !request.headers.contains("range", true)) { + response = internalResponse = makeNetworkError(); + } + if (response.status !== 0 && (request.method === "HEAD" || request.method === "CONNECT" || nullBodyStatus.includes(internalResponse.status))) { + internalResponse.body = null; + fetchParams.controller.dump = true; + } + if (request.integrity) { + const processBodyError = (reason2) => fetchFinale(fetchParams, makeNetworkError(reason2)); + if (request.responseTainting === "opaque" || response.body == null) { + processBodyError(response.error); + return; + } + const processBody = (bytes) => { + if (!bytesMatch(bytes, request.integrity)) { + processBodyError("integrity mismatch"); + return; + } + response.body = safelyExtractBody(bytes)[0]; + fetchFinale(fetchParams, response); + }; + fullyReadBody(response.body, processBody, processBodyError); + } else { + fetchFinale(fetchParams, response); + } + } catch (err) { + fetchParams.controller.terminate(err); + } + } + function schemeFetch(fetchParams) { + if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) { + return Promise.resolve(makeAppropriateNetworkError(fetchParams)); + } + const { request } = fetchParams; + const { protocol: scheme } = requestCurrentURL(request); + switch (scheme) { + case "about:": { + return Promise.resolve(makeNetworkError("about scheme is not supported")); + } + case "blob:": { + if (!resolveObjectURL) { + resolveObjectURL = require("node:buffer").resolveObjectURL; + } + const blobURLEntry = requestCurrentURL(request); + if (blobURLEntry.search.length !== 0) { + return Promise.resolve(makeNetworkError("NetworkError when attempting to fetch resource.")); + } + const blob = resolveObjectURL(blobURLEntry.toString()); + if (request.method !== "GET" || !webidl.is.Blob(blob)) { + return Promise.resolve(makeNetworkError("invalid method")); + } + const response = makeResponse(); + const fullLength = blob.size; + const serializedFullLength = isomorphicEncode(`${fullLength}`); + const type2 = blob.type; + if (!request.headersList.contains("range", true)) { + const bodyWithType = extractBody(blob); + response.statusText = "OK"; + response.body = bodyWithType[0]; + response.headersList.set("content-length", serializedFullLength, true); + response.headersList.set("content-type", type2, true); + } else { + response.rangeRequested = true; + const rangeHeader = request.headersList.get("range", true); + const rangeValue = simpleRangeHeaderValue(rangeHeader, true); + if (rangeValue === "failure") { + return Promise.resolve(makeNetworkError("failed to fetch the data URL")); + } + let { rangeStartValue: rangeStart, rangeEndValue: rangeEnd } = rangeValue; + if (rangeStart === null) { + rangeStart = fullLength - rangeEnd; + rangeEnd = rangeStart + rangeEnd - 1; + } else { + if (rangeStart >= fullLength) { + return Promise.resolve(makeNetworkError("Range start is greater than the blob's size.")); + } + if (rangeEnd === null || rangeEnd >= fullLength) { + rangeEnd = fullLength - 1; + } + } + const slicedBlob = blob.slice(rangeStart, rangeEnd + 1, type2); + const slicedBodyWithType = extractBody(slicedBlob); + response.body = slicedBodyWithType[0]; + const serializedSlicedLength = isomorphicEncode(`${slicedBlob.size}`); + const contentRange = buildContentRange(rangeStart, rangeEnd, fullLength); + response.status = 206; + response.statusText = "Partial Content"; + response.headersList.set("content-length", serializedSlicedLength, true); + response.headersList.set("content-type", type2, true); + response.headersList.set("content-range", contentRange, true); + } + return Promise.resolve(response); + } + case "data:": { + const currentURL = requestCurrentURL(request); + const dataURLStruct = dataURLProcessor(currentURL); + if (dataURLStruct === "failure") { + return Promise.resolve(makeNetworkError("failed to fetch the data URL")); + } + const mimeType = serializeAMimeType(dataURLStruct.mimeType); + return Promise.resolve(makeResponse({ + statusText: "OK", + headersList: [ + ["content-type", { name: "Content-Type", value: mimeType }] + ], + body: safelyExtractBody(dataURLStruct.body)[0] + })); + } + case "file:": { + return Promise.resolve(makeNetworkError("not implemented... yet...")); + } + case "http:": + case "https:": { + return httpFetch(fetchParams).catch((err) => makeNetworkError(err)); + } + default: { + return Promise.resolve(makeNetworkError("unknown scheme")); + } + } + } + function finalizeResponse(fetchParams, response) { + fetchParams.request.done = true; + if (fetchParams.processResponseDone != null) { + queueMicrotask(() => fetchParams.processResponseDone(response)); + } + } + function fetchFinale(fetchParams, response) { + let timingInfo = fetchParams.timingInfo; + const processResponseEndOfBody = () => { + const unsafeEndTime = Date.now(); + if (fetchParams.request.destination === "document") { + fetchParams.controller.fullTimingInfo = timingInfo; + } + fetchParams.controller.reportTimingSteps = () => { + if (!urlIsHttpHttpsScheme(fetchParams.request.url)) { + return; + } + timingInfo.endTime = unsafeEndTime; + let cacheState = response.cacheState; + const bodyInfo = response.bodyInfo; + if (!response.timingAllowPassed) { + timingInfo = createOpaqueTimingInfo(timingInfo); + cacheState = ""; + } + let responseStatus = 0; + if (fetchParams.request.mode !== "navigate" || !response.hasCrossOriginRedirects) { + responseStatus = response.status; + const mimeType = extractMimeType(response.headersList); + if (mimeType !== "failure") { + bodyInfo.contentType = minimizeSupportedMimeType(mimeType); + } + } + if (fetchParams.request.initiatorType != null) { + markResourceTiming(timingInfo, fetchParams.request.url.href, fetchParams.request.initiatorType, globalThis, cacheState, bodyInfo, responseStatus); + } + }; + const processResponseEndOfBodyTask = () => { + fetchParams.request.done = true; + if (fetchParams.processResponseEndOfBody != null) { + queueMicrotask(() => fetchParams.processResponseEndOfBody(response)); + } + if (fetchParams.request.initiatorType != null) { + fetchParams.controller.reportTimingSteps(); + } + }; + queueMicrotask(() => processResponseEndOfBodyTask()); + }; + if (fetchParams.processResponse != null) { + queueMicrotask(() => { + fetchParams.processResponse(response); + fetchParams.processResponse = null; + }); + } + const internalResponse = response.type === "error" ? response : response.internalResponse ?? response; + if (internalResponse.body == null) { + processResponseEndOfBody(); + } else { + finished(internalResponse.body.stream, () => { + processResponseEndOfBody(); + }); + } + } + async function httpFetch(fetchParams) { + const request = fetchParams.request; + let response = null; + let actualResponse = null; + const timingInfo = fetchParams.timingInfo; + if (request.serviceWorkers === "all") { + } + if (response === null) { + if (request.redirect === "follow") { + request.serviceWorkers = "none"; + } + actualResponse = response = await httpNetworkOrCacheFetch(fetchParams); + if (request.responseTainting === "cors" && corsCheck(request, response) === "failure") { + return makeNetworkError("cors failure"); + } + if (TAOCheck(request, response) === "failure") { + request.timingAllowFailed = true; + } + } + if ((request.responseTainting === "opaque" || response.type === "opaque") && crossOriginResourcePolicyCheck( + request.origin, + request.client, + request.destination, + actualResponse + ) === "blocked") { + return makeNetworkError("blocked"); + } + if (redirectStatusSet.has(actualResponse.status)) { + if (request.redirect !== "manual") { + fetchParams.controller.connection.destroy(void 0, false); + } + if (request.redirect === "error") { + response = makeNetworkError("unexpected redirect"); + } else if (request.redirect === "manual") { + response = actualResponse; + } else if (request.redirect === "follow") { + response = await httpRedirectFetch(fetchParams, response); + } else { + assert(false); + } + } + response.timingInfo = timingInfo; + return response; + } + function httpRedirectFetch(fetchParams, response) { + const request = fetchParams.request; + const actualResponse = response.internalResponse ? response.internalResponse : response; + let locationURL; + try { + locationURL = responseLocationURL( + actualResponse, + requestCurrentURL(request).hash + ); + if (locationURL == null) { + return response; + } + } catch (err) { + return Promise.resolve(makeNetworkError(err)); + } + if (!urlIsHttpHttpsScheme(locationURL)) { + return Promise.resolve(makeNetworkError("URL scheme must be a HTTP(S) scheme")); + } + if (request.redirectCount === 20) { + return Promise.resolve(makeNetworkError("redirect count exceeded")); + } + request.redirectCount += 1; + if (request.mode === "cors" && (locationURL.username || locationURL.password) && !sameOrigin(request, locationURL)) { + return Promise.resolve(makeNetworkError('cross origin not allowed for request mode "cors"')); + } + if (request.responseTainting === "cors" && (locationURL.username || locationURL.password)) { + return Promise.resolve(makeNetworkError( + 'URL cannot contain credentials for request mode "cors"' + )); + } + if (actualResponse.status !== 303 && request.body != null && request.body.source == null) { + return Promise.resolve(makeNetworkError()); + } + if ([301, 302].includes(actualResponse.status) && request.method === "POST" || actualResponse.status === 303 && !GET_OR_HEAD.includes(request.method)) { + request.method = "GET"; + request.body = null; + for (const headerName of requestBodyHeader) { + request.headersList.delete(headerName); + } + } + if (!sameOrigin(requestCurrentURL(request), locationURL)) { + request.headersList.delete("authorization", true); + request.headersList.delete("proxy-authorization", true); + request.headersList.delete("cookie", true); + request.headersList.delete("host", true); + } + if (request.body != null) { + assert(request.body.source != null); + request.body = safelyExtractBody(request.body.source)[0]; + } + const timingInfo = fetchParams.timingInfo; + timingInfo.redirectEndTime = timingInfo.postRedirectStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability); + if (timingInfo.redirectStartTime === 0) { + timingInfo.redirectStartTime = timingInfo.startTime; + } + request.urlList.push(locationURL); + setRequestReferrerPolicyOnRedirect(request, actualResponse); + return mainFetch(fetchParams, true); + } + async function httpNetworkOrCacheFetch(fetchParams, isAuthenticationFetch = false, isNewConnectionFetch = false) { + const request = fetchParams.request; + let httpFetchParams = null; + let httpRequest = null; + let response = null; + const httpCache = null; + const revalidatingFlag = false; + if (request.window === "no-window" && request.redirect === "error") { + httpFetchParams = fetchParams; + httpRequest = request; + } else { + if (request.body?.source != null) { + httpRequest = cloneRequest(request); + } else { + httpRequest = cloneRequest({ ...request, body: null }); + httpRequest.body = request.body; + } + httpFetchParams = { ...fetchParams }; + httpFetchParams.request = httpRequest; + } + const includeCredentials = request.credentials === "include" || request.credentials === "same-origin" && request.responseTainting === "basic"; + const contentLength2 = httpRequest.body ? httpRequest.body.length : null; + let contentLengthHeaderValue = null; + if (httpRequest.body == null && ["POST", "PUT"].includes(httpRequest.method)) { + contentLengthHeaderValue = "0"; + } + if (contentLength2 != null) { + contentLengthHeaderValue = isomorphicEncode(`${contentLength2}`); + } + if (contentLengthHeaderValue != null && !httpRequest.headersList.contains("content-length", true)) { + httpRequest.headersList.append("content-length", contentLengthHeaderValue, true); + } + if (contentLength2 != null && httpRequest.keepalive) { + } + if (webidl.is.URL(httpRequest.referrer)) { + httpRequest.headersList.append("referer", isomorphicEncode(httpRequest.referrer.href), true); + } + appendRequestOriginHeader(httpRequest); + appendFetchMetadata(httpRequest); + if (!httpRequest.headersList.contains("user-agent", true)) { + httpRequest.headersList.append("user-agent", defaultUserAgent, true); + } + if (httpRequest.cache === "default" && (httpRequest.headersList.contains("if-modified-since", true) || httpRequest.headersList.contains("if-none-match", true) || httpRequest.headersList.contains("if-unmodified-since", true) || httpRequest.headersList.contains("if-match", true) || httpRequest.headersList.contains("if-range", true))) { + httpRequest.cache = "no-store"; + } + if (httpRequest.cache === "no-cache" && !httpRequest.preventNoCacheCacheControlHeaderModification && !httpRequest.headersList.contains("cache-control", true)) { + httpRequest.headersList.append("cache-control", "max-age=0", true); + } + if (httpRequest.cache === "no-store" || httpRequest.cache === "reload") { + if (!httpRequest.headersList.contains("pragma", true)) { + httpRequest.headersList.append("pragma", "no-cache", true); + } + if (!httpRequest.headersList.contains("cache-control", true)) { + httpRequest.headersList.append("cache-control", "no-cache", true); + } + } + if (httpRequest.headersList.contains("range", true)) { + httpRequest.headersList.append("accept-encoding", "identity", true); + } + if (!httpRequest.headersList.contains("accept-encoding", true)) { + if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) { + httpRequest.headersList.append("accept-encoding", "br, gzip, deflate, zstd", true); + } else { + httpRequest.headersList.append("accept-encoding", "gzip, deflate", true); + } + } + httpRequest.headersList.delete("host", true); + if (includeCredentials) { + if (!httpRequest.headersList.contains("authorization", true)) { + let authorizationValue = null; + if (hasAuthenticationEntry(httpRequest) && (httpRequest.useURLCredentials === void 0 || !includesCredentials(requestCurrentURL(httpRequest)))) { + } else if (includesCredentials(requestCurrentURL(httpRequest)) && isAuthenticationFetch) { + const { username, password } = requestCurrentURL(httpRequest); + authorizationValue = `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`; + } + if (authorizationValue !== null) { + httpRequest.headersList.append("Authorization", authorizationValue, false); + } + } + } + if (httpCache == null) { + httpRequest.cache = "no-store"; + } + if (httpRequest.cache !== "no-store" && httpRequest.cache !== "reload") { + } + if (response == null) { + if (httpRequest.cache === "only-if-cached") { + return makeNetworkError("only if cached"); + } + const forwardResponse = await httpNetworkFetch( + httpFetchParams, + includeCredentials, + isNewConnectionFetch + ); + if (!safeMethodsSet.has(httpRequest.method) && forwardResponse.status >= 200 && forwardResponse.status <= 399) { + } + if (revalidatingFlag && forwardResponse.status === 304) { + } + if (response == null) { + response = forwardResponse; + } + } + response.urlList = [...httpRequest.urlList]; + if (httpRequest.headersList.contains("range", true)) { + response.rangeRequested = true; + } + response.requestIncludesCredentials = includeCredentials; + if (response.status === 401 && httpRequest.responseTainting !== "cors" && includeCredentials && (request.useURLCredentials !== void 0 || isTraversableNavigable(request.traversableForUserPrompts))) { + if (request.body != null) { + if (request.body.source == null) { + return response; + } + request.body = safelyExtractBody(request.body.source)[0]; + } + if (request.useURLCredentials === void 0 || isAuthenticationFetch) { + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams); + } + return response; + } + fetchParams.controller.connection.destroy(); + response = await httpNetworkOrCacheFetch(fetchParams, true); + } + if (response.status === 407) { + if (request.window === "no-window") { + return makeNetworkError(); + } + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams); + } + return makeNetworkError("proxy authentication required"); + } + if ( + // response’s status is 421 + response.status === 421 && // isNewConnectionFetch is false + !isNewConnectionFetch && // request’s body is null, or request’s body is non-null and request’s body’s source is non-null + (request.body == null || request.body.source != null) + ) { + if (isCancelled(fetchParams)) { + return makeAppropriateNetworkError(fetchParams); + } + fetchParams.controller.connection.destroy(); + response = await httpNetworkOrCacheFetch( + fetchParams, + isAuthenticationFetch, + true + ); + } + if (isAuthenticationFetch) { + } + return response; + } + async function httpNetworkFetch(fetchParams, includeCredentials = false, forceNewConnection = false) { + assert(!fetchParams.controller.connection || fetchParams.controller.connection.destroyed); + fetchParams.controller.connection = { + abort: null, + destroyed: false, + destroy(err, abort2 = true) { + if (!this.destroyed) { + this.destroyed = true; + if (abort2) { + this.abort?.(err ?? new DOMException("The operation was aborted.", "AbortError")); + } + } + } + }; + const request = fetchParams.request; + let response = null; + const timingInfo = fetchParams.timingInfo; + const httpCache = null; + if (httpCache == null) { + request.cache = "no-store"; + } + const newConnection = forceNewConnection ? "yes" : "no"; + if (request.mode === "websocket") { + } else { + } + let requestBody = null; + if (request.body == null && fetchParams.processRequestEndOfBody) { + queueMicrotask(() => fetchParams.processRequestEndOfBody()); + } else if (request.body != null) { + const processBodyChunk = async function* (bytes) { + if (isCancelled(fetchParams)) { + return; + } + yield bytes; + fetchParams.processRequestBodyChunkLength?.(bytes.byteLength); + }; + const processEndOfBody = () => { + if (isCancelled(fetchParams)) { + return; + } + if (fetchParams.processRequestEndOfBody) { + fetchParams.processRequestEndOfBody(); + } + }; + const processBodyError = (e) => { + if (isCancelled(fetchParams)) { + return; + } + if (e.name === "AbortError") { + fetchParams.controller.abort(); + } else { + fetchParams.controller.terminate(e); + } + }; + requestBody = (async function* () { + try { + for await (const bytes of request.body.stream) { + yield* processBodyChunk(bytes); + } + processEndOfBody(); + } catch (err) { + processBodyError(err); + } + })(); + } + try { + const { body: body2, status, statusText, headersList, socket } = await dispatch2({ body: requestBody }); + if (socket) { + response = makeResponse({ status, statusText, headersList, socket }); + } else { + const iterator = body2[Symbol.asyncIterator](); + fetchParams.controller.next = () => iterator.next(); + response = makeResponse({ status, statusText, headersList }); + } + } catch (err) { + if (err.name === "AbortError") { + fetchParams.controller.connection.destroy(); + return makeAppropriateNetworkError(fetchParams, err); + } + return makeNetworkError(err); + } + const pullAlgorithm = () => { + return fetchParams.controller.resume(); + }; + const cancelAlgorithm = (reason2) => { + if (!isCancelled(fetchParams)) { + fetchParams.controller.abort(reason2); + } + }; + const stream = new ReadableStream( + { + start(controller) { + fetchParams.controller.controller = controller; + }, + pull: pullAlgorithm, + cancel: cancelAlgorithm, + type: "bytes" + } + ); + response.body = { stream, source: null, length: null }; + if (!fetchParams.controller.resume) { + fetchParams.controller.on("terminated", onAborted); + } + fetchParams.controller.resume = async () => { + while (true) { + let bytes; + let isFailure; + try { + const { done, value: value2 } = await fetchParams.controller.next(); + if (isAborted(fetchParams)) { + break; + } + bytes = done ? void 0 : value2; + } catch (err) { + if (fetchParams.controller.ended && !timingInfo.encodedBodySize) { + bytes = void 0; + } else { + bytes = err; + isFailure = true; + } + } + if (bytes === void 0) { + readableStreamClose(fetchParams.controller.controller); + finalizeResponse(fetchParams, response); + return; + } + timingInfo.decodedBodySize += bytes?.byteLength ?? 0; + if (isFailure) { + fetchParams.controller.terminate(bytes); + return; + } + const buffer2 = new Uint8Array(bytes); + if (buffer2.byteLength) { + fetchParams.controller.controller.enqueue(buffer2); + } + if (isErrored(stream)) { + fetchParams.controller.terminate(); + return; + } + if (fetchParams.controller.controller.desiredSize <= 0) { + return; + } + } + }; + function onAborted(reason2) { + if (isAborted(fetchParams)) { + response.aborted = true; + if (isReadable(stream)) { + fetchParams.controller.controller.error( + fetchParams.controller.serializedAbortReason + ); + } + } else { + if (isReadable(stream)) { + fetchParams.controller.controller.error(new TypeError("terminated", { + cause: isErrorLike(reason2) ? reason2 : void 0 + })); + } + } + fetchParams.controller.connection.destroy(); + } + return response; + function dispatch2({ body: body2 }) { + const url2 = requestCurrentURL(request); + const agent = fetchParams.controller.dispatcher; + const path2 = url2.pathname + url2.search; + const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?"; + return dispatchWithProtocolPreference(body2); + function dispatchWithProtocolPreference(body3, allowH2) { + return new Promise((resolve, reject) => agent.dispatch( + { + path: hasTrailingQuestionMark ? `${path2}?` : path2, + origin: url2.origin, + method: request.method, + body: agent.isMockActive ? request.body && (request.body.source || request.body.stream) : body3, + // Preserve the serialized fetch body for MockAgent net-connect fallthroughs. + __mockAgentBodyForDispatch: body3, + headers: request.headersList.entries, + maxRedirections: 0, + upgrade: request.mode === "websocket" ? "websocket" : void 0, + ...allowH2 === false ? { allowH2 } : null + }, + { + body: null, + abort: null, + onRequestStart(controller) { + const { connection } = fetchParams.controller; + timingInfo.finalConnectionTimingInfo = clampAndCoarsenConnectionTimingInfo(void 0, timingInfo.postRedirectStartTime, fetchParams.crossOriginIsolatedCapability); + const abort2 = (reason2) => controller.abort(reason2); + if (connection.destroyed) { + abort2(new DOMException("The operation was aborted.", "AbortError")); + } else { + fetchParams.controller.on("terminated", abort2); + this.abort = connection.abort = abort2; + } + timingInfo.finalNetworkRequestStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability); + }, + onResponseStarted() { + timingInfo.finalNetworkResponseStartTime = coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability); + }, + onResponseStart(controller, status, headers2, statusText) { + if (status < 200) { + return; + } + const rawHeaders = controller?.rawHeaders ?? []; + const headersList = new HeadersList(); + appendHeadersListFromResponseHeaders(headersList, headers2, rawHeaders); + const location2 = headersList.get("location", true); + this.body = new Readable2({ read: () => controller.resume() }); + const willFollow = location2 && request.redirect === "follow" && redirectStatusSet.has(status); + const decoders = []; + if (request.method !== "HEAD" && request.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) { + const contentEncoding = headersList.get("content-encoding", true); + const codings = contentEncoding ? contentEncoding.toLowerCase().split(",") : []; + const maxContentEncodings = 5; + if (codings.length > maxContentEncodings) { + reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); + return; + } + for (let i = codings.length - 1; i >= 0; --i) { + const coding = codings[i].trim(); + if (coding === "x-gzip" || coding === "gzip") { + decoders.push(zlib.createGunzip({ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH + })); + } else if (coding === "deflate") { + decoders.push(createInflate({ + flush: zlib.constants.Z_SYNC_FLUSH, + finishFlush: zlib.constants.Z_SYNC_FLUSH + })); + } else if (coding === "br") { + decoders.push(zlib.createBrotliDecompress({ + flush: zlib.constants.BROTLI_OPERATION_FLUSH, + finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH + })); + } else if (coding === "zstd") { + decoders.push(zlib.createZstdDecompress({ + flush: zlib.constants.ZSTD_e_continue, + finishFlush: zlib.constants.ZSTD_e_end + })); + } else { + decoders.length = 0; + break; + } + } + } + const onError = (err) => this.onResponseError(controller, err); + resolve({ + status, + statusText, + headersList, + body: decoders.length ? pipeline(this.body, ...decoders, (err) => { + if (err) { + this.onResponseError(controller, err); + } + }).on("error", onError) : this.body.on("error", onError) + }); + }, + onResponseData(controller, chunk) { + if (fetchParams.controller.dump) { + return; + } + const bytes = chunk; + timingInfo.encodedBodySize += bytes.byteLength; + if (this.body.push(bytes) === false) { + controller.pause(); + } + }, + onResponseEnd() { + if (this.abort) { + fetchParams.controller.off("terminated", this.abort); + } + fetchParams.controller.ended = true; + this.body?.push(null); + }, + onResponseError(_controller, error2) { + if (this.abort) { + fetchParams.controller.off("terminated", this.abort); + } + if (request.mode === "websocket" && allowH2 !== false && error2?.code === "UND_ERR_INFO" && error2?.message === "HTTP/2: Extended CONNECT protocol not supported by server") { + resolve(dispatchWithProtocolPreference(body3, false)); + return; + } + this.body?.destroy(error2); + fetchParams.controller.terminate(error2); + reject(error2); + }, + onRequestUpgrade(controller, status, headers2, socket) { + if (socket.session != null && status !== 200 || socket.session == null && status !== 101) { + return false; + } + const rawHeaders = controller?.rawHeaders ?? []; + const headersList = new HeadersList(); + appendHeadersListFromResponseHeaders(headersList, headers2, rawHeaders); + resolve({ + status, + statusText: STATUS_CODES[status], + headersList, + socket + }); + return true; + } + } + )); + } + } + } + module2.exports = { + fetch: fetch2, + Fetch: Fetch2, + fetching, + finalizeAndReportTiming + }; + } +}); + +// node_modules/undici/lib/web/cache/util.js +var require_util3 = __commonJS({ + "node_modules/undici/lib/web/cache/util.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { URLSerializer } = require_data_url(); + var { isValidHeaderName } = require_util2(); + function urlEquals(A, B, excludeFragment = false) { + const serializedA = URLSerializer(A, excludeFragment); + const serializedB = URLSerializer(B, excludeFragment); + return serializedA === serializedB; + } + function getFieldValues(header) { + assert(header !== null); + const values2 = []; + for (let value2 of header.split(",")) { + value2 = value2.trim(); + if (isValidHeaderName(value2)) { + values2.push(value2); + } + } + return values2; + } + module2.exports = { + urlEquals, + getFieldValues + }; + } +}); + +// node_modules/undici/lib/web/cache/cache.js +var require_cache3 = __commonJS({ + "node_modules/undici/lib/web/cache/cache.js"(exports2, module2) { + "use strict"; + var assert = require("node:assert"); + var { kConstruct } = require_symbols(); + var { urlEquals, getFieldValues } = require_util3(); + var { kEnumerableProperty, isDisturbed } = require_util(); + var { webidl } = require_webidl(); + var { cloneResponse, fromInnerResponse, getResponseState } = require_response(); + var { Request: Request3, fromInnerRequest, getRequestState } = require_request2(); + var { fetching } = require_fetch(); + var { urlIsHttpHttpsScheme, readAllBytes } = require_util2(); + var Cache = class _Cache { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-request-response-list + * @type {requestResponseList} + */ + #relevantRequestResponseList; + constructor() { + if (arguments[0] !== kConstruct) { + webidl.illegalConstructor(); + } + webidl.util.markAsUncloneable(this); + this.#relevantRequestResponseList = arguments[1]; + } + async match(request, options2 = {}) { + webidl.brandCheck(this, _Cache); + const prefix2 = "Cache.match"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + request = webidl.converters.RequestInfo(request); + options2 = webidl.converters.CacheQueryOptions(options2, prefix2, "options"); + const p = this.#internalMatchAll(request, options2, 1); + if (p.length === 0) { + return; + } + return p[0]; + } + async matchAll(request = void 0, options2 = {}) { + webidl.brandCheck(this, _Cache); + const prefix2 = "Cache.matchAll"; + if (request !== void 0) request = webidl.converters.RequestInfo(request); + options2 = webidl.converters.CacheQueryOptions(options2, prefix2, "options"); + return this.#internalMatchAll(request, options2); + } + async add(request) { + webidl.brandCheck(this, _Cache); + const prefix2 = "Cache.add"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + request = webidl.converters.RequestInfo(request); + const requests = [request]; + const responseArrayPromise = this.addAll(requests); + return await responseArrayPromise; + } + async addAll(requests) { + webidl.brandCheck(this, _Cache); + const prefix2 = "Cache.addAll"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + const responsePromises = []; + const requestList = []; + for (let request of requests) { + if (request === void 0) { + throw webidl.errors.conversionFailed({ + prefix: prefix2, + argument: "Argument 1", + types: ["undefined is not allowed"] + }); + } + request = webidl.converters.RequestInfo(request); + if (typeof request === "string") { + continue; + } + const r2 = getRequestState(request); + if (!urlIsHttpHttpsScheme(r2.url) || r2.method !== "GET") { + throw webidl.errors.exception({ + header: prefix2, + message: "Expected http/s scheme when method is not GET." + }); + } + } + const fetchControllers = []; + for (const request of requests) { + const r2 = getRequestState(new Request3(request)); + if (!urlIsHttpHttpsScheme(r2.url)) { + throw webidl.errors.exception({ + header: prefix2, + message: "Expected http/s scheme." + }); + } + r2.initiator = "fetch"; + r2.destination = "subresource"; + requestList.push(r2); + const responsePromise = Promise.withResolvers(); + fetchControllers.push(fetching({ + request: r2, + processResponse(response) { + if (response.type === "error" || response.status === 206 || response.status < 200 || response.status > 299) { + responsePromise.reject(webidl.errors.exception({ + header: "Cache.addAll", + message: "Received an invalid status code or the request failed." + })); + } else if (response.headersList.contains("vary")) { + const fieldValues = getFieldValues(response.headersList.get("vary")); + for (const fieldValue of fieldValues) { + if (fieldValue === "*") { + responsePromise.reject(webidl.errors.exception({ + header: "Cache.addAll", + message: "invalid vary field value" + })); + for (const controller of fetchControllers) { + controller.abort(); + } + return; + } + } + } + }, + processResponseEndOfBody(response) { + if (response.aborted) { + responsePromise.reject(new DOMException("aborted", "AbortError")); + return; + } + responsePromise.resolve(response); + } + })); + responsePromises.push(responsePromise.promise); + } + const p = Promise.all(responsePromises); + const responses = await p; + const operations = []; + let index = 0; + for (const response of responses) { + const operation = { + type: "put", + // 7.3.2 + request: requestList[index], + // 7.3.3 + response + // 7.3.4 + }; + operations.push(operation); + index++; + } + const cacheJobPromise = Promise.withResolvers(); + let errorData = null; + try { + this.#batchCacheOperations(operations); + } catch (e) { + errorData = e; + } + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(void 0); + } else { + cacheJobPromise.reject(errorData); + } + }); + return cacheJobPromise.promise; + } + async put(request, response) { + webidl.brandCheck(this, _Cache); + const prefix2 = "Cache.put"; + webidl.argumentLengthCheck(arguments, 2, prefix2); + request = webidl.converters.RequestInfo(request); + response = webidl.converters.Response(response, prefix2, "response"); + let innerRequest = null; + if (webidl.is.Request(request)) { + innerRequest = getRequestState(request); + } else { + innerRequest = getRequestState(new Request3(request)); + } + if (!urlIsHttpHttpsScheme(innerRequest.url) || innerRequest.method !== "GET") { + throw webidl.errors.exception({ + header: prefix2, + message: "Expected an http/s scheme when method is not GET" + }); + } + const innerResponse = getResponseState(response); + if (innerResponse.status === 206) { + throw webidl.errors.exception({ + header: prefix2, + message: "Got 206 status" + }); + } + if (innerResponse.headersList.contains("vary")) { + const fieldValues = getFieldValues(innerResponse.headersList.get("vary")); + for (const fieldValue of fieldValues) { + if (fieldValue === "*") { + throw webidl.errors.exception({ + header: prefix2, + message: "Got * vary field value" + }); + } + } + } + if (innerResponse.body && (isDisturbed(innerResponse.body.stream) || innerResponse.body.stream.locked)) { + throw webidl.errors.exception({ + header: prefix2, + message: "Response body is locked or disturbed" + }); + } + const clonedResponse = cloneResponse(innerResponse); + const bodyReadPromise = Promise.withResolvers(); + if (innerResponse.body != null) { + const stream = innerResponse.body.stream; + const reader = stream.getReader(); + readAllBytes(reader, bodyReadPromise.resolve, bodyReadPromise.reject); + } else { + bodyReadPromise.resolve(void 0); + } + const operations = []; + const operation = { + type: "put", + // 14. + request: innerRequest, + // 15. + response: clonedResponse + // 16. + }; + operations.push(operation); + const bytes = await bodyReadPromise.promise; + if (clonedResponse.body != null) { + clonedResponse.body.source = bytes; + } + const cacheJobPromise = Promise.withResolvers(); + let errorData = null; + try { + this.#batchCacheOperations(operations); + } catch (e) { + errorData = e; + } + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(); + } else { + cacheJobPromise.reject(errorData); + } + }); + return cacheJobPromise.promise; + } + async delete(request, options2 = {}) { + webidl.brandCheck(this, _Cache); + const prefix2 = "Cache.delete"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + request = webidl.converters.RequestInfo(request); + options2 = webidl.converters.CacheQueryOptions(options2, prefix2, "options"); + let r2 = null; + if (webidl.is.Request(request)) { + r2 = getRequestState(request); + if (r2.method !== "GET" && !options2.ignoreMethod) { + return false; + } + } else { + assert(typeof request === "string"); + r2 = getRequestState(new Request3(request)); + } + const operations = []; + const operation = { + type: "delete", + request: r2, + options: options2 + }; + operations.push(operation); + const cacheJobPromise = Promise.withResolvers(); + let errorData = null; + let requestResponses; + try { + requestResponses = this.#batchCacheOperations(operations); + } catch (e) { + errorData = e; + } + queueMicrotask(() => { + if (errorData === null) { + cacheJobPromise.resolve(!!requestResponses?.length); + } else { + cacheJobPromise.reject(errorData); + } + }); + return cacheJobPromise.promise; + } + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cache-keys + * @param {any} request + * @param {import('../../../types/cache').CacheQueryOptions} options + * @returns {Promise} + */ + async keys(request = void 0, options2 = {}) { + webidl.brandCheck(this, _Cache); + const prefix2 = "Cache.keys"; + if (request !== void 0) request = webidl.converters.RequestInfo(request); + options2 = webidl.converters.CacheQueryOptions(options2, prefix2, "options"); + let r2 = null; + if (request !== void 0) { + if (webidl.is.Request(request)) { + r2 = getRequestState(request); + if (r2.method !== "GET" && !options2.ignoreMethod) { + return []; + } + } else if (typeof request === "string") { + r2 = getRequestState(new Request3(request)); + } + } + const promise = Promise.withResolvers(); + const requests = []; + if (request === void 0) { + for (const requestResponse of this.#relevantRequestResponseList) { + requests.push(requestResponse[0]); + } + } else { + const requestResponses = this.#queryCache(r2, options2); + for (const requestResponse of requestResponses) { + requests.push(requestResponse[0]); + } + } + queueMicrotask(() => { + const requestList = []; + for (const request2 of requests) { + const requestObject = fromInnerRequest( + request2, + void 0, + new AbortController().signal, + "immutable" + ); + requestList.push(requestObject); + } + promise.resolve(Object.freeze(requestList)); + }); + return promise.promise; + } + /** + * @see https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm + * @param {CacheBatchOperation[]} operations + * @returns {requestResponseList} + */ + #batchCacheOperations(operations) { + const cache2 = this.#relevantRequestResponseList; + const backupCache = [...cache2]; + const addedItems = []; + const resultList = []; + try { + for (const operation of operations) { + if (operation.type !== "delete" && operation.type !== "put") { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: 'operation type does not match "delete" or "put"' + }); + } + if (operation.type === "delete" && operation.response != null) { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: "delete operation should not have an associated response" + }); + } + if (this.#queryCache(operation.request, operation.options, addedItems).length) { + throw new DOMException("???", "InvalidStateError"); + } + let requestResponses; + if (operation.type === "delete") { + requestResponses = this.#queryCache(operation.request, operation.options); + if (requestResponses.length === 0) { + return []; + } + for (const requestResponse of requestResponses) { + const idx = cache2.indexOf(requestResponse); + assert(idx !== -1); + cache2.splice(idx, 1); + } + } else if (operation.type === "put") { + if (operation.response == null) { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: "put operation should have an associated response" + }); + } + const r2 = operation.request; + if (!urlIsHttpHttpsScheme(r2.url)) { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: "expected http or https scheme" + }); + } + if (r2.method !== "GET") { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: "not get method" + }); + } + if (operation.options != null) { + throw webidl.errors.exception({ + header: "Cache.#batchCacheOperations", + message: "options must not be defined" + }); + } + requestResponses = this.#queryCache(operation.request); + for (const requestResponse of requestResponses) { + const idx = cache2.indexOf(requestResponse); + assert(idx !== -1); + cache2.splice(idx, 1); + } + cache2.push([operation.request, operation.response]); + addedItems.push([operation.request, operation.response]); + } + resultList.push([operation.request, operation.response]); + } + return resultList; + } catch (e) { + this.#relevantRequestResponseList.length = 0; + this.#relevantRequestResponseList = backupCache; + throw e; + } + } + /** + * @see https://w3c.github.io/ServiceWorker/#query-cache + * @param {any} requestQuery + * @param {import('../../../types/cache').CacheQueryOptions} options + * @param {requestResponseList} targetStorage + * @returns {requestResponseList} + */ + #queryCache(requestQuery, options2, targetStorage) { + const resultList = []; + const storage = targetStorage ?? this.#relevantRequestResponseList; + for (const requestResponse of storage) { + const [cachedRequest, cachedResponse2] = requestResponse; + if (this.#requestMatchesCachedItem(requestQuery, cachedRequest, cachedResponse2, options2)) { + resultList.push(requestResponse); + } + } + return resultList; + } + /** + * @see https://w3c.github.io/ServiceWorker/#request-matches-cached-item-algorithm + * @param {any} requestQuery + * @param {any} request + * @param {any | null} response + * @param {import('../../../types/cache').CacheQueryOptions | undefined} options + * @returns {boolean} + */ + #requestMatchesCachedItem(requestQuery, request, response = null, options2) { + const queryURL = new URL(requestQuery.url); + const cachedURL = new URL(request.url); + if (options2?.ignoreSearch) { + cachedURL.search = ""; + queryURL.search = ""; + } + if (!urlEquals(queryURL, cachedURL, true)) { + return false; + } + if (response == null || options2?.ignoreVary || !response.headersList.contains("vary")) { + return true; + } + const fieldValues = getFieldValues(response.headersList.get("vary")); + for (const fieldValue of fieldValues) { + if (fieldValue === "*") { + return false; + } + const requestValue = request.headersList.get(fieldValue); + const queryValue = requestQuery.headersList.get(fieldValue); + if (requestValue !== queryValue) { + return false; + } + } + return true; + } + #internalMatchAll(request, options2, maxResponses = Infinity) { + let r2 = null; + if (request !== void 0) { + if (webidl.is.Request(request)) { + r2 = getRequestState(request); + if (r2.method !== "GET" && !options2.ignoreMethod) { + return []; + } + } else if (typeof request === "string") { + r2 = getRequestState(new Request3(request)); + } + } + const responses = []; + if (request === void 0) { + for (const requestResponse of this.#relevantRequestResponseList) { + responses.push(requestResponse[1]); + } + } else { + const requestResponses = this.#queryCache(r2, options2); + for (const requestResponse of requestResponses) { + responses.push(requestResponse[1]); + } + } + const responseList = []; + for (const response of responses) { + const responseObject = fromInnerResponse(cloneResponse(response), "immutable"); + responseList.push(responseObject); + if (responseList.length >= maxResponses) { + break; + } + } + return Object.freeze(responseList); + } + }; + Object.defineProperties(Cache.prototype, { + [Symbol.toStringTag]: { + value: "Cache", + configurable: true + }, + match: kEnumerableProperty, + matchAll: kEnumerableProperty, + add: kEnumerableProperty, + addAll: kEnumerableProperty, + put: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty + }); + var cacheQueryOptionConverters = [ + { + key: "ignoreSearch", + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: "ignoreMethod", + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: "ignoreVary", + converter: webidl.converters.boolean, + defaultValue: () => false + } + ]; + webidl.converters.CacheQueryOptions = webidl.dictionaryConverter(cacheQueryOptionConverters); + webidl.converters.MultiCacheQueryOptions = webidl.dictionaryConverter([ + ...cacheQueryOptionConverters, + { + key: "cacheName", + converter: webidl.converters.DOMString + } + ]); + webidl.converters.Response = webidl.interfaceConverter( + webidl.is.Response, + "Response" + ); + webidl.converters["sequence"] = webidl.sequenceConverter( + webidl.converters.RequestInfo + ); + module2.exports = { + Cache + }; + } +}); + +// node_modules/undici/lib/web/cache/cachestorage.js +var require_cachestorage = __commonJS({ + "node_modules/undici/lib/web/cache/cachestorage.js"(exports2, module2) { + "use strict"; + var { Cache } = require_cache3(); + var { webidl } = require_webidl(); + var { kEnumerableProperty } = require_util(); + var { kConstruct } = require_symbols(); + var CacheStorage = class _CacheStorage { + /** + * @see https://w3c.github.io/ServiceWorker/#dfn-relevant-name-to-cache-map + * @type {Map} + */ + async has(cacheName) { + webidl.brandCheck(this, _CacheStorage); + const prefix2 = "CacheStorage.has"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + cacheName = webidl.converters.DOMString(cacheName, prefix2, "cacheName"); + return this.#caches.has(cacheName); + } + /** + * @see https://w3c.github.io/ServiceWorker/#dom-cachestorage-open + * @param {string} cacheName + * @returns {Promise} + */ + async open(cacheName) { + webidl.brandCheck(this, _CacheStorage); + const prefix2 = "CacheStorage.open"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + cacheName = webidl.converters.DOMString(cacheName, prefix2, "cacheName"); + if (this.#caches.has(cacheName)) { + const cache3 = this.#caches.get(cacheName); + return new Cache(kConstruct, cache3); + } + const cache2 = []; + this.#caches.set(cacheName, cache2); + return new Cache(kConstruct, cache2); + } + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-delete + * @param {string} cacheName + * @returns {Promise} + */ + async delete(cacheName) { + webidl.brandCheck(this, _CacheStorage); + const prefix2 = "CacheStorage.delete"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + cacheName = webidl.converters.DOMString(cacheName, prefix2, "cacheName"); + return this.#caches.delete(cacheName); + } + /** + * @see https://w3c.github.io/ServiceWorker/#cache-storage-keys + * @returns {Promise} + */ + async keys() { + webidl.brandCheck(this, _CacheStorage); + const keys = this.#caches.keys(); + return [...keys]; + } + }; + Object.defineProperties(CacheStorage.prototype, { + [Symbol.toStringTag]: { + value: "CacheStorage", + configurable: true + }, + match: kEnumerableProperty, + has: kEnumerableProperty, + open: kEnumerableProperty, + delete: kEnumerableProperty, + keys: kEnumerableProperty + }); + module2.exports = { + CacheStorage + }; + } +}); + +// node_modules/undici/lib/web/cookies/constants.js +var require_constants5 = __commonJS({ + "node_modules/undici/lib/web/cookies/constants.js"(exports2, module2) { + "use strict"; + var maxAttributeValueSize = 1024; + var maxNameValuePairSize = 4096; + module2.exports = { + maxAttributeValueSize, + maxNameValuePairSize + }; + } +}); + +// node_modules/undici/lib/web/cookies/util.js +var require_util4 = __commonJS({ + "node_modules/undici/lib/web/cookies/util.js"(exports2, module2) { + "use strict"; + function isCTLExcludingHtab(value2) { + for (let i = 0; i < value2.length; ++i) { + const code = value2.charCodeAt(i); + if (code >= 0 && code <= 8 || code >= 10 && code <= 31 || code === 127) { + return true; + } + } + return false; + } + function validateCookieName(name2) { + for (let i = 0; i < name2.length; ++i) { + const code = name2.charCodeAt(i); + if (code < 33 || // exclude CTLs (0-31), SP and HT + code > 126 || // exclude non-ascii and DEL + code === 34 || // " + code === 40 || // ( + code === 41 || // ) + code === 60 || // < + code === 62 || // > + code === 64 || // @ + code === 44 || // , + code === 59 || // ; + code === 58 || // : + code === 92 || // \ + code === 47 || // / + code === 91 || // [ + code === 93 || // ] + code === 63 || // ? + code === 61 || // = + code === 123 || // { + code === 125) { + throw new Error("Invalid cookie name"); + } + } + } + function validateCookieValue(value2) { + let len = value2.length; + let i = 0; + if (value2[0] === '"') { + if (len === 1 || value2[len - 1] !== '"') { + throw new Error("Invalid cookie value"); + } + --len; + ++i; + } + while (i < len) { + const code = value2.charCodeAt(i++); + if (code < 33 || // exclude CTLs (0-31) + code > 126 || // non-ascii and DEL (127) + code === 34 || // " + code === 44 || // , + code === 59 || // ; + code === 92) { + throw new Error("Invalid cookie value"); + } + } + } + function validateCookiePath(path2) { + for (let i = 0; i < path2.length; ++i) { + const code = path2.charCodeAt(i); + if (code < 32 || // exclude CTLs (0-31) + code > 126 || // exclude non-ascii and DEL + code === 59) { + throw new Error("Invalid cookie path"); + } + } + } + function isLetterOrDigit(code) { + return code >= 48 && code <= 57 || // 0-9 + code >= 65 && code <= 90 || // A-Z + code >= 97 && code <= 122; + } + function validateCookieDomain(domain) { + if (domain === " ") { + return; + } + if (domain.length > 255) { + throw new Error("Invalid cookie domain"); + } + let labelLength = 0; + for (let i = 0; i < domain.length; ++i) { + const code = domain.charCodeAt(i); + if (code === 46) { + if (labelLength === 0) { + throw new Error("Invalid cookie domain"); + } + if (domain.charCodeAt(i - 1) === 45) { + throw new Error("Invalid cookie domain"); + } + labelLength = 0; + continue; + } + if (labelLength === 0 && !isLetterOrDigit(code)) { + throw new Error("Invalid cookie domain"); + } + if (!isLetterOrDigit(code) && code !== 45) { + throw new Error("Invalid cookie domain"); + } + if (++labelLength > 63) { + throw new Error("Invalid cookie domain"); + } + } + if (labelLength === 0 || domain.charCodeAt(domain.length - 1) === 45) { + throw new Error("Invalid cookie domain"); + } + } + var IMFDays = [ + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" + ]; + var IMFMonths = [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + ]; + var IMFPaddedNumbers = Array(61).fill(0).map((_, i) => i.toString().padStart(2, "0")); + function toIMFDate(date) { + if (typeof date === "number") { + date = new Date(date); + } + return `${IMFDays[date.getUTCDay()]}, ${IMFPaddedNumbers[date.getUTCDate()]} ${IMFMonths[date.getUTCMonth()]} ${date.getUTCFullYear()} ${IMFPaddedNumbers[date.getUTCHours()]}:${IMFPaddedNumbers[date.getUTCMinutes()]}:${IMFPaddedNumbers[date.getUTCSeconds()]} GMT`; + } + function validateCookieMaxAge(maxAge) { + if (maxAge < 0) { + throw new Error("Invalid cookie max-age"); + } + } + function stringify2(cookie) { + if (cookie.name.length === 0) { + return null; + } + validateCookieName(cookie.name); + validateCookieValue(cookie.value); + const out = [`${cookie.name}=${cookie.value}`]; + if (cookie.name.startsWith("__Secure-")) { + cookie.secure = true; + } + if (cookie.name.startsWith("__Host-")) { + cookie.secure = true; + cookie.domain = null; + cookie.path = "/"; + } + if (cookie.secure) { + out.push("Secure"); + } + if (cookie.httpOnly) { + out.push("HttpOnly"); + } + if (typeof cookie.maxAge === "number") { + validateCookieMaxAge(cookie.maxAge); + out.push(`Max-Age=${cookie.maxAge}`); + } + if (cookie.domain) { + validateCookieDomain(cookie.domain); + out.push(`Domain=${cookie.domain}`); + } + if (cookie.path) { + validateCookiePath(cookie.path); + out.push(`Path=${cookie.path}`); + } + if (cookie.expires && cookie.expires.toString() !== "Invalid Date") { + out.push(`Expires=${toIMFDate(cookie.expires)}`); + } + if (cookie.sameSite) { + out.push(`SameSite=${cookie.sameSite}`); + } + for (const part of cookie.unparsed) { + if (!part.includes("=")) { + throw new Error("Invalid unparsed"); + } + const [key, ...value2] = part.split("="); + const trimmedKey = key.trim(); + const joinedValue = value2.join("="); + validateCookieName(trimmedKey); + validateCookieValue(joinedValue); + out.push(`${trimmedKey}=${joinedValue}`); + } + return out.join("; "); + } + module2.exports = { + isCTLExcludingHtab, + validateCookieName, + validateCookiePath, + validateCookieValue, + toIMFDate, + stringify: stringify2 + }; + } +}); + +// node_modules/undici/lib/web/cookies/parse.js +var require_parse = __commonJS({ + "node_modules/undici/lib/web/cookies/parse.js"(exports2, module2) { + "use strict"; + var { collectASequenceOfCodePointsFast } = require_infra(); + var { maxNameValuePairSize, maxAttributeValueSize } = require_constants5(); + var { isCTLExcludingHtab } = require_util4(); + var assert = require("node:assert"); + function parseSetCookie(header) { + if (isCTLExcludingHtab(header)) { + return null; + } + let nameValuePair = ""; + let unparsedAttributes = ""; + let name2 = ""; + let value2 = ""; + if (header.includes(";")) { + const position = { position: 0 }; + nameValuePair = collectASequenceOfCodePointsFast(";", header, position); + unparsedAttributes = header.slice(position.position); + } else { + nameValuePair = header; + } + if (!nameValuePair.includes("=")) { + value2 = nameValuePair; + } else { + const position = { position: 0 }; + name2 = collectASequenceOfCodePointsFast( + "=", + nameValuePair, + position + ); + value2 = nameValuePair.slice(position.position + 1); + } + name2 = name2.trim(); + value2 = value2.trim(); + if (name2.length + value2.length > maxNameValuePairSize) { + return null; + } + return { + name: name2, + value: value2, + ...parseUnparsedAttributes(unparsedAttributes) + }; + } + function parseUnparsedAttributes(unparsedAttributes, cookieAttributeList = {}) { + if (unparsedAttributes.length === 0) { + return cookieAttributeList; + } + assert(unparsedAttributes[0] === ";"); + unparsedAttributes = unparsedAttributes.slice(1); + let cookieAv = ""; + if (unparsedAttributes.includes(";")) { + cookieAv = collectASequenceOfCodePointsFast( + ";", + unparsedAttributes, + { position: 0 } + ); + unparsedAttributes = unparsedAttributes.slice(cookieAv.length); + } else { + cookieAv = unparsedAttributes; + unparsedAttributes = ""; + } + let attributeName2 = ""; + let attributeValue2 = ""; + if (cookieAv.includes("=")) { + const position = { position: 0 }; + attributeName2 = collectASequenceOfCodePointsFast( + "=", + cookieAv, + position + ); + attributeValue2 = cookieAv.slice(position.position + 1); + } else { + attributeName2 = cookieAv; + } + attributeName2 = attributeName2.trim(); + attributeValue2 = attributeValue2.trim(); + if (attributeValue2.length > maxAttributeValueSize) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + } + const attributeNameLowercase = attributeName2.toLowerCase(); + if (attributeNameLowercase === "expires") { + const expiryTime = new Date(attributeValue2); + if (!Number.isNaN(expiryTime.getTime())) { + cookieAttributeList.expires = expiryTime; + } + } else if (attributeNameLowercase === "max-age") { + const charCode = attributeValue2.charCodeAt(0); + if ((charCode < 48 || charCode > 57) && attributeValue2[0] !== "-") { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + } + if (!/^\d+$/.test(attributeValue2)) { + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + } + const deltaSeconds = Number(attributeValue2); + cookieAttributeList.maxAge = deltaSeconds; + } else if (attributeNameLowercase === "domain") { + let cookieDomain = attributeValue2; + if (cookieDomain[0] === ".") { + cookieDomain = cookieDomain.slice(1); + } + cookieDomain = cookieDomain.toLowerCase(); + cookieAttributeList.domain = cookieDomain; + } else if (attributeNameLowercase === "path") { + let cookiePath = ""; + if (attributeValue2.length === 0 || attributeValue2[0] !== "/") { + cookiePath = "/"; + } else { + cookiePath = attributeValue2; + } + cookieAttributeList.path = cookiePath; + } else if (attributeNameLowercase === "secure") { + cookieAttributeList.secure = true; + } else if (attributeNameLowercase === "httponly") { + cookieAttributeList.httpOnly = true; + } else if (attributeNameLowercase === "samesite") { + const attributeValueLowercase = attributeValue2.toLowerCase(); + if (attributeValueLowercase === "none") { + cookieAttributeList.sameSite = "None"; + } else if (attributeValueLowercase === "strict") { + cookieAttributeList.sameSite = "Strict"; + } else if (attributeValueLowercase === "lax") { + cookieAttributeList.sameSite = "Lax"; + } + } else { + cookieAttributeList.unparsed ??= []; + cookieAttributeList.unparsed.push(`${attributeName2}=${attributeValue2}`); + } + return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + } + module2.exports = { + parseSetCookie, + parseUnparsedAttributes + }; + } +}); + +// node_modules/undici/lib/web/cookies/index.js +var require_cookies = __commonJS({ + "node_modules/undici/lib/web/cookies/index.js"(exports2, module2) { + "use strict"; + var { parseSetCookie } = require_parse(); + var { stringify: stringify2 } = require_util4(); + var { webidl } = require_webidl(); + var { Headers: Headers3 } = require_headers(); + var brandChecks = webidl.brandCheckMultiple([Headers3, globalThis.Headers].filter(Boolean)); + function getCookies(headers2) { + webidl.argumentLengthCheck(arguments, 1, "getCookies"); + brandChecks(headers2); + const cookie = headers2.get("cookie"); + const out = {}; + if (!cookie) { + return out; + } + for (const piece of cookie.split(";")) { + const [name2, ...value2] = piece.split("="); + out[name2.trim()] = value2.join("="); + } + return out; + } + function deleteCookie(headers2, name2, attributes2) { + brandChecks(headers2); + const prefix2 = "deleteCookie"; + webidl.argumentLengthCheck(arguments, 2, prefix2); + name2 = webidl.converters.DOMString(name2, prefix2, "name"); + attributes2 = webidl.converters.DeleteCookieAttributes(attributes2); + setCookie(headers2, { + name: name2, + value: "", + expires: /* @__PURE__ */ new Date(0), + ...attributes2 + }); + } + function getSetCookies(headers2) { + webidl.argumentLengthCheck(arguments, 1, "getSetCookies"); + brandChecks(headers2); + const cookies = headers2.getSetCookie(); + if (!cookies) { + return []; + } + return cookies.map((pair) => parseSetCookie(pair)); + } + function parseCookie(cookie) { + cookie = webidl.converters.DOMString(cookie); + return parseSetCookie(cookie); + } + function setCookie(headers2, cookie) { + webidl.argumentLengthCheck(arguments, 2, "setCookie"); + brandChecks(headers2); + cookie = webidl.converters.Cookie(cookie); + const str = stringify2(cookie); + if (str) { + headers2.append("set-cookie", str, true); + } + } + webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([ + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: "path", + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: "domain", + defaultValue: () => null + } + ]); + webidl.converters.Cookie = webidl.dictionaryConverter([ + { + converter: webidl.converters.DOMString, + key: "name" + }, + { + converter: webidl.converters.DOMString, + key: "value" + }, + { + converter: webidl.nullableConverter((value2) => { + if (typeof value2 === "number") { + return webidl.converters["unsigned long long"](value2); + } + return new Date(value2); + }), + key: "expires", + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters["long long"]), + key: "maxAge", + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: "domain", + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.DOMString), + key: "path", + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: "secure", + defaultValue: () => null + }, + { + converter: webidl.nullableConverter(webidl.converters.boolean), + key: "httpOnly", + defaultValue: () => null + }, + { + converter: webidl.converters.USVString, + key: "sameSite", + allowedValues: ["Strict", "Lax", "None"] + }, + { + converter: webidl.sequenceConverter(webidl.converters.DOMString), + key: "unparsed", + defaultValue: () => [] + } + ]); + module2.exports = { + getCookies, + deleteCookie, + getSetCookies, + setCookie, + parseCookie + }; + } +}); + +// node_modules/undici/lib/web/websocket/events.js +var require_events = __commonJS({ + "node_modules/undici/lib/web/websocket/events.js"(exports2, module2) { + "use strict"; + var { webidl } = require_webidl(); + var { kEnumerableProperty } = require_util(); + var { kConstruct } = require_symbols(); + var MessageEvent2 = class _MessageEvent extends Event { + #eventInit; + constructor(type2, eventInitDict = {}) { + if (type2 === kConstruct) { + super(arguments[1], arguments[2]); + webidl.util.markAsUncloneable(this); + return; + } + const prefix2 = "MessageEvent constructor"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + type2 = webidl.converters.DOMString(type2, prefix2, "type"); + eventInitDict = webidl.converters.MessageEventInit(eventInitDict, prefix2, "eventInitDict"); + super(type2, eventInitDict); + this.#eventInit = eventInitDict; + webidl.util.markAsUncloneable(this); + } + get data() { + webidl.brandCheck(this, _MessageEvent); + return this.#eventInit.data; + } + get origin() { + webidl.brandCheck(this, _MessageEvent); + return this.#eventInit.origin; + } + get lastEventId() { + webidl.brandCheck(this, _MessageEvent); + return this.#eventInit.lastEventId; + } + get source() { + webidl.brandCheck(this, _MessageEvent); + return this.#eventInit.source; + } + get ports() { + webidl.brandCheck(this, _MessageEvent); + if (!Object.isFrozen(this.#eventInit.ports)) { + Object.freeze(this.#eventInit.ports); + } + return this.#eventInit.ports; + } + initMessageEvent(type2, bubbles2 = false, cancelable2 = false, data2 = null, origin = "", lastEventId = "", source = null, ports = []) { + webidl.brandCheck(this, _MessageEvent); + webidl.argumentLengthCheck(arguments, 1, "MessageEvent.initMessageEvent"); + return new _MessageEvent(type2, { + bubbles: bubbles2, + cancelable: cancelable2, + data: data2, + origin, + lastEventId, + source, + ports + }); + } + static createFastMessageEvent(type2, init) { + const messageEvent = new _MessageEvent(kConstruct, type2, init); + messageEvent.#eventInit = init; + messageEvent.#eventInit.data ??= null; + messageEvent.#eventInit.origin ??= ""; + messageEvent.#eventInit.lastEventId ??= ""; + messageEvent.#eventInit.source ??= null; + messageEvent.#eventInit.ports ??= []; + return messageEvent; + } + }; + var { createFastMessageEvent } = MessageEvent2; + delete MessageEvent2.createFastMessageEvent; + var CloseEvent2 = class _CloseEvent extends Event { + #eventInit; + constructor(type2, eventInitDict = {}) { + const prefix2 = "CloseEvent constructor"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + type2 = webidl.converters.DOMString(type2, prefix2, "type"); + eventInitDict = webidl.converters.CloseEventInit(eventInitDict); + super(type2, eventInitDict); + this.#eventInit = eventInitDict; + webidl.util.markAsUncloneable(this); + } + get wasClean() { + webidl.brandCheck(this, _CloseEvent); + return this.#eventInit.wasClean; + } + get code() { + webidl.brandCheck(this, _CloseEvent); + return this.#eventInit.code; + } + get reason() { + webidl.brandCheck(this, _CloseEvent); + return this.#eventInit.reason; + } + }; + var ErrorEvent2 = class _ErrorEvent extends Event { + #eventInit; + constructor(type2, eventInitDict) { + const prefix2 = "ErrorEvent constructor"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + super(type2, eventInitDict); + webidl.util.markAsUncloneable(this); + type2 = webidl.converters.DOMString(type2, prefix2, "type"); + eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}); + this.#eventInit = eventInitDict; + } + get message() { + webidl.brandCheck(this, _ErrorEvent); + return this.#eventInit.message; + } + get filename() { + webidl.brandCheck(this, _ErrorEvent); + return this.#eventInit.filename; + } + get lineno() { + webidl.brandCheck(this, _ErrorEvent); + return this.#eventInit.lineno; + } + get colno() { + webidl.brandCheck(this, _ErrorEvent); + return this.#eventInit.colno; + } + get error() { + webidl.brandCheck(this, _ErrorEvent); + return this.#eventInit.error; + } + }; + Object.defineProperties(MessageEvent2.prototype, { + [Symbol.toStringTag]: { + value: "MessageEvent", + configurable: true + }, + data: kEnumerableProperty, + origin: kEnumerableProperty, + lastEventId: kEnumerableProperty, + source: kEnumerableProperty, + ports: kEnumerableProperty, + initMessageEvent: kEnumerableProperty + }); + Object.defineProperties(CloseEvent2.prototype, { + [Symbol.toStringTag]: { + value: "CloseEvent", + configurable: true + }, + reason: kEnumerableProperty, + code: kEnumerableProperty, + wasClean: kEnumerableProperty + }); + Object.defineProperties(ErrorEvent2.prototype, { + [Symbol.toStringTag]: { + value: "ErrorEvent", + configurable: true + }, + message: kEnumerableProperty, + filename: kEnumerableProperty, + lineno: kEnumerableProperty, + colno: kEnumerableProperty, + error: kEnumerableProperty + }); + webidl.converters.MessagePort = webidl.interfaceConverter( + webidl.is.MessagePort, + "MessagePort" + ); + webidl.converters["sequence"] = webidl.sequenceConverter( + webidl.converters.MessagePort + ); + var eventInit = [ + { + key: "bubbles", + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: "cancelable", + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: "composed", + converter: webidl.converters.boolean, + defaultValue: () => false + } + ]; + webidl.converters.MessageEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: "data", + converter: webidl.converters.any, + defaultValue: () => null + }, + { + key: "origin", + converter: webidl.converters.USVString, + defaultValue: () => "" + }, + { + key: "lastEventId", + converter: webidl.converters.DOMString, + defaultValue: () => "" + }, + { + key: "source", + // Node doesn't implement WindowProxy or ServiceWorker, so the only + // valid value for source is a MessagePort. + converter: webidl.nullableConverter(webidl.converters.MessagePort), + defaultValue: () => null + }, + { + key: "ports", + converter: webidl.converters["sequence"], + defaultValue: () => [] + } + ]); + webidl.converters.CloseEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: "wasClean", + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: "code", + converter: webidl.converters["unsigned short"], + defaultValue: () => 0 + }, + { + key: "reason", + converter: webidl.converters.USVString, + defaultValue: () => "" + } + ]); + webidl.converters.ErrorEventInit = webidl.dictionaryConverter([ + ...eventInit, + { + key: "message", + converter: webidl.converters.DOMString, + defaultValue: () => "" + }, + { + key: "filename", + converter: webidl.converters.USVString, + defaultValue: () => "" + }, + { + key: "lineno", + converter: webidl.converters["unsigned long"], + defaultValue: () => 0 + }, + { + key: "colno", + converter: webidl.converters["unsigned long"], + defaultValue: () => 0 + }, + { + key: "error", + converter: webidl.converters.any + } + ]); + module2.exports = { + MessageEvent: MessageEvent2, + CloseEvent: CloseEvent2, + ErrorEvent: ErrorEvent2, + createFastMessageEvent + }; + } +}); + +// node_modules/undici/lib/web/websocket/constants.js +var require_constants6 = __commonJS({ + "node_modules/undici/lib/web/websocket/constants.js"(exports2, module2) { + "use strict"; + var uid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + var staticPropertyDescriptors = { + enumerable: true, + writable: false, + configurable: false + }; + var states = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3 + }; + var sentCloseFrameState = { + SENT: 1, + RECEIVED: 2 + }; + var opcodes = { + CONTINUATION: 0, + TEXT: 1, + BINARY: 2, + CLOSE: 8, + PING: 9, + PONG: 10 + }; + var maxUnsigned16Bit = 65535; + var parserStates = { + INFO: 0, + PAYLOADLENGTH_16: 2, + PAYLOADLENGTH_64: 3, + READ_DATA: 4 + }; + var emptyBuffer = Buffer.allocUnsafe(0); + var sendHints = { + text: 1, + typedArray: 2, + arrayBuffer: 3, + blob: 4 + }; + module2.exports = { + uid, + sentCloseFrameState, + staticPropertyDescriptors, + states, + opcodes, + maxUnsigned16Bit, + parserStates, + emptyBuffer, + sendHints + }; + } +}); + +// node_modules/undici/lib/web/websocket/util.js +var require_util5 = __commonJS({ + "node_modules/undici/lib/web/websocket/util.js"(exports2, module2) { + "use strict"; + var { states, opcodes } = require_constants6(); + var { isUtf8 } = require("node:buffer"); + var { removeHTTPWhitespace } = require_data_url(); + var { collectASequenceOfCodePointsFast } = require_infra(); + function isConnecting(readyState2) { + return readyState2 === states.CONNECTING; + } + function isEstablished(readyState2) { + return readyState2 === states.OPEN; + } + function isClosing(readyState2) { + return readyState2 === states.CLOSING; + } + function isClosed(readyState2) { + return readyState2 === states.CLOSED; + } + function fireEvent(e, target2, eventFactory = (type2, init) => new Event(type2, init), eventInitDict = {}) { + const event = eventFactory(e, eventInitDict); + target2.dispatchEvent(event); + } + function websocketMessageReceived(handler, type2, data2) { + handler.onMessage(type2, data2); + } + function toArrayBuffer(buffer2) { + if (buffer2.byteLength === buffer2.buffer.byteLength) { + return buffer2.buffer; + } + return new Uint8Array(buffer2).buffer; + } + function isValidSubprotocol(protocol) { + if (protocol.length === 0) { + return false; + } + for (let i = 0; i < protocol.length; ++i) { + const code = protocol.charCodeAt(i); + if (code < 33 || // CTL, contains SP (0x20) and HT (0x09) + code > 126 || code === 34 || // " + code === 40 || // ( + code === 41 || // ) + code === 44 || // , + code === 47 || // / + code === 58 || // : + code === 59 || // ; + code === 60 || // < + code === 61 || // = + code === 62 || // > + code === 63 || // ? + code === 64 || // @ + code === 91 || // [ + code === 92 || // \ + code === 93 || // ] + code === 123 || // { + code === 125) { + return false; + } + } + return true; + } + function isValidStatusCode(code) { + if (code >= 1e3 && code < 1015) { + return code !== 1004 && // reserved + code !== 1005 && // "MUST NOT be set as a status code" + code !== 1006; + } + return code >= 3e3 && code <= 4999; + } + function isControlFrame(opcode) { + return opcode === opcodes.CLOSE || opcode === opcodes.PING || opcode === opcodes.PONG; + } + function isContinuationFrame(opcode) { + return opcode === opcodes.CONTINUATION; + } + function isTextBinaryFrame(opcode) { + return opcode === opcodes.TEXT || opcode === opcodes.BINARY; + } + function isValidOpcode(opcode) { + return isTextBinaryFrame(opcode) || isContinuationFrame(opcode) || isControlFrame(opcode); + } + function parseExtensions(extensions) { + const position = { position: 0 }; + const extensionList = /* @__PURE__ */ new Map(); + while (position.position < extensions.length) { + const pair = collectASequenceOfCodePointsFast(";", extensions, position); + const [name2, value2 = ""] = pair.split("=", 2); + extensionList.set( + removeHTTPWhitespace(name2, true, false), + removeHTTPWhitespace(value2, false, true) + ); + position.position++; + } + return extensionList; + } + function isValidClientWindowBits(value2) { + if (value2.length === 0) { + return false; + } + for (let i = 0; i < value2.length; i++) { + const byte = value2.charCodeAt(i); + if (byte < 48 || byte > 57) { + return false; + } + } + const num = Number.parseInt(value2, 10); + return num >= 8 && num <= 15; + } + function getURLRecord(url2, baseURL) { + let urlRecord; + try { + urlRecord = new URL(url2, baseURL); + } catch (e) { + throw new DOMException(e, "SyntaxError"); + } + if (urlRecord.protocol === "http:") { + urlRecord.protocol = "ws:"; + } else if (urlRecord.protocol === "https:") { + urlRecord.protocol = "wss:"; + } + if (urlRecord.protocol !== "ws:" && urlRecord.protocol !== "wss:") { + throw new DOMException("expected a ws: or wss: url", "SyntaxError"); + } + if (urlRecord.hash.length || urlRecord.href.endsWith("#")) { + throw new DOMException("hash", "SyntaxError"); + } + return urlRecord; + } + function validateCloseCodeAndReason(code, reason2) { + if (code !== null) { + if (code !== 1e3 && (code < 3e3 || code > 4999)) { + throw new DOMException("invalid code", "InvalidAccessError"); + } + } + if (reason2 !== null) { + const reasonBytesLength = Buffer.byteLength(reason2); + if (reasonBytesLength > 123) { + throw new DOMException(`Reason must be less than 123 bytes; received ${reasonBytesLength}`, "SyntaxError"); + } + } + } + var utf8Decode = (() => { + if (typeof process.versions.icu === "string") { + const fatalDecoder = new TextDecoder("utf-8", { fatal: true }); + return fatalDecoder.decode.bind(fatalDecoder); + } + return function(buffer2) { + if (isUtf8(buffer2)) { + return buffer2.toString("utf-8"); + } + throw new TypeError("Invalid utf-8 received."); + }; + })(); + module2.exports = { + isConnecting, + isEstablished, + isClosing, + isClosed, + fireEvent, + isValidSubprotocol, + isValidStatusCode, + websocketMessageReceived, + utf8Decode, + isControlFrame, + isContinuationFrame, + isTextBinaryFrame, + isValidOpcode, + parseExtensions, + isValidClientWindowBits, + toArrayBuffer, + getURLRecord, + validateCloseCodeAndReason + }; + } +}); + +// node_modules/undici/lib/web/websocket/frame.js +var require_frame = __commonJS({ + "node_modules/undici/lib/web/websocket/frame.js"(exports2, module2) { + "use strict"; + var { runtimeFeatures } = require_runtime_features(); + var { maxUnsigned16Bit, opcodes } = require_constants6(); + var BUFFER_SIZE = 8 * 1024; + var buffer2 = null; + var bufIdx = BUFFER_SIZE; + var randomFillSync = runtimeFeatures.has("crypto") ? require("node:crypto").randomFillSync : null; + function generateMask() { + if (bufIdx === BUFFER_SIZE) { + bufIdx = 0; + randomFillSync(buffer2 ??= Buffer.allocUnsafeSlow(BUFFER_SIZE), 0, BUFFER_SIZE); + } + return [buffer2[bufIdx++], buffer2[bufIdx++], buffer2[bufIdx++], buffer2[bufIdx++]]; + } + var WebsocketFrameSend = class { + /** + * @param {Buffer|undefined} data + */ + constructor(data2) { + this.frameData = data2; + } + createFrame(opcode) { + const frameData = this.frameData; + const maskKey = generateMask(); + const bodyLength = frameData?.byteLength ?? 0; + let payloadLength = bodyLength; + let offset2 = 6; + if (bodyLength > maxUnsigned16Bit) { + offset2 += 8; + payloadLength = 127; + } else if (bodyLength > 125) { + offset2 += 2; + payloadLength = 126; + } + const buffer3 = Buffer.allocUnsafe(bodyLength + offset2); + buffer3[0] = buffer3[1] = 0; + buffer3[0] |= 128; + buffer3[0] = (buffer3[0] & 240) + opcode; + buffer3[offset2 - 4] = maskKey[0]; + buffer3[offset2 - 3] = maskKey[1]; + buffer3[offset2 - 2] = maskKey[2]; + buffer3[offset2 - 1] = maskKey[3]; + buffer3[1] = payloadLength; + if (payloadLength === 126) { + buffer3.writeUInt16BE(bodyLength, 2); + } else if (payloadLength === 127) { + buffer3[2] = buffer3[3] = 0; + buffer3.writeUIntBE(bodyLength, 4, 6); + } + buffer3[1] |= 128; + for (let i = 0; i < bodyLength; ++i) { + buffer3[offset2 + i] = frameData[i] ^ maskKey[i & 3]; + } + return buffer3; + } + /** + * @param {Uint8Array} buffer + */ + static createFastTextFrame(buffer3) { + const maskKey = generateMask(); + const bodyLength = buffer3.length; + for (let i = 0; i < bodyLength; ++i) { + buffer3[i] ^= maskKey[i & 3]; + } + let payloadLength = bodyLength; + let offset2 = 6; + if (bodyLength > maxUnsigned16Bit) { + offset2 += 8; + payloadLength = 127; + } else if (bodyLength > 125) { + offset2 += 2; + payloadLength = 126; + } + const head = Buffer.allocUnsafeSlow(offset2); + head[0] = 128 | opcodes.TEXT; + head[1] = payloadLength | 128; + head[offset2 - 4] = maskKey[0]; + head[offset2 - 3] = maskKey[1]; + head[offset2 - 2] = maskKey[2]; + head[offset2 - 1] = maskKey[3]; + if (payloadLength === 126) { + head.writeUInt16BE(bodyLength, 2); + } else if (payloadLength === 127) { + head[2] = head[3] = 0; + head.writeUIntBE(bodyLength, 4, 6); + } + return [head, buffer3]; + } + }; + module2.exports = { + WebsocketFrameSend, + generateMask + // for benchmark + }; + } +}); + +// node_modules/undici/lib/web/websocket/connection.js +var require_connection = __commonJS({ + "node_modules/undici/lib/web/websocket/connection.js"(exports2, module2) { + "use strict"; + var { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = require_constants6(); + var { parseExtensions, isClosed, isClosing, isEstablished, isConnecting, validateCloseCodeAndReason } = require_util5(); + var { makeRequest } = require_request2(); + var { fetching } = require_fetch(); + var { Headers: Headers3, getHeadersList } = require_headers(); + var { getDecodeSplit } = require_util2(); + var { WebsocketFrameSend } = require_frame(); + var assert = require("node:assert"); + var { runtimeFeatures } = require_runtime_features(); + var crypto3 = runtimeFeatures.has("crypto") ? require("node:crypto") : null; + var warningEmitted = false; + function establishWebSocketConnection(url2, protocols, client, handler, options2) { + const requestURL = url2; + requestURL.protocol = url2.protocol === "ws:" ? "http:" : "https:"; + const request = makeRequest({ + urlList: [requestURL], + client, + serviceWorkers: "none", + referrer: "no-referrer", + mode: "websocket", + credentials: "include", + cache: "no-store", + redirect: "error", + useURLCredentials: true + }); + if (options2.headers) { + const headersList = getHeadersList(new Headers3(options2.headers)); + request.headersList = headersList; + } + const keyValue = crypto3.randomBytes(16).toString("base64"); + request.headersList.append("sec-websocket-key", keyValue, true); + request.headersList.append("sec-websocket-version", "13", true); + for (const protocol of protocols) { + request.headersList.append("sec-websocket-protocol", protocol, true); + } + const permessageDeflate = "permessage-deflate; client_max_window_bits"; + request.headersList.append("sec-websocket-extensions", permessageDeflate, true); + const controller = fetching({ + request, + useParallelQueue: true, + dispatcher: options2.dispatcher, + processResponse(response) { + if (response.type === "error" || response.status !== 101) { + if (response.socket?.session == null) { + failWebsocketConnection(handler, 1002, "Received network error or non-101 status code.", response.error); + return; + } + if (response.status !== 200) { + failWebsocketConnection(handler, 1002, "Received network error or non-200 status code.", response.error); + return; + } + } + if (warningEmitted === false && response.socket?.session != null) { + process.emitWarning("WebSocket over HTTP2 is experimental, and subject to change.", "ExperimentalWarning"); + warningEmitted = true; + } + if (protocols.length !== 0 && !response.headersList.get("Sec-WebSocket-Protocol")) { + failWebsocketConnection(handler, 1002, "Server did not respond with sent protocols."); + return; + } + if (response.socket.session == null && response.headersList.get("Upgrade")?.toLowerCase() !== "websocket") { + failWebsocketConnection(handler, 1002, 'Server did not set Upgrade header to "websocket".'); + return; + } + if (response.socket.session == null && response.headersList.get("Connection")?.toLowerCase() !== "upgrade") { + failWebsocketConnection(handler, 1002, 'Server did not set Connection header to "upgrade".'); + return; + } + const secWSAccept = response.headersList.get("Sec-WebSocket-Accept"); + const digest = crypto3.hash("sha1", keyValue + uid, "base64"); + if (secWSAccept !== digest) { + failWebsocketConnection(handler, 1002, "Incorrect hash received in Sec-WebSocket-Accept header."); + return; + } + const secExtension = response.headersList.get("Sec-WebSocket-Extensions"); + let extensions; + if (secExtension !== null) { + extensions = parseExtensions(secExtension); + if (!extensions.has("permessage-deflate")) { + failWebsocketConnection(handler, 1002, "Sec-WebSocket-Extensions header does not match."); + return; + } + } + const secProtocol = response.headersList.get("Sec-WebSocket-Protocol"); + if (secProtocol !== null) { + const requestProtocols = getDecodeSplit("sec-websocket-protocol", request.headersList); + if (!requestProtocols.includes(secProtocol)) { + failWebsocketConnection(handler, 1002, "Protocol was not set in the opening handshake."); + return; + } + } + response.socket.on("data", handler.onSocketData); + response.socket.on("close", handler.onSocketClose); + response.socket.on("error", handler.onSocketError); + handler.wasEverConnected = true; + handler.onConnectionEstablished(response, extensions); + } + }); + return controller; + } + function closeWebSocketConnection(object, code, reason2, validate2 = false) { + code ??= null; + reason2 ??= ""; + if (validate2) validateCloseCodeAndReason(code, reason2); + if (isClosed(object.readyState) || isClosing(object.readyState)) { + } else if (!isEstablished(object.readyState)) { + failWebsocketConnection(object); + object.readyState = states.CLOSING; + } else if (!object.closeState.has(sentCloseFrameState.SENT) && !object.closeState.has(sentCloseFrameState.RECEIVED)) { + const frame = new WebsocketFrameSend(); + if (reason2.length !== 0 && code === null) { + code = 1e3; + } + assert(code === null || Number.isInteger(code)); + if (code === null && reason2.length === 0) { + frame.frameData = emptyBuffer; + } else if (code !== null && reason2 === null) { + frame.frameData = Buffer.allocUnsafe(2); + frame.frameData.writeUInt16BE(code, 0); + } else if (code !== null && reason2 !== null) { + frame.frameData = Buffer.allocUnsafe(2 + Buffer.byteLength(reason2)); + frame.frameData.writeUInt16BE(code, 0); + frame.frameData.write(reason2, 2, "utf-8"); + } else { + frame.frameData = emptyBuffer; + } + object.socket.write(frame.createFrame(opcodes.CLOSE)); + object.closeState.add(sentCloseFrameState.SENT); + object.readyState = states.CLOSING; + } else { + object.readyState = states.CLOSING; + } + } + function failWebsocketConnection(handler, code, reason2, cause) { + if (isEstablished(handler.readyState)) { + closeWebSocketConnection(handler, code, reason2, false); + } + handler.controller.abort(); + if (isConnecting(handler.readyState)) { + handler.onSocketClose(); + } else if (handler.socket?.destroyed === false) { + handler.socket.destroy(); + } + } + module2.exports = { + establishWebSocketConnection, + failWebsocketConnection, + closeWebSocketConnection + }; + } +}); + +// node_modules/undici/lib/web/websocket/permessage-deflate.js +var require_permessage_deflate2 = __commonJS({ + "node_modules/undici/lib/web/websocket/permessage-deflate.js"(exports2, module2) { + "use strict"; + var { createInflateRaw, Z_DEFAULT_WINDOWBITS } = require("node:zlib"); + var { isValidClientWindowBits } = require_util5(); + var { MessageSizeExceededError } = require_errors2(); + var tail = Buffer.from([0, 0, 255, 255]); + var kBuffer = /* @__PURE__ */ Symbol("kBuffer"); + var kLength = /* @__PURE__ */ Symbol("kLength"); + var PerMessageDeflate2 = class { + /** @type {import('node:zlib').InflateRaw} */ + #inflate; + #options = {}; + #maxPayloadSize = 0; + /** + * @param {Map} extensions + */ + constructor(extensions, options2) { + this.#options.serverNoContextTakeover = extensions.has("server_no_context_takeover"); + this.#options.serverMaxWindowBits = extensions.get("server_max_window_bits"); + this.#maxPayloadSize = options2.maxPayloadSize; + } + /** + * Decompress a compressed payload. + * @param {Buffer} chunk Compressed data + * @param {boolean} fin Final fragment flag + * @param {Function} callback Callback function + */ + decompress(chunk, fin, callback) { + if (!this.#inflate) { + let windowBits = Z_DEFAULT_WINDOWBITS; + if (this.#options.serverMaxWindowBits) { + if (!isValidClientWindowBits(this.#options.serverMaxWindowBits)) { + callback(new Error("Invalid server_max_window_bits")); + return; + } + windowBits = Number.parseInt(this.#options.serverMaxWindowBits); + } + try { + this.#inflate = createInflateRaw({ windowBits }); + } catch (err) { + callback(err); + return; + } + this.#inflate[kBuffer] = []; + this.#inflate[kLength] = 0; + this.#inflate.on("data", (data2) => { + this.#inflate[kLength] += data2.length; + if (this.#maxPayloadSize > 0 && this.#inflate[kLength] > this.#maxPayloadSize) { + callback(new MessageSizeExceededError()); + this.#inflate.removeAllListeners(); + this.#inflate = null; + return; + } + this.#inflate[kBuffer].push(data2); + }); + this.#inflate.on("error", (err) => { + this.#inflate = null; + callback(err); + }); + } + this.#inflate.write(chunk); + if (fin) { + this.#inflate.write(tail); + } + this.#inflate.flush(() => { + if (!this.#inflate) { + return; + } + const full = Buffer.concat(this.#inflate[kBuffer], this.#inflate[kLength]); + this.#inflate[kBuffer].length = 0; + this.#inflate[kLength] = 0; + callback(null, full); + }); + } + }; + module2.exports = { PerMessageDeflate: PerMessageDeflate2 }; + } +}); + +// node_modules/undici/lib/web/websocket/receiver.js +var require_receiver2 = __commonJS({ + "node_modules/undici/lib/web/websocket/receiver.js"(exports2, module2) { + "use strict"; + var { Writable } = require("node:stream"); + var assert = require("node:assert"); + var { parserStates, opcodes, states, emptyBuffer, sentCloseFrameState } = require_constants6(); + var { + isValidStatusCode, + isValidOpcode, + websocketMessageReceived, + utf8Decode, + isControlFrame, + isTextBinaryFrame, + isContinuationFrame + } = require_util5(); + var { failWebsocketConnection } = require_connection(); + var { WebsocketFrameSend } = require_frame(); + var { PerMessageDeflate: PerMessageDeflate2 } = require_permessage_deflate2(); + var { MessageSizeExceededError } = require_errors2(); + var ByteParser = class extends Writable { + #buffers = []; + #fragmentsBytes = 0; + #byteOffset = 0; + #loop = false; + #state = parserStates.INFO; + #info = {}; + #fragments = []; + /** @type {Map} */ + #extensions; + /** @type {import('./websocket').Handler} */ + #handler; + /** @type {number} */ + #maxFragments; + /** @type {number} */ + #maxPayloadSize; + /** + * @param {import('./websocket').Handler} handler + * @param {Map|null} extensions + * @param {{ maxPayloadSize?: number }} [options] + */ + constructor(handler, extensions, options2 = {}) { + super(); + this.#handler = handler; + this.#extensions = extensions == null ? /* @__PURE__ */ new Map() : extensions; + this.#maxFragments = options2.maxFragments ?? 0; + this.#maxPayloadSize = options2.maxPayloadSize ?? 0; + if (this.#extensions.has("permessage-deflate")) { + this.#extensions.set("permessage-deflate", new PerMessageDeflate2(extensions, options2)); + } + } + /** + * @param {Buffer} chunk + * @param {() => void} callback + */ + _write(chunk, _, callback) { + this.#buffers.push(chunk); + this.#byteOffset += chunk.length; + this.#loop = true; + this.run(callback); + } + #validatePayloadLength() { + if (this.#maxPayloadSize > 0 && !isControlFrame(this.#info.opcode) && this.#info.payloadLength + this.#fragmentsBytes > this.#maxPayloadSize) { + failWebsocketConnection(this.#handler, 1009, "Payload size exceeds maximum allowed size"); + return false; + } + return true; + } + /** + * Runs whenever a new chunk is received. + * Callback is called whenever there are no more chunks buffering, + * or not enough bytes are buffered to parse. + */ + run(callback) { + while (this.#loop) { + if (this.#state === parserStates.INFO) { + if (this.#byteOffset < 2) { + return callback(); + } + const buffer2 = this.consume(2); + const fin = (buffer2[0] & 128) !== 0; + const opcode = buffer2[0] & 15; + const masked = (buffer2[1] & 128) === 128; + const fragmented = !fin && opcode !== opcodes.CONTINUATION; + const payloadLength = buffer2[1] & 127; + const rsv1 = buffer2[0] & 64; + const rsv2 = buffer2[0] & 32; + const rsv3 = buffer2[0] & 16; + if (!isValidOpcode(opcode)) { + failWebsocketConnection(this.#handler, 1002, "Invalid opcode received"); + return callback(); + } + if (masked) { + failWebsocketConnection(this.#handler, 1002, "Frame cannot be masked"); + return callback(); + } + if (rsv1 !== 0 && !this.#extensions.has("permessage-deflate")) { + failWebsocketConnection(this.#handler, 1002, "Expected RSV1 to be clear."); + return; + } + if (rsv2 !== 0 || rsv3 !== 0) { + failWebsocketConnection(this.#handler, 1002, "RSV1, RSV2, RSV3 must be clear"); + return; + } + if (fragmented && !isTextBinaryFrame(opcode)) { + failWebsocketConnection(this.#handler, 1002, "Invalid frame type was fragmented."); + return; + } + if (isTextBinaryFrame(opcode) && this.#fragments.length > 0) { + failWebsocketConnection(this.#handler, 1002, "Expected continuation frame"); + return; + } + if (this.#info.fragmented && fragmented) { + failWebsocketConnection(this.#handler, 1002, "Fragmented frame exceeded 125 bytes."); + return; + } + if ((payloadLength > 125 || fragmented) && isControlFrame(opcode)) { + failWebsocketConnection(this.#handler, 1002, "Control frame either too large or fragmented"); + return; + } + if (isContinuationFrame(opcode) && this.#fragments.length === 0 && !this.#info.compressed) { + failWebsocketConnection(this.#handler, 1002, "Unexpected continuation frame"); + return; + } + if (payloadLength <= 125) { + this.#info.payloadLength = payloadLength; + this.#state = parserStates.READ_DATA; + if (!this.#validatePayloadLength()) { + return; + } + } else if (payloadLength === 126) { + this.#state = parserStates.PAYLOADLENGTH_16; + } else if (payloadLength === 127) { + this.#state = parserStates.PAYLOADLENGTH_64; + } + if (isTextBinaryFrame(opcode)) { + this.#info.binaryType = opcode; + this.#info.compressed = rsv1 !== 0; + } + this.#info.opcode = opcode; + this.#info.masked = masked; + this.#info.fin = fin; + this.#info.fragmented = fragmented; + } else if (this.#state === parserStates.PAYLOADLENGTH_16) { + if (this.#byteOffset < 2) { + return callback(); + } + const buffer2 = this.consume(2); + this.#info.payloadLength = buffer2.readUInt16BE(0); + this.#state = parserStates.READ_DATA; + if (!this.#validatePayloadLength()) { + return; + } + } else if (this.#state === parserStates.PAYLOADLENGTH_64) { + if (this.#byteOffset < 8) { + return callback(); + } + const buffer2 = this.consume(8); + const upper = buffer2.readUInt32BE(0); + const lower = buffer2.readUInt32BE(4); + if (upper !== 0 || lower > 2 ** 31 - 1) { + failWebsocketConnection(this.#handler, 1009, "Received payload length > 2^31 bytes."); + return; + } + this.#info.payloadLength = lower; + this.#state = parserStates.READ_DATA; + if (!this.#validatePayloadLength()) { + return; + } + } else if (this.#state === parserStates.READ_DATA) { + if (this.#byteOffset < this.#info.payloadLength) { + return callback(); + } + const body2 = this.consume(this.#info.payloadLength); + if (isControlFrame(this.#info.opcode)) { + this.#loop = this.parseControlFrame(body2); + this.#state = parserStates.INFO; + } else { + if (!this.#info.compressed) { + if (!this.writeFragments(body2)) { + return; + } + if (!this.#info.fragmented && this.#info.fin) { + websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()); + } + this.#state = parserStates.INFO; + } else { + this.#extensions.get("permessage-deflate").decompress( + body2, + this.#info.fin, + (error2, data2) => { + if (error2) { + const code = error2 instanceof MessageSizeExceededError ? 1009 : 1007; + failWebsocketConnection(this.#handler, code, error2.message); + return; + } + if (!this.writeFragments(data2)) { + return; + } + if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) { + failWebsocketConnection(this.#handler, 1009, new MessageSizeExceededError().message); + return; + } + if (!this.#info.fin) { + this.#state = parserStates.INFO; + this.#loop = true; + this.run(callback); + return; + } + websocketMessageReceived(this.#handler, this.#info.binaryType, this.consumeFragments()); + this.#loop = true; + this.#state = parserStates.INFO; + this.run(callback); + }, + this.#fragmentsBytes + ); + this.#loop = false; + break; + } + } + } + } + } + /** + * Take n bytes from the buffered Buffers + * @param {number} n + * @returns {Buffer} + */ + consume(n) { + if (n > this.#byteOffset) { + throw new Error("Called consume() before buffers satiated."); + } else if (n === 0) { + return emptyBuffer; + } + this.#byteOffset -= n; + const first = this.#buffers[0]; + if (first.length > n) { + this.#buffers[0] = first.subarray(n, first.length); + return first.subarray(0, n); + } else if (first.length === n) { + return this.#buffers.shift(); + } else { + let offset2 = 0; + const buffer2 = Buffer.allocUnsafeSlow(n); + while (offset2 !== n) { + const next = this.#buffers[0]; + const length2 = next.length; + if (length2 + offset2 === n) { + buffer2.set(this.#buffers.shift(), offset2); + break; + } else if (length2 + offset2 > n) { + buffer2.set(next.subarray(0, n - offset2), offset2); + this.#buffers[0] = next.subarray(n - offset2); + break; + } else { + buffer2.set(this.#buffers.shift(), offset2); + offset2 += length2; + } + } + return buffer2; + } + } + writeFragments(fragment) { + if (this.#maxFragments > 0 && this.#fragments.length === this.#maxFragments) { + failWebsocketConnection(this.#handler, 1008, "Too many message fragments"); + return false; + } + this.#fragmentsBytes += fragment.length; + this.#fragments.push(fragment); + return true; + } + consumeFragments() { + const fragments = this.#fragments; + if (fragments.length === 1) { + this.#fragmentsBytes = 0; + return fragments.shift(); + } + let offset2 = 0; + const output = Buffer.allocUnsafeSlow(this.#fragmentsBytes); + for (let i = 0; i < fragments.length; ++i) { + const buffer2 = fragments[i]; + output.set(buffer2, offset2); + offset2 += buffer2.length; + } + this.#fragments = []; + this.#fragmentsBytes = 0; + return output; + } + parseCloseBody(data2) { + assert(data2.length !== 1); + let code; + if (data2.length >= 2) { + code = data2.readUInt16BE(0); + } + if (code !== void 0 && !isValidStatusCode(code)) { + return { code: 1002, reason: "Invalid status code", error: true }; + } + let reason2 = data2.subarray(2); + if (reason2[0] === 239 && reason2[1] === 187 && reason2[2] === 191) { + reason2 = reason2.subarray(3); + } + try { + reason2 = utf8Decode(reason2); + } catch { + return { code: 1007, reason: "Invalid UTF-8", error: true }; + } + return { code, reason: reason2, error: false }; + } + /** + * Parses control frames. + * @param {Buffer} body + */ + parseControlFrame(body2) { + const { opcode, payloadLength } = this.#info; + if (opcode === opcodes.CLOSE) { + if (payloadLength === 1) { + failWebsocketConnection(this.#handler, 1002, "Received close frame with a 1-byte body."); + return false; + } + this.#info.closeInfo = this.parseCloseBody(body2); + if (this.#info.closeInfo.error) { + const { code, reason: reason2 } = this.#info.closeInfo; + failWebsocketConnection(this.#handler, code, reason2); + return false; + } + if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + let body3 = emptyBuffer; + if (this.#info.closeInfo.code) { + body3 = Buffer.allocUnsafe(2); + body3.writeUInt16BE(this.#info.closeInfo.code, 0); + } + const closeFrame = new WebsocketFrameSend(body3); + this.#handler.socket.write(closeFrame.createFrame(opcodes.CLOSE)); + this.#handler.closeState.add(sentCloseFrameState.SENT); + } + this.#handler.readyState = states.CLOSING; + this.#handler.closeState.add(sentCloseFrameState.RECEIVED); + return false; + } else if (opcode === opcodes.PING) { + if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + const frame = new WebsocketFrameSend(body2); + this.#handler.socket.write(frame.createFrame(opcodes.PONG)); + this.#handler.onPing(body2); + } + } else if (opcode === opcodes.PONG) { + this.#handler.onPong(body2); + } + return true; + } + get closingInfo() { + return this.#info.closeInfo; + } + }; + module2.exports = { + ByteParser + }; + } +}); + +// node_modules/undici/lib/web/websocket/sender.js +var require_sender2 = __commonJS({ + "node_modules/undici/lib/web/websocket/sender.js"(exports2, module2) { + "use strict"; + var { WebsocketFrameSend } = require_frame(); + var { opcodes, sendHints } = require_constants6(); + var FixedQueue = require_fixed_queue(); + var SendQueue = class { + /** + * @type {FixedQueue} + */ + #queue = new FixedQueue(); + /** + * @type {boolean} + */ + #running = false; + /** @type {import('node:net').Socket} */ + #socket; + constructor(socket) { + this.#socket = socket; + } + add(item, cb, hint) { + if (hint !== sendHints.blob) { + if (!this.#running) { + if (hint === sendHints.text) { + const { 0: head, 1: body2 } = WebsocketFrameSend.createFastTextFrame(item); + this.#socket.cork(); + this.#socket.write(head); + this.#socket.write(body2, cb); + this.#socket.uncork(); + } else { + this.#socket.write(createFrame(item, hint), cb); + } + } else { + const node2 = { + promise: null, + callback: cb, + frame: createFrame(item, hint) + }; + this.#queue.push(node2); + } + return; + } + const node = { + promise: item.arrayBuffer().then((ab) => { + node.promise = null; + node.frame = createFrame(ab, hint); + }), + callback: cb, + frame: null + }; + this.#queue.push(node); + if (!this.#running) { + this.#run(); + } + } + async #run() { + this.#running = true; + const queue = this.#queue; + while (!queue.isEmpty()) { + const node = queue.shift(); + if (node.promise !== null) { + await node.promise; + } + this.#socket.write(node.frame, node.callback); + node.callback = node.frame = null; + } + this.#running = false; + } + }; + function createFrame(data2, hint) { + return new WebsocketFrameSend(toBuffer(data2, hint)).createFrame(hint === sendHints.text ? opcodes.TEXT : opcodes.BINARY); + } + function toBuffer(data2, hint) { + switch (hint) { + case sendHints.text: + case sendHints.typedArray: + return new Uint8Array(data2.buffer, data2.byteOffset, data2.byteLength); + case sendHints.arrayBuffer: + case sendHints.blob: + return new Uint8Array(data2); + } + } + module2.exports = { SendQueue }; + } +}); + +// node_modules/undici/lib/web/websocket/websocket.js +var require_websocket2 = __commonJS({ + "node_modules/undici/lib/web/websocket/websocket.js"(exports2, module2) { + "use strict"; + var { isArrayBuffer } = require("node:util/types"); + var { webidl } = require_webidl(); + var { URLSerializer } = require_data_url(); + var { environmentSettingsObject } = require_util2(); + var { staticPropertyDescriptors, states, sentCloseFrameState, sendHints, opcodes } = require_constants6(); + var { + isConnecting, + isEstablished, + isClosing, + isClosed, + isValidSubprotocol, + fireEvent, + utf8Decode, + toArrayBuffer, + getURLRecord + } = require_util5(); + var { establishWebSocketConnection, closeWebSocketConnection, failWebsocketConnection } = require_connection(); + var { ByteParser } = require_receiver2(); + var { kEnumerableProperty } = require_util(); + var { getGlobalDispatcher } = require_global2(); + var { ErrorEvent: ErrorEvent2, CloseEvent: CloseEvent2, createFastMessageEvent } = require_events(); + var { SendQueue } = require_sender2(); + var { WebsocketFrameSend } = require_frame(); + var { channels } = require_diagnostics(); + var kRef = /* @__PURE__ */ Symbol.for("nodejs.ref"); + var kUnref = /* @__PURE__ */ Symbol.for("nodejs.unref"); + function getSocketAddress(socket) { + if (typeof socket?.address === "function") { + return socket.address(); + } + if (typeof socket?.session?.socket?.address === "function") { + return socket.session.socket.address(); + } + return null; + } + var WebSocket3 = class _WebSocket extends EventTarget { + #events = { + open: null, + error: null, + close: null, + message: null + }; + #bufferedAmount = 0; + #protocol = ""; + #extensions = ""; + #refed = true; + /** @type {SendQueue} */ + #sendQueue; + /** @type {Handler} */ + #handler = { + onConnectionEstablished: (response, extensions) => this.#onConnectionEstablished(response, extensions), + onMessage: (opcode, data2) => this.#onMessage(opcode, data2), + onParserError: (err) => failWebsocketConnection(this.#handler, null, err.message), + onParserDrain: () => this.#onParserDrain(), + onSocketData: (chunk) => { + if (!this.#parser.write(chunk)) { + this.#handler.socket.pause(); + } + }, + onSocketError: (err) => { + this.#handler.readyState = states.CLOSING; + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(err); + } + this.#handler.socket.destroy(); + }, + onSocketClose: () => this.#onSocketClose(), + onPing: (body2) => { + if (channels.ping.hasSubscribers) { + channels.ping.publish({ + payload: body2, + websocket: this + }); + } + }, + onPong: (body2) => { + if (channels.pong.hasSubscribers) { + channels.pong.publish({ + payload: body2, + websocket: this + }); + } + }, + readyState: states.CONNECTING, + socket: null, + closeState: /* @__PURE__ */ new Set(), + controller: null, + wasEverConnected: false + }; + #url; + #binaryType; + /** @type {import('./receiver').ByteParser} */ + #parser; + /** + * @param {string} url + * @param {string|string[]} protocols + */ + constructor(url2, protocols = []) { + super(); + webidl.util.markAsUncloneable(this); + const prefix2 = "WebSocket constructor"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + const options2 = webidl.converters["DOMString or sequence or WebSocketInit"](protocols, prefix2, "options"); + url2 = webidl.converters.USVString(url2); + protocols = options2.protocols; + const baseURL = environmentSettingsObject.settingsObject.baseUrl; + const urlRecord = getURLRecord(url2, baseURL); + if (typeof protocols === "string") { + protocols = [protocols]; + } + if (protocols.length !== new Set(protocols.map((p) => p.toLowerCase())).size) { + throw new DOMException("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); + } + if (protocols.length > 0 && !protocols.every((p) => isValidSubprotocol(p))) { + throw new DOMException("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); + } + this.#url = new URL(urlRecord.href); + const client = environmentSettingsObject.settingsObject; + this.#handler.controller = establishWebSocketConnection( + urlRecord, + protocols, + client, + this.#handler, + options2 + ); + this.#handler.readyState = _WebSocket.CONNECTING; + this.#binaryType = "blob"; + } + [kRef]() { + webidl.brandCheck(this, _WebSocket); + this.#refed = true; + this.#handler.socket?.ref?.(); + } + [kUnref]() { + webidl.brandCheck(this, _WebSocket); + this.#refed = false; + this.#handler.socket?.unref?.(); + } + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-close + * @param {number|undefined} code + * @param {string|undefined} reason + */ + close(code = void 0, reason2 = void 0) { + webidl.brandCheck(this, _WebSocket); + const prefix2 = "WebSocket.close"; + if (code !== void 0) { + code = webidl.converters["unsigned short"](code, prefix2, "code", webidl.attributes.Clamp); + } + if (reason2 !== void 0) { + reason2 = webidl.converters.USVString(reason2); + } + code ??= null; + reason2 ??= ""; + closeWebSocketConnection(this.#handler, code, reason2, true); + } + /** + * @see https://websockets.spec.whatwg.org/#dom-websocket-send + * @param {NodeJS.TypedArray|ArrayBuffer|Blob|string} data + */ + send(data2) { + webidl.brandCheck(this, _WebSocket); + const prefix2 = "WebSocket.send"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + data2 = webidl.converters.WebSocketSendData(data2, prefix2, "data"); + if (isConnecting(this.#handler.readyState)) { + throw new DOMException("Sent before connected.", "InvalidStateError"); + } + if (!isEstablished(this.#handler.readyState) || isClosing(this.#handler.readyState)) { + return; + } + if (typeof data2 === "string") { + const buffer2 = Buffer.from(data2); + this.#bufferedAmount += buffer2.byteLength; + this.#sendQueue.add(buffer2, () => { + this.#bufferedAmount -= buffer2.byteLength; + }, sendHints.text); + } else if (isArrayBuffer(data2)) { + this.#bufferedAmount += data2.byteLength; + this.#sendQueue.add(data2, () => { + this.#bufferedAmount -= data2.byteLength; + }, sendHints.arrayBuffer); + } else if (ArrayBuffer.isView(data2)) { + this.#bufferedAmount += data2.byteLength; + this.#sendQueue.add(data2, () => { + this.#bufferedAmount -= data2.byteLength; + }, sendHints.typedArray); + } else if (webidl.is.Blob(data2)) { + this.#bufferedAmount += data2.size; + this.#sendQueue.add(data2, () => { + this.#bufferedAmount -= data2.size; + }, sendHints.blob); + } + } + get readyState() { + webidl.brandCheck(this, _WebSocket); + return this.#handler.readyState; + } + get bufferedAmount() { + webidl.brandCheck(this, _WebSocket); + return this.#bufferedAmount; + } + get url() { + webidl.brandCheck(this, _WebSocket); + return URLSerializer(this.#url); + } + get extensions() { + webidl.brandCheck(this, _WebSocket); + return this.#extensions; + } + get protocol() { + webidl.brandCheck(this, _WebSocket); + return this.#protocol; + } + get onopen() { + webidl.brandCheck(this, _WebSocket); + return this.#events.open; + } + set onopen(fn) { + webidl.brandCheck(this, _WebSocket); + if (this.#events.open) { + this.removeEventListener("open", this.#events.open); + } + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("open", listener); + this.#events.open = fn; + } else { + this.#events.open = null; + } + } + get onerror() { + webidl.brandCheck(this, _WebSocket); + return this.#events.error; + } + set onerror(fn) { + webidl.brandCheck(this, _WebSocket); + if (this.#events.error) { + this.removeEventListener("error", this.#events.error); + } + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("error", listener); + this.#events.error = fn; + } else { + this.#events.error = null; + } + } + get onclose() { + webidl.brandCheck(this, _WebSocket); + return this.#events.close; + } + set onclose(fn) { + webidl.brandCheck(this, _WebSocket); + if (this.#events.close) { + this.removeEventListener("close", this.#events.close); + } + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("close", listener); + this.#events.close = fn; + } else { + this.#events.close = null; + } + } + get onmessage() { + webidl.brandCheck(this, _WebSocket); + return this.#events.message; + } + set onmessage(fn) { + webidl.brandCheck(this, _WebSocket); + if (this.#events.message) { + this.removeEventListener("message", this.#events.message); + } + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("message", listener); + this.#events.message = fn; + } else { + this.#events.message = null; + } + } + get binaryType() { + webidl.brandCheck(this, _WebSocket); + return this.#binaryType; + } + set binaryType(type2) { + webidl.brandCheck(this, _WebSocket); + if (type2 !== "blob" && type2 !== "arraybuffer") { + this.#binaryType = "blob"; + } else { + this.#binaryType = type2; + } + } + /** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + */ + #onConnectionEstablished(response, parsedExtensions) { + this.#handler.socket = response.socket; + if (!this.#refed) { + this.#handler.socket.unref?.(); + } + const maxFragments = this.#handler.controller.dispatcher?.webSocketOptions?.maxFragments; + const maxPayloadSize = this.#handler.controller.dispatcher?.webSocketOptions?.maxPayloadSize; + const parser = new ByteParser(this.#handler, parsedExtensions, { + maxFragments, + maxPayloadSize + }); + parser.on("drain", () => this.#handler.onParserDrain()); + parser.on("error", (err) => this.#handler.onParserError(err)); + this.#parser = parser; + this.#sendQueue = new SendQueue(response.socket); + this.#handler.readyState = states.OPEN; + const extensions = response.headersList.get("sec-websocket-extensions"); + if (extensions !== null) { + this.#extensions = extensions; + } + const protocol = response.headersList.get("sec-websocket-protocol"); + if (protocol !== null) { + this.#protocol = protocol; + } + fireEvent("open", this); + if (channels.open.hasSubscribers) { + const headers2 = response.headersList.entries; + channels.open.publish({ + address: getSocketAddress(response.socket), + protocol: this.#protocol, + extensions: this.#extensions, + websocket: this, + handshakeResponse: { + status: response.status, + statusText: response.statusText, + headers: headers2 + } + }); + } + } + #onMessage(type2, data2) { + if (this.#handler.readyState !== states.OPEN) { + return; + } + let dataForEvent; + if (type2 === opcodes.TEXT) { + try { + dataForEvent = utf8Decode(data2); + } catch { + failWebsocketConnection(this.#handler, 1007, "Received invalid UTF-8 in text frame."); + return; + } + } else if (type2 === opcodes.BINARY) { + if (this.#binaryType === "blob") { + dataForEvent = new Blob([data2]); + } else { + dataForEvent = toArrayBuffer(data2); + } + } + fireEvent("message", this, createFastMessageEvent, { + origin: this.#url.origin, + data: dataForEvent + }); + } + #onParserDrain() { + this.#handler.socket.resume(); + } + /** + * @see https://websockets.spec.whatwg.org/#feedback-from-the-protocol + * @see https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.4 + */ + #onSocketClose() { + const wasClean = this.#handler.closeState.has(sentCloseFrameState.SENT) && this.#handler.closeState.has(sentCloseFrameState.RECEIVED); + let code = 1005; + let reason2 = ""; + const result3 = this.#parser?.closingInfo; + if (result3 && !result3.error) { + code = result3.code ?? 1005; + reason2 = result3.reason; + } + this.#handler.readyState = states.CLOSED; + if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + code = 1006; + fireEvent("error", this, (type2, init) => new ErrorEvent2(type2, init), { + error: new TypeError(reason2) + }); + } + fireEvent("close", this, (type2, init) => new CloseEvent2(type2, init), { + wasClean, + code, + reason: reason2 + }); + if (channels.close.hasSubscribers) { + channels.close.publish({ + websocket: this, + code, + reason: reason2 + }); + } + } + /** + * @param {WebSocket} ws + * @param {Buffer|undefined} buffer + */ + static ping(ws, buffer2) { + if (Buffer.isBuffer(buffer2)) { + if (buffer2.length > 125) { + throw new TypeError("A PING frame cannot have a body larger than 125 bytes."); + } + } else if (buffer2 !== void 0) { + throw new TypeError("Expected buffer payload"); + } + const readyState2 = ws.#handler.readyState; + if (isEstablished(readyState2) && !isClosing(readyState2) && !isClosed(readyState2)) { + const frame = new WebsocketFrameSend(buffer2); + ws.#handler.socket.write(frame.createFrame(opcodes.PING)); + } + } + }; + var { ping } = WebSocket3; + Reflect.deleteProperty(WebSocket3, "ping"); + WebSocket3.CONNECTING = WebSocket3.prototype.CONNECTING = states.CONNECTING; + WebSocket3.OPEN = WebSocket3.prototype.OPEN = states.OPEN; + WebSocket3.CLOSING = WebSocket3.prototype.CLOSING = states.CLOSING; + WebSocket3.CLOSED = WebSocket3.prototype.CLOSED = states.CLOSED; + Object.defineProperties(WebSocket3.prototype, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors, + url: kEnumerableProperty, + readyState: kEnumerableProperty, + bufferedAmount: kEnumerableProperty, + onopen: kEnumerableProperty, + onerror: kEnumerableProperty, + onclose: kEnumerableProperty, + close: kEnumerableProperty, + onmessage: kEnumerableProperty, + binaryType: kEnumerableProperty, + send: kEnumerableProperty, + extensions: kEnumerableProperty, + protocol: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "WebSocket", + writable: false, + enumerable: false, + configurable: true + } + }); + Object.defineProperties(WebSocket3, { + CONNECTING: staticPropertyDescriptors, + OPEN: staticPropertyDescriptors, + CLOSING: staticPropertyDescriptors, + CLOSED: staticPropertyDescriptors + }); + webidl.converters["sequence"] = webidl.sequenceConverter( + webidl.converters.DOMString + ); + webidl.converters["DOMString or sequence"] = function(V, prefix2, argument) { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT && Symbol.iterator in V) { + return webidl.converters["sequence"](V); + } + return webidl.converters.DOMString(V, prefix2, argument); + }; + webidl.converters.WebSocketInit = webidl.dictionaryConverter([ + { + key: "protocols", + converter: webidl.converters["DOMString or sequence"], + defaultValue: () => [] + }, + { + key: "dispatcher", + converter: webidl.converters.any, + defaultValue: () => getGlobalDispatcher() + }, + { + key: "headers", + converter: webidl.nullableConverter(webidl.converters.HeadersInit) + } + ]); + webidl.converters["DOMString or sequence or WebSocketInit"] = function(V) { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT && !(Symbol.iterator in V)) { + return webidl.converters.WebSocketInit(V); + } + return { protocols: webidl.converters["DOMString or sequence"](V) }; + }; + webidl.converters.WebSocketSendData = function(V) { + if (webidl.util.Type(V) === webidl.util.Types.OBJECT) { + if (webidl.is.Blob(V)) { + return V; + } + if (webidl.is.BufferSource(V)) { + return V; + } + } + return webidl.converters.USVString(V); + }; + module2.exports = { + WebSocket: WebSocket3, + ping + }; + } +}); + +// node_modules/undici/lib/web/websocket/stream/websocketerror.js +var require_websocketerror = __commonJS({ + "node_modules/undici/lib/web/websocket/stream/websocketerror.js"(exports2, module2) { + "use strict"; + var { webidl } = require_webidl(); + var { validateCloseCodeAndReason } = require_util5(); + var { kConstruct } = require_symbols(); + var { kEnumerableProperty } = require_util(); + function createInheritableDOMException() { + class Test extends DOMException { + get reason() { + return ""; + } + } + if (new Test().reason !== void 0) { + return DOMException; + } + return new Proxy(DOMException, { + construct(target2, args, newTarget) { + const instance = Reflect.construct(target2, args, target2); + Object.setPrototypeOf(instance, newTarget.prototype); + return instance; + } + }); + } + var WebSocketError = class _WebSocketError extends createInheritableDOMException() { + #closeCode; + #reason; + constructor(message = "", init = void 0) { + message = webidl.converters.DOMString(message, "WebSocketError", "message"); + super(message, "WebSocketError"); + if (init === kConstruct) { + return; + } else if (init !== null) { + init = webidl.converters.WebSocketCloseInfo(init); + } + let code = init.closeCode ?? null; + const reason2 = init.reason ?? ""; + validateCloseCodeAndReason(code, reason2); + if (reason2.length !== 0 && code === null) { + code = 1e3; + } + this.#closeCode = code; + this.#reason = reason2; + } + get closeCode() { + return this.#closeCode; + } + get reason() { + return this.#reason; + } + /** + * @param {string} message + * @param {number|null} code + * @param {string} reason + */ + static createUnvalidatedWebSocketError(message, code, reason2) { + const error2 = new _WebSocketError(message, kConstruct); + error2.#closeCode = code; + error2.#reason = reason2; + return error2; + } + }; + var { createUnvalidatedWebSocketError } = WebSocketError; + delete WebSocketError.createUnvalidatedWebSocketError; + Object.defineProperties(WebSocketError.prototype, { + closeCode: kEnumerableProperty, + reason: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "WebSocketError", + writable: false, + enumerable: false, + configurable: true + } + }); + webidl.is.WebSocketError = webidl.util.MakeTypeAssertion(WebSocketError); + module2.exports = { WebSocketError, createUnvalidatedWebSocketError }; + } +}); + +// node_modules/undici/lib/web/websocket/stream/websocketstream.js +var require_websocketstream = __commonJS({ + "node_modules/undici/lib/web/websocket/stream/websocketstream.js"(exports2, module2) { + "use strict"; + var { addAbortListener } = require("node:events"); + var { environmentSettingsObject, readableStreamClose } = require_util2(); + var { states, opcodes, sentCloseFrameState } = require_constants6(); + var { webidl } = require_webidl(); + var { getURLRecord, isValidSubprotocol, isEstablished, utf8Decode } = require_util5(); + var { establishWebSocketConnection, failWebsocketConnection, closeWebSocketConnection } = require_connection(); + var { channels } = require_diagnostics(); + var { WebsocketFrameSend } = require_frame(); + var { ByteParser } = require_receiver2(); + var { WebSocketError, createUnvalidatedWebSocketError } = require_websocketerror(); + var { kEnumerableProperty } = require_util(); + var { utf8DecodeBytes } = require_encoding(); + var emittedExperimentalWarning = false; + var WebSocketStream = class { + // Each WebSocketStream object has an associated url , which is a URL record . + /** @type {URL} */ + #url; + // Each WebSocketStream object has an associated opened promise , which is a promise. + /** @type {ReturnType} */ + #openedPromise; + // Each WebSocketStream object has an associated closed promise , which is a promise. + /** @type {ReturnType} */ + #closedPromise; + // Each WebSocketStream object has an associated readable stream , which is a ReadableStream . + /** @type {ReadableStream} */ + #readableStream; + /** @type {ReadableStreamDefaultController} */ + #readableStreamController; + // Each WebSocketStream object has an associated writable stream , which is a WritableStream . + /** @type {WritableStream} */ + #writableStream; + // Each WebSocketStream object has an associated boolean handshake aborted , which is initially false. + #handshakeAborted = false; + /** @type {import('../websocket').Handler} */ + #handler = { + // https://whatpr.org/websockets/48/7b748d3...d5570f3.html#feedback-to-websocket-stream-from-the-protocol + onConnectionEstablished: (response, extensions) => this.#onConnectionEstablished(response, extensions), + onMessage: (opcode, data2) => this.#onMessage(opcode, data2), + onParserError: (err) => failWebsocketConnection(this.#handler, null, err.message), + onParserDrain: () => this.#handler.socket.resume(), + onSocketData: (chunk) => { + if (!this.#parser.write(chunk)) { + this.#handler.socket.pause(); + } + }, + onSocketError: (err) => { + this.#handler.readyState = states.CLOSING; + if (channels.socketError.hasSubscribers) { + channels.socketError.publish(err); + } + this.#handler.socket.destroy(); + }, + onSocketClose: () => this.#onSocketClose(), + onPing: () => { + }, + onPong: () => { + }, + readyState: states.CONNECTING, + socket: null, + closeState: /* @__PURE__ */ new Set(), + controller: null, + wasEverConnected: false + }; + /** @type {import('../receiver').ByteParser} */ + #parser; + constructor(url2, options2 = void 0) { + if (!emittedExperimentalWarning) { + process.emitWarning("WebSocketStream is experimental! Expect it to change at any time.", { + code: "UNDICI-WSS" + }); + emittedExperimentalWarning = true; + } + webidl.argumentLengthCheck(arguments, 1, "WebSocket"); + url2 = webidl.converters.USVString(url2); + if (options2 !== null) { + options2 = webidl.converters.WebSocketStreamOptions(options2); + } + const baseURL = environmentSettingsObject.settingsObject.baseUrl; + const urlRecord = getURLRecord(url2, baseURL); + const protocols = options2.protocols; + if (protocols.length !== new Set(protocols.map((p) => p.toLowerCase())).size) { + throw new DOMException("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); + } + if (protocols.length > 0 && !protocols.every((p) => isValidSubprotocol(p))) { + throw new DOMException("Invalid Sec-WebSocket-Protocol value", "SyntaxError"); + } + this.#url = urlRecord.toString(); + this.#openedPromise = Promise.withResolvers(); + this.#closedPromise = Promise.withResolvers(); + if (options2.signal != null) { + const signal2 = options2.signal; + if (signal2.aborted) { + this.#openedPromise.reject(signal2.reason); + this.#closedPromise.reject(signal2.reason); + return; + } + addAbortListener(signal2, () => { + if (!isEstablished(this.#handler.readyState)) { + failWebsocketConnection(this.#handler); + this.#handler.readyState = states.CLOSING; + this.#openedPromise.reject(signal2.reason); + this.#closedPromise.reject(signal2.reason); + this.#handshakeAborted = true; + } + }); + } + const client = environmentSettingsObject.settingsObject; + this.#handler.controller = establishWebSocketConnection( + urlRecord, + protocols, + client, + this.#handler, + options2 + ); + } + // The url getter steps are to return this 's url , serialized . + get url() { + return this.#url.toString(); + } + // The opened getter steps are to return this 's opened promise . + get opened() { + return this.#openedPromise.promise; + } + // The closed getter steps are to return this 's closed promise . + get closed() { + return this.#closedPromise.promise; + } + // The close( closeInfo ) method steps are: + close(closeInfo = void 0) { + if (closeInfo !== null) { + closeInfo = webidl.converters.WebSocketCloseInfo(closeInfo); + } + const code = closeInfo.closeCode ?? null; + const reason2 = closeInfo.reason; + closeWebSocketConnection(this.#handler, code, reason2, true); + } + #write(chunk) { + chunk = webidl.converters.WebSocketStreamWrite(chunk); + const promise = Promise.withResolvers(); + let data2 = null; + let opcode = null; + if (webidl.is.BufferSource(chunk)) { + data2 = new Uint8Array(ArrayBuffer.isView(chunk) ? new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength) : chunk.slice()); + opcode = opcodes.BINARY; + } else { + let string; + try { + string = webidl.converters.DOMString(chunk); + } catch (e) { + promise.reject(e); + return promise.promise; + } + data2 = new TextEncoder().encode(string); + opcode = opcodes.TEXT; + } + if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + const frame = new WebsocketFrameSend(data2); + this.#handler.socket.write(frame.createFrame(opcode), () => { + promise.resolve(void 0); + }); + } + return promise.promise; + } + /** @type {import('../websocket').Handler['onConnectionEstablished']} */ + #onConnectionEstablished(response, parsedExtensions) { + this.#handler.socket = response.socket; + const maxFragments = this.#handler.controller.dispatcher?.webSocketOptions?.maxFragments; + const maxPayloadSize = this.#handler.controller.dispatcher?.webSocketOptions?.maxPayloadSize; + const parser = new ByteParser(this.#handler, parsedExtensions, { + maxFragments, + maxPayloadSize + }); + parser.on("drain", () => this.#handler.onParserDrain()); + parser.on("error", (err) => this.#handler.onParserError(err)); + this.#parser = parser; + this.#handler.readyState = states.OPEN; + const extensions = parsedExtensions ?? ""; + const protocol = response.headersList.get("sec-websocket-protocol") ?? ""; + const readable = new ReadableStream({ + start: (controller) => { + this.#readableStreamController = controller; + }, + cancel: (reason2) => this.#cancel(reason2) + }); + const writable = new WritableStream({ + write: (chunk) => this.#write(chunk), + close: () => closeWebSocketConnection(this.#handler, null, null), + abort: (reason2) => this.#closeUsingReason(reason2) + }); + this.#readableStream = readable; + this.#writableStream = writable; + this.#openedPromise.resolve({ + extensions, + protocol, + readable, + writable + }); + } + /** @type {import('../websocket').Handler['onMessage']} */ + #onMessage(type2, data2) { + if (this.#handler.readyState !== states.OPEN) { + return; + } + let chunk; + if (type2 === opcodes.TEXT) { + try { + chunk = utf8Decode(data2); + } catch { + failWebsocketConnection(this.#handler, 1007, "Received invalid UTF-8 in text frame."); + return; + } + } else if (type2 === opcodes.BINARY) { + chunk = new Uint8Array(data2.buffer, data2.byteOffset, data2.byteLength); + } + this.#readableStreamController.enqueue(chunk); + } + /** @type {import('../websocket').Handler['onSocketClose']} */ + #onSocketClose() { + const wasClean = this.#handler.closeState.has(sentCloseFrameState.SENT) && this.#handler.closeState.has(sentCloseFrameState.RECEIVED); + this.#handler.readyState = states.CLOSED; + if (this.#handshakeAborted) { + return; + } + if (!this.#handler.wasEverConnected) { + this.#openedPromise.reject(new WebSocketError("Socket never opened")); + } + const result3 = this.#parser?.closingInfo; + let code = result3?.code ?? 1005; + if (!this.#handler.closeState.has(sentCloseFrameState.SENT) && !this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) { + code = 1006; + } + const reason2 = result3?.reason == null ? "" : utf8DecodeBytes(Buffer.from(result3.reason)); + if (wasClean) { + readableStreamClose(this.#readableStreamController); + if (!this.#writableStream.locked) { + this.#writableStream.abort(new DOMException("A closed WebSocketStream cannot be written to", "InvalidStateError")); + } + this.#closedPromise.resolve({ + closeCode: code, + reason: reason2 + }); + } else { + const error2 = createUnvalidatedWebSocketError("unclean close", code, reason2); + this.#readableStreamController?.error(error2); + this.#writableStream?.abort(error2); + this.#closedPromise.reject(error2); + } + } + #closeUsingReason(reason2) { + let code = null; + let reasonString = ""; + if (webidl.is.WebSocketError(reason2)) { + code = reason2.closeCode; + reasonString = reason2.reason; + } + closeWebSocketConnection(this.#handler, code, reasonString); + } + // To cancel a WebSocketStream stream given reason , close using reason giving stream and reason . + #cancel(reason2) { + this.#closeUsingReason(reason2); + } + }; + Object.defineProperties(WebSocketStream.prototype, { + url: kEnumerableProperty, + opened: kEnumerableProperty, + closed: kEnumerableProperty, + close: kEnumerableProperty, + [Symbol.toStringTag]: { + value: "WebSocketStream", + writable: false, + enumerable: false, + configurable: true + } + }); + webidl.converters.WebSocketStreamOptions = webidl.dictionaryConverter([ + { + key: "protocols", + converter: webidl.sequenceConverter(webidl.converters.USVString), + defaultValue: () => [] + }, + { + key: "signal", + converter: webidl.nullableConverter(webidl.converters.AbortSignal), + defaultValue: () => null + } + ]); + webidl.converters.WebSocketCloseInfo = webidl.dictionaryConverter([ + { + key: "closeCode", + converter: (V) => webidl.converters["unsigned short"](V, webidl.attributes.EnforceRange) + }, + { + key: "reason", + converter: webidl.converters.USVString, + defaultValue: () => "" + } + ]); + webidl.converters.WebSocketStreamWrite = function(V) { + if (typeof V === "string") { + return webidl.converters.USVString(V); + } + return webidl.converters.BufferSource(V); + }; + module2.exports = { WebSocketStream }; + } +}); + +// node_modules/undici/lib/web/eventsource/util.js +var require_util6 = __commonJS({ + "node_modules/undici/lib/web/eventsource/util.js"(exports2, module2) { + "use strict"; + var { makeRequest } = require_request2(); + function isValidLastEventId(value2) { + return value2.indexOf("\0") === -1; + } + function isASCIINumber(value2) { + if (value2.length === 0) return false; + for (let i = 0; i < value2.length; i++) { + if (value2.charCodeAt(i) < 48 || value2.charCodeAt(i) > 57) return false; + } + return true; + } + function createPotentialCORSRequest(url2, destination, corsAttributeState, sameOriginFallback) { + let mode2 = corsAttributeState === "no cors" ? "no-cors" : "cors"; + if (sameOriginFallback && mode2 === "no-cors") { + mode2 = "same-origin"; + } + let credentialsMode = "include"; + if (corsAttributeState === "anonymous") { + credentialsMode = "same-origin"; + } + return makeRequest({ + urlList: [url2], + destination, + mode: mode2, + credentials: credentialsMode, + useURLCredentials: true + }); + } + module2.exports = { + isValidLastEventId, + isASCIINumber, + createPotentialCORSRequest + }; + } +}); + +// node_modules/undici/lib/web/eventsource/eventsource-stream.js +var require_eventsource_stream = __commonJS({ + "node_modules/undici/lib/web/eventsource/eventsource-stream.js"(exports2, module2) { + "use strict"; + var { Transform } = require("node:stream"); + var { isASCIINumber, isValidLastEventId } = require_util6(); + var BOM = [239, 187, 191]; + var LF = 10; + var CR = 13; + var COLON = 58; + var SPACE = 32; + var DATA = Buffer.from("data"); + var EVENT = Buffer.from("event"); + var ID = Buffer.from("id"); + var RETRY = Buffer.from("retry"); + function isASCIINumberBytes(buffer2, start2) { + if (start2 >= buffer2.length) { + return false; + } + for (let i = start2; i < buffer2.length; i++) { + if (buffer2[i] < 48 || buffer2[i] > 57) { + return false; + } + } + return true; + } + function isValidLastEventIdBytes(buffer2, start2) { + for (let i = start2; i < buffer2.length; i++) { + if (buffer2[i] === 0) { + return false; + } + } + return true; + } + function isFieldName(line, length2, field) { + if (length2 !== field.length) { + return false; + } + for (let i = 0; i < length2; i++) { + if (line[i] !== field[i]) { + return false; + } + } + return true; + } + var EventSourceStream = class extends Transform { + /** + * @type {eventSourceSettings} + */ + state; + /** + * Leading byte-order-mark check. + * @type {boolean} + */ + checkBOM = true; + /** + * @type {boolean} + */ + crlfCheck = false; + /** + * @type {boolean} + */ + eventEndCheck = false; + /** + * @type {Buffer[]} + */ + chunks = []; + chunkIndex = 0; + pos = 0; + lineChunkIndex = 0; + linePos = 0; + event = { + data: void 0, + event: void 0, + id: void 0, + retry: void 0 + }; + /** + * @param {object} options + * @param {boolean} [options.readableObjectMode] + * @param {eventSourceSettings} [options.eventSourceSettings] + * @param {(chunk: any, encoding?: BufferEncoding | undefined) => boolean} [options.push] + */ + constructor(options2 = {}) { + options2.readableObjectMode = true; + super(options2); + this.state = options2.eventSourceSettings || {}; + if (options2.push) { + this.push = options2.push; + } + } + /** + * @param {Buffer} chunk + * @param {string} _encoding + * @param {Function} callback + * @returns {void} + */ + _transform(chunk, _encoding, callback) { + if (chunk.length === 0) { + callback(); + return; + } + this.chunks.push(chunk); + if (this.checkBOM) { + if (this.handleBOM()) { + callback(); + return; + } + } + while (this.hasCurrentByte()) { + const byte = this.currentByte(); + if (this.eventEndCheck) { + if (this.crlfCheck) { + if (byte === LF) { + this.crlfCheck = false; + this.consumeCurrentByte(); + continue; + } + this.crlfCheck = false; + } + if (byte === LF || byte === CR) { + if (byte === CR) { + this.crlfCheck = true; + } + this.consumeCurrentByte(); + if (this.hasPendingEvent()) { + this.processEvent(this.event); + } + this.clearEvent(); + continue; + } + this.eventEndCheck = false; + continue; + } + if (byte === LF || byte === CR) { + if (byte === CR) { + this.crlfCheck = true; + } + this.parseLine(this.readLine(), this.event); + this.consumeCurrentByte(); + this.eventEndCheck = true; + continue; + } + this.advanceCursor(); + } + callback(); + } + /** + * @param {Buffer} line + * @param {EventSourceStreamEvent} event + */ + parseLine(line, event) { + if (line.length === 0) { + return; + } + const colonPosition = line.indexOf(COLON); + if (colonPosition === 0) { + return; + } + let fieldLength = line.length; + let valueStart = line.length; + if (colonPosition !== -1) { + fieldLength = colonPosition; + valueStart = colonPosition + 1; + if (line[valueStart] === SPACE) { + ++valueStart; + } + } + if (isFieldName(line, fieldLength, DATA)) { + const value2 = line.toString("utf8", valueStart); + if (event.data === void 0) { + event.data = value2; + } else { + event.data += ` +${value2}`; + } + return; + } + if (isFieldName(line, fieldLength, RETRY)) { + if (isASCIINumberBytes(line, valueStart)) { + event.retry = line.toString("utf8", valueStart); + } + return; + } + if (isFieldName(line, fieldLength, ID)) { + if (isValidLastEventIdBytes(line, valueStart)) { + event.id = line.toString("utf8", valueStart); + } + return; + } + if (isFieldName(line, fieldLength, EVENT)) { + const value2 = line.toString("utf8", valueStart); + if (value2.length > 0) { + event.event = value2; + } + } + } + /** + * @param {EventSourceStreamEvent} event + */ + processEvent(event) { + if (event.retry && isASCIINumber(event.retry)) { + this.state.reconnectionTime = parseInt(event.retry, 10); + } + if (event.id !== void 0 && isValidLastEventId(event.id)) { + this.state.lastEventId = event.id; + } + if (event.data !== void 0) { + this.push({ + type: event.event || "message", + options: { + data: event.data, + lastEventId: this.state.lastEventId, + origin: this.state.origin + } + }); + } + } + clearEvent() { + this.event.data = void 0; + this.event.event = void 0; + this.event.id = void 0; + this.event.retry = void 0; + } + hasPendingEvent() { + return this.event.data !== void 0 || this.event.event !== void 0 || this.event.id !== void 0 || this.event.retry !== void 0; + } + hasCurrentByte() { + return this.chunkIndex < this.chunks.length && this.pos < this.chunks[this.chunkIndex].length; + } + currentByte() { + return this.chunks[this.chunkIndex][this.pos]; + } + consumeCurrentByte() { + this.advanceCursor(); + this.syncLineStartToCursor(); + } + advanceCursor() { + this.pos++; + while (this.chunkIndex < this.chunks.length && this.pos >= this.chunks[this.chunkIndex].length) { + this.chunkIndex++; + this.pos = 0; + } + } + syncLineStartToCursor() { + this.lineChunkIndex = this.chunkIndex; + this.linePos = this.pos; + this.dropConsumedChunks(); + } + dropConsumedChunks() { + while (this.lineChunkIndex > 0) { + this.chunks.shift(); + this.lineChunkIndex--; + this.chunkIndex--; + } + if (this.chunkIndex === this.chunks.length) { + this.chunks.length = 0; + this.chunkIndex = 0; + this.pos = 0; + this.lineChunkIndex = 0; + this.linePos = 0; + } + } + readLine() { + if (this.lineChunkIndex === this.chunkIndex) { + return this.chunks[this.chunkIndex].subarray(this.linePos, this.pos); + } + const chunks = []; + let length2 = 0; + for (let i = this.lineChunkIndex; i <= this.chunkIndex; i++) { + const chunk = this.chunks[i]; + const start2 = i === this.lineChunkIndex ? this.linePos : 0; + const end2 = i === this.chunkIndex ? this.pos : chunk.length; + const slice = chunk.subarray(start2, end2); + length2 += slice.length; + chunks.push(slice); + } + return Buffer.concat(chunks, length2); + } + peekBufferedByte(offset2) { + let chunkIndex = this.lineChunkIndex; + let pos = this.linePos; + while (chunkIndex < this.chunks.length) { + const chunk = this.chunks[chunkIndex]; + const remaining = chunk.length - pos; + if (offset2 < remaining) { + return chunk[pos + offset2]; + } + offset2 -= remaining; + chunkIndex++; + pos = 0; + } + } + discardLeadingBytes(count) { + while (count > 0 && this.lineChunkIndex < this.chunks.length) { + const chunk = this.chunks[this.lineChunkIndex]; + const remaining = chunk.length - this.linePos; + if (count < remaining) { + this.linePos += count; + count = 0; + } else { + count -= remaining; + this.lineChunkIndex++; + this.linePos = 0; + } + } + this.chunkIndex = this.lineChunkIndex; + this.pos = this.linePos; + this.dropConsumedChunks(); + } + handleBOM() { + const first = this.peekBufferedByte(0); + const second = this.peekBufferedByte(1); + const third = this.peekBufferedByte(2); + if (second === void 0) { + if (first === BOM[0]) { + return true; + } + this.checkBOM = false; + return true; + } + if (third === void 0) { + if (first === BOM[0] && second === BOM[1]) { + return true; + } + this.checkBOM = false; + return false; + } + if (first === BOM[0] && second === BOM[1] && third === BOM[2]) { + this.discardLeadingBytes(3); + } + this.checkBOM = false; + return !this.hasCurrentByte(); + } + }; + module2.exports = { + EventSourceStream + }; + } +}); + +// node_modules/undici/lib/web/eventsource/eventsource.js +var require_eventsource = __commonJS({ + "node_modules/undici/lib/web/eventsource/eventsource.js"(exports2, module2) { + "use strict"; + var { pipeline } = require("node:stream"); + var { fetching } = require_fetch(); + var { webidl } = require_webidl(); + var { EventSourceStream } = require_eventsource_stream(); + var { parseMIMEType } = require_data_url(); + var { createFastMessageEvent } = require_events(); + var { isNetworkError } = require_response(); + var { kEnumerableProperty } = require_util(); + var { environmentSettingsObject } = require_util2(); + var { createPotentialCORSRequest } = require_util6(); + var experimentalWarned = false; + var defaultReconnectionTime = 3e3; + var CONNECTING = 0; + var OPEN = 1; + var CLOSED = 2; + var ANONYMOUS = "anonymous"; + var USE_CREDENTIALS = "use-credentials"; + var EventSource = class _EventSource extends EventTarget { + #events = { + open: null, + error: null, + message: null + }; + #url; + #withCredentials = false; + /** + * @type {ReadyState} + */ + #readyState = CONNECTING; + #request = null; + #controller = null; + #dispatcher; + /** + * @type {import('./eventsource-stream').eventSourceSettings} + */ + #state; + /** + * Creates a new EventSource object. + * @param {string} url + * @param {EventSourceInit} [eventSourceInitDict={}] + * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#the-eventsource-interface + */ + constructor(url2, eventSourceInitDict = {}) { + super(); + webidl.util.markAsUncloneable(this); + const prefix2 = "EventSource constructor"; + webidl.argumentLengthCheck(arguments, 1, prefix2); + if (!experimentalWarned) { + experimentalWarned = true; + process.emitWarning("EventSource is experimental, expect them to change at any time.", { + code: "UNDICI-ES" + }); + } + url2 = webidl.converters.USVString(url2); + eventSourceInitDict = webidl.converters.EventSourceInitDict(eventSourceInitDict, prefix2, "eventSourceInitDict"); + this.#dispatcher = eventSourceInitDict.node.dispatcher || eventSourceInitDict.dispatcher; + this.#state = { + lastEventId: "", + reconnectionTime: eventSourceInitDict.node.reconnectionTime + }; + const settings2 = environmentSettingsObject; + let urlRecord; + try { + urlRecord = new URL(url2, settings2.settingsObject.baseUrl); + this.#state.origin = urlRecord.origin; + } catch (e) { + throw new DOMException(e, "SyntaxError"); + } + this.#url = urlRecord.href; + let corsAttributeState = ANONYMOUS; + if (eventSourceInitDict.withCredentials === true) { + corsAttributeState = USE_CREDENTIALS; + this.#withCredentials = true; + } + const request = createPotentialCORSRequest(urlRecord, "", corsAttributeState); + request.client = environmentSettingsObject.settingsObject; + request.headersList.set("Accept", "text/event-stream"); + request.cache = "no-store"; + request.initiator = "other"; + this.#request = request; + this.#connect(); + } + /** + * Returns the state of this EventSource object's connection. It can have the + * values described below. + * @returns {ReadyState} + * @readonly + */ + get readyState() { + return this.#readyState; + } + /** + * Returns the URL providing the event stream. + * @readonly + * @returns {string} + */ + get url() { + return this.#url; + } + /** + * Returns a boolean indicating whether the EventSource object was + * instantiated with CORS credentials set (true), or not (false, the default). + */ + get withCredentials() { + return this.#withCredentials; + } + #connect() { + if (this.#readyState === CLOSED) return; + this.#readyState = CONNECTING; + const fetchParams = { + request: this.#request, + dispatcher: this.#dispatcher + }; + const processEventSourceEndOfBody = (response) => { + if (!isNetworkError(response)) { + return this.#reconnect(); + } + }; + fetchParams.processResponseEndOfBody = processEventSourceEndOfBody; + fetchParams.processResponse = (response) => { + if (isNetworkError(response)) { + if (response.aborted) { + this.close(); + this.dispatchEvent(new Event("error")); + return; + } else { + this.#reconnect(); + return; + } + } + const contentType2 = response.headersList.get("content-type", true); + const mimeType = contentType2 !== null ? parseMIMEType(contentType2) : "failure"; + const contentTypeValid = mimeType !== "failure" && mimeType.essence === "text/event-stream"; + if (response.status !== 200 || contentTypeValid === false) { + this.close(); + this.dispatchEvent(new Event("error")); + return; + } + this.#readyState = OPEN; + this.dispatchEvent(new Event("open")); + this.#state.origin = response.urlList[response.urlList.length - 1].origin; + const eventSourceStream = new EventSourceStream({ + eventSourceSettings: this.#state, + push: (event) => { + this.dispatchEvent(createFastMessageEvent( + event.type, + event.options + )); + } + }); + pipeline( + response.body.stream, + eventSourceStream, + (error2) => { + if (error2?.aborted === false) { + this.close(); + this.dispatchEvent(new Event("error")); + } + } + ); + }; + this.#controller = fetching(fetchParams); + } + /** + * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#sse-processing-model + * @returns {void} + */ + #reconnect() { + if (this.#readyState === CLOSED) return; + this.#readyState = CONNECTING; + this.dispatchEvent(new Event("error")); + setTimeout(() => { + if (this.#readyState !== CONNECTING) return; + if (this.#state.lastEventId.length) { + this.#request.headersList.set("last-event-id", this.#state.lastEventId, true); + } + this.#connect(); + }, this.#state.reconnectionTime)?.unref(); + } + /** + * Closes the connection, if any, and sets the readyState attribute to + * CLOSED. + */ + close() { + webidl.brandCheck(this, _EventSource); + if (this.#readyState === CLOSED) return; + this.#readyState = CLOSED; + this.#controller.abort(); + this.#request = null; + } + get onopen() { + return this.#events.open; + } + set onopen(fn) { + if (this.#events.open) { + this.removeEventListener("open", this.#events.open); + } + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("open", listener); + this.#events.open = fn; + } else { + this.#events.open = null; + } + } + get onmessage() { + return this.#events.message; + } + set onmessage(fn) { + if (this.#events.message) { + this.removeEventListener("message", this.#events.message); + } + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("message", listener); + this.#events.message = fn; + } else { + this.#events.message = null; + } + } + get onerror() { + return this.#events.error; + } + set onerror(fn) { + if (this.#events.error) { + this.removeEventListener("error", this.#events.error); + } + const listener = webidl.converters.EventHandlerNonNull(fn); + if (listener !== null) { + this.addEventListener("error", listener); + this.#events.error = fn; + } else { + this.#events.error = null; + } + } + }; + var constantsPropertyDescriptors = { + CONNECTING: { + __proto__: null, + configurable: false, + enumerable: true, + value: CONNECTING, + writable: false + }, + OPEN: { + __proto__: null, + configurable: false, + enumerable: true, + value: OPEN, + writable: false + }, + CLOSED: { + __proto__: null, + configurable: false, + enumerable: true, + value: CLOSED, + writable: false + } + }; + Object.defineProperties(EventSource, constantsPropertyDescriptors); + Object.defineProperties(EventSource.prototype, constantsPropertyDescriptors); + Object.defineProperties(EventSource.prototype, { + close: kEnumerableProperty, + onerror: kEnumerableProperty, + onmessage: kEnumerableProperty, + onopen: kEnumerableProperty, + readyState: kEnumerableProperty, + url: kEnumerableProperty, + withCredentials: kEnumerableProperty + }); + webidl.converters.EventSourceInitDict = webidl.dictionaryConverter([ + { + key: "withCredentials", + converter: webidl.converters.boolean, + defaultValue: () => false + }, + { + key: "dispatcher", + // undici only + converter: webidl.converters.any + }, + { + key: "node", + // undici only + converter: webidl.dictionaryConverter([ + { + key: "reconnectionTime", + converter: webidl.converters["unsigned long"], + defaultValue: () => defaultReconnectionTime + }, + { + key: "dispatcher", + converter: webidl.converters.any + } + ]), + defaultValue: () => ({}) + } + ]); + module2.exports = { + EventSource, + defaultReconnectionTime + }; + } +}); -// src/provider/providers.ts -var ZAI_PROVIDER = { - id: "zai", - displayName: "Z.AI", - anthropicBaseURL: "https://api.z.ai/api/anthropic", - openaiBaseURL: "https://api.z.ai/api/coding/paas/v4", - bizHost: "https://api.z.ai" -}; -var BIGMODEL_PROVIDER = { - id: "bigmodel", - displayName: "BigModel / \u667A\u8C31", - anthropicBaseURL: "https://open.bigmodel.cn/api/anthropic", - openaiBaseURL: "https://open.bigmodel.cn/api/coding/paas/v4", - bizHost: "https://open.bigmodel.cn" -}; -var PROVIDERS = { - zai: ZAI_PROVIDER, - bigmodel: BIGMODEL_PROVIDER -}; -function getProvider(id2) { - const def = PROVIDERS[id2]; - if (!def) { - throw new Error(`Unknown provider: "${id2}"`); +// node_modules/undici/index.js +var require_undici = __commonJS({ + "node_modules/undici/index.js"(exports2, module2) { + "use strict"; + var Client = require_client(); + var Dispatcher = require_dispatcher(); + var Pool = require_pool(); + var BalancedPool = require_balanced_pool(); + var RoundRobinPool = require_round_robin_pool(); + var Agent = require_agent(); + var Dispatcher1Wrapper = require_dispatcher1_wrapper(); + var ProxyAgent2 = require_proxy_agent(); + var Socks5ProxyAgent = require_socks5_proxy_agent(); + var EnvHttpProxyAgent = require_env_http_proxy_agent(); + var RetryAgent = require_retry_agent(); + var H2CClient = require_h2c_client(); + var errors = require_errors2(); + var util = require_util(); + var { InvalidArgumentError } = errors; + var api = require_api(); + var buildConnector = require_connect(); + var MockClient = require_mock_client(); + var { MockCallHistory, MockCallHistoryLog } = require_mock_call_history(); + var MockAgent = require_mock_agent(); + var MockPool = require_mock_pool(); + var SnapshotAgent = require_snapshot_agent(); + var mockErrors = require_mock_errors(); + var RetryHandler = require_retry_handler(); + var { getGlobalDispatcher, setGlobalDispatcher: setGlobalDispatcher2 } = require_global2(); + var DecoratorHandler = require_decorator_handler(); + var RedirectHandler = require_redirect_handler(); + Object.assign(Dispatcher.prototype, api); + module2.exports.Dispatcher = Dispatcher; + module2.exports.Client = Client; + module2.exports.Pool = Pool; + module2.exports.BalancedPool = BalancedPool; + module2.exports.RoundRobinPool = RoundRobinPool; + module2.exports.Agent = Agent; + module2.exports.Dispatcher1Wrapper = Dispatcher1Wrapper; + module2.exports.ProxyAgent = ProxyAgent2; + module2.exports.Socks5ProxyAgent = Socks5ProxyAgent; + module2.exports.EnvHttpProxyAgent = EnvHttpProxyAgent; + module2.exports.RetryAgent = RetryAgent; + module2.exports.H2CClient = H2CClient; + module2.exports.RetryHandler = RetryHandler; + module2.exports.DecoratorHandler = DecoratorHandler; + module2.exports.RedirectHandler = RedirectHandler; + module2.exports.interceptors = { + redirect: require_redirect(), + responseError: require_response_error(), + retry: require_retry(), + dump: require_dump(), + dns: require_dns(), + cache: require_cache2(), + decompress: require_decompress(), + deduplicate: require_deduplicate() + }; + module2.exports.cacheStores = { + MemoryCacheStore: require_memory_cache_store() + }; + var SqliteCacheStore = require_sqlite_cache_store(); + module2.exports.cacheStores.SqliteCacheStore = SqliteCacheStore; + module2.exports.buildConnector = buildConnector; + module2.exports.errors = errors; + module2.exports.util = { + parseHeaders: util.parseHeaders, + headerNameToString: util.headerNameToString + }; + function makeDispatcher(fn) { + return (url2, opts, handler) => { + if (typeof opts === "function") { + handler = opts; + opts = null; + } + if (!url2 || typeof url2 !== "string" && typeof url2 !== "object" && !(url2 instanceof URL)) { + throw new InvalidArgumentError("invalid url"); + } + if (opts != null && typeof opts !== "object") { + throw new InvalidArgumentError("invalid opts"); + } + if (opts && opts.path != null) { + if (typeof opts.path !== "string") { + throw new InvalidArgumentError("invalid opts.path"); + } + let path2 = opts.path; + if (!opts.path.startsWith("/")) { + path2 = `/${path2}`; + } + url2 = new URL(util.parseOrigin(url2).origin + path2); + } else { + if (!opts) { + opts = typeof url2 === "object" ? url2 : {}; + } + url2 = util.parseURL(url2); + } + const { agent, dispatcher = getGlobalDispatcher(), ...restOpts } = opts; + if (agent) { + throw new InvalidArgumentError("unsupported opts.agent. Did you mean opts.client?"); + } + return fn.call(dispatcher, { + ...restOpts, + origin: url2.origin, + path: url2.search ? `${url2.pathname}${url2.search}` : url2.pathname, + method: opts.method || (opts.body ? "PUT" : "GET") + }, handler); + }; + } + module2.exports.setGlobalDispatcher = setGlobalDispatcher2; + module2.exports.getGlobalDispatcher = getGlobalDispatcher; + var fetchImpl = require_fetch().fetch; + var currentFilename = typeof __filename !== "undefined" ? __filename : void 0; + function appendFetchStackTrace(err, filename) { + if (!err || typeof err !== "object") { + return; + } + const stack = typeof err.stack === "string" ? err.stack : ""; + const normalizedFilename = filename.replace(/\\/g, "/"); + if (stack && (stack.includes(filename) || stack.includes(normalizedFilename))) { + return; + } + const capture = {}; + Error.captureStackTrace(capture, appendFetchStackTrace); + if (!capture.stack) { + return; + } + const captureLines = capture.stack.split("\n").slice(1).join("\n"); + err.stack = stack ? `${stack} +${captureLines}` : capture.stack; + } + module2.exports.fetch = function fetch2(init, options2 = void 0) { + return fetchImpl(init, options2).catch((err) => { + if (currentFilename) { + appendFetchStackTrace(err, currentFilename); + } else if (err && typeof err === "object") { + Error.captureStackTrace(err, module2.exports.fetch); + } + throw err; + }); + }; + module2.exports.Headers = require_headers().Headers; + module2.exports.Response = require_response().Response; + module2.exports.Request = require_request2().Request; + module2.exports.FormData = require_formdata().FormData; + var { setGlobalOrigin, getGlobalOrigin } = require_global(); + module2.exports.setGlobalOrigin = setGlobalOrigin; + module2.exports.getGlobalOrigin = getGlobalOrigin; + var { CacheStorage } = require_cachestorage(); + var { kConstruct } = require_symbols(); + module2.exports.caches = new CacheStorage(kConstruct); + var { deleteCookie, getCookies, getSetCookies, setCookie, parseCookie } = require_cookies(); + module2.exports.deleteCookie = deleteCookie; + module2.exports.getCookies = getCookies; + module2.exports.getSetCookies = getSetCookies; + module2.exports.setCookie = setCookie; + module2.exports.parseCookie = parseCookie; + var { parseMIMEType, serializeAMimeType } = require_data_url(); + module2.exports.parseMIMEType = parseMIMEType; + module2.exports.serializeAMimeType = serializeAMimeType; + var { CloseEvent: CloseEvent2, ErrorEvent: ErrorEvent2, MessageEvent: MessageEvent2 } = require_events(); + var { WebSocket: WebSocket3, ping } = require_websocket2(); + module2.exports.WebSocket = WebSocket3; + module2.exports.CloseEvent = CloseEvent2; + module2.exports.ErrorEvent = ErrorEvent2; + module2.exports.MessageEvent = MessageEvent2; + module2.exports.ping = ping; + module2.exports.WebSocketStream = require_websocketstream().WebSocketStream; + module2.exports.WebSocketError = require_websocketerror().WebSocketError; + module2.exports.request = makeDispatcher(api.request); + module2.exports.stream = makeDispatcher(api.stream); + module2.exports.pipeline = makeDispatcher(api.pipeline); + module2.exports.connect = makeDispatcher(api.connect); + module2.exports.upgrade = makeDispatcher(api.upgrade); + module2.exports.MockClient = MockClient; + module2.exports.MockCallHistory = MockCallHistory; + module2.exports.MockCallHistoryLog = MockCallHistoryLog; + module2.exports.MockPool = MockPool; + module2.exports.MockAgent = MockAgent; + module2.exports.SnapshotAgent = SnapshotAgent; + module2.exports.mockErrors = mockErrors; + var { EventSource } = require_eventsource(); + module2.exports.EventSource = EventSource; + function install() { + globalThis.fetch = module2.exports.fetch; + globalThis.Headers = module2.exports.Headers; + globalThis.Response = module2.exports.Response; + globalThis.Request = module2.exports.Request; + globalThis.FormData = module2.exports.FormData; + globalThis.WebSocket = module2.exports.WebSocket; + globalThis.CloseEvent = module2.exports.CloseEvent; + globalThis.ErrorEvent = module2.exports.ErrorEvent; + globalThis.MessageEvent = module2.exports.MessageEvent; + globalThis.EventSource = module2.exports.EventSource; + } + module2.exports.install = install; + } +}); + +// src/proxy/captcha-happy.ts +var captcha_happy_exports = {}; +__export(captcha_happy_exports, { + createDom: () => createDom, + destroyDom: () => destroyDom, + makeDualConsole: () => makeDualConsole, + solveTraceless: () => solveTraceless +}); +function ensureSyncFetchWorker() { + if (_syncFetchWorker) return _syncFetchWorker; + _syncFetchWorker = new import_node_worker_threads.Worker(SYNC_WORKER_SRC, { eval: true }); + return _syncFetchWorker; +} +function syncFetchBlocking(url2, init, timeoutMs = 3e4) { + try { + const worker = ensureSyncFetchWorker(); + const sab = new SharedArrayBuffer(SYNC_FETCH_HEADER_BYTES + SYNC_FETCH_BUF_BYTES); + const i32 = new Int32Array(sab); + const u8 = new Uint8Array(sab); + worker.postMessage({ sab, url: url2, init }); + const waitResult = Atomics.wait(i32, 0, 0, timeoutMs); + if (waitResult === "timed-out") return { error: "sync fetch timeout" }; + const dec = new TextDecoder(); + const payloadAt = SYNC_FETCH_HEADER_BYTES; + let off = payloadAt; + const readSlice = (len) => { + const slice = u8.subarray(off, off + len); + off += len; + return slice; + }; + const statusText = dec.decode(readSlice(i32[2])); + const headers2 = i32[3] ? JSON.parse(dec.decode(readSlice(i32[3]))) : {}; + const setCookie = i32[4] ? JSON.parse(dec.decode(readSlice(i32[4]))) : []; + const body2 = Buffer.from(readSlice(i32[5])); + if (i32[0] === 2) return { error: dec.decode(u8.subarray(payloadAt, payloadAt + i32[5])) || "sync fetch failed" }; + return { status: i32[1], statusText, headers: headers2, setCookie, body: body2 }; + } catch (err) { + try { + _syncFetchWorker?.terminate(); + } catch { + } + _syncFetchWorker = null; + return { error: `sync fetch error: ${err?.message ?? err}` }; + } +} +function shutdownSyncFetchWorker() { + try { + _syncFetchWorker?.terminate(); + } catch { + } + _syncFetchWorker = null; +} +function noteStallAndMaybeEvict(peUrl) { + try { + if (!peUrl || !/dynamicJS\//.test(peUrl)) return; + _bypassPeCacheOnce = true; + const n = (_stallCounts.get(peUrl) || 0) + 1; + _stallCounts.set(peUrl, n); + if (n >= 2 && !_DEBUG) { + process.stderr.write(`[pe-cache-evict] ${peUrl.split("/").pop()} stalled ${n}x \u2014 evicting cache +`); + } + if (n >= 2) { + _memCdnCache.delete(peUrl); + try { + import_node_fs3.default.unlinkSync(diskPathFor(peUrl)); + } catch (_) { + } + _stallCounts.delete(peUrl); + } + } catch (_) { + } +} +function generateFingerprint() { + const userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"; + const uaMajor = "127"; + const uaFull = "127.0.0.0"; + const platform = "Linux x86_64"; + const screen2 = { w: 1280, h: 720, aw: 1280, ah: 720 }; + const webglUnmaskedVendor = "Google Inc. (Google)"; + const webglUnmaskedRenderer = "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)"; + const canvasImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="; + return { userAgent, uaMajor, uaFull, platform, screen: screen2, webglUnmaskedVendor, webglUnmaskedRenderer, canvasImage }; +} +function diskPathFor(url2) { + return import_node_path.default.join(CDN_CACHE_DIR, import_node_crypto2.default.createHash("sha1").update(String(url2)).digest("hex")); +} +function sniffMime(url2) { + if (/\.js(\?|$)/i.test(url2)) return "application/javascript"; + if (/\.css(\?|$)/i.test(url2)) return "text/css"; + if (/\.png(\?|$)/i.test(url2)) return "image/png"; + if (/\.(jpg|jpeg)(\?|$)/i.test(url2)) return "image/jpeg"; + if (/\.json(\?|$)/i.test(url2)) return "application/json"; + return "application/octet-stream"; +} +function patchPeBundle(buf, url2) { + if (process.env.PE_PATCH === "off") return buf; + if (!/dynamicJS\/[^/]*\/pe\.\d+\./.test(url2)) return buf; + let src = buf.toString("utf8"); + if (src.includes("__DBT")) return buf; + const m = src.match(peVmCallRegex); + if (!m) return buf; + const locals = m[1]; + const hook = `55==A?(f=r[n++],l=e.pop(),h=e.pop(),o=[],v(f).forEach(function(){o.unshift(e.pop())}),p=null===h?l.apply(${locals},o):h[l].apply(h,o),r[n++]&&e.push(p),function(){try{if(l===window.btoa||l===window.atob){window.__DBT=window.__DBT||[];var __sav=[];for(var __i=0;__i 0) { + return cookies.map((c) => `${c.name}=${c.value}`).join("; "); + } + } catch (_) { + } + return null; +} +function storeSetCookies(res, url2) { + try { + const list = typeof res.headers.getSetCookie === "function" ? res.headers.getSetCookie() : []; + if (list.length) { + const cookieContainer = global.__cookieContainer; + if (cookieContainer) { + for (const raw of list) { + const u = new URL(url2); + const parts = raw.split(";"); + const pair = parts[0].split("="); + const cookie = { + name: pair[0].trim(), + value: pair.slice(1).join("=").trim(), + url: u.origin, + domain: u.hostname, + path: "/" + }; + for (const p of parts.slice(1)) { + const kv = p.trim().split(/=(.*)/s); + const k = (kv[0] || "").toLowerCase(); + if (k === "domain" && kv[1]) cookie.domain = kv[1]; + if (k === "path" && kv[1]) cookie.path = kv[1]; + if (k === "expires") cookie.expires = new Date(kv[1]).getTime(); + if (k === "max-age") cookie.maxAge = parseInt(kv[1], 10); + if (k === "httponly") cookie.httpOnly = true; + if (k === "secure") cookie.secure = true; + if (k === "samesite") cookie.sameSite = kv[1]; + } + try { + cookieContainer.addCookies([cookie]); + } catch (_) { + } + } + } + } + } catch (_) { + } +} +function makeInterceptor(bypassPeCache = false) { + const skipPeCache = (url2) => bypassPeCache && /dynamicJS\/.*\/pe\.\d+\./.test(url2); + return { + async beforeAsyncRequest({ request, window: w2 }) { + const url2 = request.url; + _requestLog.push({ at: Date.now(), method: request.method, url: url2 }); + injectRequestHeaders(request); + if (/\balicdn\.com/i.test(url2)) { + let body2 = skipPeCache(url2) ? null : getCachedBody(url2); + if (body2 && /\.js(\?|$)/i.test(url2)) { + try { + new Function(body2.toString("utf8")); + } catch (parseErr) { + process.stderr.write(`[cache-bad-js] ${url2} len=${body2.length} ${parseErr.message} \u2014 refetch fresh +`); + _memCdnCache.delete(url2); + try { + import_node_fs3.default.unlinkSync(diskPathFor(url2)); + } catch (_) { + } + body2 = null; + } + } + if (body2) { + if (/dynamicJS\/[^/]*\/pe\.\d+\./.test(url2)) { + try { + w2.__lastPeUrl = url2; + } catch (_) { + } + } + return new w2.Response(patchPeBundle(Buffer.from(body2), url2), { + status: 200, + statusText: "OK", + headers: { "content-type": sniffMime(url2) } + }); + } + } + try { + const init = { method: request.method, headers: {} }; + request.headers.forEach((value2, key) => { + init.headers[key] = value2; + }); + const bs = new URL(url2); + const cookie = cookieHeader(request, w2, global.__browserFrame); + if (cookie) init.headers.cookie = cookie; + let hasBody = false; + try { + if (request.body) { + const ab = await request.arrayBuffer(); + if (ab && ab.byteLength > 0) { + init.body = ab; + hasBody = true; + } + } + } catch (_) { + } + const res = await fetch(url2, init); + const buf = Buffer.from(await res.arrayBuffer()); + storeSetCookies(res, url2); + if (_DEBUG && /captcha-open|verify\.|device\.saf|cloudauth-device|upload\./i.test(url2) && buf.length && buf.length < 4096) { + try { + process.stderr.write(`[xhr-body] ${request.method} ${bs.hostname}${bs.pathname}-> ${res.status} ${buf.toString("utf8").slice(0, 1200)} +`); + } catch (_) { + } + } + const headers2 = {}; + const ct = res.headers.get("content-type"); + if (ct) headers2["content-type"] = ct; + const logHost = bs.hostname; + if (_DEBUG) + process.stderr.write( + `[xhr] ${request.method} ${logHost}${bs.pathname} -> ${res.status} (${buf.length}b) +` + ); + return new w2.Response(buf, { + status: res.status, + statusText: res.statusText || "", + headers: headers2 + }); + } catch (err) { + if (_DEBUG) process.stderr.write(`[xhr-err] ${url2}: ${err.message} +`); + return new w2.Response("", { status: 503, statusText: "passthrough failed" }); + } + }, + beforeSyncRequest({ request, window: w2 }) { + const url2 = request.url; + _requestLog.push({ at: Date.now(), method: request.method, url: url2, sync: true }); + injectRequestHeaders(request); + let body2 = null; + if (/\balicdn\.com/i.test(url2)) { + body2 = skipPeCache(url2) ? null : getCachedBody(url2); + if (body2 && /\.js(\?|$)/i.test(url2)) { + try { + new Function(body2.toString("utf8")); + } catch (parseErr) { + process.stderr.write(`[cache-bad-js:sync] ${url2} len=${body2.length} ${parseErr.message} \u2014 refetch fresh +`); + _memCdnCache.delete(url2); + try { + import_node_fs3.default.unlinkSync(diskPathFor(url2)); + } catch (_) { + } + body2 = null; + } + } + } + if (body2) { + if (/dynamicJS\/[^/]*\/pe\.\d+\./.test(url2)) { + try { + w2.__lastPeUrl = url2; + } catch (_) { + } + } + return { + status: 200, + statusText: "OK", + ok: true, + url: url2, + redirected: false, + headers: new w2.Headers({ "content-type": sniffMime(url2) }), + body: patchPeBundle(Buffer.from(body2), url2), + [PropertySymbol_exports.virtualServerFile]: null + }; + } + const init = { method: request.method, headers: {} }; + request.headers.forEach((value2, key) => { + init.headers[key] = value2; + }); + const cookie = cookieHeader(request, w2, global.__browserFrame); + if (cookie) init.headers.cookie = cookie; + try { + if (request.body) { + const ab = request.body; + if (ab && ab.byteLength > 0) init.body = ab; + } + } catch (_) { + } + const res = syncFetchBlocking(url2, init); + if (res.error) { + process.stderr.write(`[sync-xhr-err] ${url2}: ${res.error} +`); + return new w2.Response("", { status: 503, statusText: "sync fetch failed" }); + } + try { + for (const raw of res.setCookie || []) { + const cookieContainer = global.__cookieContainer; + if (!cookieContainer) break; + const u = new URL(url2); + const parts = raw.split(";"); + const pair = parts[0].split("="); + const cookie2 = { + name: pair[0].trim(), + value: pair.slice(1).join("=").trim(), + url: u.origin, + domain: u.hostname, + path: "/" + }; + for (const p of parts.slice(1)) { + const kv = p.trim().split(/=(.*)/s); + const k = (kv[0] || "").toLowerCase(); + if (k === "domain" && kv[1]) cookie2.domain = kv[1]; + if (k === "path" && kv[1]) cookie2.path = kv[1]; + if (k === "expires") cookie2.expires = new Date(kv[1]).getTime(); + if (k === "max-age") cookie2.maxAge = parseInt(kv[1], 10); + if (k === "httponly") cookie2.httpOnly = true; + if (k === "secure") cookie2.secure = true; + if (k === "samesite") cookie2.sameSite = kv[1]; + } + try { + cookieContainer.addCookies([cookie2]); + } catch (_) { + } + } + } catch (_) { + } + const hdrs = {}; + for (const [k, v] of Object.entries(res.headers || {})) hdrs[k] = String(v); + return { + status: res.status, + statusText: res.statusText || "", + ok: res.status >= 200 && res.status < 300, + url: url2, + redirected: false, + headers: new w2.Headers(hdrs), + body: Buffer.from(res.body), + [PropertySymbol_exports.virtualServerFile]: null + }; + } + }; +} +function installEvalInstrumentation(w2) { + const sym = PropertySymbol_exports && PropertySymbol_exports.evaluateScript; + if (!sym || typeof w2[sym] !== "function") { + process.stderr.write("[instr] no evaluateScript symbol, host hook skipped\n"); + return; + } + const orig = w2[sym]; + w2[sym] = function(code, options2) { + try { + return orig.call(this, code, options2); + } catch (err) { + try { + const src = String(code || ""); + const filename = options2 && options2.filename || "?"; + const sha1 = import_node_crypto2.default.createHash("sha1").update(src).digest("hex"); + process.stderr.write( + ` +[EVAL-PARSE-FAIL] file=${filename} len=${src.length} sha1=${sha1} + head300: ${JSON.stringify(src.slice(0, 300))} + tail100: ${JSON.stringify(src.slice(-100))} + err: ${err && err.message} +` + ); + if (/^https?:/.test(filename)) { + (async () => { + try { + const res = await fetch(filename, { headers: { "user-agent": fp.userAgent } }); + const fresh = Buffer.from(await res.arrayBuffer()); + process.stderr.write( + `[EVAL-CACHE-COMPARE] cachedLen=${src.length} freshLen=${fresh.length} freshSha1=${import_node_crypto2.default.createHash("sha1").update(fresh).digest("hex")} http=${res.status} +` + ); + if (fresh.length > 0 && fresh.length !== src.length) { + process.stderr.write(`[EVAL-CACHE-MISMATCH] deleting ${diskPathFor(filename)} (stale/truncated cache) +`); + try { + import_node_fs3.default.unlinkSync(diskPathFor(filename)); + } catch (_) { + } + _memCdnCache.delete(filename); + } + } catch (fetchErr) { + process.stderr.write(`[EVAL-CACHE-COMPARE-ERR] ${fetchErr.message} +`); + } + })(); + } + } catch (e2) { + } + throw err; + } + }; +} +function installNativeToString(w2) { + const realToString = Function.prototype.toString; + const nativeRe = /\[native code\]/; + const mask = (fn) => { + if (typeof fn !== "function") return; + try { + if (nativeRe.test(realToString.call(fn))) return; + const name2 = fn.name || ""; + const nativeStr = `function ${name2}() { [native code] }`; + Object.defineProperty(fn, "toString", { + value: () => nativeStr, + configurable: true, + writable: true + }); + } catch (_) { + } + }; + const seen = new w2.Set(); + const maskObj = (obj, depth) => { + if (!obj || typeof obj !== "object" && typeof obj !== "function" || depth > 5) + return; + try { + if (obj.constructor && obj.constructor.prototype !== Object.prototype) { + const ctorName = obj.constructor.name; + if (/^(WriteStream|ReadStream|Socket|Process|Timeout|Immediate)$/.test(ctorName)) return; + } + } catch (_) { + } + if (seen.has(obj)) return; + try { + seen.add(obj); + } catch (_) { + return; + } + let names = []; + try { + names = Object.getOwnPropertyNames(obj); + } catch (_) { + return; + } + for (const name2 of names) { + if (name2 === "toString" || name2 === "constructor") continue; + let desc; + try { + desc = Object.getOwnPropertyDescriptor(obj, name2); + } catch (_) { + continue; + } + if (!desc) continue; + if (typeof desc.value === "function") { + mask(desc.value); + } else if (typeof desc.get === "function") { + mask(desc.get); + try { + const v = desc.get.call(obj); + if (typeof v === "function") mask(v); + } catch (_) { + } + } + if (depth < 3) { + try { + const v = desc.value; + if (v && (typeof v === "function" || typeof v === "object")) + maskObj(v, depth + 1); + } catch (_) { + } + } + } + }; + const targets = [ + w2, + w2.navigator, + w2.document, + w2.Document && w2.Document.prototype, + w2.Element && w2.Element.prototype, + w2.HTMLElement && w2.HTMLElement.prototype, + w2.Node && w2.Node.prototype, + w2.EventTarget && w2.EventTarget.prototype, + w2.HTMLCanvasElement && w2.HTMLCanvasElement.prototype, + w2.XMLHttpRequest && w2.XMLHttpRequest.prototype, + w2.Event && w2.Event.prototype, + w2.Window && w2.Window.prototype + ].filter(Boolean); + for (const t of targets) { + try { + maskObj(t, 0); + } catch (_) { + } + } +} +function applyPolyfills(w2) { + if (process.env.CAPTCHA_DEBUG_BODIES === "1") { + installTrafficLogger(w2); + } + if (typeof w2.Option !== "function") { + w2.Option = class Option extends w2.HTMLOptionElement { + constructor(text, value2, defaultSelected, selected) { + super(); + if (text !== void 0) { + const el = w2.document.createElement("option"); + el.text = text; + if (value2 !== void 0) el.value = value2; + if (defaultSelected) el.defaultSelected = true; + if (selected) el.selected = true; + return el; + } + } + }; + } + if (typeof w2.Video !== "function" && w2.HTMLVideoElement) { + w2.Video = class Video extends w2.HTMLVideoElement { + constructor() { + return w2.document.createElement("video"); + } + }; + } + if (typeof w2.alert !== "function") w2.alert = () => { + }; + if (typeof w2.prompt !== "function") w2.prompt = () => null; + if (typeof w2.confirm !== "function") w2.confirm = () => false; + if (typeof w2.open !== "function") w2.open = () => null; + if (typeof w2.close !== "function") w2.close = () => { + }; + try { + Object.defineProperty(w2, "alert", { value: w2.alert, configurable: true, writable: true }); + } catch (_) { + } + try { + Object.defineProperty(w2, "prompt", { value: w2.prompt, configurable: true, writable: true }); + } catch (_) { + } + try { + Object.defineProperty(w2, "confirm", { value: w2.confirm, configurable: true, writable: true }); + } catch (_) { + } + try { + Object.defineProperty(w2, "open", { value: w2.open, configurable: true, writable: true }); + } catch (_) { + } + try { + Object.defineProperty(w2, "close", { value: w2.close, configurable: true, writable: true }); + } catch (_) { + } + const extraGlobals = { + print: () => { + }, + stop: () => { + }, + moveTo: () => { + }, + moveBy: () => { + }, + showModalDialog: () => null, + find: () => false + }; + for (const [k, v] of Object.entries(extraGlobals)) { + try { + Object.defineProperty(w2, k, { value: v, configurable: true, writable: true }); + } catch (_) { + } + } + try { + Object.defineProperty(w2, "open", { value: () => null, configurable: true, writable: true }); + } catch (_) { + } + try { + Object.defineProperty(w2, "close", { value: () => { + }, configurable: true, writable: true }); + } catch (_) { + } + if (!w2.Option) { + w2.Option = class { + constructor(text, value2, defaultSelected, selected) { + this.text = text ?? ""; + this.value = value2 ?? ""; + this.selected = selected ?? defaultSelected ?? false; + this.defaultSelected = !!defaultSelected; + this.disabled = false; + this.label = this.text; + this.index = 0; + } + }; + } + if (!w2.EventSource) { + w2.EventSource = class { + constructor() { + this.readyState = 2; + this.onopen = null; + this.onmessage = null; + this.onerror = null; + } + close() { + this.readyState = 2; + } + addEventListener() { + } + removeEventListener() { + } + }; + } + if (!w2.Beacon) w2.Beacon = class { + }; + if (!w2.RTCPeerConnection) { + w2.RTCPeerConnection = class { + constructor() { + } + createDataChannel() { + return {}; + } + close() { + } + createOffer() { + return Promise.resolve({}); + } + setLocalDescription() { + return Promise.resolve(); + } + addEventListener() { + } + removeEventListener() { + } + }; + } + if (!w2.MessageChannel) { + w2.MessageChannel = class { + constructor() { + this.port1 = { onmessage: null, postMessage() { + }, start() { + }, close() { + }, addEventListener() { + }, removeEventListener() { + } }; + this.port2 = { onmessage: null, postMessage() { + }, start() { + }, close() { + }, addEventListener() { + }, removeEventListener() { + } }; + } + }; + } + w2.IntersectionObserver = w2.IntersectionObserver || class { + constructor(cb) { + this.cb = cb; + } + observe() { + } + unobserve() { + } + disconnect() { + } + takeRecords() { + return []; + } + }; + w2.ResizeObserver = w2.ResizeObserver || class { + observe() { + } + unobserve() { + } + disconnect() { + } + }; + w2.DeviceOrientationEvent = w2.DeviceOrientationEvent || class extends w2.Event { + constructor(type2, opts) { + super(type2, opts); + } + alpha = null; + beta = null; + gamma = null; + absolute = false; + }; + w2.DeviceMotionEvent = w2.DeviceMotionEvent || class extends w2.Event { + constructor(type2, opts) { + super(type2, opts); + } + acceleration = null; + accelerationIncludingGravity = null; + rotationRate = null; + interval = 16; + }; + w2.requestIdleCallback = w2.requestIdleCallback || ((cb) => setTimeout(() => cb({ didTimeout: false, timeRemaining: () => 10 }), 1)); + w2.cancelIdleCallback = w2.cancelIdleCallback || ((id2) => clearTimeout(id2)); + w2.matchMedia = w2.matchMedia || (() => ({ + matches: false, + media: "", + onchange: null, + addListener() { + }, + removeListener() { + }, + addEventListener() { + }, + removeEventListener() { + }, + dispatchEvent() { + return false; + } + })); + if (!w2.visualViewport) { + const VisualViewport = function() { + }; + VisualViewport.prototype = { + width: fp.screen.w - 16, + height: fp.screen.h - 120, + scale: 1, + offsetLeft: 0, + offsetTop: 0, + pageLeft: 0, + pageTop: 0, + onresize: null, + onscroll: null, + onscrollend: null + }; + w2.VisualViewport = VisualViewport; + w2.visualViewport = Object.create(w2.VisualViewport.prototype); + } + if (!w2.indexedDB) { + const IDBFactory = function() { + }; + IDBFactory.prototype = { + open: () => ({ onupgradeneeded: null, onsuccess: null, onerror: null }), + deleteDatabase: () => ({}), + databases: () => Promise.resolve([]) + }; + w2.IDBFactory = IDBFactory; + w2.indexedDB = Object.create(w2.IDBFactory.prototype); + } + if (!w2.speechSynthesis) { + const SpeechSynthesis = function() { + }; + SpeechSynthesis.prototype = { + speak() { + }, + cancel() { + }, + pause() { + }, + resume() { + }, + getVoices: () => [] + }; + w2.SpeechSynthesis = SpeechSynthesis; + w2.speechSynthesis = Object.create(w2.SpeechSynthesis.prototype); + w2.SpeechSynthesisUtterance = function() { + }; + } + w2.Worker = w2.Worker || class { + postMessage() { + } + terminate() { + } + addEventListener() { + } + removeEventListener() { + } + }; + w2.Notification = w2.Notification || class { + static permission = "default"; + static requestPermission() { + return Promise.resolve("default"); + } + close() { + } + }; + const proto = w2.HTMLCanvasElement.prototype; + const nativeGetContext = typeof proto.getContext === "function" ? proto.getContext : null; + proto.getContext = function(type2, ...rest) { + if (/webgl/i.test(type2)) { + return makeWebGLMock(this); + } + if (nativeGetContext) { + try { + const ctx = nativeGetContext.call(this, type2, ...rest); + if (ctx) return ctx; + } catch (_) { + } + } + return make2DStub(this); + }; + function makeWebGLMock(canvas2) { + return { + canvas: canvas2, + getParameter(p) { + if (p === 7936) return "WebKit"; + if (p === 7937) return "WebKit WebGL"; + if (p === 7938) return "WebGL 1.0 (OpenGL ES 2.0 Chromium)"; + if (p === 35724) return "WebGL GLSL ES 1.0 (OpenGL ES GLSL ES 1.0 Chromium)"; + if (p === 37445) return fp.webglUnmaskedVendor; + if (p === 37446) return fp.webglUnmaskedRenderer; + return "Intel Inc."; + }, + getExtension(name2) { + if (name2 === "WEBGL_debug_renderer_info") { + return { UNMASKED_VENDOR_WEBGL: 37445, UNMASKED_RENDERER_WEBGL: 37446 }; + } + return null; + }, + getSupportedExtensions() { + return [ + "ANGLE_instanced_arrays", + "EXT_blend_minmax", + "EXT_color_buffer_half_float", + "EXT_disjoint_timer_query", + "EXT_float_blend", + "EXT_frag_depth", + "EXT_shader_texture_lod", + "EXT_texture_compression_bptc", + "EXT_texture_compression_rgtc", + "EXT_texture_filter_anisotropic", + "EXT_sRGB", + "KHR_parallel_shader_compile", + "OES_element_index_uint", + "OES_fbo_render_mipmap", + "OES_standard_derivatives", + "OES_texture_float", + "OES_texture_float_linear", + "OES_texture_half_float", + "OES_texture_half_float_linear", + "OES_vertex_array_object", + "WEBGL_color_buffer_float", + "WEBGL_compressed_texture_astc", + "WEBGL_compressed_texture_etc", + "WEBGL_compressed_texture_etc1", + "WEBGL_compressed_texture_s3tc", + "WEBGL_compressed_texture_s3tc_srgb", + "WEBGL_debug_renderer_info", + "WEBGL_debug_shaders", + "WEBGL_depth_texture", + "WEBGL_draw_buffers", + "WEBGL_lose_context", + "WEBGL_multi_draw" + ]; + }, + getContextAttributes() { + return { + alpha: true, + antialias: true, + depth: true, + failIfMajorPerformanceCaveat: false, + powerPreference: "default", + premultipliedAlpha: true, + preserveDrawingBuffer: false, + stencil: false, + desynchronized: false + }; + }, + getShaderPrecisionFormat() { + return { precision: 23, rangeMin: 127, rangeMax: 127 }; + } + }; + } + function make2DStub(canvas2) { + return { + canvas: canvas2, + fillRect() { + }, + clearRect() { + }, + getImageData: (_x, _y, w22 = 1, h2 = 1) => new w2.ImageData(w22, h2), + putImageData() { + }, + createImageData: (w22 = 1, h2 = 1) => new w2.ImageData(w22, h2), + setTransform() { + }, + transform() { + }, + drawImage() { + }, + save() { + }, + restore() { + }, + beginPath() { + }, + moveTo() { + }, + lineTo() { + }, + bezierCurveTo() { + }, + quadraticCurveTo() { + }, + closePath() { + }, + clip() { + }, + stroke() { + }, + fill() { + }, + arc() { + }, + rect() { + }, + ellipse() { + }, + translate() { + }, + scale() { + }, + rotate() { + }, + fillText() { + }, + strokeText() { + }, + measureText: (t) => ({ width: String(t).length * 8 }), + createLinearGradient: () => ({ addColorStop() { + } }), + createRadialGradient: () => ({ addColorStop() { + } }), + createPattern: () => ({}), + isPointInPath: () => false, + font: "10px sans-serif", + textBaseline: "alphabetic", + textAlign: "start", + fillStyle: "#000", + strokeStyle: "#000", + globalAlpha: 1, + lineWidth: 1, + shadowBlur: 0, + shadowColor: "" + }; + } + const nativeToDataURL = typeof proto.toDataURL === "function" ? proto.toDataURL : null; + proto.toDataURL = function(...a) { + try { + if (nativeToDataURL) return nativeToDataURL.apply(this, a); + } catch (_) { + } + return fp.canvasImage; + }; + if (typeof proto.toBlob !== "function") { + proto.toBlob = (cb) => cb && cb(new w2.Blob()); + } + w2.OffscreenCanvas = w2.OffscreenCanvas || class { + constructor(width2, height2) { + this.width = width2; + this.height = height2; + } + getContext() { + return proto.getContext.call(this); + } + }; + const audioMock = class { + constructor() { + this.sampleRate = 44100; + this.currentTime = 0; + this.state = "suspended"; + } + createOscillator() { + return { + type: "sine", + frequency: { value: 440, setValueAtTime() { + } }, + connect() { + }, + start() { + }, + stop() { + } + }; + } + createDynamicsCompressor() { + return { + threshold: { value: -24, setValueAtTime() { + } }, + knee: { value: 30, setValueAtTime() { + } }, + ratio: { value: 12, setValueAtTime() { + } }, + attack: { value: 3e-3, setValueAtTime() { + } }, + release: { value: 0.25, setValueAtTime() { + } }, + connect() { + } + }; + } + createAnalyser() { + return { + fftSize: 2048, + frequencyBinCount: 1024, + getByteFrequencyData() { + }, + getByteTimeDomainData() { + }, + connect() { + } + }; + } + createGain() { + return { gain: { value: 1 }, connect() { + } }; + } + destination = {}; + resume() { + this.state = "running"; + return Promise.resolve(); + } + close() { + this.state = "closed"; + return Promise.resolve(); + } + }; + w2.AudioContext = w2.AudioContext || audioMock; + w2.OfflineAudioContext = w2.OfflineAudioContext || class extends audioMock { + constructor(_channels, length2, sampleRate) { + super(); + this.length = length2; + this.sampleRate = sampleRate; + } + startRendering() { + const len = this.length || 44100; + const sr = this.sampleRate || 44100; + const buf = new Float32Array(len); + for (let i = 0; i < len; i += 1) { + const t = i / sr; + buf[i] = Math.sin(2 * Math.PI * 1e3 * t) * Math.exp(-t * 1.2) * 0.6 + Math.sin(2 * Math.PI * 3e3 * t) * Math.exp(-t * 1.5) * 0.25 + Math.sin(2 * Math.PI * 5e3 * t) * Math.exp(-t * 2) * 0.12; + } + return Promise.resolve({ + numberOfChannels: 1, + length: len, + sampleRate: sr, + getChannelData: () => buf + }); + } + }; + w2.requestAnimationFrame = w2.requestAnimationFrame || ((cb) => setTimeout(() => cb(Date.now()), 16)); + w2.cancelAnimationFrame = w2.cancelAnimationFrame || ((id2) => clearTimeout(id2)); + try { + Object.defineProperty(w2.document, "hidden", { value: false, configurable: true }); + Object.defineProperty(w2.document, "visibilityState", { + value: "visible", + configurable: true + }); + } catch (_) { + } + if (!w2.document.fonts) { + w2.document.fonts = { + ready: Promise.resolve(), + check: () => true, + addEventListener() { + }, + removeEventListener() { + } + }; + } + if (!w2.chrome) { + w2.chrome = { + app: { + isInstalled: false, + InstallState: { DISABLED: "disabled", INSTALLED: "installed", NOT_INSTALLED: "not_installed" }, + RunningState: { CANNOT_RUN: "cannot_run", CAN_RUN: "can_run", RUNNING: "running" }, + getDetails() { + return null; + }, + getIsInstalled() { + return false; + }, + installState(cb) { + if (cb) cb("not_installed"); + }, + runningState(cb) { + if (cb) cb("cannot_run"); + } + }, + csi() { + const now = Date.now(); + return { startE: now - 100, onloadT: now, pageT: 100, tran: 15 }; + }, + loadTimes() { + const now = Date.now() / 1e3; + return { + requestTime: now - 0.1, + startLoadTime: now - 0.1, + commitLoadTime: now - 0.05, + finishDocumentLoadTime: now, + finishLoadTime: now, + firstPaintTime: now - 0.02, + firstPaintAfterLoadTime: 0, + navigationType: "Other", + wasFetchedViaSpdy: true, + wasNpnNegotiated: true, + npnNegotiatedProtocol: "h2", + wasAlternateProtocolAvailable: false, + connectionInfo: "h2" + }; + } + }; + } + const nav = w2.navigator; + const plugins = createNavigatorPlugins(w2); + const navPatch = { + userAgent: fp.userAgent, + platform: fp.platform, + language: "en-US", + languages: ["en-US", "en"], + vendor: "Google Inc.", + webdriver: false, + hardwareConcurrency: 12, + deviceMemory: 8, + maxTouchPoints: 0, + cookieEnabled: true, + plugins: plugins.plugins, + mimeTypes: plugins.mimeTypes, + appVersion: fp.userAgent.replace(/^Mozilla\//, ""), + appName: "Netscape", + appCodeName: "Mozilla", + product: "Gecko", + productSub: "20030107", + vendorSub: "", + oscpu: void 0, + doNotTrack: null, + sendBeacon: (url2, data2) => { + try { + const xhr = new w2.XMLHttpRequest(); + xhr.open("POST", url2, true); + xhr.send(data2); + return true; + } catch (_) { + return false; + } + } + }; + for (const [k, v] of Object.entries(navPatch)) { + try { + Object.defineProperty(nav, k, { value: v, configurable: true }); + } catch (_) { + } } - return def; -} - -// src/auth/types.ts -function credentialString(cred) { - if (cred.secret) { - return `${cred.apiKey}.${cred.secret}`; + const makeNS = (protoObj) => { + const C = new w2.Function(); + C.prototype = protoObj; + return new C(); + }; + if (!nav.connection) { + const NetInfo = () => { + }; + NetInfo.prototype = { onchange: null, effectiveType: "4g", rtt: 50, downlink: 10, saveData: false }; + w2.NetworkInformation = NetInfo; + try { + Object.defineProperty(nav, "connection", { value: makeNS(NetInfo.prototype), configurable: true }); + } catch (_) { + } } - return cred.apiKey; + if (!nav.userAgentData) { + const UAData = function() { + }; + UAData.prototype = { + brands: [ + { brand: "Chromium", version: fp.uaMajor }, + { brand: "Not)A;Brand", version: "24" } + ], + mobile: false, + platform: "Linux", + getHighEntropyValues: () => Promise.resolve({ + brands: [ + { brand: "Chromium", version: fp.uaMajor }, + { brand: "Not)A;Brand", version: "24" } + ], + mobile: false, + platform: "Linux", + platformVersion: "6.5.0", + architecture: "x86", + model: "", + uaFullVersion: fp.uaFull, + fullVersionList: [ + { brand: "Chromium", version: fp.uaFull }, + { brand: "Not)A;Brand", version: "24.0.0.0" } + ] + }) + }; + try { + Object.defineProperty(nav, "userAgentData", { value: makeNS(UAData.prototype), configurable: true }); + } catch (_) { + } + } + if (!w2.Permissions) { + const Perms = () => { + }; + Perms.prototype = { + query: (param) => Promise.resolve({ state: param.name === "notifications" ? "prompt" : "granted", onchange: null }) + }; + w2.Permissions = Perms; + } + try { + if (!nav.permissions) Object.defineProperty(nav, "permissions", { value: makeNS(w2.Permissions.prototype), configurable: true }); + } catch (_) { + } + try { + if (!nav.clipboard) + Object.defineProperty(nav, "clipboard", { + value: makeNS({ readText: () => Promise.resolve(""), writeText: () => Promise.resolve() }), + configurable: true + }); + } catch (_) { + } + try { + if (!nav.geolocation) + Object.defineProperty(nav, "geolocation", { + value: makeNS({ + getCurrentPosition: (s) => s && s({ coords: { latitude: 0, longitude: 0, accuracy: 1 } }), + watchPosition: () => 1, + clearWatch: () => { + } + }), + configurable: true + }); + } catch (_) { + } + try { + if (!nav.credentials) + Object.defineProperty(nav, "credentials", { + value: makeNS({ get: () => Promise.resolve(null), create: () => Promise.resolve(null), store: () => Promise.resolve(), preventSilentAccess: () => Promise.resolve() }), + configurable: true + }); + } catch (_) { + } + try { + if (!nav.storage) + Object.defineProperty(nav, "storage", { + value: makeNS({ estimate: () => Promise.resolve({ quota: 1e8, usage: 0 }), persisted: () => Promise.resolve(false), persist: () => Promise.resolve(false) }), + configurable: true + }); + } catch (_) { + } + try { + if (!nav.usb) + Object.defineProperty(nav, "usb", { + value: makeNS({ getDevices: () => Promise.resolve([]), requestDevice: () => Promise.reject(new Error("no devices")) }), + configurable: true + }); + } catch (_) { + } + try { + if (!nav.mediaDevices) + Object.defineProperty(nav, "mediaDevices", { + value: makeNS({ enumerateDevices: () => Promise.resolve([]), getUserMedia: () => Promise.reject(new Error("NotAllowedError")) }), + configurable: true + }); + } catch (_) { + } + const screenPatch = { + width: fp.screen.w, + height: fp.screen.h, + availWidth: fp.screen.w, + availHeight: fp.screen.ah, + availLeft: 0, + availTop: 0, + colorDepth: 24, + pixelDepth: 24, + orientation: { angle: 0, type: "landscape-primary", onchange: null } + }; + for (const [k, v] of Object.entries(screenPatch)) { + try { + Object.defineProperty(w2.screen, k, { get: () => v, configurable: true }); + } catch (_) { + } + } + w2.outerWidth = fp.screen.w; + w2.outerHeight = fp.screen.h - 40; + w2.innerWidth = fp.screen.w - 16; + w2.innerHeight = fp.screen.h - 120; + w2.devicePixelRatio = 1; } - -// src/proxy/upstream.ts -init_identity(); - -// src/proxy/trace-headers.ts -var QUERY_PREFIX = "query_"; -var SUBAGENT_PREFIX = "subagent_agent_"; -var SESSION_PREFIXES = ["sess_", SUBAGENT_PREFIX]; -function resolveSessionType(ctx) { - const explicit = ctx.sessionType?.trim(); - if (explicit === "main" || explicit === "subagent" || explicit === "other") return explicit; - if (ctx.sessionId?.startsWith(SUBAGENT_PREFIX) && ctx.sessionId.length > SUBAGENT_PREFIX.length) return "subagent"; - return "main"; +function createNavigatorPlugins(w2) { + const indexed = [ + { name: "PDF Viewer", filename: "internal-pdf-viewer", description: "Portable Document Format" }, + { name: "Chrome PDF Viewer", filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai", description: "" }, + { name: "Chromium PDF Viewer", filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai", description: "" } + ]; + const plugins = w2.PluginArray ? Object.create(w2.PluginArray.prototype) : {}; + const mockIndexed = []; + for (let i = 0; i < indexed.length; i++) { + const p = Object.create(w2.Plugin && w2.Plugin.prototype || Object.prototype); + Object.defineProperty(p, "name", { value: indexed[i].name, configurable: true, enumerable: true }); + Object.defineProperty(p, "filename", { value: indexed[i].filename, configurable: true, enumerable: true }); + Object.defineProperty(p, "description", { value: indexed[i].description, configurable: true, enumerable: true }); + Object.defineProperty(p, "length", { value: 1, configurable: true, enumerable: true }); + Object.defineProperty(p, "0", { value: p, configurable: true, enumerable: true }); + p.item = () => p; + p.namedItem = () => p; + plugins[i] = p; + mockIndexed.push(p); + } + Object.defineProperty(plugins, "length", { value: indexed.length, configurable: true, enumerable: true }); + plugins.item = (i) => plugins[i] ?? null; + plugins.namedItem = (name2) => mockIndexed.find((p) => p.name === name2) ?? null; + plugins.refresh = () => { + }; + const mimeTypes = w2.MimeTypeArray ? Object.create(w2.MimeTypeArray.prototype) : {}; + Object.defineProperty(mimeTypes, "length", { value: 0, configurable: true, enumerable: true }); + mimeTypes.item = () => null; + mimeTypes.namedItem = () => null; + return { plugins, mimeTypes }; } -function buildZcodeTraceHeaders(ctx = {}) { - const queryId = ctx.queryId ? stripHeaderInternalPrefixes(ctx.queryId, [QUERY_PREFIX]) : void 0; - const sessionId = ctx.sessionId ? stripHeaderInternalPrefixes(ctx.sessionId, SESSION_PREFIXES) : void 0; - return { - "x-request-id": ctx.requestId ?? crypto.randomUUID(), - "x-zcode-session-type": resolveSessionType(ctx), - "x-zcode-trace-id": ctx.traceId ?? crypto.randomUUID(), - ...queryId ? { "x-query-id": queryId } : {}, - ...sessionId ? { "x-session-id": sessionId } : {} +function installTrafficLogger(w2) { + const origOpen = w2.XMLHttpRequest.prototype.open; + const origSend = w2.XMLHttpRequest.prototype.send; + w2.XMLHttpRequest.prototype.open = function(method2, url2, ...rest) { + this.__capMethod = method2; + this.__capUrl = url2; + return origOpen.call(this, method2, url2, ...rest); + }; + w2.XMLHttpRequest.prototype.send = function(body2) { + const url2 = String(this.__capUrl || ""); + const DEBUG_HOSTS = /(cloudauth-device|captcha-open|verify|upload|nocaptcha|aliyuncs)/i; + if (DEBUG_HOSTS.test(url2)) { + this.addEventListener("load", () => { + let respPreview = ""; + try { + respPreview = String(this.responseText || "").slice(0, 3e3); + } catch (_) { + } + try { + process.stderr.write( + ` +===== XHR ${String(this.__capMethod || "?")} ${url2} +--- RESP (${respPreview.length}b) --- +${respPreview} +===== +` + ); + } catch (_) { + } + }); + } + return origSend.call(this, body2); }; } -function stripHeaderInternalPrefixes(value2, prefixes) { - let out = value2; - for (const prefix2 of prefixes) { - if (out.startsWith(prefix2) && out.length > prefix2.length) out = out.slice(prefix2.length); +function safeJson(x3) { + try { + if (x3 instanceof Error) return `Error: ${x3.message} +${(x3.stack || "").slice(0, 1500)}`; + const s = JSON.stringify(x3); + return s !== void 0 && s.length < 3e3 ? s : String(x3); + } catch (_) { + return String(x3); } - return out || value2; } - -// src/proxy/client-session.ts -var import_node_crypto = __toESM(require("node:crypto"), 1); -function createClientSessionResolver(now = () => Date.now()) { - const nodes = /* @__PURE__ */ new Map(); - const sessions = /* @__PURE__ */ new Map(); - function remember(nodeHash, session, config) { - const stored = { ...session, nodeHash, lastSeenAt: now() }; - nodes.set(nodeHash, stored); - sessions.set(stored.sessionId, stored); - prune(config); - } - function prune(config) { - const cutoff = now() - config.ttlSeconds * 1e3; - for (const [hash, node] of nodes.entries()) { - if (node.lastSeenAt < cutoff) nodes.delete(hash); +function simulateBehavior(w2, durationMs = 600) { + const { document, MouseEvent: MouseEvent2, KeyboardEvent: KeyboardEvent2, UIEvent: UIEvent2 } = w2; + if (!document || !MouseEvent2) return; + const fire = (type2, ctor, opts) => { + try { + const Ctor = ctor || UIEvent2; + const ev = new Ctor(type2, { bubbles: true, cancelable: true, view: w2, ...opts }); + document.dispatchEvent(ev); + if (document.body) document.body.dispatchEvent(ev); + } catch (_) { } - for (const [id2, node] of sessions.entries()) { - if (node.lastSeenAt < cutoff) sessions.delete(id2); + }; + let x3 = 140 + Math.random() * 30; + let y3 = 110 + Math.random() * 20; + const targetX2 = 540 + Math.random() * 40; + const targetY2 = 380 + Math.random() * 30; + const steps = 22; + let i = 0; + const start2 = Date.now(); + const moveStep = () => { + if (i > steps) return; + x3 += (targetX2 - x3) * 0.16 + (Math.random() - 0.5) * 5; + y3 += (targetY2 - y3) * 0.16 + (Math.random() - 0.5) * 4; + fire("mousemove", MouseEvent2, { + screenX: Math.round(x3), + screenY: Math.round(y3), + clientX: Math.round(x3), + clientY: Math.round(y3), + button: 0, + buttons: 1 + }); + i += 1; + const done = Date.now() - start2 >= durationMs; + if (i <= steps && !done) { + setTimeout(moveStep, 26 + Math.floor(Math.random() * 32)); + } else { + fire("mousedown", MouseEvent2, { clientX: Math.round(x3), clientY: Math.round(y3), button: 0, buttons: 1 }); + fire("mouseup", MouseEvent2, { clientX: Math.round(x3), clientY: Math.round(y3), button: 0, buttons: 0 }); + fire("click", MouseEvent2, { clientX: Math.round(x3), clientY: Math.round(y3), button: 0 }); + try { + fire("keyup", KeyboardEvent2, { key: "a", code: "KeyA", keyCode: 65, which: 65 }); + } catch (_) { + } } - while (sessions.size > config.maxSessions) { - let oldestId = ""; - let oldestAt = Infinity; - for (const [id2, node] of sessions.entries()) { - if (node.lastSeenAt < oldestAt) { - oldestAt = node.lastSeenAt; - oldestId = id2; - } + }; + moveStep(); +} +function waitFor(cond, timeoutMs = 15e3, intervalMs = 40) { + return new Promise((res, rej) => { + const started = Date.now(); + const timer = setInterval(() => { + let ok = false; + try { + ok = cond(); + } catch (_) { } - if (!oldestId) break; - sessions.delete(oldestId); - for (const [hash, node] of nodes.entries()) { - if (node.sessionId === oldestId) nodes.delete(hash); + if (ok) { + clearInterval(timer); + res(); + } else if (Date.now() - started > timeoutMs) { + clearInterval(timer); + rej(new Error("timeout")); } + }, intervalMs); + }); +} +async function createDom(region, prefix2) { + let cookies = []; + const now = Date.now(); + if (_cookieCache.ts > 0 && now - _cookieCache.ts < COOKIE_CACHE_TTL_MS) { + cookies = _cookieCache.cookies; + } else { + try { + const res = await fetch("https://zcode.z.ai/", { + headers: { + "User-Agent": fp.userAgent, + "sec-ch-ua": '"Chromium";v="' + fp.uaMajor + '", "Not)A;Brand";v="24"', + "sec-ch-ua-mobile": "?0", + "sec-ch-ua-platform": '"Linux"', + "Accept-Language": "en-US,en;q=0.9" + } + }); + cookies = typeof res.headers.getSetCookie === "function" ? res.headers.getSetCookie() : []; + _cookieCache = { cookies, ts: Date.now() }; + } catch (_) { } } - function action(config) { - return config.mode; + const interceptor = makeInterceptor(_bypassPeCacheOnce); + _bypassPeCacheOnce = false; + if (!process.__capUnhandledRejectionHooked) { + process.__capUnhandledRejectionHooked = true; + process.on("unhandledRejection", (reason2) => { + if (!_DEBUG) return; + try { + const r2 = reason2 && reason2.stack ? reason2.stack : String(reason2); + process.stderr.write(`[host-unhandledRejection] ${typeof reason2} ${JSON.stringify(reason2).slice(0, 200)} ${r2} +`); + } catch (_) { + } + }); + process.on("uncaughtException", (err) => { + try { + const msg = err && err.message ? err.message : String(err); + process.stderr.write(`[captcha-guest-uncaught] ${msg} +`); + } catch (_) { + } + }); } - return { - resolve(req, body2, format, model, config) { - if (config.mode === "off") return { source: "none", action: "off", confidence: 0 }; - prune(config); - const explicitTrace = requestTraceContext(req, body2); - if (explicitTrace.sessionId) return explicitResult(explicitTrace, config); - const canonical = canonicalize(body2, format, model); - if (!canonical) { - if (hasTraceContext(explicitTrace)) return explicitResult(explicitTrace, config); - return { source: "none", action: action(config), confidence: 0 }; + const noop = () => { + }; + const guestConsole = _DEBUG ? { + log: (...a) => process.stderr.write(`[guest-log] ${a.map((x3) => typeof x3 === "object" ? safeJson(x3) : String(x3)).join(" ")} +`), + warn: (...a) => process.stderr.write(`[guest-warn] ${a.map((x3) => typeof x3 === "object" ? safeJson(x3) : String(x3)).join(" ")} +`), + error: (...a) => process.stderr.write(`[guest-err] ${a.map((x3) => typeof x3 === "object" ? safeJson(x3) : String(x3)).join(" ")} +`), + info: (...a) => process.stderr.write(`[guest-info] ${a.map((x3) => typeof x3 === "object" ? safeJson(x3) : String(x3)).join(" ")} +`), + debug: (...a) => process.stderr.write(`[guest-debug] ${a.map((x3) => typeof x3 === "object" ? safeJson(x3) : String(x3)).join(" ")} +`), + trace: (...a) => process.stderr.write(`[guest-trace] ${a.map((x3) => typeof x3 === "object" ? safeJson(x3) : String(x3)).join(" ")} +`) + } : { log: noop, warn: noop, error: noop, info: noop, debug: noop, trace: noop }; + const w2 = new GlobalWindow({ + url: "https://zcode.z.ai/", + console: guestConsole, + settings: { + enableJavaScriptEvaluation: true, + enableImageFileLoading: true, + suppressInsecureJavaScriptEnvironmentWarning: true, + navigator: { userAgent: fp.userAgent }, + viewport: { width: fp.screen.w, height: fp.screen.h, devicePixelRatio: 1 }, + fetch: { + disableSameOriginPolicy: true, + interceptor } - const nodeHash = hashJson(canonical.identity); - const existing = nodes.get(nodeHash); - if (existing) { - remember(nodeHash, existing, config); - return withTraceContext(result("lineage", action(config), existing, 0.95), explicitTrace); + } + }); + const browserFrame = new WindowBrowserContext(w2).getBrowserFrame(); + global.__browserFrame = browserFrame; + global.__cookieContainer = browserFrame.page.context.cookieContainer; + for (const raw of cookies) { + try { + const u = new URL("https://zcode.z.ai/"); + const parts = raw.split(";"); + const pair = parts[0].split("="); + const cookie = { + name: pair[0].trim(), + value: pair.slice(1).join("=").trim(), + url: u.origin, + domain: u.hostname, + path: "/" + }; + for (const p of parts.slice(1)) { + const kv = p.trim().split(/=(.*)/s); + const k = (kv[0] || "").toLowerCase(); + if (k === "domain" && kv[1]) cookie.domain = kv[1]; + if (k === "path" && kv[1]) cookie.path = kv[1]; + if (k === "expires") cookie.expires = new Date(kv[1]).getTime(); + if (k === "max-age") cookie.maxAge = parseInt(kv[1], 10); + if (k === "httponly") cookie.httpOnly = true; + if (k === "secure") cookie.secure = true; + if (k === "samesite") cookie.sameSite = kv[1]; } - const parent2 = findLinearParent(canonical, nodes); - if (parent2) { - remember(nodeHash, parent2, config); - return withTraceContext(result("lineage", action(config), parent2, 0.9), explicitTrace); + browserFrame.page.context.cookieContainer.addCookies([cookie]); + } catch (_) { + } + } + const visitorId = import_node_crypto2.default.randomUUID(); + const deviceMid = import_node_crypto2.default.randomUUID(); + const pre = [ + { name: "zcode_visitor_id", value: visitorId, domain: "zcode.z.ai" }, + { name: "zcode_device_mid", value: deviceMid, domain: "zcode.z.ai" }, + { name: "visitor_id", value: visitorId, domain: "zcode.z.ai", httpOnly: true } + ]; + for (const c of pre) { + try { + browserFrame.page.context.cookieContainer.addCookies([{ ...c, url: "https://zcode.z.ai", path: "/" }]); + } catch (_) { + } + } + applyPolyfills(w2); + installNativeToString(w2); + installEvalInstrumentation(w2); + const needsGlobalAlias = typeof Bun !== "undefined"; + if (needsGlobalAlias) { + const g = globalThis; + installGlobalWindowAlias(g, w2); + } + if (w2.Error) { + w2.Error.prepareStackTrace = Error.prepareStackTrace; + } + w2.__capDebugDump = (url2, src, kind2) => { + try { + const s = String(src || ""); + const sha1 = import_node_crypto2.default.createHash("sha1").update(s).digest("hex"); + process.stderr.write( + ` +[${kind2}] url=${url2} len=${s.length} sha1=${sha1} + head300: ${JSON.stringify(s.slice(0, 300))} + tail100: ${JSON.stringify(s.slice(-100))} +` + ); + if (/^https?:/.test(String(url2))) { + (async () => { + try { + const res = await fetch(url2, { headers: { "user-agent": fp.userAgent } }); + const fresh = Buffer.from(await res.arrayBuffer()); + process.stderr.write( + `[${kind2}-CACHE-COMPARE] cachedLen=${s.length} freshLen=${fresh.length} freshSha1=${import_node_crypto2.default.createHash("sha1").update(fresh).digest("hex")} http=${res.status} +` + ); + if (fresh.length > 0 && fresh.length !== s.length) { + process.stderr.write(`[${kind2}-MISMATCH] deleting ${diskPathFor(url2)} (stale/truncated cache) +`); + try { + import_node_fs3.default.unlinkSync(diskPathFor(url2)); + } catch (_) { + } + _memCdnCache.delete(url2); + } + } catch (fetchErr) { + process.stderr.write(`[${kind2}-CACHE-COMPARE-ERR] ${fetchErr.message} +`); + } + })(); } - const fresh = newSession(); - remember(nodeHash, fresh, config); - return withTraceContext(result("lineage", action(config), fresh, 0.75), explicitTrace); + } catch (_) { } }; + w2.eval(GUEST_EVAL_PATCH); + w2.document.write(HTML); + w2.AliyunCaptchaConfig = { region, prefix: prefix2 }; + return { window: w2, browserFrame }; } -var defaultClientSessionResolver = createClientSessionResolver(); -function result(source, action, node, confidence) { - return { - source, - action, - confidence, - sessionId: node.sessionId, - upstreamSessionId: node.upstreamSessionId - }; -} -function requestTraceContext(req, body2) { - const bodyTrace = bodyMetadataTrace(body2); - return { - requestId: firstHeader(req.headers, ["x-request-id"]) ?? bodyTrace.requestId, - traceId: firstHeader(req.headers, ["x-zcode-trace-id"]) ?? bodyTrace.traceId, - queryId: firstHeader(req.headers, ["x-query-id"]) ?? bodyTrace.queryId, - sessionId: firstHeader(req.headers, ["x-opencode-session", "x-claude-code-session-id", "x-session-id", "x-parent-session-id", "helicone-session-id"]) ?? bodyTrace.sessionId - }; -} -function explicitResult(trace, config) { - return { - source: "explicit", - action: config.mode, - confidence: 1, - ...trace.requestId ? { requestId: trace.requestId } : {}, - ...trace.traceId ? { traceId: trace.traceId } : {}, - ...trace.queryId ? { queryId: trace.queryId } : {}, - ...trace.sessionId ? { sessionId: trace.sessionId, upstreamSessionId: trace.sessionId } : {} - }; -} -function withTraceContext(session, trace) { - if (!trace.requestId && !trace.traceId && !trace.queryId) return session; - return { - ...session, - ...trace.requestId ? { requestId: trace.requestId } : {}, - ...trace.traceId ? { traceId: trace.traceId } : {}, - ...trace.queryId ? { queryId: trace.queryId } : {} - }; -} -function hasTraceContext(trace) { - return Boolean(trace.requestId || trace.traceId || trace.queryId || trace.sessionId); -} -function firstHeader(headers2, names) { - for (const name2 of names) { - const value2 = headers2.get(name2); - if (value2 && value2.trim()) return value2.trim(); - } - return null; +function isGuestConsoleCall() { + const stack = new Error().stack ?? ""; + return /alicdn\.com|aliyuncs\.com/i.test(stack); } -function bodyMetadataTrace(body2) { - if (!body2) return {}; - try { - const parsed = JSON.parse(body2); - const metadata = parsed?.metadata; - if (!metadata || typeof metadata !== "object") return {}; - return { - requestId: stringProperty(metadata, ["requestId", "request_id"]), - traceId: stringProperty(metadata, ["traceId", "trace_id"]), - queryId: stringProperty(metadata, ["queryId", "query_id"]), - sessionId: stringProperty(metadata, ["sessionId", "session_id", "conversationId", "conversation_id"]) +function makeDualConsole(isGuest = isGuestConsoleCall) { + const host2 = console; + const dual = {}; + for (const key of Object.keys(host2)) { + const fn = host2[key]; + if (typeof fn !== "function") { + dual[key] = fn; + continue; + } + dual[key] = (...args) => { + if (isGuest()) return; + return fn.apply(host2, args); }; - } catch { - return {}; } + return dual; } -function stringProperty(obj, names) { - for (const name2 of names) { - const value2 = obj[name2]; - if (typeof value2 === "string" && value2.trim()) return value2.trim(); +function installGlobalWindowAlias(g, w2) { + _aliasRefCount += 1; + if (_aliasRefCount === 1 && !process.env.CAPTCHA_DEBUG) { + _dualConsole = makeDualConsole(); + _savedConsoleDescriptor = Object.getOwnPropertyDescriptor(g, "console"); + try { + Object.defineProperty(g, "console", { + get() { + return _dualConsole; + }, + set(v) { + try { + w2.console = v; + } catch (_) { + } + }, + configurable: true + }); + } catch (_) { + } + } + const props = new Set(Object.getOwnPropertyNames(w2)); + for (const name2 of EXTRA_WINDOW_PROPS) props.add(name2); + for (const proto = Object.getPrototypeOf(w2); proto && proto !== Object.prototype; ) { + for (const name2 of Object.getOwnPropertyNames(proto)) props.add(name2); + break; + } + for (const prop of props) { + if (HOST_CRITICAL_GLOBALS.has(prop)) continue; + try { + Object.defineProperty(g, prop, { + get() { + return w2[prop]; + }, + set(v) { + try { + w2[prop] = v; + } catch (_) { + } + }, + configurable: true + }); + } catch (_) { + } + } + for (const prop of ["window", "self", "top", "parent"]) { + try { + Object.defineProperty(g, prop, { get() { + return w2; + }, configurable: true }); + } catch (_) { + } + } + for (const prop of ["setTimeout", "setInterval", "clearTimeout", "clearInterval"]) { + try { + Object.defineProperty(g, prop, { + get() { + return w2[prop]?.bind(w2); + }, + configurable: true + }); + } catch (_) { + } } - return void 0; -} -function canonicalize(body2, format, fallbackModel) { - if (!body2) return null; - let parsed; try { - parsed = JSON.parse(body2); - } catch { - return null; + Object.defineProperty(g, "__capWindowFor", { + get() { + return w2; + }, + configurable: true + }); + } catch (_) { } - if (!parsed || typeof parsed !== "object") return null; - const model = typeof parsed.model === "string" ? parsed.model : fallbackModel; - const messages = Array.isArray(parsed.messages) ? parsed.messages : []; - if (messages.length === 0) return null; - const identity = { - format, - model, - system: parsed.system, - developer: messages.filter((m) => typeof m === "object" && m !== null && m.role === "developer"), - tools: parsed.tools, - tool_choice: parsed.tool_choice, - messages - }; - return { model, identity, messages }; -} -function findLinearParent(canonical, nodes) { - if (canonical.messages.length < 3) return null; - const prefix2 = { - ...canonical.identity, - messages: canonical.messages.slice(0, -2) - }; - if (prefix2.messages.length === 0) return null; - return nodes.get(hashJson(prefix2)) ?? null; -} -function newSession() { - const upstreamSessionId = crypto.randomUUID(); - return { - nodeHash: "", - sessionId: `ses_${upstreamSessionId.replace(/-/g, "").slice(0, 12)}`, - upstreamSessionId, - lastSeenAt: Date.now() - }; -} -function hashJson(value2) { - return hashString(stableStringify(value2)); -} -function hashString(value2) { - return import_node_crypto.default.createHash("sha256").update(value2, "utf-8").digest("hex"); -} -function stableStringify(value2) { - if (value2 === null || typeof value2 !== "object") return JSON.stringify(value2); - if (Array.isArray(value2)) return `[${value2.map(stableStringify).join(",")}]`; - const obj = value2; - return `{${Object.keys(obj).sort().map((k) => `${JSON.stringify(k)}:${stableStringify(obj[k])}`).join(",")}}`; -} - -// src/proxy/session-context.ts -function resolveSessionContext(input) { - if (input.config.clientIdentity.mode === "off") return void 0; - const resolver = input.resolver ?? defaultClientSessionResolver; - return resolver.resolve(input.clientReq, input.body, input.upstreamFormat, input.model, input.config.clientIdentity); -} -function shouldUseExactTraceHeaders(plan, session) { - return plan === "start-plan" || hasExplicitTraceHeaders(session) || shouldForwardSessionId(session); -} -function shouldForwardSessionId(session) { - return session?.source === "explicit" || session?.action === "enforce"; -} -function sessionIdForHeader(session) { - if (!session || !shouldForwardSessionId(session)) return void 0; - return session.upstreamSessionId ?? session.sessionId; -} -function hasExplicitTraceHeaders(session) { - return Boolean(session?.requestId || session?.traceId || session?.queryId); } - -// src/proxy/upstream.ts -var ANTHROPIC_VERSION = "2023-06-01"; -var STARTPLAN_ANTHROPIC_BASE = "https://zcode.z.ai/api/v1/zcode-plan"; -var STRIP_HEADERS = /* @__PURE__ */ new Set([ - "host", - "authorization", - "x-api-key", - "anthropic-version", - "content-length", - "connection", - "proxy-authorization", - "proxy-authenticate", - "transfer-encoding", - "x-request-id", - "x-zcode-trace-id", - "x-zcode-session-type", - "x-query-id", - "x-session-id", - // V4 signing headers are proxy-generated only; inbound copies must never - // reach the upstream (spoofed values would either fail verification or - // silently disable proxy signing via the existing-header guard). - "x-client-ts", - "x-client-version", - "x-client-sig", - "x-client-nonce", - "x-app-id", - "x-client-pow", - "x-client-sign-verified" -]); -function buildUpstreamURL(format, provider, plan = "coding-plan") { - if (plan === "start-plan") { - return `${STARTPLAN_ANTHROPIC_BASE}/anthropic/v1/messages`; +function removeGlobalWindowAlias(g, w2) { + _aliasRefCount -= 1; + if (_aliasRefCount > 0) return; + for (const name2 of Object.getOwnPropertyNames(w2)) { + try { + const d = Object.getOwnPropertyDescriptor(g, name2); + if (d?.get) delete g[name2]; + } catch (_) { + } } - if (format === "anthropic") { - return `${provider.anthropicBaseURL}/v1/messages`; + for (const prop of ["window", "self", "top", "parent"]) { + try { + delete g[prop]; + } catch (_) { + } } - return `${provider.openaiBaseURL}/chat/completions`; -} -function buildAuthHeaders(format, cred, identity, plan = "coding-plan", clientSession) { - const credStr = plan === "start-plan" && cred.jwt ? cred.jwt : credentialString(cred); - const base = { - ...buildIdentityHeaders(identity), - ...buildTraceHeaders(plan, clientSession) - }; - if (format === "anthropic") { - if (plan === "start-plan" && cred.jwt) { - base["authorization"] = `Bearer ${cred.jwt}`; - } else { - base["x-api-key"] = credStr; + if (_savedConsoleDescriptor) { + try { + Object.defineProperty(g, "console", _savedConsoleDescriptor); + } catch (_) { } - base["anthropic-version"] = ANTHROPIC_VERSION; - } else { - base["authorization"] = `Bearer ${credStr}`; + _savedConsoleDescriptor = void 0; + _dualConsole = null; } - return base; } -function buildTraceHeaders(plan, clientSession) { - if (shouldUseExactTraceHeaders(plan, clientSession)) { - return buildZcodeTraceHeaders({ - requestId: clientSession?.requestId, - traceId: clientSession?.traceId, - queryId: clientSession?.queryId, - sessionId: sessionIdForHeader(clientSession) - }); +function destroyDom(win) { + try { + const cap = win.document.getElementById("cap"); + if (cap) cap.replaceChildren(); + win.happyDOM.close(); + } catch (_) { } - const headers2 = { - "x-request-id": crypto.randomUUID(), - // ZCode 3.9.1 attributes every model request; a forwarded conversation turn is the main-agent loop. - "x-zcode-session-type": "main", - "x-zcode-trace-id": crypto.randomUUID() - }; - if (plan !== "start-plan") { - headers2["x-query-id"] = crypto.randomUUID(); - headers2["x-session-id"] = crypto.randomUUID(); + try { + global.__cookieContainer = null; + global.__browserFrame = null; + } catch (_) { + } + try { + if (typeof Bun !== "undefined") removeGlobalWindowAlias(globalThis, win); + } catch (_) { + } + try { + shutdownSyncFetchWorker(); + } catch (_) { } - return headers2; } -function collectPassthroughHeaders(req) { - const result3 = {}; - for (const [key, value2] of req.headers.entries()) { - const lower = key.toLowerCase(); - if (STRIP_HEADERS.has(lower)) continue; - if (lower === "anthropic-beta") { - result3[lower] = value2; +function extractVerifyParam(param) { + let verifyParam = param; + if (param && typeof param === "object") { + verifyParam = param.verifyParam || param.data || param.param; + } + if (!verifyParam || String(verifyParam).length < 20) { + throw new Error("solver returned empty param: " + JSON.stringify(param)); + } + const str = String(verifyParam); + if (str.length < 200) { + throw new Error( + "verify param too short (" + str.length + " chars) \u2014 degraded result, refusing: " + str.slice(0, 80) + ); + } + try { + const decoded = JSON.parse(Buffer.from(str, "base64").toString("utf8")); + const secTok = decoded && (decoded.securityToken || decoded.SecurityToken); + if (!secTok || String(secTok).length < 50) { + throw new Error( + "verify param missing securityToken \u2014 refusing degraded result: " + str.slice(0, 80) + ); + } + } catch (err) { + if (err instanceof SyntaxError || /securityToken/.test(String(err.message))) { + throw err instanceof SyntaxError ? new Error("verify param not base64-JSON: " + str.slice(0, 80)) : err; } + throw err; } - return result3; + return str; } -function buildUpstreamHeaderPairs(clientReq, format, cred, identity, plan = "coding-plan", extraHeaders, clientSession) { - const clientAcceptEncoding = clientReq.headers.get("accept-encoding") ?? "gzip"; - return [ - ["content-type", "application/json"], - ["accept-encoding", clientAcceptEncoding], - ...Object.entries(collectPassthroughHeaders(clientReq)), - ...Object.entries(buildAuthHeaders(format, cred, identity, plan, clientSession)), - ...Object.entries(extraHeaders ?? {}) - ]; +function handleCaptchaResult(result3) { + if (result3 && typeof result3 === "object" && result3.verifyResult === false) { + throw new Error( + "verify rejected: " + JSON.stringify({ verifyCode: result3.verifyCode, certifyId: result3.certifyId }) + ); + } + return result3; } -function buildUpstreamRequest(clientReq, format, provider, cred, body2, identity, plan = "coding-plan", extraHeaders, clientSession) { - const url2 = buildUpstreamURL(format, provider, plan); - const headerPairs = buildUpstreamHeaderPairs(clientReq, format, cred, identity, plan, extraHeaders, clientSession); - const init = { - method: "POST", - headers: Object.fromEntries(headerPairs) - }; - if (body2 !== void 0) { - init.body = body2; +function takeReusableWindow() { + const p = _reusePool; + if (!p.window) return null; + if (p.solves >= REUSE_MAX_SOLVES) { + discardReusableWindow(); + return null; } - return new Request(url2, init); + if (Date.now() - p.lastUsedAt > REUSE_MAX_IDLE_MS) { + discardReusableWindow(); + return null; + } + return { window: p.window, browserFrame: p.browserFrame, reused: true }; } - -// src/proxy/endpoint-routing.ts -init_identity(); -var DEFAULT_ORIGIN = "https://zcode.z.ai"; -var CONFIG_PATH = "/api/v1/agent/configs"; -var SUCCESS_TTL_MS = 3e5; -var FAILURE_COOLDOWN_MS = 3e4; -var REQUEST_TIMEOUT_MS = 3e3; -var MAX_MAPPING_ENTRIES = 256; -function normalizePath(pathname) { - if (pathname === "/") return "/"; - return pathname.replace(/\/+$/u, "") || "/"; +function stageReusableWindow(window2, browserFrame) { + _reusePool.window = window2; + _reusePool.browserFrame = browserFrame; + _reusePool.solves = 0; + _reusePool.lastUsedAt = Date.now(); } -function routingKey(url2) { - const port = url2.port || "443"; - return `${url2.protocol}//${url2.hostname.toLowerCase()}:${port}${normalizePath(url2.pathname)}`; +function discardReusableWindow() { + const p = _reusePool; + if (p.window) { + try { + destroyDom(p.window); + } catch (_) { + } + } + p.window = null; + p.browserFrame = null; + p.solves = 0; } -function parseMappingUrl(value2, field) { - if (typeof value2 !== "string") throw new Error(`mapping.${field} must be a string`); - const parsed = new URL(value2); - if (parsed.protocol !== "https:" || parsed.username || parsed.password || parsed.search || parsed.hash) { - throw new Error(`mapping.${field} URL is not a plain https URL`); +function noteWindowSolved() { + _reusePool.solves += 1; + _reusePool.lastUsedAt = Date.now(); +} +async function solveTraceless(opts) { + const scene = opts.scene || "11xygtvd"; + const region = opts.region || "sgp"; + const prefix2 = opts.prefix || "no8xfe"; + const timeoutMs = opts.timeoutMs ?? 3e4; + const wantReuse = opts.reuseWindow ?? process.env.CAPTCHA_WINDOW_REUSE === "1"; + let dom; + let reused = false; + if (wantReuse) { + dom = takeReusableWindow(); + if (dom) reused = true; + } + if (!dom) { + dom = await createDom(region, prefix2); + } + const { window: w2, browserFrame } = dom; + const solveStart = Date.now(); + let solveSucceeded = false; + let keepWindow = false; + try { + await waitFor(() => typeof w2.initAliyunCaptcha === "function", timeoutMs, 50); + simulateBehavior(w2, 600); + const param = await new Promise((resolve, reject) => { + const timer = setTimeout(() => { + const peUrl = (() => { + try { + return w2.__lastPeUrl || "?"; + } catch (_) { + return "?"; + } + })(); + const reqs = _requestLog.filter((r2) => r2.at >= solveStart).map((r2) => `${r2.at - solveStart}ms ${r2.method} ${String(r2.url).replace(/^https?:\/\//, "").slice(0, 60)}`).slice(-12); + reject(new Error(`captcha solve timeout pe=${peUrl.split("/").pop() || peUrl} reqs=${JSON.stringify(reqs)}`)); + }, timeoutMs); + const stallMs = opts.stallMs ?? Number(process.env.CAPTCHA_STALL_MS || 6e3); + const stallTimer = setInterval(() => { + const last = _requestLog[_requestLog.length - 1]; + if (last && Date.now() - last.at > stallMs) { + const peUrl = (() => { + try { + return w2.__lastPeUrl || "?"; + } catch (_) { + return "?"; + } + })(); + noteStallAndMaybeEvict(peUrl); + const reqs = _requestLog.filter((r2) => r2.at >= solveStart).map((r2) => `${r2.at - solveStart}ms ${r2.method} ${String(r2.url).replace(/^https?:\/\//, "").slice(0, 60)}`).slice(-12); + clearTimeout(timer); + clearInterval(stallTimer); + reject(new Error(`captcha solve stall pe=${peUrl.split("/").pop() || peUrl} lastXhr=${last.at - solveStart}ms reqs=${JSON.stringify(reqs)}`)); + } + }, 500); + const finish = (fn) => (value2) => { + clearTimeout(timer); + clearInterval(stallTimer); + fn(value2); + }; + try { + w2.initAliyunCaptcha({ + SceneId: scene, + mode: "popup", + region, + prefix: prefix2, + language: "en", + element: "#cap", + button: "#btn", + captchaLogoImg: "", + showErrorTip: false, + getInstance: (inst) => { + try { + (inst.startTracelessVerification || inst.show).call(inst); + } catch (e) { + finish(reject)(new Error(`start: ${e.message}`)); + } + }, + success: (result3) => { + try { + finish(resolve)(handleCaptchaResult(result3)); + } catch (err) { + finish(reject)(err); + } + }, + fail: (err) => finish(reject)(new Error(`fail: ${JSON.stringify(err)}`)), + onError: (err) => finish(reject)(new Error(`onError: ${JSON.stringify(err)}`)) + }); + } catch (err) { + clearTimeout(timer); + reject(err); + } + }); + try { + const okPe = w2.__lastPeUrl; + if (okPe) _stallCounts.delete(okPe); + } catch (_) { + } + if (process.env.CAPTCHA_DUMP_DBT === "1") { + try { + const dbt = w2.__DBT || []; + import_node_fs3.default.writeFileSync( + process.env.CAPTCHA_DBT_FILE || "/tmp/pe-dbt.json", + JSON.stringify({ count: dbt.length, last: dbt.slice(-8), all: dbt }, null, 1) + ); + } catch (_) { + } + } + solveSucceeded = true; + const out = extractVerifyParam(param); + if (wantReuse) { + if (reused) noteWindowSolved(); + else stageReusableWindow(w2, browserFrame); + keepWindow = true; + } + return out; + } finally { + if (!keepWindow) { + if (_reusePool.window === w2) _reusePool.window = null; + destroyDom(w2); + } } - return parsed; } -var EndpointRoutingService = class { - configUrl; - identity; - credential; - fetchImpl; - now; - successTtlMs; - failureCooldownMs; - requestTimeoutMs; - onSnapshot; - snapshot; - retryAfter = 0; - refreshPromise; - constructor(opts) { - this.configUrl = `${(opts.origin?.trim() || DEFAULT_ORIGIN).replace(/\/+$/u, "")}${CONFIG_PATH}`; - this.identity = opts.identity; - this.credential = opts.credential; - this.fetchImpl = opts.fetchImpl ?? fetch; - this.now = opts.now ?? Date.now; - this.successTtlMs = opts.successTtlMs ?? SUCCESS_TTL_MS; - this.failureCooldownMs = opts.failureCooldownMs ?? FAILURE_COOLDOWN_MS; - this.requestTimeoutMs = opts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS; - this.onSnapshot = opts.onSnapshot; - } - /** True when at least one successful snapshot has been fetched. */ - hasSnapshot() { - return this.snapshot !== void 0; - } - /** - * Resolve a request URL through the mapping table. Never throws: any error - * resolves to `{ routed: false, url }` so the caller keeps the original URL. - * The optional `credential` (coding-plan key) is attached as `x-api-key` on - * a mapping refresh fetch, mirroring the client's `sourceHeaders`. - */ - async resolve(url2, credential) { - let parsed; - try { - parsed = new URL(url2); - } catch { - return { routed: false, url: url2 }; +var import_undici, import_node_crypto2, import_node_fs3, import_node_os2, import_node_path, import_node_worker_threads, SYNC_FETCH_BUF_BYTES, SYNC_FETCH_HEADER_BYTES, _syncFetchWorker, SYNC_WORKER_SRC, CDN_CACHE_DIR, _memCdnCache, _cookieCache, COOKIE_CACHE_TTL_MS, _DEBUG, proxyUrl, _requestLog, _stallCounts, _bypassPeCacheOnce, fp, HTML, peVmCallRegex, GUEST_EVAL_PATCH, HOST_CRITICAL_GLOBALS, EXTRA_WINDOW_PROPS, _aliasRefCount, _savedConsoleDescriptor, _dualConsole, _reusePool, REUSE_MAX_SOLVES, REUSE_MAX_IDLE_MS; +var init_captcha_happy = __esm({ + "src/proxy/captcha-happy.ts"() { + "use strict"; + init_lib(); + init_WindowBrowserContext(); + import_undici = __toESM(require_undici(), 1); + import_node_crypto2 = __toESM(require("node:crypto"), 1); + import_node_fs3 = __toESM(require("node:fs"), 1); + import_node_os2 = __toESM(require("node:os"), 1); + import_node_path = __toESM(require("node:path"), 1); + import_node_worker_threads = require("node:worker_threads"); + SYNC_FETCH_BUF_BYTES = 8 * 1024 * 1024; + SYNC_FETCH_HEADER_BYTES = 64; + _syncFetchWorker = null; + SYNC_WORKER_SRC = ` + const { parentPort } = require("node:worker_threads"); + const enc = new TextEncoder(); + parentPort.on("message", (m) => { + (async () => { + const i32 = new Int32Array(m.sab); + const u8 = new Uint8Array(m.sab); + // Fixed-size header (bytes), NOT i32.length * 4 \u2014 that is the whole SAB. + const payloadAt = 64; + const fail = (msg) => { + const b = enc.encode(msg); + u8.set(b, payloadAt); + i32[5] = b.length; i32[1] = 0; i32[2] = 0; i32[3] = 0; i32[4] = 0; + i32[0] = 2; Atomics.notify(i32, 0); + }; + try { + const res = await fetch(m.url, m.init); + const body = Buffer.from(await res.arrayBuffer()); + const headers = {}; + for (const [k, v] of res.headers) headers[k] = v; + const setCookie = typeof res.headers.getSetCookie === "function" ? res.headers.getSetCookie() : []; + const statusText = enc.encode(res.statusText || ""); + const headersJson = enc.encode(JSON.stringify(headers)); + const setCookieJson = enc.encode(JSON.stringify(setCookie)); + let off = payloadAt; + u8.set(statusText, off); i32[2] = statusText.length; off += statusText.length; + u8.set(headersJson, off); i32[3] = headersJson.length; off += headersJson.length; + u8.set(setCookieJson, off); i32[4] = setCookieJson.length; off += setCookieJson.length; + u8.set(body, off); i32[5] = body.length; + i32[1] = res.status; + i32[0] = 1; Atomics.notify(i32, 0); + } catch (err) { + fail(String((err && err.message) || err)); + } + })(); + }); +`; + CDN_CACHE_DIR = import_node_path.default.join(import_node_os2.default.homedir(), ".zcode-captcha-cdn-cache"); + _memCdnCache = /* @__PURE__ */ new Map(); + _cookieCache = { cookies: [], ts: 0 }; + COOKIE_CACHE_TTL_MS = 5 * 60 * 1e3; + _DEBUG = /^(1|true|yes)$/i.test( + process.env.CAPTCHA_DEBUG || process.env.CAPTCHA_DEBUG_BODIES || "" + ); + proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY; + if (proxyUrl) { + try { + (0, import_undici.setGlobalDispatcher)(new import_undici.ProxyAgent(proxyUrl)); + } catch (_) { + } } - try { - await this.ensureFresh(credential); - } catch { + _requestLog = []; + _stallCounts = /* @__PURE__ */ new Map(); + _bypassPeCacheOnce = false; + fp = generateFingerprint(); + HTML = ` +
+ +`; + peVmCallRegex = /55==A\?\(f=r\[n\+\+\],l=e\.pop\(\),h=e\.pop\(\),o=\[\],\w+\(f\)\.forEach\(function\(\)\{o\.unshift\(e\.pop\(\)\)\}\),p=null===h\?l\.apply\((\w+),o\):h\[l\]\.apply\(h,o\),r\[n\+\+\]&&e\.push\(p\)\):/; + GUEST_EVAL_PATCH = ` +(function() { + try { + Object.defineProperty(Event.prototype, "isTrusted", { + get() { return true; }, + configurable: true + }); + } catch (e) {} + try { + if (window.HTMLDocument) { + Object.defineProperty(window.HTMLDocument, "name", { value: "HTMLDocument", configurable: true }); + Object.defineProperty(window.HTMLDocument.prototype, Symbol.toStringTag, { value: "HTMLDocument", configurable: true }); } - const target2 = this.snapshot?.mapping.get(routingKey(parsed)); - if (!target2) return { routed: false, url: url2 }; - const rewritten = new URL(target2); - rewritten.search = parsed.search; - return { routed: true, url: rewritten.href }; - } - async ensureFresh(credential) { - const now = this.now(); - if (this.snapshot && this.snapshot.expiresAt > now || this.retryAfter > now) return; - const pending = this.refreshPromise ?? this.beginRefresh(credential); - await pending; - } - beginRefresh(credential) { - const promise = this.refresh(credential).finally(() => { - if (this.refreshPromise === promise) this.refreshPromise = void 0; + } catch (e) {} + try { + Object.defineProperty(window.Document.prototype, Symbol.toStringTag, { value: "HTMLDocument", configurable: true }); + } catch (e) {} + try { + window.addEventListener("unhandledrejection", function(e) { + var r = e && e.reason; + try { + console.error("[UH-REASON]", typeof r, r && r.stack ? r.stack.split("\\n").slice(0,6).join(" | ") : (r && r.message), JSON.stringify(r)); + } catch (e2) {} }); - this.refreshPromise = promise; - return promise; - } - async refresh(credential) { - const identityHeaders = Object.fromEntries( - Object.entries(buildIdentityHeaders(this.identity)).filter(([name2]) => name2 !== "X-ZCode-Agent") - ); - const headers2 = { - ...identityHeaders, - Accept: "application/json" - }; - const key = credential ?? this.credential?.(); - if (key) headers2["x-api-key"] = key; - const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs); + } catch (e) {} + try { + window.addEventListener("error", function(e) { + try { + console.error("[WINDOW-ERROR]", e && e.message, e && e.error && e.error.stack ? e.error.stack.split("\\n").slice(0,6).join(" | ") : ""); + } catch (e2) {} + }); + } catch (e) {} + // ---- eval/Function parse-fail instrumentation (installed before pe chain) ---- + // Catches SyntaxError from guest-side eval()/new Function() (the dynamic pe.* + // chunk is evaluated this way in some SDK paths). Host-side twin: the + // PropertySymbol.evaluateScript wrapper in installEvalInstrumentation(). + function __capFailDump(kind, code) { try { - const resp = await this.fetchImpl(this.configUrl, { - method: "GET", - headers: headers2, - redirect: "manual", - signal: controller.signal - }); - if (resp.status < 200 || resp.status >= 300) throw new Error(`agent_configs_http_${resp.status}`); - const parsed = await resp.json(); - const envelope = parsed; - if (!envelope || typeof envelope !== "object" || envelope.code !== 0) { - throw new Error("agent_configs_nonzero_code"); - } - const data2 = envelope.data; - const entries2 = data2?.proxyEndpoint?.mapping; - const list = Array.isArray(entries2) ? entries2 : []; - if (list.length > MAX_MAPPING_ENTRIES) throw new Error("agent_configs_too_many_mappings"); - const mapping = /* @__PURE__ */ new Map(); - for (const entry of list) { - const raw = entry; - const from = parseMappingUrl(raw.from, "from"); - const to = parseMappingUrl(raw.to, "to"); - const key2 = routingKey(from); - if (mapping.has(key2)) throw new Error("agent_configs_duplicate_from"); - mapping.set(key2, to.href); - } - this.snapshot = { expiresAt: this.now() + this.successTtlMs, mapping }; - this.retryAfter = 0; - this.onSnapshot?.(mapping.size); - } catch { - this.retryAfter = this.now() + this.failureCooldownMs; - } finally { - clearTimeout(timer); - } + var src = String(code || ""); + if (typeof window.__capDebugDump === "function") { + window.__capDebugDump(window.__lastPeUrl || "?", src, kind); + } else { + console.error("[" + kind + "] url=" + (window.__lastPeUrl || "?") + " len=" + src.length + " head=" + JSON.stringify(src.slice(0, 300)) + " tail=" + JSON.stringify(src.slice(-100))); + } + } catch (e2) {} } -}; -var defaultRouting = null; -var defaultRoutingKey = ""; -function identityCacheKey(identity) { - return JSON.stringify([identity.appVersion, identity.sourceTitle, identity.refererOrigin, identity.deviceMid ?? ""]); -} -function getDefaultEndpointRouting(config) { - if (!config.endpointRouting.enabled) return null; - const key = `${config.endpointRouting.origin} -${identityCacheKey(config.identity)}`; - if (!defaultRouting || key !== defaultRoutingKey) { - defaultRouting = new EndpointRoutingService({ - origin: config.endpointRouting.origin, - identity: config.identity - }); - defaultRoutingKey = key; + try { + var _origEval2 = window.eval; + if (_origEval2) { + window.eval = function(code) { + try { return _origEval2.call(window, code); } + catch (e) { + if (e && (/unexpected|invalid|parse|syntax/i.test(String((e && e.message) || e)))) { + __capFailDump("REALM-EVAL-FAIL", code); + } + throw e; + } + }; + } + } catch (e) {} + try { + var _of = window.Function; + if (_of) { + var _WF = function() { + var args = Array.prototype.slice.call(arguments); + var body = args.length ? String(args[args.length - 1]) : ""; + try { return _of.apply(this, args); } + catch (e) { + if (e && (/unexpected|invalid|parse|syntax/i.test(String((e && e.message) || e)))) { + __capFailDump("REALM-FN-FAIL", body); + } + throw e; + } + }; + _WF.prototype = _of.prototype; + try { Object.defineProperty(_WF, "name", { value: "Function", configurable: true }); } catch (e) {} + window.Function = _WF; + } + } catch (e) {} +})(); +`; + HOST_CRITICAL_GLOBALS = /* @__PURE__ */ new Set([ + "process", + "Bun", + "console", + "performance", + "crypto", + "fetch", + "queueMicrotask", + "structuredClone", + "TextEncoder", + "TextDecoder", + "requestAnimationFrame", + "cancelAnimationFrame", + // NOTE: `print` was removed from this list (2026-08-29). The polyfill + // defines a harmless no-op on the window, but the alias pass skipped it, + // so under Bun (guest scripts run in the HOST realm) the Aliyun pe risk + // engine hit a bare `print` reference → ReferenceError → broken + // fingerprint chain → degraded solve success rate (711 WINDOW-ERRORs in + // one day). Bun's host global has no native `print`, so aliasing the + // stub shadows nothing critical. + "URL", + "URLSearchParams", + "AbortController", + "AbortSignal", + "ReadableStream", + "WritableStream", + "TransformStream", + "Blob", + "File", + "FormData", + "Headers", + "Request", + "Response", + "Event", + "EventTarget", + "MessageChannel", + "MessagePort", + "Buffer", + "global", + "globalThis", + // JS intrinsics — GlobalWindow re-exposes them as class fields; the host + // versions are fine, so never shadow them. + "Array", + "ArrayBuffer", + "Boolean", + "DataView", + "Date", + "Error", + "EvalError", + "Float32Array", + "Float64Array", + "Function", + "Infinity", + "Int8Array", + "Int16Array", + "Int32Array", + "Intl", + "JSON", + "Map", + "Math", + "NaN", + "Number", + "Object", + "Promise", + "RangeError", + "ReferenceError", + "RegExp", + "Reflect", + "Set", + "String", + "Symbol", + "SyntaxError", + "TypeError", + "URIError", + "Uint8Array", + "Uint8ClampedArray", + "Uint16Array", + "Uint32Array", + "WeakMap", + "WeakSet", + "decodeURI", + "decodeURIComponent", + "encodeURI", + "encodeURIComponent", + "escape", + "isFinite", + "isNaN", + "parseFloat", + "parseInt", + "unescape", + "eval" + ]); + EXTRA_WINDOW_PROPS = [ + "moveBy", + "moveTo", + "resizeBy", + "resizeTo", + "scrollTo", + "scrollBy", + "scroll", + "open", + "close", + "stop", + "focus", + "blur", + "print", + "alert", + "confirm", + "prompt", + "getSelection", + "find" + ]; + _aliasRefCount = 0; + _dualConsole = null; + _reusePool = { window: null, browserFrame: null, solves: 0, lastUsedAt: 0 }; + REUSE_MAX_SOLVES = Number(process.env.CAPTCHA_REUSE_MAX_SOLVES || 25); + REUSE_MAX_IDLE_MS = Number(process.env.CAPTCHA_REUSE_MAX_IDLE_MS || 12e4); } - return defaultRouting; -} +}); -// src/proxy/client-signing.ts -init_identity(); -var DEFAULT_ORIGIN2 = "https://zcode.z.ai"; -var GATE_PATH = "/api/v1/agent/configs"; -var HANDSHAKE_PATH = "/api/paas/c1f3a7e2/v2/client"; -var APP_ID = "zcode"; -var POW_BITS = 8; -var NONCE_BYTES = 16; -var POW_NONCE_BYTES = 12; -var KDF_SALT = "WD_CLIENT_SIGN_KDF_SALT"; -var KDF_INFO_HMAC = "getSignKey_hmac"; -var KDF_INFO_ED25519 = "ed25519_priv"; -var HANDSHAKE_METHOD = "get_sign_key"; -var GATE_TTL_MS = 36e5; -var GATE_FAILURE_COOLDOWN_MS = 6e4; -var GATE_UNAVAILABLE_COOLDOWN_MS = 3e4; -var GATE_TIMEOUT_MS = 15e3; -var HANDSHAKE_TIMEOUT_MS = 1e4; -var VERIFY_SIGNATURE_INVALID = "VERIFY_SIGNATURE_INVALID"; -var VERIFY_APIKEY_EXPIRED = "VERIFY_APIKEY_EXPIRED"; -var UNSIGNED_PATHS = /* @__PURE__ */ new Set([ - "/api/v1/zcode-plan/anthropic/v1/messages", - "/api/v1/zcode-plan/chat/completions", - "/api/v1/off-peak/anthropic/v1/messages" -]); -var SIGNING_HEADER_NAMES = /* @__PURE__ */ new Set([ - "x-client-ts", - "x-client-version", - "x-client-sig", - "x-client-nonce", - "x-app-id", - "x-client-pow", - "x-client-sign-verified" -]); -var encoder = new TextEncoder(); -function encodeUtf8(value2) { - const bytes = encoder.encode(value2); - const out = new Uint8Array(bytes.byteLength); - out.set(bytes); - return out; +// src/proxy/captcha-solver.ts +async function runCaptchaSolve(scene, region, prefix2) { + if (BACKEND !== "happy") { + throw new Error(`captcha backend "${BACKEND}" is not available; use ZCODE_CAPTCHA_BACKEND=happy`); + } + if (!happyMod) happyMod = await Promise.resolve().then(() => (init_captcha_happy(), captcha_happy_exports)); + return happyMod.solveTraceless({ scene, region, prefix: prefix2 }); } -function bytesToBase64(bytes) { - let binary = ""; - for (const b of bytes) binary += String.fromCharCode(b); - return btoa(binary); +function setCaptchaSolverConcurrency(_n) { } -function bytesToHex(bytes) { - return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(""); +function shutdownCaptchaSolver() { } -function randomHex(byteCount) { - return bytesToHex(crypto.getRandomValues(new Uint8Array(byteCount))); +function captchaSolverConcurrency() { + return Number(process.env.CAPTCHA_DAEMON_CONCURRENCY || 4); } -function base64ToBytes(value2) { - if (!value2 || value2.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(value2)) { - throw new Error("invalid base64"); +var BACKEND, happyMod; +var init_captcha_solver = __esm({ + "src/proxy/captcha-solver.ts"() { + "use strict"; + BACKEND = process.env.ZCODE_CAPTCHA_BACKEND?.trim().toLowerCase() || "happy"; + happyMod = null; + } +}); + +// src/proxy/captcha-cpu-governor.ts +async function readCpuCounters() { + try { + const stat = await import_promises.default.readFile("/proc/stat", "utf8"); + const line = stat.split("\n")[0] ?? ""; + const parts = line.split(/\s+/).slice(1).map((v) => Number(v) || 0); + const idle = (parts[3] ?? 0) + (parts[4] ?? 0); + const total = parts.reduce((sum, n) => sum + n, 0); + return { idle, total }; + } catch { + const load = import_node_os3.default.loadavg()[0] ?? 0; + const cpus = Math.max(1, import_node_os3.default.cpus().length); + const pct = load / cpus * 100; + return { idle: 100 - pct, total: 100 }; } - const binary = atob(value2); - const out = new Uint8Array(binary.length); - for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i); - return out; } -async function hkdfBytes(secret, info) { - const key = await crypto.subtle.importKey("raw", encodeUtf8(secret), "HKDF", false, ["deriveBits"]); - return new Uint8Array(await crypto.subtle.deriveBits( - { name: "HKDF", hash: "SHA-256", salt: encodeUtf8(KDF_SALT), info: encodeUtf8(info) }, - key, - 256 - )); +function resolveCpuGovernorConfig(opts) { + const poolSizeMin = opts.poolSizeMin ?? Number(process.env.CAPTCHA_POOL_MIN || 40); + const poolSizeMax = Math.max( + poolSizeMin, + opts.poolSizeMax ?? Number(process.env.CAPTCHA_POOL_MAX || 120) + ); + const maxSolveConcurrency = opts.solveConcurrency ?? Number( + process.env.CAPTCHA_SOLVE_CONCURRENCY || (process.env.ZCODE_CAPTCHA_LOW_CPU === "1" ? 3 : 6) + ); + const cpuLimitPercent = opts.cpuLimitPercent ?? (process.env.CAPTCHA_CPU_GOVERNOR === "0" ? 0 : DEFAULT_CPU_LIMIT); + const intervalMs = opts.cpuGovernorIntervalSec != null ? opts.cpuGovernorIntervalSec * 1e3 : DEFAULT_INTERVAL_MS; + return { + cpuLimitPercent, + hysteresisPercent: 5, + poolSizeMin, + poolSizeMax, + maxSolveConcurrency, + intervalMs + }; } -async function handshakeSignature(secret, message) { - const bits = await hkdfBytes(secret, KDF_INFO_HMAC); - try { - const key = await crypto.subtle.importKey("raw", bits, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]); - const mac = new Uint8Array(await crypto.subtle.sign("HMAC", key, encodeUtf8(message))); - try { - return bytesToBase64(mac); - } finally { - mac.fill(0); - } - } finally { - bits.fill(0); +var import_promises, import_node_os3, DEFAULT_CPU_LIMIT, DEFAULT_INTERVAL_MS, TARGET_STEP, CaptchaCpuGovernor; +var init_captcha_cpu_governor = __esm({ + "src/proxy/captcha-cpu-governor.ts"() { + "use strict"; + import_promises = __toESM(require("node:fs/promises"), 1); + import_node_os3 = __toESM(require("node:os"), 1); + DEFAULT_CPU_LIMIT = Number(process.env.CAPTCHA_CPU_LIMIT_PCT || 100); + DEFAULT_INTERVAL_MS = Number(process.env.CAPTCHA_CPU_GOVERNOR_INTERVAL_MS || 2e3); + TARGET_STEP = 15; + CaptchaCpuGovernor = class { + constructor(cfg) { + this.cfg = cfg; + this.concurrency = 1; + this.maxEffectiveTarget = cfg.poolSizeMin; + } + cfg; + prevCpu = null; + lastCpuPercent = 0; + concurrency; + maxEffectiveTarget; + timer = null; + get enabled() { + return this.cfg.cpuLimitPercent > 0; + } + configure(partial) { + this.cfg = { ...this.cfg, ...partial }; + this.maxEffectiveTarget = Math.max( + this.cfg.poolSizeMin, + Math.min(this.maxEffectiveTarget, this.cfg.poolSizeMax) + ); + this.concurrency = Math.min(this.concurrency, this.cfg.maxSolveConcurrency); + } + start() { + if (!this.enabled || this.timer) return; + void this.tick(); + this.timer = setInterval(() => void this.tick(), this.cfg.intervalMs); + } + stop() { + if (this.timer) { + clearInterval(this.timer); + this.timer = null; + } + } + snapshot() { + const limit = this.cfg.cpuLimitPercent; + return { + cpuPercent: Math.round(this.lastCpuPercent * 10) / 10, + limitPercent: limit, + concurrency: this.concurrency, + maxEffectiveTarget: this.maxEffectiveTarget, + throttled: this.lastCpuPercent >= limit - 3 + }; + } + /** Parallel background solves allowed right now (may be 0 when pool is warm). */ + backgroundConcurrency(readyTokens) { + if (!this.enabled) return this.cfg.maxSolveConcurrency; + const cpu = this.lastCpuPercent; + const limit = this.cfg.cpuLimitPercent; + let allowed = this.concurrency; + if (cpu >= limit) { + allowed = 0; + } else if (cpu >= limit - 4) { + allowed = Math.min(allowed, 1); + } else if (cpu >= limit - 10) { + allowed = Math.min(allowed, 2); + } + if (readyTokens < this.cfg.poolSizeMin) { + return Math.max(1, allowed); + } + return allowed; + } + maxPoolTarget() { + return this.maxEffectiveTarget; + } + async tick() { + const cpu = await this.sampleCpuPercent(); + this.lastCpuPercent = cpu; + const limit = this.cfg.cpuLimitPercent; + const rampThreshold = limit - this.cfg.hysteresisPercent; + if (cpu >= limit) { + this.concurrency = 1; + this.maxEffectiveTarget = this.cfg.poolSizeMin; + } else if (cpu >= limit - 4) { + if (this.concurrency > 1) this.concurrency -= 1; + this.maxEffectiveTarget = this.cfg.poolSizeMin; + } else if (cpu >= limit - 10) { + if (this.concurrency > 2) this.concurrency -= 1; + this.maxEffectiveTarget = Math.max( + this.cfg.poolSizeMin, + this.maxEffectiveTarget - TARGET_STEP + ); + } else if (cpu <= rampThreshold) { + if (this.concurrency < this.cfg.maxSolveConcurrency) { + this.concurrency += 1; + } + if (this.maxEffectiveTarget < this.cfg.poolSizeMax) { + this.maxEffectiveTarget = Math.min( + this.cfg.poolSizeMax, + this.maxEffectiveTarget + TARGET_STEP + ); + } + } + } + async sampleCpuPercent() { + const cur = await readCpuCounters(); + if (!this.prevCpu) { + this.prevCpu = cur; + return this.lastCpuPercent; + } + const idleDelta = cur.idle - this.prevCpu.idle; + const totalDelta = cur.total - this.prevCpu.total; + this.prevCpu = cur; + if (totalDelta <= 0) return this.lastCpuPercent; + const used = (totalDelta - idleDelta) / totalDelta * 100; + return Math.max(0, Math.min(100, used)); + } + }; } -} -async function decryptSigningPrivateKey(apiKeyId, secret, privateCipher) { - const cipher = base64ToBytes(privateCipher); - if (cipher.byteLength <= 12 + 16) throw new Error("privateCipher is too short"); - const aesKeyBits = await hkdfBytes(secret, KDF_INFO_ED25519); +}); + +// src/proxy/captcha-token.ts +function parseCertifyId(param) { try { - const aesKey = await crypto.subtle.importKey("raw", aesKeyBits, "AES-GCM", false, ["decrypt"]); - const plain = new Uint8Array( - await crypto.subtle.decrypt( - { name: "AES-GCM", iv: cipher.slice(0, 12), additionalData: encodeUtf8(apiKeyId), tagLength: 128 }, - aesKey, - cipher.slice(12) - ) - ); - try { - const pkcs8 = base64ToBytes(new TextDecoder().decode(plain)); - return await crypto.subtle.importKey("pkcs8", pkcs8, "Ed25519", false, ["sign"]); - } finally { - plain.fill(0); - } - } finally { - aesKeyBits.fill(0); + const json = JSON.parse(Buffer.from(param, "base64").toString("utf8")); + return typeof json.certifyId === "string" && json.certifyId.length > 0 ? json.certifyId : null; + } catch { + return null; } } -async function signBusinessMessage(privateKey, message) { - const sig = new Uint8Array(await crypto.subtle.sign("Ed25519", privateKey, encodeUtf8(message))); - try { - return bytesToBase64(sig); - } finally { - sig.fill(0); - } +function isCaptchaDuplicateError(message) { + return /F008|"verifyCode"\s*:\s*"F008"/i.test(message); } -function hasLeadingZeroBits(bytes, bits) { - const fullBytes = Math.floor(bits / 8); - for (let i = 0; i < fullBytes; i++) { - if (bytes[i] !== 0) return false; - } - const remainder = bits % 8; - if (remainder === 0) return true; - const mask = 255 << 8 - remainder & 255; - return ((bytes[fullBytes] ?? 255) & mask) === 0; +function isCaptchaIpBlockError(message) { + if (isCaptchaDuplicateError(message)) return false; + return CAPTCHA_IP_BLOCK_RE.test(message); } -async function createProofOfWork(apiKeyId, sessionId, ts, signal2) { - const seedDigest = new Uint8Array( - await crypto.subtle.digest("SHA-256", encodeUtf8(`${apiKeyId} -${APP_ID} -${sessionId} -${ts}`)) - ); - const seed2 = bytesToHex(seedDigest).slice(0, 32); - const nonce = randomHex(POW_NONCE_BYTES); - for (let counter = 0; counter <= 4294967295; counter++) { - signal2?.throwIfAborted(); - const candidate = `${nonce}${counter.toString(16).padStart(8, "0")}`; - const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", encodeUtf8(`${seed2} -${candidate}`))); - if (hasLeadingZeroBits(digest, POW_BITS)) return candidate; +var CAPTCHA_IP_BLOCK_RE; +var init_captcha_token = __esm({ + "src/proxy/captcha-token.ts"() { + "use strict"; + CAPTCHA_IP_BLOCK_RE = /too many|request was denied|risk control|frequent|rate\s*limit|exceeded.*(?:request|limit)|ip\s*suspicious|denied due to|retry later/i; } - throw new Error("Unable to solve client request proof of work"); +}); + +// src/proxy/captcha-pool.ts +function resolvePoolOpts(opts) { + const max = opts.poolSizeMax ?? opts.poolSize ?? DEFAULT_POOL_MAX; + const min = Math.min(opts.poolSizeMin ?? DEFAULT_POOL_MIN, max); + return { + poolSizeMin: min, + poolSizeMax: max, + idleFloor: Math.min(opts.idleFloor ?? DEFAULT_IDLE_FLOOR, min), + deepIdleAfterMs: Math.max( + opts.deepIdleAfterMs ?? DEFAULT_DEEP_IDLE_AFTER_MS, + opts.scaleDownIdleMs ?? DEFAULT_SCALE_DOWN_IDLE_MS + ), + scaleDownIdleMs: opts.scaleDownIdleMs ?? DEFAULT_SCALE_DOWN_IDLE_MS, + tokenTtlMs: opts.tokenTtlMs ?? DEFAULT_TOKEN_TTL_MS, + refillIntervalMs: opts.refillIntervalMs ?? DEFAULT_REFILL_INTERVAL_MS, + solveRetries: opts.solveRetries ?? SOLVE_RETRIES, + staggerMs: opts.staggerMs ?? DEFAULT_STAGGER_MS, + solveConcurrency: opts.solveConcurrency ?? DEFAULT_SOLVE_CONCURRENCY, + emptyTakeRace: Math.max(1, opts.emptyTakeRace ?? EMPTY_TAKE_RACE), + onCaptchaIpBlock: opts.onCaptchaIpBlock + }; } -function parseSigningCredential(credential) { - const dot = credential.indexOf("."); - if (dot <= 0 || dot !== credential.lastIndexOf(".")) return void 0; - const apiKeyId = credential.slice(0, dot); - const apiKeySecret = credential.slice(dot + 1); - if (!apiKeyId.trim() || !apiKeySecret.trim()) return void 0; - return { apiKeyId, apiKeySecret }; +function configureCaptchaPool(opts) { + pool.configure(opts); } -function isUnsignedPath(pathname) { - let path2 = pathname; - try { - path2 = decodeURIComponent(pathname); - } catch { - } - path2 = path2.replace(/\/+$/u, ""); - return UNSIGNED_PATHS.has(path2); +function getCaptchaPoolStats() { + return pool.stats(); } -function findHeader(pairs, name2) { - const lower = name2.toLowerCase(); - for (const [key, value2] of pairs) { - if (key.toLowerCase() === lower) return value2; - } - return void 0; +function stopCaptchaPool() { + pool.stopBackgroundRefill(); + shutdownCaptchaSolver(); } -var ClientSigningManager = class { - gateUrl; - identity; - fetchImpl; - now; - states = /* @__PURE__ */ new Map(); - notedKeys = /* @__PURE__ */ new Set(); - onEvent; - constructor(opts) { - this.gateUrl = `${(opts.origin?.trim() || DEFAULT_ORIGIN2).replace(/\/+$/u, "")}${GATE_PATH}`; - this.identity = opts.identity; - this.fetchImpl = opts.fetchImpl ?? fetch; - this.now = opts.now ?? Date.now; - this.onEvent = opts.onEvent; - } - /** - * Add the V4 signing headers to an upstream header-pair list. Returns the - * input pairs unchanged whenever signing does not apply: exempt path, - * bypass, non-signable credential, missing session id, gate off/unreachable, - * or handshake failure. Never throws. - */ - async sign(url2, pairs, cred) { - return (await this.signWithStatus(url2, pairs, cred)).pairs; - } - /** - * `sign` with a `signed` flag so the retry ladder can distinguish - * "signed but rejected" from "never signed" without identity checks on the - * returned array reference. Cheap local eligibility checks (credential - * separator, session id) run BEFORE the gate probe so non-signable - * credentials never pay for network fetches. - */ - async signWithStatus(url2, pairs, cred) { - let parsed; - try { - parsed = new URL(url2); - } catch { - return { pairs, signed: false }; - } - if (parsed.protocol !== "https:") return { pairs, signed: false }; - if (isUnsignedPath(parsed.pathname)) return { pairs, signed: false }; - if (pairs.some(([k]) => k.toLowerCase() === "x-client-sig")) return { pairs, signed: false }; - const stateKey = `${parsed.origin} -${cred.credential}`; - const state2 = this.stateFor(stateKey); - if (state2.bypass) return { pairs, signed: false }; - const parsedCred = parseSigningCredential(cred.credential); - if (!parsedCred) { - this.noteOnce(stateKey, "credential has no {apiKeyId}.{apiKeySecret} separator \u2014 signing skipped"); - return { pairs, signed: false }; - } - const sessionId = findHeader(pairs, "x-session-id")?.trim(); - if (!sessionId) { - this.noteOnce(stateKey, "upstream request has no x-session-id \u2014 signing skipped"); - return { pairs, signed: false }; - } - if (!await this.gateEnabled(state2, cred)) return { pairs, signed: false }; - let privateKey; - try { - privateKey = await this.ensurePrivateKey(state2, stateKey, parsedCred, parsed.origin); - } catch { - this.noteOnce(stateKey, "signing handshake failed \u2014 sending unsigned"); - this.invalidateState(stateKey); - return { pairs, signed: false }; - } - const signedPairs = await this.buildSignedPairs(stateKey, pairs, privateKey, parsedCred, sessionId, cred.appVersion); - return signedPairs ? { pairs: signedPairs, signed: true } : { pairs, signed: false }; - } - async buildSignedPairs(stateKey, pairs, privateKey, parsedCred, sessionId, appVersion) { - const ts = String(Date.now()); - const nonce = randomHex(NONCE_BYTES); - let pow; - let sig; - try { - pow = await createProofOfWork(parsedCred.apiKeyId, sessionId, ts); - sig = await signBusinessMessage( - privateKey, - `${parsedCred.apiKeyId} -${ts} -${appVersion} -${sessionId} -${nonce}` - ); - } catch (err) { - if (err.name !== "AbortError") { - this.noteOnce(stateKey, `signing failed (${err.message}) \u2014 sending unsigned`); - } - return null; - } - const cleaned = pairs.filter(([k]) => { - const lower = k.toLowerCase(); - return !SIGNING_HEADER_NAMES.has(lower) && lower !== "x-session-id"; - }); - return [ - ...cleaned, - ["X-Client-Ts", ts], - ["X-Client-Version", appVersion], - ["X-Client-Sig", sig], - // canonical case replaces the lowercase trace copy in this append position - // (mirrors the client's i.set("X-Session-Id") Headers.set semantics) - ["X-Session-Id", sessionId], - ["X-Client-Nonce", nonce], - ["X-App-Id", APP_ID], - ["X-Client-Pow", pow] - ]; - } - /** - * True when the response is a signing rejection the client retries on: - * HTTP 401 whose envelope mentions VERIFY_SIGNATURE_INVALID / VERIFY_APIKEY_EXPIRED. - * Reads a clone; the response body stays consumable by the caller. - */ - async isVerifyFailure(resp) { - if (resp.status !== 401) return false; - try { - const body2 = await resp.clone().json(); - if (!body2 || typeof body2 !== "object" || Array.isArray(body2)) return false; - const data2 = body2.data; - const error2 = body2.error; - const candidates = [body2.msg, body2.reason, data2?.reason, error2?.reason, error2?.message]; - return candidates.some((v) => v === VERIFY_SIGNATURE_INVALID || v === VERIFY_APIKEY_EXPIRED); - } catch { - return false; - } - } - /** Drop the cached signing key for a (origin, credential) pair after a VERIFY rejection. */ - invalidate(url2, credential) { - try { - const stateKey = `${new URL(url2).origin} -${credential}`; - this.invalidateState(stateKey); - } catch { - } - } - /** Permanently stop signing for a (origin, credential) pair (two VERIFY rejections). */ - setBypass(url2, credential) { - try { - const stateKey = `${new URL(url2).origin} -${credential}`; - const state2 = this.stateFor(stateKey); - state2.bypass = true; - this.invalidateState(stateKey); - this.onEvent?.("client-signing: VERIFY rejection persisted \u2014 bypassing signing for this credential"); - } catch { - } - } - invalidateState(stateKey) { - const state2 = this.states.get(stateKey); - if (!state2) return; - state2.epoch += 1; - state2.privKey = void 0; - state2.handshake = void 0; - } - stateFor(stateKey) { - let state2 = this.states.get(stateKey); - if (!state2) { - state2 = { gateEnabled: false, gateExpiresAt: 0, gateNegUntil: 0, epoch: 0, bypass: false }; - this.states.set(stateKey, state2); - } - return state2; - } - async gateEnabled(state2, cred) { - const now = this.now(); - if (state2.gateExpiresAt > now) return state2.gateEnabled; - if (state2.gateNegUntil > now) return false; - if (state2.gatePromise) return state2.gatePromise; - const promise = this.probeGate(state2, cred).finally(() => { - if (state2.gatePromise === promise) state2.gatePromise = void 0; - }); - state2.gatePromise = promise; - return promise; - } - async probeGate(state2, cred) { - const now = this.now(); - let outcome; - try { - outcome = await this.fetchGate(cred); - } catch { - state2.gateNegUntil = now + GATE_FAILURE_COOLDOWN_MS; - return false; - } - state2.gateEnabled = outcome === "enabled"; - if (outcome === "unavailable") { - state2.gateNegUntil = now + GATE_UNAVAILABLE_COOLDOWN_MS; - } else { - state2.gateExpiresAt = now + GATE_TTL_MS; - state2.gateNegUntil = 0; - } - if (state2.gateEnabled) this.onEvent?.("client-signing: server enabled codingPlanSignature \u2014 signing requests"); - return state2.gateEnabled; - } - async fetchGate(cred) { - const identityHeaders = Object.fromEntries( - Object.entries(buildIdentityHeaders(this.identity)).filter(([name2]) => name2 !== "X-ZCode-Agent" && name2 !== "X-Device-Mid") - ); - const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), GATE_TIMEOUT_MS); - try { - const resp = await this.fetchImpl(this.gateUrl, { - method: "GET", - headers: { ...identityHeaders, "x-api-key": cred.credential }, - redirect: "manual", - signal: controller.signal - }); - if (!resp.ok) return "unavailable"; - const parsed = await resp.json(); - if (!parsed || parsed.code !== 0) return "unavailable"; - const data2 = parsed.data; - if (!data2 || !Object.prototype.hasOwnProperty.call(data2, "codingPlanSignature")) return "disabled"; - const signature = data2.codingPlanSignature; - return signature?.enable === true ? "enabled" : "disabled"; - } finally { - clearTimeout(timer); - } - } - async ensurePrivateKey(state2, stateKey, parsedCred, origin) { - if (state2.privKey) return state2.privKey; - if (state2.handshake) return state2.handshake; - const epoch = state2.epoch; - const handshake = this.performHandshake(parsedCred, origin).then((key) => { - if (state2.epoch !== epoch) throw new Error("signing key changed during handshake"); - state2.privKey = key; - return key; - }); - const clear = () => { - if (state2.handshake === handshake) state2.handshake = void 0; - }; - handshake.then(clear, clear); - state2.handshake = handshake; - return handshake; - } - async performHandshake(parsedCred, origin) { - const ts = String(Date.now()); - const nonce = randomHex(NONCE_BYTES); - const sig = await handshakeSignature( - parsedCred.apiKeySecret, - `${HANDSHAKE_METHOD} -${parsedCred.apiKeyId} -${ts} -${nonce}` - ); - const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), HANDSHAKE_TIMEOUT_MS); - try { - const resp = await this.fetchImpl(`${origin}${HANDSHAKE_PATH}`, { - method: "POST", - headers: { Authorization: `${parsedCred.apiKeyId}.${parsedCred.apiKeySecret}`, "Content-Type": "application/json" }, - body: JSON.stringify({ apiKey: `${parsedCred.apiKeyId}.${parsedCred.apiKeySecret}`, nonce, sig, ts }), - redirect: "manual", - signal: controller.signal - }); - if (resp.status !== 200) throw new Error(`handshake_http_${resp.status}`); - const envelope = await resp.json(); - if (envelope.code === 500) throw new Error("handshake_server_500"); - if (envelope.code !== 200) throw new Error(`handshake_rejected: ${String(envelope.msg)}`); - const cipher = envelope.data?.privateCipher; - if (typeof cipher !== "string" || !cipher) throw new Error("handshake_omitted_privateCipher"); - return await decryptSigningPrivateKey(parsedCred.apiKeyId, parsedCred.apiKeySecret, cipher); - } finally { - clearTimeout(timer); - } - } - noteOnce(stateKey, message) { - if (this.notedKeys.has(stateKey)) return; - this.notedKeys.add(stateKey); - this.onEvent?.(`client-signing: ${message}`); +async function takeCaptchaToken(cfg) { + if (!cfg.enabled || !cfg.prefix || !cfg.sceneId) { + throw new Error("Captcha config unavailable from ZCode API"); } -}; -async function sendWithClientSigning(signer, params) { - const { url: url2, headerPairs, credential, appVersion, send, debug } = params; - if (!signer) return send(headerPairs); - const first = await signer.signWithStatus(url2, headerPairs, { credential, appVersion }); - let resp = await send(first.pairs); - if (!first.signed || !await signer.isVerifyFailure(resp)) return resp; - debug?.("401 VERIFY_SIGNATURE_* \u2014 invalidating signing key and retrying once"); - signer.invalidate(url2, credential); - const second = await signer.signWithStatus(url2, headerPairs, { credential, appVersion }); - resp = await send(second.pairs); - if (!second.signed || !await signer.isVerifyFailure(resp)) return resp; - signer.setBypass(url2, credential); - debug?.("401 VERIFY_SIGNATURE_* twice \u2014 sending unsigned (signing bypassed)"); - return send(headerPairs); + return pool.takeToken(cfg); } -var defaultSigner = null; -var defaultSignerKey = ""; -function identityCacheKey2(identity) { - return JSON.stringify([identity.appVersion, identity.sourceTitle, identity.refererOrigin, identity.deviceMid ?? ""]); +function startCaptchaPoolRefill(cfg) { + if (!cfg.enabled || !cfg.prefix || !cfg.sceneId) return; + pool.startBackgroundRefill(cfg); } -function getDefaultClientSigning(config) { - if (!config.clientSigning.enabled) return null; - const key = `${config.clientSigning.origin} -${identityCacheKey2(config.identity)}`; - if (!defaultSigner || key !== defaultSignerKey) { - defaultSigner = new ClientSigningManager({ - identity: config.identity, - origin: config.clientSigning.origin - }); - defaultSignerKey = key; - } - return defaultSigner; +async function prefillCaptchaPool(cfg, count) { + if (!cfg.enabled || !cfg.prefix || !cfg.sceneId) return; + await pool.prefill(cfg, count); } - -// src/proxy/ordered-transport.ts -var import_node_net = require("node:net"); -var import_node_tls = require("node:tls"); -var CRLF = "\r\n"; -var HEADER_END = new Uint8Array([13, 10, 13, 10]); -var HEADER_NAME = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/; -async function sendOrderedUpstreamRequest(req) { - const url2 = new URL(req.url); - const bodyBytes = bodyToBytes(req.body); - const requestHead = buildRequestHead(url2, req.method ?? "POST", req.headers, bodyBytes.byteLength); - const socket = await openSocket(url2); - return await new Promise((resolve, reject) => { - let headerBuffer = new Uint8Array(0); - let responseStarted = false; - let postWrite = false; - let bodyController = null; - let chunkedDecoder = null; - let remainingContentLength = null; - const bodyStream = new ReadableStream({ - start(controller) { - bodyController = controller; - }, - cancel() { - socket.destroy(); +function urgentCaptchaRefill() { + pool.requestUrgentRefill(); +} +var CertifyIdRegistry, DEFAULT_POOL_MIN, DEFAULT_POOL_MAX, DEFAULT_TOKEN_TTL_MS, DEFAULT_REFILL_INTERVAL_MS, DEFAULT_STAGGER_MS, DEFAULT_SOLVE_CONCURRENCY, DEFAULT_SCALE_DOWN_IDLE_MS, DEFAULT_IDLE_FLOOR, DEFAULT_DEEP_IDLE_AFTER_MS, EMPTY_TAKE_RACE, SOLVE_RETRIES, SCALE_UP_STEP, TAKE_RATE_WINDOW_MS, CaptchaTokenPool, pool; +var init_captcha_pool = __esm({ + "src/proxy/captcha-pool.ts"() { + "use strict"; + init_captcha_cpu_governor(); + init_captcha_solver(); + init_captcha_token(); + CertifyIdRegistry = class { + constructor(ttlMs) { + this.ttlMs = ttlMs; + } + ttlMs; + seen = /* @__PURE__ */ new Map(); + setTtlMs(ttlMs) { + this.ttlMs = ttlMs; + } + prune() { + const cutoff = Date.now() - this.ttlMs; + for (const [id2, at] of this.seen) { + if (at < cutoff) this.seen.delete(id2); + } + } + has(id2) { + this.prune(); + return this.seen.has(id2); + } + add(id2) { + this.prune(); + this.seen.set(id2, Date.now()); + } + clear() { + this.seen.clear(); + } + }; + DEFAULT_POOL_MIN = Number(process.env.CAPTCHA_POOL_MIN || 40); + DEFAULT_POOL_MAX = Number(process.env.CAPTCHA_POOL_MAX || 120); + DEFAULT_TOKEN_TTL_MS = Number(process.env.CAPTCHA_CACHE_TTL_MS || 95e3); + DEFAULT_REFILL_INTERVAL_MS = Number(process.env.CAPTCHA_REFILL_INTERVAL_MS || 1e3); + DEFAULT_STAGGER_MS = Number(process.env.CAPTCHA_SOLVE_STAGGER_MS || 0); + DEFAULT_SOLVE_CONCURRENCY = Number( + process.env.CAPTCHA_SOLVE_CONCURRENCY || (process.env.ZCODE_CAPTCHA_LOW_CPU === "1" ? 3 : 8) + ); + DEFAULT_SCALE_DOWN_IDLE_MS = Number(process.env.CAPTCHA_POOL_SCALE_DOWN_IDLE_MS || 12e4); + DEFAULT_IDLE_FLOOR = Number(process.env.CAPTCHA_POOL_IDLE_FLOOR || 1); + DEFAULT_DEEP_IDLE_AFTER_MS = Number(process.env.CAPTCHA_DEEP_IDLE_AFTER_MS || 9e5); + EMPTY_TAKE_RACE = Math.max(1, Number(process.env.CAPTCHA_EMPTY_TAKE_RACE || 3)); + SOLVE_RETRIES = Number(process.env.ZCODE_CAPTCHA_RETRIES || 4); + SCALE_UP_STEP = 20; + TAKE_RATE_WINDOW_MS = 12e4; + CaptchaTokenPool = class { + tokens = []; + opts; + effectiveTarget; + refillTimer = null; + refillInFlight = false; + lastSolveAt = 0; + activeSolves = 0; + cfg = null; + pausedUntil = 0; + lastTakeAt; + takeTimestamps = []; + certifyIds; + governor = null; + // Mint-storm detection: sliding windows of failed vs successful mint + // attempts. A burst of failures with zero successes means velocity/IP + // flagging — fire the telegram IP reset automatically. + mintFailures = []; + mintSuccesses = []; + lastStormResetAt = 0; + constructor(opts = {}) { + const hasOpts = Object.keys(opts).length > 0; + this.opts = resolvePoolOpts(opts); + this.effectiveTarget = hasOpts ? this.opts.poolSizeMin : 0; + this.lastTakeAt = Date.now(); + this.certifyIds = new CertifyIdRegistry(this.opts.tokenTtlMs); + this.initGovernor(opts); + setCaptchaSolverConcurrency(this.opts.solveConcurrency); + } + configure(opts) { + this.opts = resolvePoolOpts({ ...this.opts, ...opts }); + this.certifyIds.setTtlMs(this.opts.tokenTtlMs); + this.effectiveTarget = Math.max( + this.opts.poolSizeMin, + Math.min(this.effectiveTarget, this.opts.poolSizeMax) + ); + this.initGovernor(opts); + setCaptchaSolverConcurrency(this.opts.solveConcurrency); + this.trimToTarget(); + } + stats() { + this.pruneExpired(); + return { + ready: this.tokens.length, + target: this.effectiveTarget, + min: this.opts.poolSizeMin, + max: this.opts.poolSizeMax, + activeSolves: this.activeSolves, + solverWorkers: captchaSolverConcurrency(), + cpu: this.governor?.enabled ? this.governor.snapshot() : void 0 + }; + } + invalidate() { + this.tokens = []; + this.certifyIds.clear(); + this.pausedUntil = Date.now() + this.opts.staggerMs; + } + startBackgroundRefill(cfg) { + this.cfg = cfg; + this.stopBackgroundRefill(); + this.governor?.start(); + void this.refill({ urgent: false }); + this.refillTimer = setInterval(() => { + void this.refill({ urgent: false }); + }, this.opts.refillIntervalMs); + } + stopBackgroundRefill() { + this.governor?.stop(); + if (this.refillTimer) { + clearInterval(this.refillTimer); + this.refillTimer = null; + } + } + async takeToken(cfg) { + this.cfg = cfg; + const readyBefore = this.tokens.length; + const token = this.popFresh(); + if (token) { + this.onTokenTaken(false, readyBefore - 1); + void this.refill({ urgent: true }); + return token; + } + this.onTokenTaken(true, 0); + this.effectiveTarget = Math.max(this.effectiveTarget, this.computeActiveTarget()); + let param; + try { + const raceDeadlineMs = Number(process.env.CAPTCHA_SOLVE_RACE_DEADLINE_MS || 25e3); + param = await Promise.race([ + this.solveRaced(cfg), + new Promise( + (_, rej) => setTimeout( + () => rej(new Error(`captcha take deadline (${raceDeadlineMs}ms)`)), + Math.max(1e3, raceDeadlineMs) + ) + ) + ]); + } catch (err) { + const graceMs = Number(process.env.CAPTCHA_TAKE_GRACE_MS || 1e4); + const deadline = Date.now() + Math.max(0, graceMs); + while (Date.now() < deadline) { + await new Promise((r2) => setTimeout(r2, 400)); + const token2 = this.popFresh(); + if (token2) { + this.markParamIssued(token2); + void this.refill({ urgent: true }); + return token2; + } + } + throw err; + } + this.markParamIssued(param); + void this.refill({ urgent: true }); + return param; + } + async prefill(cfg, count) { + this.cfg = cfg; + const target2 = Math.min(count ?? this.effectiveTarget, this.effectiveTarget); + while (this.tokens.length + this.activeSolves < target2) { + const need = target2 - this.tokens.length - this.activeSolves; + if (need <= 0) break; + const concurrency = this.governor?.enabled ? this.governor.backgroundConcurrency(this.tokens.length) : this.opts.solveConcurrency; + await this.solveBatch(cfg, need, Math.max(1, concurrency)); + } + } + requestUrgentRefill() { + void this.refill({ urgent: true }); + } + poolHasCertifyId(certifyId) { + return this.tokens.some((t) => t.certifyId === certifyId); + } + isDuplicateParam(param) { + const certifyId = parseCertifyId(param); + if (!certifyId) return false; + return this.certifyIds.has(certifyId) || this.poolHasCertifyId(certifyId); + } + markParamIssued(param) { + const certifyId = parseCertifyId(param); + if (certifyId) this.certifyIds.add(certifyId); + } + popFresh() { + this.pruneExpired(); + while (this.tokens.length > 0) { + const entry = this.tokens.pop(); + if (entry.certifyId && this.certifyIds.has(entry.certifyId)) continue; + this.markParamIssued(entry.param); + return entry.param; + } + return null; + } + pushToken(param) { + this.pruneExpired(); + if (this.tokens.length >= this.effectiveTarget) return; + const certifyId = parseCertifyId(param); + if (certifyId && (this.certifyIds.has(certifyId) || this.poolHasCertifyId(certifyId))) { + return; + } + this.tokens.push({ param, cachedAt: Date.now(), certifyId }); + } + pruneExpired() { + const now = Date.now(); + this.tokens = this.tokens.filter((t) => now - t.cachedAt < this.opts.tokenTtlMs); + } + deficit() { + this.pruneExpired(); + return Math.max(0, this.effectiveTarget - this.tokens.length - this.activeSolves); + } + pruneTakeWindow() { + const cutoff = Date.now() - TAKE_RATE_WINDOW_MS; + this.takeTimestamps = this.takeTimestamps.filter((t) => t > cutoff); + } + demandTarget() { + this.pruneTakeWindow(); + if (this.takeTimestamps.length === 0) return this.opts.poolSizeMin; + const ratePerSec = this.takeTimestamps.length / (TAKE_RATE_WINDOW_MS / 1e3); + const ttlSec = this.opts.tokenTtlMs / 1e3; + return Math.ceil(ratePerSec * ttlSec * 1.25); + } + /** + * Target while traffic is recent: measured demand (take rate × TTL × + * margin) plus one token of arrival-jitter headroom, floored at + * poolSizeMin, capped by governor + poolSizeMax. This is the ONLY sizing + * authority while active — bursts raise demand, quiet periods drain it. + */ + computeActiveTarget() { + const demand = Math.max(this.demandTarget(), this.opts.poolSizeMin); + const raw = Math.ceil(demand * 1.25) + 1; + const governorMax = this.governor?.maxPoolTarget() ?? this.opts.poolSizeMax; + return Math.max( + this.currentFloor(), + Math.min(this.opts.poolSizeMax, governorMax, raw) + ); + } + onTokenTaken(wasEmpty, readyAfter) { + this.lastTakeAt = Date.now(); + this.takeTimestamps.push(this.lastTakeAt); + this.pruneTakeWindow(); + this.wakeFromIdle(); } - }); - function fail(err) { - if (!responseStarted && postWrite) { - try { - err.postWrite = true; - } catch { + maybeScaleDown() { + if (this.lastTakeAt === 0) return; + const idleMs = Date.now() - this.lastTakeAt; + if (idleMs < this.opts.scaleDownIdleMs) return; + this.pruneTakeWindow(); + const recentTakes = this.takeTimestamps.filter((t) => t > Date.now() - 6e4).length; + if (recentTakes > 1) return; + const floor = this.currentFloor(); + if (this.effectiveTarget > floor) { + this.effectiveTarget = Math.max(floor, this.effectiveTarget - SCALE_UP_STEP); + this.trimToTarget(); } } - if (responseStarted) bodyController?.error(err); - else reject(err); - socket.destroy(); - } - function finish() { - if (chunkedDecoder && !chunkedDecoder.done) { + /** + * Active traffic → poolSizeMin. After scaleDownIdleMs of no takes → + * idleFloor (keeper churn ≈ 1 mint/TTL). After deepIdleAfterMs → 0: + * background solving stops; the banked token still serves a wake-up take. + */ + currentFloor() { + if (this.lastTakeAt === 0) return this.opts.poolSizeMin; + const idleMs = Date.now() - this.lastTakeAt; + if (idleMs >= this.opts.deepIdleAfterMs) return 0; + if (idleMs >= this.opts.scaleDownIdleMs) { + return Math.min(this.opts.idleFloor, this.opts.poolSizeMin); + } + return this.opts.poolSizeMin; + } + /** Traffic returned: restore the full configured floor immediately. */ + wakeFromIdle() { + if (this.effectiveTarget < this.opts.poolSizeMin) { + this.effectiveTarget = this.opts.poolSizeMin; + } + } + trimToTarget() { + this.pruneExpired(); + const floor = Math.max(this.effectiveTarget, 1); + while (this.tokens.length > floor) { + this.tokens.shift(); + } + } + applyGovernorCaps() { + if (!this.governor?.enabled) return; + const governorMax = this.governor.maxPoolTarget(); + const floor = this.currentFloor(); + this.effectiveTarget = Math.max( + floor, + Math.min(this.effectiveTarget, governorMax, this.opts.poolSizeMax) + ); + } + async refill(opts) { + if (!this.cfg) return; + const idleDecay = this.lastTakeAt > 0 && Date.now() - this.lastTakeAt >= this.opts.scaleDownIdleMs; + if (!idleDecay) { + this.effectiveTarget = this.computeActiveTarget(); + } else { + this.maybeScaleDown(); + } + if (!opts.urgent && idleDecay) { + if (this.tokens.length >= Math.max(this.currentFloor(), 1)) return; + } + if (this.refillInFlight || Date.now() < this.pausedUntil) return; + this.applyGovernorCaps(); + const ready = this.tokens.length; + const concurrency = this.governor?.enabled ? opts.urgent ? Math.max(1, this.governor.backgroundConcurrency(ready) || this.governor.snapshot().concurrency) : this.governor.backgroundConcurrency(ready) : this.opts.solveConcurrency; + if (!opts.urgent && concurrency === 0 && ready >= this.opts.poolSizeMin) { + return; + } + const need = this.deficit(); + if (need <= 0) return; + this.refillInFlight = true; try { - bodyController?.error(new Error("upstream chunked body truncated")); - } catch { + await this.solveBatch(this.cfg, need, Math.max(1, concurrency)); + } finally { + this.refillInFlight = false; } - socket.destroy(); - return; } - try { - bodyController?.close(); - } catch { + /** Fire up to `need` solves in parallel waves of solveConcurrency. */ + async solveBatch(cfg, need, concurrency = this.opts.solveConcurrency) { + let remaining = need; + while (remaining > 0 && this.tokens.length + this.activeSolves < this.effectiveTarget) { + const wave = Math.min(remaining, concurrency, this.deficit()); + if (wave <= 0) break; + if (this.opts.staggerMs > 0) await this.waitForStagger(); + const results = await Promise.allSettled( + Array.from({ length: wave }, () => this.solveOne(cfg)) + ); + for (const r2 of results) { + if (r2.status === "fulfilled") { + this.pushToken(r2.value); + } else { + console.warn("[captcha-pool] parallel solve failed:", r2.reason); + } + } + remaining -= wave; + if (results.every((r2) => r2.status === "rejected")) break; + } } - } - function pushBody(bytes) { - if (!bodyController || bytes.byteLength === 0) return; - if (chunkedDecoder) { - chunkedDecoder.push(bytes, bodyController); - if (chunkedDecoder.done) finish(); - return; + async waitForStagger() { + const elapsed = Date.now() - this.lastSolveAt; + const wait = this.opts.staggerMs - elapsed; + if (wait > 0) { + await new Promise((r2) => setTimeout(r2, wait)); + } } - if (remainingContentLength !== null) { - const next = bytes.slice(0, remainingContentLength); - remainingContentLength -= next.byteLength; - if (next.byteLength > 0) bodyController.enqueue(next); - if (remainingContentLength === 0) finish(); - return; + noteMintFailure(reason2) { + const now = Date.now(); + this.mintFailures.push(now); + const cutoff = now - 36e4; + this.mintFailures = this.mintFailures.filter((t) => t > cutoff); + this.maybeFireMintStormReset(reason2); } - bodyController.enqueue(bytes); - } - socket.on("data", (chunk) => { - try { - const bytes = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); - if (!responseStarted) { - headerBuffer = concatBytes(headerBuffer, bytes); - const headerEnd = indexOfBytes(headerBuffer, HEADER_END); - if (headerEnd < 0) return; - const headerBytes = headerBuffer.slice(0, headerEnd); - const rest = headerBuffer.slice(headerEnd + HEADER_END.byteLength); - const parsed = parseResponseHeaders(headerBytes); - responseStarted = true; - const transferEncoding = parsed.headers.get("transfer-encoding")?.toLowerCase() ?? ""; - if (transferEncoding.split(",").map((s) => s.trim()).includes("chunked")) { - parsed.headers.delete("transfer-encoding"); - chunkedDecoder = new ChunkedDecoder(); - } else { - const contentLength2 = parsed.headers.get("content-length"); - remainingContentLength = contentLength2 ? Number.parseInt(contentLength2, 10) : null; - if (!Number.isFinite(remainingContentLength)) remainingContentLength = null; + noteMintSuccess() { + const now = Date.now(); + this.mintSuccesses.push(now); + const cutoff = now - 36e4; + this.mintSuccesses = this.mintSuccesses.filter((t) => t > cutoff); + } + /** Velocity/IP flagging signature: many failed mints in the last 5 min + * while nothing succeeded in the last 3. Fires the telegram IP reset at + * most once per cooldown — requestCaptchaIpResetSync dedupes further. */ + maybeFireMintStormReset(latestReason) { + const now = Date.now(); + const fails = this.mintFailures.filter((t) => t > now - 3e5).length; + const succs = this.mintSuccesses.filter((t) => t > now - 18e4).length; + if (fails < 8 || succs > 0) return; + if (now - this.lastStormResetAt < 12 * 6e4) return; + this.lastStormResetAt = now; + console.warn( + `[captcha] mint storm detected (${fails} failures/5min, ${succs} successes/3min; latest: ${latestReason.slice(0, 120)}) -> requesting IP reset` + ); + try { + this.opts.onCaptchaIpBlock?.(`mint storm: ${fails} failed mints in 5min`); + } catch { + } + } + async solveFresh(cfg) { + this.activeSolves += 1; + this.lastSolveAt = Date.now(); + try { + let lastErr = null; + let sawIpBlock = false; + for (let attempt = 1; attempt <= this.opts.solveRetries; attempt += 1) { + try { + const param = await runCaptchaSolve(cfg.sceneId, cfg.region, cfg.prefix); + if (!param) { + lastErr = "solver returned empty"; + continue; + } + if (this.isDuplicateParam(param)) { + lastErr = `duplicate certifyId ${parseCertifyId(param) ?? "?"}`; + continue; + } + this.noteMintSuccess(); + return param; + } catch (err) { + lastErr = err instanceof Error ? err.message : String(err); + if (isCaptchaDuplicateError(lastErr)) { + lastErr = `duplicate certifyId (F008)`; + } else if (isCaptchaIpBlockError(lastErr)) { + sawIpBlock = true; + } + this.noteMintFailure(lastErr); + } } - let responseBody = bodyStream; - if (req.decompress && parsed.headers.get("content-encoding")?.toLowerCase() === "gzip") { - parsed.headers.delete("content-encoding"); - parsed.headers.delete("content-length"); - const gzip = new DecompressionStream("gzip"); - responseBody = bodyStream.pipeThrough(gzip); + if (sawIpBlock && this.opts.onCaptchaIpBlock) { + try { + this.opts.onCaptchaIpBlock(lastErr ?? "captcha ip block"); + } catch (_) { + } } - resolve(new Response(responseBody, { - status: parsed.status, - statusText: parsed.statusText, - headers: parsed.headers - })); - pushBody(rest); - return; + throw new Error(`captcha failed after ${this.opts.solveRetries} attempts: ${lastErr ?? "unknown"}`); + } finally { + this.activeSolves -= 1; } - pushBody(bytes); - } catch (err) { - fail(err); } - }); - socket.once("error", fail); - socket.once("end", () => { - if (!responseStarted) { - reject(new Error("upstream closed before sending response headers")); - return; + async solveOne(cfg) { + return this.solveFresh(cfg); } - finish(); - }); - socket.write(requestHead); - if (bodyBytes.byteLength > 0) socket.write(bodyBytes); - postWrite = true; - }); -} -function openSocket(url2) { - const isHttps = url2.protocol === "https:"; - if (!isHttps && url2.protocol !== "http:") { - return Promise.reject(new Error(`Unsupported upstream protocol: ${url2.protocol}`)); - } - const port = Number(url2.port || (isHttps ? 443 : 80)); - return new Promise((resolve, reject) => { - const onConnect = () => { - socket.off("error", reject); - resolve(socket); - }; - const socket = isHttps ? (0, import_node_tls.connect)({ host: url2.hostname, port, servername: url2.hostname }, onConnect) : (0, import_node_net.connect)({ host: url2.hostname, port }, onConnect); - socket.once("error", reject); - }); -} -function buildRequestHead(url2, method2, headers2, contentLength2) { - const path2 = `${url2.pathname || "/"}${url2.search}`; - const lines = [ - `${method2} ${path2} HTTP/1.1`, - `Host: ${url2.host}`, - ...headers2.map(headerLine), - `Content-Length: ${contentLength2}`, - "Connection: close", - "", - "" - ]; - return lines.join(CRLF); -} -function headerLine([name2, value2]) { - if (!HEADER_NAME.test(name2)) throw new Error(`Invalid upstream header name: ${name2}`); - if (/[\r\n]/.test(value2)) throw new Error(`Invalid upstream header value for ${name2}`); - return `${name2}: ${value2}`; -} -function bodyToBytes(body2) { - if (body2 === void 0) return new Uint8Array(0); - if (typeof body2 === "string") return new TextEncoder().encode(body2); - return body2; -} -function parseResponseHeaders(bytes) { - const text = new TextDecoder("latin1").decode(bytes); - const lines = text.split(CRLF); - const statusLine = lines.shift() ?? ""; - const match = /^HTTP\/\d(?:\.\d)?\s+(\d{3})(?:\s+(.*))?$/.exec(statusLine); - if (!match) throw new Error(`Invalid upstream status line: ${statusLine}`); - const headers2 = new Headers(); - for (const line of lines) { - if (!line) continue; - const idx = line.indexOf(":"); - if (idx <= 0) continue; - headers2.append(line.slice(0, idx), line.slice(idx + 1).trimStart()); - } - return { status: Number(match[1]), statusText: match[2] ?? "", headers: headers2 }; -} -var ChunkedDecoder = class { - buffer = new Uint8Array(0); - expectedSize = null; - done = false; - push(bytes, controller) { - if (this.done) return; - this.buffer = concatBytes(this.buffer, bytes); - while (!this.done) { - if (this.expectedSize === null) { - const lineEnd = indexOfCrlf(this.buffer); - if (lineEnd < 0) return; - const line = new TextDecoder("latin1").decode(this.buffer.slice(0, lineEnd)); - const sizeHex = line.split(";", 1)[0].trim(); - const size = Number.parseInt(sizeHex, 16); - if (!Number.isFinite(size)) throw new Error(`Invalid chunk size: ${line}`); - this.buffer = this.buffer.slice(lineEnd + 2); - this.expectedSize = size; - if (size === 0) { - this.done = true; - return; - } + /** + * Empty-pool serve: race up to `emptyTakeRace` solves in parallel and + * resolve with the first success so the client waits for one mint, not a + * sequential retry chain. Extra successes are banked into the pool instead + * of being wasted; the race only rejects when every racer fails. + */ + solveRaced(cfg) { + const racers = Math.max(1, Math.min(this.opts.emptyTakeRace, this.opts.solveConcurrency)); + if (racers <= 1) return this.solveFresh(cfg); + return new Promise((resolve, reject) => { + let pending = racers; + let served = false; + let lastErr = null; + for (let i = 0; i < racers; i += 1) { + this.solveFresh(cfg).then( + (param) => { + if (served) { + this.pushToken(param); + } else { + served = true; + resolve(param); + } + }, + (err) => { + lastErr = err ?? lastErr; + } + ).finally(() => { + pending -= 1; + if (pending === 0 && !served) { + reject( + lastErr instanceof Error ? lastErr : new Error(String(lastErr ?? "captcha race failed")) + ); + } + }); + } + }); } - if (this.buffer.byteLength < this.expectedSize + 2) return; - const chunk = this.buffer.slice(0, this.expectedSize); - controller.enqueue(chunk); - this.buffer = this.buffer.slice(this.expectedSize + 2); - this.expectedSize = null; - } - } -}; -function concatBytes(a, b) { - const out = new Uint8Array(a.byteLength + b.byteLength); - if (a.byteLength > 0) out.set(a, 0); - if (b.byteLength > 0) out.set(b, a.byteLength); - return out; -} -function indexOfBytes(haystack, needle) { - outer: for (let i = 0; i <= haystack.byteLength - needle.byteLength; i++) { - for (let j = 0; j < needle.byteLength; j++) { - if (haystack[i + j] !== needle[j]) continue outer; - } - return i; - } - return -1; -} -function indexOfCrlf(bytes) { - for (let i = 0; i < bytes.byteLength - 1; i++) { - if (bytes[i] === 13 && bytes[i + 1] === 10) return i; - } - return -1; -} - -// src/proxy/zcode_system.json -var zcode_system_default = [ - { - type: "text", - text: "You are ZCode, an interactive coding agent", - cache_control: { - type: "ephemeral" - } - }, - { - type: "text", - text: "\nYou are an interactive ZCode agent that helps users with software engineering tasks.\n\nIMPORTANT: Assist with authorized security testing, defensive security, CTF challenges, and educational contexts. Refuse requests for destructive techniques, DoS attacks, mass targeting, supply chain compromise, or detection evasion for malicious purposes. Dual-use security tools (C2 frameworks, credential testing, exploit development) require clear authorization context: pentesting engagements, CTF competitions, security research, or defensive use cases.\n\n# Harness\n- Text you output outside of tool use is displayed to the user as Github-flavored markdown in a terminal.\n- Tools run behind a user-selected permission mode; a denied call means the user declined it \u2014 adjust, don't retry verbatim.\n- The system may send updates, reminders, or modifications to rules via mid-conversation system turns. These are system-controlled, unlike function results. Hooks may intercept tool calls; treat hook output as user feedback.\n- Prefer the dedicated file/search tools over shell commands when one fits. Independent tool calls can run in parallel in one response.\n- Reference code as `file_path:line_number` \u2014 it's clickable.", - cache_control: { - type: "ephemeral" - } - }, - { - type: "text", - text: "# Environment\nYou have been invoked in the following environment:\n- Primary working directory: unknown\n- Is a git repository: no\n- Platform: unknown\n- Shell: unknown\n- OS Version: unknown", - cache_control: { - type: "ephemeral" - } - } -]; - -// src/proxy/system-prompt.ts -var ZCODE_SYSTEM_BLOCKS = zcode_system_default; -function buildStartPlanSystem(existingSystem, currentModel) { - const official = ZCODE_SYSTEM_BLOCKS.map((b) => structuredClone(b)); - if (currentModel && currentModel.trim().length > 0) { - official.push({ - type: "text", - text: `- You are powered by the model named ${currentModel}.`, - cache_control: { type: "ephemeral" } - }); - } - const userBlocks = normalizeUserSystem(existingSystem); - return [...official, ...userBlocks]; -} -function normalizeUserSystem(system) { - if (system == null) return []; - if (typeof system === "string") { - const text = system.trim(); - return text ? [{ type: "text", text }] : []; - } - if (!Array.isArray(system)) return []; - const out = []; - for (const item of system) { - if (typeof item === "string") { - if (item.trim()) out.push({ type: "text", text: item }); - } else if (item && typeof item === "object") { - const b = item; - if (b.type === "text" && typeof b.text === "string" && b.text.trim()) { - out.push({ - type: "text", - text: b.text, - ...typeof b.cache_control === "object" && b.cache_control !== null ? { cache_control: b.cache_control } : {} + initGovernor(opts) { + const cfg = resolveCpuGovernorConfig({ + poolSizeMin: this.opts.poolSizeMin, + poolSizeMax: this.opts.poolSizeMax, + solveConcurrency: this.opts.solveConcurrency, + cpuLimitPercent: opts.cpuLimitPercent, + cpuGovernorIntervalSec: opts.cpuGovernorIntervalSec }); + if (!this.governor) { + this.governor = new CaptchaCpuGovernor(cfg); + } else { + this.governor.configure(cfg); + } } - } + }; + pool = new CaptchaTokenPool(); } - return out; -} +}); -// src/proxy/body-transformer.ts -function transformRequestBody(body2, ctx) { - if (body2 === void 0 || body2.length === 0) return body2; - let parsed; +// src/proxy/captcha.ts +var captcha_exports = {}; +__export(captcha_exports, { + RETRY_HEADERS: () => RETRY_HEADERS, + captchaPoolStats: () => captchaPoolStats, + configureCaptchaSolving: () => configureCaptchaSolving, + detectCaptchaChallenge: () => detectCaptchaChallenge, + getCaptchaToken: () => getCaptchaToken, + shutdownCaptcha: () => shutdownCaptcha, + startCaptchaPool: () => startCaptchaPool, + urgentCaptcha: () => urgentCaptcha +}); +function detectCaptchaChallenge(resp) { + const v = resp.headers.get(CAPTCHA_HEADER); + return v && v.trim().length > 0 ? v.trim() : null; +} +async function fetchCaptchaConfig(appVersion) { + if (cachedConfig.value && cachedConfig.expiresAt > Date.now()) return cachedConfig.value; try { - parsed = JSON.parse(body2); + const resp = await fetch(`${CONFIGS_API}?app_version=${encodeURIComponent(appVersion)}&platform=win32-x64`); + const json = await resp.json(); + const cfg = json?.data?.configs?.captcha ?? null; + cachedConfig = { value: cfg, expiresAt: Date.now() + 6e4 }; + return cfg; } catch { - return body2; - } - if (typeof parsed !== "object" || parsed === null) return body2; - let modified = false; - if (ctx.format === "openai") { - if (ctx.startPlan) { - modified = applyStartPlanOpenAISystem(parsed) || modified; - } - modified = applyStreamOptionsIncludeUsage(parsed) || modified; - } - if (ctx.format === "anthropic") { - const obj = parsed; - if (ctx.startPlan) { - modified = applyStartPlanSystem(obj) || modified; - } - modified = applyAnthropicCacheControl(obj) || modified; - if (ctx.userId) { - modified = applyAnthropicUserId(obj, ctx.userId) || modified; - } - } - return modified ? JSON.stringify(parsed) : body2; -} -function applyStreamOptionsIncludeUsage(body2) { - if (body2.stream !== true) return false; - const existing = body2.stream_options; - if (isPlainObject(existing) && existing.include_usage === true) { - return false; + return null; } - const merged = isPlainObject(existing) ? { ...existing } : {}; - merged.include_usage = true; - body2.stream_options = merged; - return true; -} -function isPlainObject(v) { - return typeof v === "object" && v !== null; } -function applyAnthropicCacheControl(body2) { - const messages = body2.messages; - if (!Array.isArray(messages) || messages.length === 0) return false; - for (let i = messages.length - 1; i >= 0; i--) { - const msg = messages[i]; - if (typeof msg !== "object" || msg === null) continue; - if (msg.role === "system") continue; - if (typeof msg.content === "string") { - msg.content = [{ type: "text", text: msg.content, cache_control: { type: "ephemeral" } }]; - return true; - } - if (Array.isArray(msg.content) && msg.content.length > 0) { - const lastBlock = msg.content[msg.content.length - 1]; - if (typeof lastBlock === "object" && lastBlock !== null && !lastBlock.cache_control) { - lastBlock.cache_control = { type: "ephemeral" }; - return true; - } - } - return false; - } - return false; +async function getCaptchaToken(appVersion) { + const cfg = await fetchCaptchaConfig(appVersion); + if (!cfg || !cfg.enabled || !cfg.prefix || !cfg.sceneId) throw new Error("Captcha config unavailable"); + const verifyParam = await takeCaptchaToken(cfg); + return { verifyParam, region: cfg.region }; } -function applyAnthropicUserId(body2, userId) { - const existing = body2.metadata; - if (isPlainObject(existing) && existing.user_id === userId) { - return false; +function shutdownCaptcha() { + try { + shutdownCaptchaSolver(); + } catch { + } + try { + stopCaptchaPool(); + } catch { } - body2.metadata = { - ...isPlainObject(existing) ? existing : {}, - user_id: userId - }; - return true; } -function applyStartPlanSystem(body2) { - const model = typeof body2.model === "string" ? body2.model : void 0; - body2.system = buildStartPlanSystem(body2.system, model); - return true; +async function startCaptchaPool(appVersion) { + const cfg = await fetchCaptchaConfig(appVersion); + if (!cfg || !cfg.enabled) return; + const min = Number(process.env.CAPTCHA_POOL_MIN || 20); + const max = Number(process.env.CAPTCHA_POOL_MAX || Math.max(min * 6, 120)); + configureCaptchaPool({ poolSizeMin: min, poolSizeMax: max }); + startCaptchaPoolRefill(cfg); + await prefillCaptchaPool(cfg, min); } -function applyStartPlanOpenAISystem(body2) { - const messages = body2.messages; - if (!Array.isArray(messages)) return false; - const model = typeof body2.model === "string" ? body2.model : void 0; - const official = buildStartPlanSystem(void 0, model).map((block) => ({ - role: "system", - content: typeof block === "object" && block !== null && "text" in block ? String(block.text) : "" - })); - body2.messages = [...official, ...messages]; - return true; +function urgentCaptcha() { + urgentCaptchaRefill(); +} +function captchaPoolStats() { + return getCaptchaPoolStats(); } +function configureCaptchaSolving(opts) { + configureCaptchaPool(opts); +} +var CAPTCHA_HEADER, REGION_HEADER, CONFIGS_API, cachedConfig, RETRY_HEADERS; +var init_captcha = __esm({ + "src/proxy/captcha.ts"() { + "use strict"; + init_captcha_solver(); + init_captcha_pool(); + CAPTCHA_HEADER = "x-aliyun-captcha-verify-param"; + REGION_HEADER = "x-aliyun-captcha-verify-region"; + CONFIGS_API = "https://zcode.z.ai/api/v1/client/configs"; + cachedConfig = { value: null, expiresAt: 0 }; + RETRY_HEADERS = { PARAM: CAPTCHA_HEADER, REGION: REGION_HEADER }; + } +}); // src/proxy/handler.ts -var import_node_zlib = require("node:zlib"); - -// src/provider/models.ts -var MODELS = [ - { id: "glm-4.5-air", name: "GLM 4.5 Air", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, - { id: "glm-4.6", name: "GLM 4.6", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, - { id: "glm-4.6v", name: "GLM 4.6V", contextWindow: 2e5, maxOutputTokens: 128e3 }, - { id: "glm-4.7", name: "GLM 4.7", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, - { id: "glm-5", name: "GLM 5", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, - { id: "glm-5-turbo", name: "GLM 5 Turbo", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, - { id: "glm-5v-turbo", name: "GLM 5V Turbo", contextWindow: 2e5, maxOutputTokens: 128e3 }, - { id: "glm-5.1", name: "GLM 5.1", contextWindow: 2e5, maxOutputTokens: 128e3, reasoning: true }, - { id: "glm-5.2", name: "GLM 5.2", contextWindow: 1e6, maxOutputTokens: 128e3, reasoning: true }, - { id: "glm-5.3", name: "GLM 5.3", contextWindow: 1e6, maxOutputTokens: 128e3, reasoning: true }, - // start-plan gateway serves the -flash variant (used by claimed trial plans - // like the weekend package); advertised so client-side discovery lists it. - { id: "glm-5.3-flash", name: "GLM 5.3 Flash", contextWindow: 1e6, maxOutputTokens: 128e3, reasoning: true } -]; - -// src/provider/reasoning.ts -var GLM53_DEFAULT_EFFORT = "max"; -var GLM53_THINKING_BUDGETS = { - low: 8e3, - high: 16e3, - max: 32e3 -}; -var GLM53_MIN_THINKING_BUDGET = 1024; -var GLM53_ANSWER_RESERVE = 1024; -var GLM53_MODEL_PATTERN = /glm-5\.3(?![0-9])/i; -function isGlm53Model(model) { - if (!model) return false; - return GLM53_MODEL_PATTERN.test(model); +async function loadCaptcha() { + if (!captchaModule) captchaModule = await Promise.resolve().then(() => (init_captcha(), captcha_exports)); + return captchaModule; } -function normalizeGlm53Effort(effort) { - switch (effort) { - case "none": - case "minimal": - case "light": - case "low": - return "low"; - case "medium": - case "high": - return "high"; - case "xhigh": - case "max": - case "ultra": - return "max"; - default: - return GLM53_DEFAULT_EFFORT; +async function proxyRequest(clientReq, format, opts) { + const { config, auth } = opts; + const fetchImpl = opts.fetchImpl ?? fetch; + const hasCustomFetchImpl = opts.fetchImpl !== void 0; + const debug = opts.debug === true; + const started = Date.now(); + const reqId = nextReqId(); + let body2; + try { + body2 = await readBody(clientReq); + } catch (err) { + if (err instanceof InflatedBodyTooLargeError) { + return errorResponse(413, "request_too_large", err.message); + } + return errorResponse(400, "invalid_request_error", err.message); } -} -function buildGlm53Reasoning(effort) { - return { - thinking: { type: "enabled", budget_tokens: GLM53_THINKING_BUDGETS[effort] }, - output_config: { effort } - }; -} -function fitGlm53Budget(budget, maxTokens) { - if (typeof maxTokens !== "number" || !Number.isFinite(maxTokens)) return budget; - const clamped = Math.min(budget, Math.floor(maxTokens) - GLM53_ANSWER_RESERVE); - return clamped >= GLM53_MIN_THINKING_BUDGET ? clamped : void 0; -} - -// src/translator/openai-to-anthropic.ts -var DEFAULT_MAX_TOKENS = 4096; -function translateRequestOpenAIToAnthropic(req) { - const systemMessages = req.messages.filter((m) => m.role === "system"); - const nonSystemMessages = req.messages.filter((m) => m.role !== "system"); - const system = systemMessages.length > 0 ? systemMessages.map((m) => extractText(m)).join("\n\n") : void 0; - const anthropicMessages = translateMessagesWithToolCoalescing(nonSystemMessages); - const result3 = { - model: req.model, - messages: anthropicMessages, - max_tokens: req.max_tokens ?? resolveDefaultMaxTokens(req.model) - }; - if (system) result3.system = system; - if (req.temperature !== void 0) result3.temperature = req.temperature; - if (req.top_p !== void 0) result3.top_p = req.top_p; - if (req.stream !== void 0) result3.stream = req.stream; - if (req.stop) result3.stop_sequences = Array.isArray(req.stop) ? req.stop : [req.stop]; - if (isGlm53Model(req.model)) { - const { thinking, output_config } = translateGlm53Reasoning(req, result3.max_tokens); - result3.thinking = thinking; - if (output_config) result3.output_config = output_config; - } else { - const thinking = translateThinking(req); - if (thinking) result3.thinking = thinking; + const meta = peekBody(body2); + if (dumpEnabled()) { + dumpPhase(reqId, "client_in", { + method: clientReq.method, + url: clientReq.url, + headers: dumpHeaders(clientReq.headers), + body: dumpBody(body2) + }); } - if (req.tools?.length && req.tool_choice !== "none") { - result3.tools = req.tools.map(translateToolOpenAIToAnthropic); + const staticProvider = getProvider(config.provider); + const provider = { + ...staticProvider, + anthropicBaseURL: config.providers[config.provider].anthropicBase, + openaiBaseURL: config.providers[config.provider].openaiBase + }; + let cred; + try { + cred = await auth.getCredential(); + } catch (err) { + if (debug) debugError(reqId, "credential_unavailable", err.message); + printRow(reqId, format, meta, 503, started, Date.now(), 0, 0, 0); + return errorResponse(503, "credential_unavailable", err.message); } - if (req.tool_choice !== void 0 && req.tool_choice !== "none") { - const translated = translateToolChoice(req.tool_choice); - if (translated) result3.tool_choice = translated; + const startPlan = config.plan === "start-plan"; + const translateAnthropicToOpenAI = false; + const translateOpenAIToAnthropic = format === "openai"; + const upstreamFormat = "anthropic"; + const clientSession = resolveSessionContext({ clientReq, body: body2, upstreamFormat, model: meta.model, config }); + if (debug && clientSession) { + const shortSession = clientSession.sessionId ? clientSession.sessionId.slice(0, 10) : "-"; + debugLine(reqId, `clientIdentity source=${clientSession.source} action=${clientSession.action} confidence=${clientSession.confidence.toFixed(2)} session=${shortSession}`); } - return result3; -} -function translateThinking(req) { - const explicit = req.thinking; - if (explicit && typeof explicit === "object") { - if (explicit.type === "disabled") return { type: "disabled" }; - if (explicit.type === "enabled" || explicit.type === "adaptive") { - const budget = explicit.budget_tokens ?? explicit.budgetTokens; - return { - type: explicit.type, - ...typeof budget === "number" && Number.isFinite(budget) && budget > 0 ? { budget_tokens: Math.floor(budget) } : {}, - ...explicit.type === "adaptive" && typeof explicit.display === "boolean" ? { display: explicit.display } : {} - }; - } + let upstreamBody = body2; + if (translateOpenAIToAnthropic) { + const translated = translateOpenAIBody(body2); + if (translated instanceof Response) return translated; + upstreamBody = translated; + if (debug) debugLine(reqId, `translated OpenAI\u2192Anthropic (bytes=${upstreamBody?.length ?? 0})`); + } else if (translateAnthropicToOpenAI) { + const translated = translateAnthropicBody(body2); + if (translated instanceof Response) return translated; + upstreamBody = translated; + if (debug) debugLine(reqId, `translated Anthropic\u2192OpenAI (bytes=${upstreamBody?.length ?? 0})`); } - if (req.reasoning_effort === "none") return { type: "disabled" }; - if (isReasoningModel(req.model)) return { type: "enabled" }; - return void 0; -} -function isReasoningModel(model) { - return MODELS.some((m) => m.id === model && m.reasoning === true); -} -function resolveDefaultMaxTokens(model) { - if (!isGlm53Model(model)) return DEFAULT_MAX_TOKENS; - const catalogEntry = MODELS.find((m) => m.id === model); - return catalogEntry?.maxOutputTokens ?? DEFAULT_MAX_TOKENS; -} -function translateGlm53Reasoning(req, maxTokens) { - const explicit = req.thinking; - if (explicit && typeof explicit === "object" && explicit.type === "disabled") { - return { thinking: { type: "disabled" } }; + const transformedBody = transformRequestBody(upstreamBody, { format: upstreamFormat, userId: startPlan ? void 0 : cred.userId, startPlan }); + if (debug && transformedBody !== upstreamBody) { + debugLine(reqId, `body transformed (upstreamFormat=${upstreamFormat}, startPlan=${startPlan}, bytes=${transformedBody?.length ?? 0})`); } - const effort = normalizeGlm53Effort(req.reasoning_effort); - const base = buildGlm53Reasoning(effort); - let budget = base.thinking.budget_tokens; - if (explicit && typeof explicit === "object" && (explicit.type === "enabled" || explicit.type === "adaptive")) { - const explicitBudget = explicit.budget_tokens ?? explicit.budgetTokens; - if (typeof explicitBudget === "number" && Number.isFinite(explicitBudget)) { - const floored = Math.floor(explicitBudget); - if (floored > 0) budget = floored; + let captchaHeaders; + if (startPlan) { + try { + const captcha2 = await loadCaptcha(); + const token = await captcha2.getCaptchaToken(config.identity.appVersion); + captchaHeaders = { [captcha2.RETRY_HEADERS.PARAM]: token.verifyParam, [captcha2.RETRY_HEADERS.REGION]: token.region }; + } catch { } } - const fitted = fitGlm53Budget(budget, maxTokens); - return { - thinking: fitted !== void 0 ? { type: "enabled", budget_tokens: fitted } : { type: "enabled" }, - output_config: base.output_config + const useOrderedTransport = shouldUseOrderedTransport(config, clientSession, hasCustomFetchImpl); + let upstreamHeaderPairs = buildUpstreamHeaderPairs(clientReq, upstreamFormat, cred, config.identity, config.plan, captchaHeaders, clientSession); + let upstreamReq = buildUpstreamRequest(clientReq, upstreamFormat, provider, cred, transformedBody, config.identity, config.plan, captchaHeaders, clientSession); + const routing = opts.endpointRouting !== void 0 ? opts.endpointRouting : getDefaultEndpointRouting(config); + const signer = opts.clientSigning !== void 0 ? opts.clientSigning : getDefaultClientSigning(config); + const translateMode = translateOpenAIToAnthropic || translateAnthropicToOpenAI; + const dispatch2 = async (req, pairs) => { + let sendUrl = req.url; + if (routing) { + const routed = await routing.resolve(req.url, credentialString(cred)); + if (routed.routed) { + sendUrl = routed.url; + if (debug) debugLine(reqId, `endpoint routing: ${req.url} -> ${routed.url}`); + } + } + return sendWithClientSigning(signer, { + url: req.url, + headerPairs: pairs, + credential: credentialString(cred), + appVersion: config.identity.appVersion, + debug: debug ? (message) => debugLine(reqId, message) : void 0, + send: (finalPairs) => { + const sendReq = sendUrl === req.url && finalPairs === pairs ? req : new Request(sendUrl, { + method: req.method, + headers: Object.fromEntries(finalPairs), + body: transformedBody ?? void 0 + }); + return sendUpstreamRequest(sendReq, finalPairs, transformedBody, translateMode, useOrderedTransport, fetchImpl, clientReq.signal, hasCustomFetchImpl); + } + }); }; -} -function translateToolChoice(choice) { - if (choice === "auto") return { type: "auto" }; - if (choice === "required") return { type: "any" }; - if (typeof choice === "object" && choice.type === "function") { - return { type: "tool", name: choice.function.name }; + if (debug) { + debugLine(reqId, `\u2192 POST ${upstreamReq.url}`); + debugLine(reqId, ` ${formatHeaderPairs(upstreamReq.headers)}`); + if (transformedBody) debugLine(reqId, ` body preview: ${previewBody(transformedBody)}`); } - return void 0; -} -function translateMessagesWithToolCoalescing(messages) { - const out = []; - let i = 0; - while (i < messages.length) { - const m = messages[i]; - if (m.role === "tool" && m.tool_call_id) { - const results = []; - while (i < messages.length) { - const tool = messages[i]; - const toolCallId = tool.tool_call_id; - if (tool.role !== "tool" || !toolCallId) break; - results.push({ - type: "tool_result", - tool_use_id: toolCallId, - content: toolResultContent(tool) - }); - i++; + if (dumpEnabled()) { + dumpPhase(reqId, "upstream_out", { + method: upstreamReq.method, + url: upstreamReq.url, + headers: dumpHeaders(upstreamReq.headers), + body: dumpBody(transformedBody), + upstreamFormat, + translateMode: translateOpenAIToAnthropic || translateAnthropicToOpenAI, + useOrderedTransport, + startPlan + }); + } + let upstreamResp; + try { + const maxConnectAttempts = 3; + for (let attempt = 1; ; attempt++) { + if (clientReq.signal.aborted) throw new Error("client aborted before upstream connect"); + try { + upstreamResp = await dispatch2(upstreamReq, upstreamHeaderPairs); + break; + } catch (err) { + if (err.postWrite) throw err; + if (attempt >= maxConnectAttempts) throw err; + const backoffMs = 500 * attempt; + if (debug) debugError(reqId, "upstream_connect_retry", `attempt ${attempt}/${maxConnectAttempts - 1} failed (${err.message}), retrying in ${backoffMs}ms`); + console.log(`${reqId} upstream connect failed (${err.message}), retry ${attempt + 1}/${maxConnectAttempts} in ${backoffMs}ms`); + await new Promise((r2) => setTimeout(r2, backoffMs)); + upstreamReq = buildUpstreamRequest(clientReq, upstreamFormat, provider, cred, transformedBody, config.identity, config.plan, captchaHeaders, clientSession); } - out.push({ role: "user", content: results }); - continue; } - out.push(translateMessageOpenAIToAnthropic(m)); - i++; + } catch (err) { + if (debug) debugError(reqId, "upstream_unreachable", err.message); + printRow(reqId, format, meta, 502, started, Date.now(), 0, 0, 0); + return errorResponse(502, "upstream_unreachable", err.message); } - return out; -} -function translateMessageOpenAIToAnthropic(msg) { - if (msg.role === "assistant" && msg.tool_calls?.length) { - const blocks = []; - const text = extractText(msg); - if (text.length > 0) blocks.push({ type: "text", text }); - for (const tc of msg.tool_calls) { - blocks.push({ - type: "tool_use", - id: tc.id, - name: tc.function.name, - input: parseToolArguments(tc.function.arguments) - }); - } - return { role: "assistant", content: blocks }; + const headersAt = Date.now(); + if (debug) { + debugLine(reqId, `\u2190 ${upstreamResp.status} ${upstreamResp.statusText}`); + debugLine(reqId, ` ${formatResponseHeaders(upstreamResp.headers)}`); } - return { - role: msg.role === "assistant" ? "assistant" : "user", - content: translateContentOpenAIToAnthropic(msg) - }; -} -function parseToolArguments(raw) { - if (!raw) return {}; - try { - const parsed = JSON.parse(raw); - return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {}; - } catch { - return {}; + if (dumpEnabled()) { + dumpPhase(reqId, "upstream_in", { + status: upstreamResp.status, + statusText: upstreamResp.statusText, + headers: dumpHeaders(upstreamResp.headers), + isSSE: upstreamResp.headers.get("content-type")?.includes("text/event-stream") ?? false, + ttfbMs: headersAt - started + }); } -} -function toolResultContent(msg) { - if (typeof msg.content === "string") return msg.content; - if (!Array.isArray(msg.content)) return ""; - if (msg.content.every((c) => c.type === "text")) { - const joined = msg.content.map((c) => c.text ?? "").join(""); - return joined; + if (upstreamResp.status === 401 && startPlan) { + if (debug) debugError(reqId, "start_plan_jwt_invalid", "JWT rejected upstream"); + printRow(reqId, format, meta, 401, started, headersAt, 0, 0, 0); + return errorResponse(401, "start_plan_jwt_invalid", "Start-plan JWT was rejected. Re-run: zcode-proxy auth login"); } - return msg.content.map((c) => { - if (c.type === "text") return { type: "text", text: c.text ?? "" }; - if (c.type === "image_url" && c.image_url?.url) { - return imageUrlToAnthropicBlock(c.image_url.url); + const captcha = startPlan ? await loadCaptcha() : null; + let captchaChallenge = captcha ? captcha.detectCaptchaChallenge(upstreamResp) : null; + if (!captchaChallenge && captcha && !upstreamResp.ok) { + const ctype = upstreamResp.headers.get("content-type") ?? ""; + if (!ctype.includes("text/event-stream")) { + try { + const peek = await upstreamResp.clone().text(); + if (peek.includes('"code":3007') || peek.includes('"code": 3007')) { + captchaChallenge = "in-body-3007"; + } + } catch { + } } - return { type: "text", text: "" }; - }); -} -function parseDataUrl(url2) { - const m = /^data:([^;]+);base64,(.*)$/s.exec(url2); - if (!m) return void 0; - return { mediaType: m[1], data: m[2] }; -} -function imageUrlToAnthropicBlock(url2) { - const parsed = parseDataUrl(url2); - if (parsed) { - return { - type: "image", - source: { type: "base64", media_type: parsed.mediaType, data: parsed.data } - }; } - if (/^https?:\/\//i.test(url2)) { - return { type: "image", source: { type: "url", url: url2 } }; + if (captchaChallenge && captcha) { + if (debug) debugLine(reqId, "captcha challenge \u2014 re-solving and retrying once"); + try { + upstreamResp.body?.cancel(); + } catch { + } + console.log(`${reqId} captcha challenge, re-solving...`); + try { + const fresh = await captcha.getCaptchaToken(config.identity.appVersion); + console.log(`${reqId} captcha re-solved (token ${fresh.verifyParam.length} chars), retrying...`); + const retryHeaders = { + [captcha.RETRY_HEADERS.PARAM]: fresh.verifyParam, + [captcha.RETRY_HEADERS.REGION]: fresh.region + }; + upstreamHeaderPairs = buildUpstreamHeaderPairs(clientReq, upstreamFormat, cred, config.identity, config.plan, retryHeaders, clientSession); + upstreamReq = buildUpstreamRequest(clientReq, upstreamFormat, provider, cred, transformedBody, config.identity, config.plan, retryHeaders, clientSession); + upstreamResp = await dispatch2(upstreamReq, upstreamHeaderPairs).catch((err) => { + if (debug) debugError(reqId, "upstream_unreachable", err.message); + printRow(reqId, format, meta, 502, started, Date.now(), 0, 0, 0); + return errorResponse(502, "upstream_unreachable", err.message); + }); + if (debug) debugLine(reqId, `\u2190 retry ${upstreamResp.status} ${upstreamResp.statusText}`); + } catch (err) { + if (debug) debugError(reqId, "captcha_solver_failed", err.message); + printRow(reqId, format, meta, 503, started, Date.now(), 0, 0, 0); + return errorResponse(503, "captcha_solver_failed", err.message); + } } - return { type: "text", text: url2 }; -} -function anthropicUsageToOpenAI(usage) { - const inputTokens = usage?.input_tokens ?? 0; - const outputTokens = usage?.output_tokens ?? 0; - const cacheRead = usage?.cache_read_input_tokens ?? 0; - const cacheCreation = usage?.cache_creation_input_tokens ?? 0; - const promptTokens = inputTokens + cacheRead + cacheCreation; - return { - prompt_tokens: promptTokens, - completion_tokens: outputTokens, - total_tokens: promptTokens + outputTokens, - // Presence-preserving: an upstream explicitly reporting 0 cache reads stays - // distinguishable from one reporting no cache breakdown at all. - ...usage?.cache_read_input_tokens != null ? { prompt_tokens_details: { cached_tokens: cacheRead } } : {} - }; -} -function translateResponseAnthropicToOpenAI(resp, model) { - const textBlocks = resp.content.filter((b) => b.type === "text"); - const toolUseBlocks = resp.content.filter((b) => b.type === "tool_use"); - const thinkingBlocks = resp.content.filter((b) => b.type === "thinking"); - const content2 = textBlocks.map((b) => b.text).join("") || null; - const reasoningContent = thinkingBlocks.map((b) => b.thinking ?? "").join("") || void 0; - const toolCalls = toolUseBlocks.length > 0 ? toolUseBlocks.map((b, i) => ({ - id: b.id, - type: "function", - function: { - name: b.name, - arguments: JSON.stringify(b.input ?? {}) + const isSSE = upstreamResp.headers.get("content-type")?.includes("text/event-stream") ?? false; + if (translateOpenAIToAnthropic) { + if (!upstreamResp.ok) { + const errBody = await upstreamResp.text().catch(() => ""); + printRow(reqId, format, meta, 502, started, headersAt, 0, 0, 0); + return errorResponse(502, "translation_failed", `upstream returned ${upstreamResp.status}: ${errBody.slice(0, 200)}`); } - })) : void 0; - const finishReason = mapStopReasonToFinishReason(resp.stop_reason); - return { - id: resp.id, - object: "chat.completion", - created: Math.floor(Date.now() / 1e3), - model, - choices: [{ - index: 0, - message: { - role: "assistant", - content: content2, - ...reasoningContent ? { reasoning_content: reasoningContent } : {}, - ...toolCalls ? { tool_calls: toolCalls } : {} - }, - finish_reason: finishReason - }], - usage: anthropicUsageToOpenAI(resp.usage) - }; -} -function extractText(msg) { - if (typeof msg.content === "string") return msg.content; - if (Array.isArray(msg.content)) { - return msg.content.filter((c) => c.type === "text").map((c) => c.text ?? "").join(""); + if (isSSE && upstreamResp.body) { + const translated = anthropicSseToOpenaiSse(upstreamResp.body, meta.model); + const [clientBody, statsBody] = translated.tee(); + observeStream(reqId, format, meta, upstreamResp.status, started, statsBody, null); + return translatedSseResponse(clientBody); + } + return await translatedBatchResponse(clientReq, upstreamResp, meta.model, reqId, format, meta, started, headersAt); + } + if (translateAnthropicToOpenAI) { + if (!upstreamResp.ok) { + const errBody = await upstreamResp.text().catch(() => ""); + printRow(reqId, format, meta, 502, started, headersAt, 0, 0, 0); + return errorResponse(502, "translation_failed", `upstream returned ${upstreamResp.status}: ${errBody.slice(0, 200)}`); + } + if (isSSE && upstreamResp.body) { + const translated = openaiSseToAnthropicSse(upstreamResp.body, meta.model); + const [clientBody, statsBody] = translated.tee(); + observeStream(reqId, format, meta, upstreamResp.status, started, statsBody, null); + return translatedSseResponse(clientBody); + } + return await translatedOpenAIToAnthropicBatchResponse(clientReq, upstreamResp, reqId, format, meta, started, headersAt); } - return ""; -} -function translateContentOpenAIToAnthropic(msg) { - if (typeof msg.content === "string") return msg.content; - if (msg.content === null) return ""; - if (Array.isArray(msg.content)) { - return msg.content.map((c) => { - if (c.type === "text") return { type: "text", text: c.text ?? "" }; - if (c.type === "image_url" && c.image_url?.url) { - return imageUrlToAnthropicBlock(c.image_url.url); - } - return { type: "text", text: "" }; - }); + if (isSSE && upstreamResp.body) { + const [clientBody, statsBody] = upstreamResp.body.tee(); + observeStream(reqId, format, meta, upstreamResp.status, started, statsBody, upstreamResp.headers.get("content-encoding")); + return passthroughResponse(upstreamResp, clientAcceptsGzip(clientReq), clientBody); } - return ""; + printRow(reqId, format, meta, upstreamResp.status, started, headersAt, 0, 0, 0); + return passthroughResponse(upstreamResp, clientAcceptsGzip(clientReq)); } -function translateToolOpenAIToAnthropic(tool) { - return { - name: tool.function.name, - ...tool.function.description ? { description: tool.function.description } : {}, - ...tool.function.parameters ? { input_schema: tool.function.parameters } : {} - }; +function shouldUseOrderedTransport(config, clientSession, hasCustomFetchImpl) { + if (hasCustomFetchImpl) return false; + return clientSession?.action === "enforce" || clientSession?.source === "explicit"; } -function mapStopReasonToFinishReason(stopReason) { - switch (stopReason) { - case "end_turn": - case "stop_sequence": - return "stop"; - case "max_tokens": - return "length"; - case "tool_use": - return "tool_calls"; - default: - return null; +function stripAutoDecodedEncoding(resp) { + const encoding = resp.headers.get("content-encoding")?.toLowerCase().trim() ?? ""; + if (!encoding) return resp; + const codings = encoding.split(",").map((c) => c.trim()); + if (!codings.every((c) => AUTO_DECODED_ENCODINGS.has(c))) return resp; + const headers2 = new Headers(resp.headers); + headers2.delete("content-encoding"); + headers2.delete("content-length"); + return new Response(resp.body, { + status: resp.status, + statusText: resp.statusText, + headers: headers2 + }); +} +async function sendUpstreamRequest(upstreamReq, headerPairs, body2, translateMode, useOrderedTransport, fetchImpl, abortSignal, hasCustomFetchImpl = false) { + if (useOrderedTransport) { + return sendOrderedUpstreamRequest({ + url: upstreamReq.url, + method: upstreamReq.method, + headers: headerPairs, + body: body2, + decompress: translateMode + }); } + const fetchOpts = translateMode ? {} : { decompress: false }; + if (abortSignal) fetchOpts.signal = abortSignal; + const resp = await fetchImpl(upstreamReq, fetchOpts); + if (!translateMode && FETCH_AUTO_DECOMPRESSES && !hasCustomFetchImpl) { + return stripAutoDecodedEncoding(resp); + } + return resp; } - -// src/translator/anthropic-to-openai.ts -function translateRequestAnthropicToOpenAI(req) { - const messages = []; - if (req.system) { - const systemText = typeof req.system === "string" ? req.system : req.system.map((s) => s.text).join("\n"); - messages.push({ role: "system", content: systemText }); +async function readBody(req) { + if (req.method === "GET" || req.method === "HEAD") return void 0; + const bytes = new Uint8Array(await req.arrayBuffer()); + if (bytes.byteLength === 0) return void 0; + const encoding = req.headers.get("content-encoding")?.toLowerCase().trim() ?? ""; + if (encoding === "gzip" || encoding === "x-gzip") { + return new TextDecoder().decode(await inflateGzipBody(bytes)); } - for (const m of req.messages) { - messages.push(...translateMessageAnthropicToOpenAI(m)); + return new TextDecoder().decode(bytes); +} +async function inflateGzipBody(bytes) { + const gunzip = new DecompressionStream("gzip"); + const source = new ReadableStream({ + start(controller) { + controller.enqueue(bytes); + controller.close(); + } + }); + const reader = source.pipeThrough(gunzip).getReader(); + const parts = []; + let total = 0; + try { + for (; ; ) { + const { done, value: value2 } = await reader.read(); + if (done) break; + total += value2.byteLength; + if (total > MAX_INFLATED_BODY_BYTES) { + await reader.cancel().catch(() => { + }); + throw new InflatedBodyTooLargeError(MAX_INFLATED_BODY_BYTES); + } + parts.push(value2); + } + } catch (err) { + if (err instanceof InflatedBodyTooLargeError) throw err; + throw new Error(`request body is marked content-encoding: gzip but failed to decompress: ${err.message}`); + } finally { + reader.releaseLock?.(); } - const result3 = { - model: req.model, - messages, - ...req.temperature !== void 0 ? { temperature: req.temperature } : {}, - ...req.top_p !== void 0 ? { top_p: req.top_p } : {}, - ...req.stream !== void 0 ? { stream: req.stream } : {}, - ...req.max_tokens !== void 0 ? { max_tokens: req.max_tokens } : {} - }; - if (req.stop_sequences?.length) { - result3.stop = req.stop_sequences.length === 1 ? req.stop_sequences[0] : req.stop_sequences; + return Buffer.concat(parts); +} +function passthroughResponse(upstream, clientAcceptsGzip2, body2) { + const headers2 = new Headers(); + const forwardHeaders = [ + "content-type", + "content-encoding", + "cache-control", + "x-request-id", + "anthropic-ratelimit-requests-limit", + "anthropic-ratelimit-requests-remaining", + "anthropic-ratelimit-requests-reset", + "anthropic-ratelimit-tokens-limit", + "anthropic-ratelimit-tokens-remaining", + "anthropic-ratelimit-tokens-reset" + ]; + for (const h of forwardHeaders) { + const v = upstream.headers.get(h); + if (v) headers2.set(h, v); } - if (req.thinking) { - result3.thinking = req.thinking; + const upstreamEncoding = headers2.get("content-encoding")?.toLowerCase() ?? ""; + const source = body2 ?? upstream.body; + if (upstreamEncoding.includes("gzip") && !clientAcceptsGzip2 && source) { + const gunzip = new DecompressionStream("gzip"); + const decompressed = source.pipeThrough(gunzip); + headers2.delete("content-encoding"); + headers2.delete("content-length"); + return new Response(decompressed, { + status: upstream.status, + statusText: upstream.statusText, + headers: headers2 + }); } - if (isGlm53Model(req.model) && req.output_config?.effort) { - result3.reasoning_effort = req.output_config.effort; + return new Response(source, { + status: upstream.status, + statusText: upstream.statusText, + headers: headers2 + }); +} +function errorResponse(status, type2, message) { + const body2 = JSON.stringify({ + error: { type: type2, message } + }); + return new Response(body2, { + status, + headers: { "content-type": "application/json" } + }); +} +function translateOpenAIBody(body2) { + if (body2 === void 0 || body2.length === 0) { + return errorResponse(400, "translation_failed", "OpenAI request body is empty; cannot translate."); } - if (req.tools?.length) { - result3.tools = req.tools.map((t) => ({ - type: "function", - function: { - name: t.name, - ...t.description ? { description: t.description } : {}, - ...t.input_schema ? { parameters: t.input_schema } : {} - } - })); + let parsed; + try { + parsed = JSON.parse(body2); + } catch (err) { + return errorResponse(400, "translation_failed", `OpenAI request body is not valid JSON: ${err.message}`); } - if (req.tool_choice) { - const translated = mapToolChoiceAnthropicToOpenAI(req.tool_choice); - if (translated !== void 0) result3.tool_choice = translated; + try { + const translated = translateRequestOpenAIToAnthropic(parsed); + return JSON.stringify(translated); + } catch (err) { + return errorResponse(400, "translation_failed", `OpenAI\u2192Anthropic translation failed: ${err.message}`); } - return result3; } -function mapToolChoiceAnthropicToOpenAI(choice) { - switch (choice.type) { - case "auto": - return "auto"; - case "any": - return "required"; - case "tool": - return { type: "function", function: { name: choice.name } }; - default: - return void 0; - } +function clientAcceptsGzip(req) { + const ae = req.headers.get("accept-encoding"); + if (!ae) return false; + return /\bgzip\b(?!\s*;\s*q=0(?:\.0+)?\s*(?:,|$))/i.test(ae); } -function translateResponseOpenAIToAnthropic(resp) { - const choice = resp.choices?.[0]; - const content2 = []; - if (choice?.message?.reasoning_content) { - content2.push({ type: "thinking", thinking: choice.message.reasoning_content }); +async function translatedBatchResponse(clientReq, upstream, model, reqId, format, meta, started, headersAt) { + const raw = await upstream.text(); + let parsedAnthropic; + try { + parsedAnthropic = JSON.parse(raw); + } catch (err) { + printRow(reqId, format, meta, 502, started, headersAt, 0, 0, 0); + return errorResponse(502, "translation_failed", `upstream returned non-JSON body: ${err.message}`); } - if (choice?.message?.content) { - const textContent = typeof choice.message.content === "string" ? choice.message.content : Array.isArray(choice.message.content) ? choice.message.content.filter((c) => c.type === "text").map((c) => c.text ?? "").join("") : ""; - if (textContent) content2.push({ type: "text", text: textContent }); + if (!isAnthropicMessagesResponse(parsedAnthropic)) { + printRow(reqId, format, meta, 502, started, headersAt, 0, 0, 0); + return errorResponse(502, "translation_failed", `upstream returned invalid Anthropic message: ${raw.slice(0, 200)}`); } - if (choice?.message?.tool_calls) { - for (const tc of choice.message.tool_calls) { - let input = {}; - try { - input = JSON.parse(tc.function.arguments); - } catch { - input = {}; - } - content2.push({ - type: "tool_use", - id: tc.id, - name: tc.function.name, - input - }); - } + const openaiResp = translateResponseAnthropicToOpenAI(parsedAnthropic, model); + const json = JSON.stringify(openaiResp); + const payload = new TextEncoder().encode(json); + const respHeaders = new Headers(); + respHeaders.set("content-type", "application/json"); + for (const h of forwardedUpstreamHeaders()) { + const v = upstream.headers.get(h); + if (v) respHeaders.set(h, v); } - const stopReason = mapFinishReasonToStopReason(choice?.finish_reason); - return { - id: resp.id, - type: "message", - role: "assistant", - content: content2.length > 0 ? content2 : [{ type: "text", text: "" }], - model: resp.model, - stop_reason: stopReason, - stop_sequence: null, - usage: openaiUsageToAnthropic(resp.usage) - }; + if (clientAcceptsGzip(clientReq)) { + respHeaders.set("content-encoding", "gzip"); + printRow(reqId, format, meta, upstream.status, started, headersAt, openaiResp.usage?.completion_tokens ?? 0, 0, 0); + return new Response((0, import_node_zlib.gzipSync)(payload), { + status: upstream.status, + headers: respHeaders + }); + } + printRow(reqId, format, meta, upstream.status, started, headersAt, openaiResp.usage?.completion_tokens ?? 0, 0, 0); + return new Response(payload, { + status: upstream.status, + headers: respHeaders + }); } -function translateMessageAnthropicToOpenAI(m) { - if (typeof m.content === "string") { - return [{ role: m.role, content: m.content }]; +async function translatedOpenAIToAnthropicBatchResponse(clientReq, upstream, reqId, format, meta, started, headersAt) { + const raw = await upstream.text(); + let parsedOpenAI; + try { + parsedOpenAI = JSON.parse(raw); + } catch (err) { + printRow(reqId, format, meta, 502, started, headersAt, 0, 0, 0); + return errorResponse(502, "translation_failed", `upstream returned non-JSON body: ${err.message}`); } - const result3 = []; - const contentParts = []; - const toolCalls = []; - const reasoningParts = []; - for (const block of m.content) { - switch (block.type) { - case "text": { - contentParts.push({ type: "text", text: block.text }); - break; - } - case "image": { - if (block.source.type === "base64") { - contentParts.push({ - type: "image_url", - image_url: { url: `data:${block.source.media_type};base64,${block.source.data}` } - }); - } else if (block.source.type === "url") { - contentParts.push({ - type: "image_url", - image_url: { url: block.source.url } - }); - } - break; - } - case "tool_use": { - toolCalls.push({ - id: block.id, - type: "function", - function: { name: block.name, arguments: JSON.stringify(block.input ?? {}) } - }); - break; - } - case "tool_result": { - result3.push({ - role: "tool", - tool_call_id: block.tool_use_id, - content: toolResultContentToOpenAI(block.content, block.is_error === true) - }); - break; - } - case "thinking": { - if (block.thinking.length > 0) reasoningParts.push(block.thinking); - break; - } - default: - break; - } + const anthropicResp = translateResponseOpenAIToAnthropic(parsedOpenAI); + const json = JSON.stringify(anthropicResp); + const payload = new TextEncoder().encode(json); + const respHeaders = new Headers(); + respHeaders.set("content-type", "application/json"); + for (const h of forwardedUpstreamHeaders()) { + const v = upstream.headers.get(h); + if (v) respHeaders.set(h, v); } - const hasReasoning = m.role === "assistant" && reasoningParts.length > 0; - if (contentParts.length > 0 || toolCalls.length > 0 || hasReasoning) { - const content2 = contentParts.length === 0 ? null : contentParts.length === 1 && contentParts[0].type === "text" ? contentParts[0].text ?? "" : contentParts; - result3.push({ - role: m.role, - content: content2, - ...hasReasoning ? { reasoning_content: reasoningParts.join("\n") } : {}, - ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {} + if (clientAcceptsGzip(clientReq)) { + respHeaders.set("content-encoding", "gzip"); + printRow(reqId, format, meta, upstream.status, started, headersAt, anthropicResp.usage.output_tokens, 0, 0); + return new Response((0, import_node_zlib.gzipSync)(payload), { + status: upstream.status, + headers: respHeaders }); } - if (result3.length === 0) { - result3.push({ role: m.role, content: null }); + printRow(reqId, format, meta, upstream.status, started, headersAt, anthropicResp.usage.output_tokens, 0, 0); + return new Response(payload, { + status: upstream.status, + headers: respHeaders + }); +} +function translateAnthropicBody(body2) { + if (body2 === void 0 || body2.length === 0) { + return errorResponse(400, "translation_failed", "Anthropic request body is empty; cannot translate."); + } + let parsed; + try { + parsed = JSON.parse(body2); + } catch (err) { + return errorResponse(400, "translation_failed", `Anthropic request body is not valid JSON: ${err.message}`); + } + try { + const translated = translateRequestAnthropicToOpenAI(parsed); + return JSON.stringify(translated); + } catch (err) { + return errorResponse(400, "translation_failed", `Anthropic\u2192OpenAI translation failed: ${err.message}`); } - return result3; } -function toolResultContentToOpenAI(content2, isError) { - const body2 = flattenToolResultContent(content2); - return isError && body2.length > 0 ? `[tool_error] ${body2}` : body2; +function isAnthropicMessagesResponse(value2) { + if (typeof value2 !== "object" || value2 === null) return false; + const candidate = value2; + return candidate.type === "message" && candidate.role === "assistant" && Array.isArray(candidate.content); } -function flattenToolResultContent(content2) { - if (typeof content2 === "string") return content2; - if (!Array.isArray(content2)) return ""; - const texts = content2.filter((b) => b.type === "text").map((b) => b.text); - if (texts.length > 0) return texts.join(""); - return JSON.stringify(content2); +function forwardedUpstreamHeaders() { + return [ + "x-request-id", + "anthropic-ratelimit-requests-limit", + "anthropic-ratelimit-requests-remaining", + "anthropic-ratelimit-requests-reset", + "anthropic-ratelimit-tokens-limit", + "anthropic-ratelimit-tokens-remaining", + "anthropic-ratelimit-tokens-reset" + ]; } -function mapFinishReasonToStopReason(finishReason) { - switch (finishReason) { - case "stop": - return "end_turn"; - case "length": - return "max_tokens"; - case "tool_calls": - return "tool_use"; - case "content_filter": - return "end_turn"; - default: - return null; +function translatedSseResponse(body2) { + return new Response(body2, { + status: 200, + headers: { + "content-type": "text/event-stream", + "cache-control": "no-cache" + } + }); +} +function peekBody(body2) { + if (!body2) return { model: "-", stream: false }; + try { + const p = JSON.parse(body2); + return { + model: typeof p.model === "string" ? p.model : "-", + stream: p.stream === true + }; + } catch { + return { model: "-", stream: false }; } } -function openaiUsageToAnthropic(usage) { - const promptTokens = usage?.prompt_tokens ?? 0; - const cacheRead = usage?.cache_read_input_tokens ?? usage?.prompt_tokens_details?.cached_tokens ?? 0; - const cacheCreation = usage?.cache_creation_input_tokens ?? 0; - const inputTokens = Math.max(0, promptTokens - cacheRead - cacheCreation); - const result3 = { - input_tokens: inputTokens, - output_tokens: usage?.completion_tokens ?? 0 - }; - if (cacheRead > 0) result3.cache_read_input_tokens = cacheRead; - if (cacheCreation > 0) result3.cache_creation_input_tokens = cacheCreation; - return result3; +function localTime(ms) { + const d = new Date(ms); + const hh = String(d.getHours()).padStart(2, "0"); + const mm = String(d.getMinutes()).padStart(2, "0"); + const ss = String(d.getSeconds()).padStart(2, "0"); + return `${hh}:${mm}:${ss}`; } - -// src/translator/sse-translator.ts -function parseSSEChunk(raw) { - const results = []; - const blocks = raw.split("\n\n"); - for (const block of blocks) { - const lines = block.trim().split("\n").filter(Boolean); - if (lines.length === 0) continue; - let eventType = ""; - let dataStr = ""; - for (const line of lines) { - if (line.startsWith("event: ")) { - eventType = line.slice(7).trim(); - } else if (line.startsWith("data: ")) { - dataStr = line.slice(6); - } - } - if (dataStr) { - try { - results.push({ event: eventType, data: JSON.parse(dataStr) }); - } catch { - } - } +function nextReqId() { + return `#${String(++reqCounter).padStart(3, "0")}`; +} +function debugLine(reqId, msg) { + console.log(`${reqId} debug: ${msg}`); +} +function debugError(reqId, kind2, msg) { + console.log(`${reqId} debug: ERROR ${kind2}: ${msg}`); +} +function redactHeaderVal(key, val) { + const k = key.toLowerCase(); + if (!SENSITIVE_HEADERS2.has(k)) return val; + if (k === "authorization") { + const sp = val.indexOf(" "); + return sp > 0 ? `${val.slice(0, sp)} ` : ""; + } + if (val.length <= 10) return ""; + return `${val.slice(0, 6)}...${val.slice(-4)}`; +} +function formatHeaderPairs(headers2) { + const pairs = []; + for (const [k, v] of headers2.entries()) { + pairs.push(`${k}=${redactHeaderVal(k, v)}`); } - return results; -} -function initState(model) { - return { - messageId: "", - model, - roleSent: false, - usage: { input_tokens: 0, output_tokens: 0 }, - toolCallIndex: 0, - blockIndexToToolCallIndex: /* @__PURE__ */ new Map(), - finishReasonSent: false - }; + return pairs.join(" "); } -function mergeAnthropicUsage(target2, patch) { - if (!patch) return; - if (patch.input_tokens != null) target2.input_tokens = patch.input_tokens; - if (patch.output_tokens != null) target2.output_tokens = patch.output_tokens; - if (patch.cache_read_input_tokens != null) target2.cache_read_input_tokens = patch.cache_read_input_tokens; - if (patch.cache_creation_input_tokens != null) target2.cache_creation_input_tokens = patch.cache_creation_input_tokens; +function formatResponseHeaders(headers2) { + const interesting = [ + "content-type", + "content-encoding", + "content-length", + "x-request-id", + "anthropic-ratelimit-requests-remaining", + "anthropic-ratelimit-tokens-remaining" + ]; + const pairs = []; + for (const h of interesting) { + const v = headers2.get(h); + if (v) pairs.push(`${h}=${v}`); + } + return pairs.length > 0 ? pairs.join(" ") : "(no notable headers)"; } -function makeChunk(state2, delta, finishReason = null, usage) { - const chunk = { - id: state2.messageId || "chatcmpl-stream", - object: "chat.completion.chunk", - created: Math.floor(Date.now() / 1e3), - model: state2.model, - choices: [{ - index: 0, - delta, - finish_reason: finishReason - }] - }; - if (usage) chunk.usage = usage; - return `data: ${JSON.stringify(chunk)} - -`; +function previewBody(body2) { + const flat = body2.replace(/\s+/g, " ").trim(); + if (flat.length <= DEBUG_BODY_PREVIEW) return flat; + return `${flat.slice(0, DEBUG_BODY_PREVIEW)}\u2026(${flat.length} bytes total)`; } -function anthropicSseToOpenaiSse(upstream, model = "glm-4.6") { - const state2 = initState(model); - const decoder = new TextDecoder(); - const encoder2 = new TextEncoder(); - let buffer2 = ""; - return new ReadableStream({ - async start(controller) { - const reader = upstream.getReader(); - let errored = false; - try { - while (true) { - const { done, value: value2 } = await reader.read(); - if (done) break; - buffer2 += decoder.decode(value2, { stream: true }); - const blocks = buffer2.split("\n\n"); - buffer2 = blocks.pop() ?? ""; - for (const block of blocks) { - const parsed = parseSSEChunk(block); - for (const p of parsed) { - const output = translateEvent(state2, p); - if (output) { - controller.enqueue(encoder2.encode(output)); - } - } - } - } - if (buffer2.trim()) { - const parsed = parseSSEChunk(buffer2); - for (const p of parsed) { - const output = translateEvent(state2, p); - if (output) controller.enqueue(encoder2.encode(output)); - } - } - controller.enqueue(encoder2.encode("data: [DONE]\n\n")); - } catch (err) { - errored = true; - try { - controller.error(err); - } catch { - } - } finally { - if (!errored) { - try { - controller.close(); - } catch { - } - } - reader.releaseLock(); - } - } - }); +function printHeader() { + if (headerPrinted) return; + headerPrinted = true; + if (COMPACT_LOG) return; + console.log( + "| # | Time | Fmt | Model | Mode | Stat | TTFB | Tok | tok/s | Total |" + ); + console.log( + "|------|------------|-----|-------------|--------|------|---------|-------|--------|---------|" + ); } -function translateEvent(state2, sse) { - const data2 = sse.data; - switch (data2.type) { - case "message_start": { - const msg = data2.message; - state2.messageId = msg?.id ?? "msg_stream"; - state2.model = msg?.model ?? state2.model; - mergeAnthropicUsage(state2.usage, msg?.usage); - if (!state2.roleSent) { - state2.roleSent = true; - return makeChunk(state2, { role: "assistant" }); - } - return null; - } - case "content_block_start": { - if (data2.type !== "content_block_start") return null; - const block = data2.content_block; - const blockIdx = data2.index; - if (block.type === "tool_use") { - const myIndex = state2.toolCallIndex++; - state2.blockIndexToToolCallIndex.set(blockIdx, myIndex); - return makeChunk(state2, { - tool_calls: [{ - index: myIndex, - id: block.id, - type: "function", - function: { name: block.name, arguments: "" } - }] - }); - } - return null; - } - case "content_block_delta": { - if (data2.type !== "content_block_delta") return null; - const delta = data2.delta; - const blockIdx = data2.index; - if (delta.type === "text_delta") { - return makeChunk(state2, { content: delta.text }); - } - if (delta.type === "thinking_delta") { - return makeChunk(state2, { reasoning_content: delta.thinking }); - } - if (delta.type === "signature_delta") { - return null; - } - if (delta.type === "input_json_delta") { - const myIndex = state2.blockIndexToToolCallIndex.get(blockIdx); - if (myIndex === void 0) return null; - return makeChunk(state2, { - tool_calls: [{ - index: myIndex, - function: { arguments: delta.partial_json ?? "" } - }] - }); - } - return null; - } - case "message_delta": { - mergeAnthropicUsage(state2.usage, data2.usage); - if (data2.delta?.stop_reason && !state2.finishReasonSent) { - const finishReason = mapStopReason(data2.delta.stop_reason); - state2.finishReasonSent = true; - return makeChunk(state2, {}, finishReason, anthropicUsageToOpenAI(state2.usage)); - } - return null; - } - case "message_stop": { - if (state2.finishReasonSent) return null; - state2.finishReasonSent = true; - return makeChunk(state2, {}, "stop", anthropicUsageToOpenAI(state2.usage)); +function printRow(reqId, format, meta, status, started, headersAt, tokens, avgTps, streamEndAt) { + printHeader(); + const tag = format === "anthropic" ? "ANT" : "OAI"; + const mode2 = meta.stream ? "stream" : "batch"; + if (COMPACT_LOG) { + const ttfbMs = headersAt - started; + const totalMs = streamEndAt > started ? streamEndAt - started : ttfbMs; + const ttfbStr = fmtMs(ttfbMs); + const tokStr = tokens > 0 ? `${tokens}tok` : ""; + const tpsStr = avgTps > 0 ? `${avgTps.toFixed(0)}t/s` : ""; + const parts = [reqId, tag, meta.model, String(status), mode2]; + if (meta.stream && streamEndAt > started) { + parts.push(`${ttfbStr}\u2192${fmtMs(totalMs)}`); + } else { + parts.push(ttfbStr); } - case "ping": - case "content_block_stop": - return null; - default: - return null; + if (tokStr) parts.push(tokStr); + if (tpsStr) parts.push(tpsStr); + console.log(parts.join(" ")); + return; } + const ts = localTime(started); + const ttfb = `${headersAt - started}ms`; + const total = streamEndAt > started ? `${streamEndAt - started}ms` : "-"; + const tok = tokens > 0 ? String(tokens) : "-"; + const tps = avgTps > 0 ? avgTps.toFixed(1) : "-"; + console.log( + `| ${reqId.padEnd(4)} | ${ts.padEnd(10)} | ${tag} | ${meta.model.padEnd(11)} | ${mode2.padEnd(6)} | ${String(status).padStart(4)} | ${ttfb.padStart(7)} | ${tok.padStart(5)} | ${tps.padStart(6)} | ${total.padStart(7)} |` + ); } -function mapStopReason(stopReason) { - switch (stopReason) { - case "end_turn": - case "stop_sequence": - return "stop"; - case "max_tokens": - return "length"; - case "tool_use": - return "tool_calls"; - default: - return "stop"; - } +function fmtMs(ms) { + if (ms < 1e3) return `${ms}ms`; + if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`; + return `${Math.floor(ms / 6e4)}m${Math.floor(ms % 6e4 / 1e3)}s`; } -function openaiSseToAnthropicSse(upstream, model = "glm-4.6") { - const encoder2 = new TextEncoder(); - const decoder = new TextDecoder(); - let buffer2 = ""; - let messageStarted = false; - let blockIndex = 0; - let activeBlock = null; - const toolBlocks = /* @__PURE__ */ new Map(); - const openToolBlockIndices = []; - let outputTokens = 0; - let latestUsage; - let pendingStopReason = null; - let contentClosed = false; - let messageDeltaSent = false; - let messageStopped = false; - const messageId = `msg_${Date.now()}`; - return new ReadableStream({ - async start(controller) { - const reader = upstream.getReader(); - let errored = false; - const enqueueAnthropicEvent = (eventType, data2) => { - controller.enqueue(encoder2.encode(formatAnthropicSSE(eventType, data2))); - }; - const closeActiveBlock = () => { - if (!activeBlock) return; - enqueueAnthropicEvent("content_block_stop", { - type: "content_block_stop", - index: activeBlock.index - }); - activeBlock = null; - }; - const closeToolBlocks = () => { - for (const idx of openToolBlockIndices) { - enqueueAnthropicEvent("content_block_stop", { - type: "content_block_stop", - index: idx - }); - } - openToolBlockIndices.length = 0; - }; - const ensureActiveBlock = (type2) => { - if (activeBlock?.type === type2) return activeBlock.index; - closeActiveBlock(); - const index = blockIndex++; - activeBlock = { type: type2, index }; - enqueueAnthropicEvent("content_block_start", { - type: "content_block_start", - index, - content_block: type2 === "text" ? { type: "text", text: "" } : { type: "thinking", thinking: "", signature: "" } - }); - return index; - }; - const handleToolCalls = (toolCalls) => { - closeActiveBlock(); - for (const tc of toolCalls) { - const idx = tc.index ?? 0; - let state2 = toolBlocks.get(idx); - if (!state2) { - state2 = { index: blockIndex++, id: "", name: "", started: false, pendingArgs: "" }; - toolBlocks.set(idx, state2); - } - if (tc.id) state2.id = tc.id; - if (tc.function?.name) state2.name = tc.function.name; - if (!state2.started && state2.id && state2.name) { - state2.started = true; - enqueueAnthropicEvent("content_block_start", { - type: "content_block_start", - index: state2.index, - content_block: { type: "tool_use", id: state2.id, name: state2.name, input: {} } - }); - openToolBlockIndices.push(state2.index); - if (state2.pendingArgs.length > 0) { - enqueueAnthropicEvent("content_block_delta", { - type: "content_block_delta", - index: state2.index, - delta: { type: "input_json_delta", partial_json: state2.pendingArgs } - }); - state2.pendingArgs = ""; - } - } - const argsDelta = tc.function?.arguments; - if (argsDelta) { - if (state2.started) { - enqueueAnthropicEvent("content_block_delta", { - type: "content_block_delta", - index: state2.index, - delta: { type: "input_json_delta", partial_json: argsDelta } - }); - } else { - state2.pendingArgs += argsDelta; - } - } - } - }; - const startPendingToolBlocks = () => { - const lateStarts = []; - for (const [openaiIdx, state2] of toolBlocks) { - if (state2.started) continue; - if (!state2.pendingArgs && !state2.id && !state2.name) continue; - state2.started = true; - lateStarts.push({ - index: state2.index, - id: state2.id || `tool_call_${openaiIdx}`, - name: state2.name || "unknown_tool", - args: state2.pendingArgs - }); - state2.pendingArgs = ""; - openToolBlockIndices.push(state2.index); +function observeStream(reqId, format, meta, status, requestSentAt, body2, contentEncoding) { + const compressed = contentEncoding !== null; + const dumpOn = dumpEnabled(); + let tokens = 0; + let sseBuffer = ""; + let firstChunkAt = 0; + let totalBytes = 0; + let firstBytesSample = ""; + function parseSse(text) { + for (const line of text.split("\n")) { + if (!line.startsWith("data:") || line.includes("[DONE]")) continue; + try { + const j = JSON.parse(line.slice(5).trim()); + if (j.usage?.completion_tokens) { + tokens = j.usage.completion_tokens; + continue; } - lateStarts.sort((a, b) => a.index - b.index); - for (const ls of lateStarts) { - enqueueAnthropicEvent("content_block_start", { - type: "content_block_start", - index: ls.index, - content_block: { type: "tool_use", id: ls.id, name: ls.name, input: {} } - }); - if (ls.args.length > 0) { - enqueueAnthropicEvent("content_block_delta", { - type: "content_block_delta", - index: ls.index, - delta: { type: "input_json_delta", partial_json: ls.args } - }); - } + if (j.usage?.output_tokens) { + tokens = j.usage.output_tokens; + continue; } - }; - const closeContent = () => { - if (contentClosed) return; - contentClosed = true; - closeActiveBlock(); - startPendingToolBlocks(); - closeToolBlocks(); - }; - const finalizeStream = () => { - closeContent(); - if (!messageDeltaSent) { - messageDeltaSent = true; - const usage = openaiUsageToAnthropic(latestUsage); - if (!latestUsage) usage.output_tokens = outputTokens; - enqueueAnthropicEvent("message_delta", { - type: "message_delta", - delta: { - stop_reason: pendingStopReason ?? "end_turn", - stop_sequence: null - }, - usage - }); + const oai = j.choices?.[0]?.delta?.content; + if (typeof oai === "string" && oai.length > 0) { + tokens++; + continue; } - if (!messageStopped) { - messageStopped = true; - enqueueAnthropicEvent("message_stop", { type: "message_stop" }); + if (j.type === "content_block_delta" && j.delta?.type === "text_delta") { + const t = j.delta?.text; + if (typeof t === "string" && t.length > 0) tokens++; } - }; - try { - while (true) { - const { done, value: value2 } = await reader.read(); - if (done) break; - buffer2 += decoder.decode(value2, { stream: true }); - const lines = buffer2.split("\n"); - buffer2 = lines.pop() ?? ""; - for (const line of lines) { - if (!line.startsWith("data: ")) continue; - const dataStr = line.slice(6).trim(); - if (dataStr === "[DONE]") { - finalizeStream(); - continue; - } - try { - const chunk = JSON.parse(dataStr); - const choice = chunk.choices?.[0]; - if (chunk.usage) { - latestUsage = chunk.usage; - outputTokens = chunk.usage.completion_tokens ?? outputTokens; - } - if (!messageStarted) { - messageStarted = true; - const startUsage = openaiUsageToAnthropic(chunk.usage); - enqueueAnthropicEvent("message_start", { - type: "message_start", - message: { - id: chunk.id ?? messageId, - type: "message", - role: "assistant", - content: [], - model: chunk.model || model, - stop_reason: null, - stop_sequence: null, - usage: startUsage - } - }); - } - if (choice?.delta?.content) { - const index = ensureActiveBlock("text"); - enqueueAnthropicEvent("content_block_delta", { - type: "content_block_delta", - index, - delta: { type: "text_delta", text: choice.delta.content } - }); - } - if (choice?.delta?.reasoning_content) { - const index = ensureActiveBlock("thinking"); - enqueueAnthropicEvent("content_block_delta", { - type: "content_block_delta", - index, - delta: { type: "thinking_delta", thinking: choice.delta.reasoning_content } - }); - } - if (choice?.delta?.tool_calls?.length) { - handleToolCalls(choice.delta.tool_calls); - } - if (choice?.finish_reason) { - pendingStopReason = mapFinishReason(choice.finish_reason); - closeContent(); - } - } catch { - } + } catch { + } + } + } + (async () => { + const reader = body2.getReader(); + const decoder = new TextDecoder(); + try { + while (true) { + const { done, value: value2 } = await reader.read(); + if (done) break; + if (firstChunkAt === 0) firstChunkAt = Date.now(); + if (dumpOn && value2) { + totalBytes += value2.byteLength; + if (firstBytesSample.length < 4096) { + firstBytesSample += decoder.decode(value2.slice(0, 4096 - firstBytesSample.length), { stream: true }); } } - finalizeStream(); - } catch (err) { - errored = true; - try { - controller.error(err); - } catch { - } - } finally { - if (!errored) { - try { - controller.close(); - } catch { + if (!compressed) { + sseBuffer += decoder.decode(value2, { stream: true }); + const idx = sseBuffer.lastIndexOf("\n"); + if (idx >= 0) { + parseSse(sseBuffer.slice(0, idx)); + sseBuffer = sseBuffer.slice(idx + 1); } } - reader.releaseLock(); } + if (!compressed && sseBuffer) parseSse(sseBuffer); + } catch { + } + const endAt = Date.now(); + const ttfbMs = (firstChunkAt > 0 ? firstChunkAt : endAt) - requestSentAt; + const totalMs = endAt - requestSentAt; + const avgTps = tokens > 0 && totalMs > 0 ? tokens / (totalMs / 1e3) : 0; + printRow(reqId, format, meta, status, requestSentAt, requestSentAt + ttfbMs, tokens, avgTps, endAt); + if (dumpOn) { + dumpPhase(reqId, "upstream_stream_summary", { + status, + contentEncoding, + compressed, + totalBytes, + tokensObserved: tokens, + ttfbMs, + totalMs, + firstBytesSample: firstBytesSample.length > 0 ? firstBytesSample.slice(0, 4096) : "(empty stream)" + }); } + })().catch(() => { }); } -function formatAnthropicSSE(eventType, data2) { - return `event: ${eventType} -data: ${JSON.stringify(data2)} +var import_node_zlib, captchaModule, FETCH_AUTO_DECOMPRESSES, AUTO_DECODED_ENCODINGS, MAX_INFLATED_BODY_BYTES, InflatedBodyTooLargeError, reqCounter, headerPrinted, DEBUG_BODY_PREVIEW, SENSITIVE_HEADERS2, COMPACT_LOG; +var init_handler = __esm({ + "src/proxy/handler.ts"() { + "use strict"; + init_providers(); + init_upstream(); + init_endpoint_routing(); + init_client_signing(); + init_types(); + init_ordered_transport(); + init_body_transformer(); + init_session_context(); + import_node_zlib = require("node:zlib"); + init_openai_to_anthropic(); + init_anthropic_to_openai(); + init_sse_translator(); + init_dump(); + captchaModule = null; + FETCH_AUTO_DECOMPRESSES = typeof Bun === "undefined"; + AUTO_DECODED_ENCODINGS = /* @__PURE__ */ new Set(["gzip", "x-gzip", "deflate", "br"]); + MAX_INFLATED_BODY_BYTES = 64 * 1024 * 1024; + InflatedBodyTooLargeError = class extends Error { + constructor(limit) { + super(`gzip request body exceeds ${limit} bytes after decompression`); + this.name = "InflatedBodyTooLargeError"; + } + }; + reqCounter = 0; + headerPrinted = false; + DEBUG_BODY_PREVIEW = 200; + SENSITIVE_HEADERS2 = /* @__PURE__ */ new Set(["authorization", "x-api-key", "cookie", "set-cookie", "proxy-authorization"]); + COMPACT_LOG = process.env.ZCODE_LOG_FORMAT === "compact"; + } +}); -`; +// src/server/routes-openai.ts +async function handleChatCompletions(req, opts) { + return proxyRequest(req, "openai", opts); } -function mapFinishReason(finishReason) { - switch (finishReason) { - case "stop": - return "end_turn"; - case "length": - return "max_tokens"; - case "tool_calls": - return "tool_use"; - default: - return "end_turn"; - } +function handleListModels() { + const list = { + object: "list", + data: MODELS.map((m) => ({ + id: m.id, + object: "model", + owned_by: "zcode-proxy" + })) + }; + return new Response(JSON.stringify(list), { + status: 200, + headers: { "content-type": "application/json" } + }); } +var init_routes_openai = __esm({ + "src/server/routes-openai.ts"() { + "use strict"; + init_handler(); + init_models(); + } +}); -// src/proxy/dump.ts -var import_node_fs2 = require("node:fs"); -var DUMP_PATH = process.env.ZCODE_DUMP_UPSTREAM; -var SENSITIVE_HEADERS = /* @__PURE__ */ new Set([ - "authorization", - "x-api-key", - "proxy-authorization", - "proxy-api-key", - "x-zcode-captcha-verify-param", - "x-zcode-captcha-verify-region", - "cookie" -]); -function maskHeaderValue(key, value2) { - if (!SENSITIVE_HEADERS.has(key.toLowerCase())) return value2; - if (value2.length <= 12) return ""; - return `${value2.slice(0, 8)}\u2026${value2.slice(-4)} (len=${value2.length})`; +// src/server/routes-anthropic.ts +async function handleMessages(req, opts) { + return proxyRequest(req, "anthropic", opts); } -function dumpHeaders(headers2) { - const out = {}; - for (const [k, v] of headers2.entries()) { - out[k] = maskHeaderValue(k, v); +var init_routes_anthropic = __esm({ + "src/server/routes-anthropic.ts"() { + "use strict"; + init_handler(); } - return out; +}); + +// src/translator/responses-types.ts +function generateResponsesId(prefix2 = "resp_") { + const bytes = new Uint8Array(16); + crypto.getRandomValues(bytes); + const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(""); + return `${prefix2}${hex}`; } -function dumpBody(body2) { - if (body2 === void 0 || body2 === null) return void 0; - if (body2.length === 0) return ""; - try { - return JSON.parse(body2); - } catch { - return body2; - } +function generateItemId() { + return generateResponsesId("item_"); } -function dumpPhase(reqId, phase, data2) { - if (!DUMP_PATH) return; - try { - const line = { - ts: (/* @__PURE__ */ new Date()).toISOString(), - reqId, - phase, - ...data2 - }; - (0, import_node_fs2.appendFileSync)(DUMP_PATH, JSON.stringify(line) + "\n", "utf-8"); - } catch { - } +function generateCallId() { + return generateResponsesId("call_"); } -function dumpEnabled() { - return !!DUMP_PATH; +function isHostedTool(t) { + return t.type === "file_search" || t.type === "code_interpreter" || t.type === "computer_use_preview" || t.type === "image_generation" || t.type === "mcp"; } - -// src/proxy/handler.ts -var captchaModule = null; -async function loadCaptcha() { - if (!captchaModule) captchaModule = await Promise.resolve().then(() => (init_captcha(), captcha_exports)); - return captchaModule; +function isWebSearchTool(t) { + return t.type === "web_search" || t.type === "web_search_preview"; } -async function proxyRequest(clientReq, format, opts) { - const { config, auth } = opts; - const fetchImpl = opts.fetchImpl ?? fetch; - const hasCustomFetchImpl = opts.fetchImpl !== void 0; - const debug = opts.debug === true; - const started = Date.now(); - const reqId = nextReqId(); - let body2; - try { - body2 = await readBody(clientReq); - } catch (err) { - if (err instanceof InflatedBodyTooLargeError) { - return errorResponse(413, "request_too_large", err.message); - } - return errorResponse(400, "invalid_request_error", err.message); +var init_responses_types = __esm({ + "src/translator/responses-types.ts"() { + "use strict"; } - const meta = peekBody(body2); - if (dumpEnabled()) { - dumpPhase(reqId, "client_in", { - method: clientReq.method, - url: clientReq.url, - headers: dumpHeaders(clientReq.headers), - body: dumpBody(body2) - }); +}); + +// src/translator/responses-to-chat.ts +function responsesToChatCompletions(req) { + const messages = []; + if (typeof req.instructions === "string" && req.instructions.trim().length > 0) { + messages.push({ role: "system", content: req.instructions }); } - const staticProvider = getProvider(config.provider); - const provider = { - ...staticProvider, - anthropicBaseURL: config.providers[config.provider].anthropicBase, - openaiBaseURL: config.providers[config.provider].openaiBase - }; - let cred; - try { - cred = await auth.getCredential(); - } catch (err) { - if (debug) debugError(reqId, "credential_unavailable", err.message); - printRow(reqId, format, meta, 503, started, Date.now(), 0, 0, 0); - return errorResponse(503, "credential_unavailable", err.message); + const inputItems = normaliseInput(req.input); + const built = buildMessagesFromItems(inputItems); + messages.push(...built); + const customToolNames = /* @__PURE__ */ new Set(); + const namespaceMap = /* @__PURE__ */ new Map(); + const convertibleToolNames = /* @__PURE__ */ new Set(); + let hasWebSearch = false; + let hasToolSearch = false; + const tools = []; + if (Array.isArray(req.tools)) { + for (const tool of req.tools) { + collectTools(tool, "", tools, customToolNames, namespaceMap, convertibleToolNames, (ref) => { + if (ref === "web_search") hasWebSearch = true; + if (ref === "tool_search") hasToolSearch = true; + }); + } } - const startPlan = config.plan === "start-plan"; - const translateAnthropicToOpenAI = false; - const translateOpenAIToAnthropic = format === "openai"; - const upstreamFormat = "anthropic"; - const clientSession = resolveSessionContext({ clientReq, body: body2, upstreamFormat, model: meta.model, config }); - if (debug && clientSession) { - const shortSession = clientSession.sessionId ? clientSession.sessionId.slice(0, 10) : "-"; - debugLine(reqId, `clientIdentity source=${clientSession.source} action=${clientSession.action} confidence=${clientSession.confidence.toFixed(2)} session=${shortSession}`); + const chatRequest = { + model: req.model, + messages, + ...req.max_output_tokens !== void 0 ? { max_tokens: req.max_output_tokens } : {}, + ...req.temperature !== void 0 ? { temperature: req.temperature } : {}, + ...req.top_p !== void 0 ? { top_p: req.top_p } : {}, + ...req.stream !== void 0 ? { stream: req.stream } : {}, + ...req.user !== void 0 ? { user: req.user } : {} + }; + if (tools.length > 0) chatRequest.tools = tools; + if (tools.length > 0 && req.tool_choice !== void 0) { + const mapped = mapToolChoice(req.tool_choice, convertibleToolNames, hasToolSearch); + if (mapped !== void 0) chatRequest.tool_choice = mapped; } - let upstreamBody = body2; - if (translateOpenAIToAnthropic) { - const translated = translateOpenAIBody(body2); - if (translated instanceof Response) return translated; - upstreamBody = translated; - if (debug) debugLine(reqId, `translated OpenAI\u2192Anthropic (bytes=${upstreamBody?.length ?? 0})`); - } else if (translateAnthropicToOpenAI) { - const translated = translateAnthropicBody(body2); - if (translated instanceof Response) return translated; - upstreamBody = translated; - if (debug) debugLine(reqId, `translated Anthropic\u2192OpenAI (bytes=${upstreamBody?.length ?? 0})`); + if (tools.length > 0 && req.parallel_tool_calls !== void 0) { + chatRequest.parallel_tool_calls = req.parallel_tool_calls; } - const transformedBody = transformRequestBody(upstreamBody, { format: upstreamFormat, userId: startPlan ? void 0 : cred.userId, startPlan }); - if (debug && transformedBody !== upstreamBody) { - debugLine(reqId, `body transformed (upstreamFormat=${upstreamFormat}, startPlan=${startPlan}, bytes=${transformedBody?.length ?? 0})`); + if (req.reasoning?.effort) { + chatRequest.reasoning_effort = req.reasoning.effort; } - let captchaHeaders; - if (startPlan) { - try { - const captcha2 = await loadCaptcha(); - const token = await captcha2.getCaptchaToken(config.identity.appVersion); - captchaHeaders = { [captcha2.RETRY_HEADERS.PARAM]: token.verifyParam, [captcha2.RETRY_HEADERS.REGION]: token.region }; - } catch { - } + return { + chatRequest, + customToolNames, + namespaceMap, + hasWebSearch, + hasToolSearch, + convertibleToolNames + }; +} +function normaliseInput(input) { + if (typeof input === "string") { + return [{ type: "message", role: "user", content: input }]; } - const useOrderedTransport = shouldUseOrderedTransport(config, clientSession, hasCustomFetchImpl); - let upstreamHeaderPairs = buildUpstreamHeaderPairs(clientReq, upstreamFormat, cred, config.identity, config.plan, captchaHeaders, clientSession); - let upstreamReq = buildUpstreamRequest(clientReq, upstreamFormat, provider, cred, transformedBody, config.identity, config.plan, captchaHeaders, clientSession); - const routing = opts.endpointRouting !== void 0 ? opts.endpointRouting : getDefaultEndpointRouting(config); - const signer = opts.clientSigning !== void 0 ? opts.clientSigning : getDefaultClientSigning(config); - const translateMode = translateOpenAIToAnthropic || translateAnthropicToOpenAI; - const dispatch2 = async (req, pairs) => { - let sendUrl = req.url; - if (routing) { - const routed = await routing.resolve(req.url, credentialString(cred)); - if (routed.routed) { - sendUrl = routed.url; - if (debug) debugLine(reqId, `endpoint routing: ${req.url} -> ${routed.url}`); + if (!Array.isArray(input)) return []; + return input.filter((x3) => x3 !== null && typeof x3 === "object"); +} +function buildMessagesFromItems(items2) { + const out = []; + let pendingReasoning = ""; + for (const item of items2) { + const type2 = item.type ?? ""; + switch (type2) { + case "message": { + const role = item.role; + const chatRole = role === "assistant" ? "assistant" : role === "developer" || role === "system" ? "system" : "user"; + const content2 = contentPartsToChat(item.content, chatRole); + out.push({ role: chatRole, content: content2 }); + if (chatRole !== "assistant") pendingReasoning = ""; + continue; } - } - return sendWithClientSigning(signer, { - url: req.url, - headerPairs: pairs, - credential: credentialString(cred), - appVersion: config.identity.appVersion, - debug: debug ? (message) => debugLine(reqId, message) : void 0, - send: (finalPairs) => { - const sendReq = sendUrl === req.url && finalPairs === pairs ? req : new Request(sendUrl, { - method: req.method, - headers: Object.fromEntries(finalPairs), - body: transformedBody ?? void 0 + case "reasoning": { + const text = extractReasoningText(item); + if (text) pendingReasoning = text; + continue; + } + case "function_call": { + const fc = item; + const args = (fc.arguments ?? "").trim().length === 0 ? "{}" : fc.arguments; + const toolCall = { + id: fc.call_id, + type: "function", + function: { name: fc.name, arguments: args } + }; + mergeToolCallIntoAssistant(out, toolCall, pendingReasoning); + pendingReasoning = ""; + continue; + } + case "custom_tool_call": { + const ct = item; + const argObj = JSON.stringify({ input: ct.input ?? "" }); + const toolCall = { + id: ct.call_id, + type: "function", + function: { name: ct.name, arguments: argObj } + }; + mergeToolCallIntoAssistant(out, toolCall, pendingReasoning); + pendingReasoning = ""; + continue; + } + case "function_call_output": + case "custom_tool_call_output": { + const fco = item; + out.push({ + role: "tool", + tool_call_id: fco.call_id, + content: fco.output ?? "" }); - return sendUpstreamRequest(sendReq, finalPairs, transformedBody, translateMode, useOrderedTransport, fetchImpl, clientReq.signal, hasCustomFetchImpl); + pendingReasoning = ""; + continue; } - }); - }; - if (debug) { - debugLine(reqId, `\u2192 POST ${upstreamReq.url}`); - debugLine(reqId, ` ${formatHeaderPairs(upstreamReq.headers)}`); - if (transformedBody) debugLine(reqId, ` body preview: ${previewBody(transformedBody)}`); - } - if (dumpEnabled()) { - dumpPhase(reqId, "upstream_out", { - method: upstreamReq.method, - url: upstreamReq.url, - headers: dumpHeaders(upstreamReq.headers), - body: dumpBody(transformedBody), - upstreamFormat, - translateMode: translateOpenAIToAnthropic || translateAnthropicToOpenAI, - useOrderedTransport, - startPlan - }); - } - let upstreamResp; - try { - const maxConnectAttempts = 3; - for (let attempt = 1; ; attempt++) { - if (clientReq.signal.aborted) throw new Error("client aborted before upstream connect"); - try { - upstreamResp = await dispatch2(upstreamReq, upstreamHeaderPairs); - break; - } catch (err) { - if (err.postWrite) throw err; - if (attempt >= maxConnectAttempts) throw err; - const backoffMs = 500 * attempt; - if (debug) debugError(reqId, "upstream_connect_retry", `attempt ${attempt}/${maxConnectAttempts - 1} failed (${err.message}), retrying in ${backoffMs}ms`); - console.log(`${reqId} upstream connect failed (${err.message}), retry ${attempt + 1}/${maxConnectAttempts} in ${backoffMs}ms`); - await new Promise((r2) => setTimeout(r2, backoffMs)); - upstreamReq = buildUpstreamRequest(clientReq, upstreamFormat, provider, cred, transformedBody, config.identity, config.plan, captchaHeaders, clientSession); + case "tool_search_call": { + const tsc = item; + const argStr = typeof tsc.arguments === "string" ? tsc.arguments : JSON.stringify(tsc.arguments ?? {}); + const toolCall = { + id: tsc.call_id ?? "", + type: "function", + function: { name: "tool_search", arguments: argStr } + }; + mergeToolCallIntoAssistant(out, toolCall, pendingReasoning); + pendingReasoning = ""; + continue; } - } - } catch (err) { - if (debug) debugError(reqId, "upstream_unreachable", err.message); - printRow(reqId, format, meta, 502, started, Date.now(), 0, 0, 0); - return errorResponse(502, "upstream_unreachable", err.message); - } - const headersAt = Date.now(); - if (debug) { - debugLine(reqId, `\u2190 ${upstreamResp.status} ${upstreamResp.statusText}`); - debugLine(reqId, ` ${formatResponseHeaders(upstreamResp.headers)}`); - } - if (dumpEnabled()) { - dumpPhase(reqId, "upstream_in", { - status: upstreamResp.status, - statusText: upstreamResp.statusText, - headers: dumpHeaders(upstreamResp.headers), - isSSE: upstreamResp.headers.get("content-type")?.includes("text/event-stream") ?? false, - ttfbMs: headersAt - started - }); - } - if (upstreamResp.status === 401 && startPlan) { - if (debug) debugError(reqId, "start_plan_jwt_invalid", "JWT rejected upstream"); - printRow(reqId, format, meta, 401, started, headersAt, 0, 0, 0); - return errorResponse(401, "start_plan_jwt_invalid", "Start-plan JWT was rejected. Re-run: zcode-proxy auth login"); - } - const captcha = startPlan ? await loadCaptcha() : null; - let captchaChallenge = captcha ? captcha.detectCaptchaChallenge(upstreamResp) : null; - if (!captchaChallenge && captcha && !upstreamResp.ok) { - const ctype = upstreamResp.headers.get("content-type") ?? ""; - if (!ctype.includes("text/event-stream")) { - try { - const peek = await upstreamResp.clone().text(); - if (peek.includes('"code":3007') || peek.includes('"code": 3007')) { - captchaChallenge = "in-body-3007"; - } - } catch { + case "tool_search_output": { + const tso = item; + out.push({ + role: "tool", + tool_call_id: tso.call_id ?? "", + content: typeof tso.output === "string" ? tso.output : JSON.stringify(tso.output ?? {}) + }); + pendingReasoning = ""; + continue; } + case "additional_tools": + continue; + default: + if (type2 !== "") pendingReasoning = ""; + continue; } } - if (captchaChallenge && captcha) { - if (debug) debugLine(reqId, "captcha challenge \u2014 re-solving and retrying once"); - try { - upstreamResp.body?.cancel(); - } catch { - } - console.log(`${reqId} captcha challenge, re-solving...`); - try { - const fresh = await captcha.getCaptchaToken(config.identity.appVersion); - console.log(`${reqId} captcha re-solved (token ${fresh.verifyParam.length} chars), retrying...`); - const retryHeaders = { - [captcha.RETRY_HEADERS.PARAM]: fresh.verifyParam, - [captcha.RETRY_HEADERS.REGION]: fresh.region - }; - upstreamHeaderPairs = buildUpstreamHeaderPairs(clientReq, upstreamFormat, cred, config.identity, config.plan, retryHeaders, clientSession); - upstreamReq = buildUpstreamRequest(clientReq, upstreamFormat, provider, cred, transformedBody, config.identity, config.plan, retryHeaders, clientSession); - upstreamResp = await dispatch2(upstreamReq, upstreamHeaderPairs).catch((err) => { - if (debug) debugError(reqId, "upstream_unreachable", err.message); - printRow(reqId, format, meta, 502, started, Date.now(), 0, 0, 0); - return errorResponse(502, "upstream_unreachable", err.message); - }); - if (debug) debugLine(reqId, `\u2190 retry ${upstreamResp.status} ${upstreamResp.statusText}`); - } catch (err) { - if (debug) debugError(reqId, "captcha_solver_failed", err.message); - printRow(reqId, format, meta, 503, started, Date.now(), 0, 0, 0); - return errorResponse(503, "captcha_solver_failed", err.message); - } - } - const isSSE = upstreamResp.headers.get("content-type")?.includes("text/event-stream") ?? false; - if (translateOpenAIToAnthropic) { - if (!upstreamResp.ok) { - const errBody = await upstreamResp.text().catch(() => ""); - printRow(reqId, format, meta, 502, started, headersAt, 0, 0, 0); - return errorResponse(502, "translation_failed", `upstream returned ${upstreamResp.status}: ${errBody.slice(0, 200)}`); - } - if (isSSE && upstreamResp.body) { - const translated = anthropicSseToOpenaiSse(upstreamResp.body, meta.model); - const [clientBody, statsBody] = translated.tee(); - observeStream(reqId, format, meta, upstreamResp.status, started, statsBody, null); - return translatedSseResponse(clientBody); - } - return await translatedBatchResponse(clientReq, upstreamResp, meta.model, reqId, format, meta, started, headersAt); - } - if (translateAnthropicToOpenAI) { - if (!upstreamResp.ok) { - const errBody = await upstreamResp.text().catch(() => ""); - printRow(reqId, format, meta, 502, started, headersAt, 0, 0, 0); - return errorResponse(502, "translation_failed", `upstream returned ${upstreamResp.status}: ${errBody.slice(0, 200)}`); - } - if (isSSE && upstreamResp.body) { - const translated = openaiSseToAnthropicSse(upstreamResp.body, meta.model); - const [clientBody, statsBody] = translated.tee(); - observeStream(reqId, format, meta, upstreamResp.status, started, statsBody, null); - return translatedSseResponse(clientBody); - } - return await translatedOpenAIToAnthropicBatchResponse(clientReq, upstreamResp, reqId, format, meta, started, headersAt); - } - if (isSSE && upstreamResp.body) { - const [clientBody, statsBody] = upstreamResp.body.tee(); - observeStream(reqId, format, meta, upstreamResp.status, started, statsBody, upstreamResp.headers.get("content-encoding")); - return passthroughResponse(upstreamResp, clientAcceptsGzip(clientReq), clientBody); - } - printRow(reqId, format, meta, upstreamResp.status, started, headersAt, 0, 0, 0); - return passthroughResponse(upstreamResp, clientAcceptsGzip(clientReq)); -} -function shouldUseOrderedTransport(config, clientSession, hasCustomFetchImpl) { - if (hasCustomFetchImpl) return false; - return clientSession?.action === "enforce" || clientSession?.source === "explicit"; -} -var FETCH_AUTO_DECOMPRESSES = typeof Bun === "undefined"; -var AUTO_DECODED_ENCODINGS = /* @__PURE__ */ new Set(["gzip", "x-gzip", "deflate", "br"]); -function stripAutoDecodedEncoding(resp) { - const encoding = resp.headers.get("content-encoding")?.toLowerCase().trim() ?? ""; - if (!encoding) return resp; - const codings = encoding.split(",").map((c) => c.trim()); - if (!codings.every((c) => AUTO_DECODED_ENCODINGS.has(c))) return resp; - const headers2 = new Headers(resp.headers); - headers2.delete("content-encoding"); - headers2.delete("content-length"); - return new Response(resp.body, { - status: resp.status, - statusText: resp.statusText, - headers: headers2 - }); + return out; } -async function sendUpstreamRequest(upstreamReq, headerPairs, body2, translateMode, useOrderedTransport, fetchImpl, abortSignal, hasCustomFetchImpl = false) { - if (useOrderedTransport) { - return sendOrderedUpstreamRequest({ - url: upstreamReq.url, - method: upstreamReq.method, - headers: headerPairs, - body: body2, - decompress: translateMode - }); - } - const fetchOpts = translateMode ? {} : { decompress: false }; - if (abortSignal) fetchOpts.signal = abortSignal; - const resp = await fetchImpl(upstreamReq, fetchOpts); - if (!translateMode && FETCH_AUTO_DECOMPRESSES && !hasCustomFetchImpl) { - return stripAutoDecodedEncoding(resp); +function mergeToolCallIntoAssistant(out, toolCall, reasoning) { + const last = out[out.length - 1]; + if (last && last.role === "assistant" && Array.isArray(last.tool_calls)) { + last.tool_calls.push(toolCall); + if (!last.reasoning_content && reasoning) last.reasoning_content = reasoning; + } else { + out.push({ + role: "assistant", + content: null, + tool_calls: [toolCall], + ...reasoning ? { reasoning_content: reasoning } : {} + }); } - return resp; } -async function readBody(req) { - if (req.method === "GET" || req.method === "HEAD") return void 0; - const bytes = new Uint8Array(await req.arrayBuffer()); - if (bytes.byteLength === 0) return void 0; - const encoding = req.headers.get("content-encoding")?.toLowerCase().trim() ?? ""; - if (encoding === "gzip" || encoding === "x-gzip") { - return new TextDecoder().decode(await inflateGzipBody(bytes)); - } - return new TextDecoder().decode(bytes); +function extractReasoningText(item) { + const r2 = item; + const parts = Array.isArray(r2.summary) && r2.summary.length > 0 ? r2.summary : r2.content; + if (!Array.isArray(parts)) return ""; + return parts.map((p) => typeof p.text === "string" ? p.text : "").filter((t) => t.length > 0).join("\n"); } -var MAX_INFLATED_BODY_BYTES = 64 * 1024 * 1024; -var InflatedBodyTooLargeError = class extends Error { - constructor(limit) { - super(`gzip request body exceeds ${limit} bytes after decompression`); - this.name = "InflatedBodyTooLargeError"; +function contentPartsToChat(content2, role) { + if (typeof content2 === "string") return content2; + if (!Array.isArray(content2)) return ""; + const textParts = []; + const chatParts = []; + let hasImage = false; + for (const part of content2) { + if ((part.type === "input_text" || part.type === "output_text" || part.type === "text") && typeof part.text === "string") { + if (part.text.length === 0) continue; + textParts.push(part.text); + chatParts.push({ type: "text", text: part.text }); + } else if (part.type === "input_image" || part.type === "image_url") { + const url2 = typeof part.image_url === "string" ? part.image_url : part.image_url?.url; + if (!url2) continue; + hasImage = true; + chatParts.push({ type: "image_url", image_url: { url: url2 } }); + } } -}; -async function inflateGzipBody(bytes) { - const gunzip = new DecompressionStream("gzip"); - const source = new ReadableStream({ - start(controller) { - controller.enqueue(bytes); - controller.close(); + if (!hasImage) return textParts.join("\n"); + if (role !== "user") return textParts.join("\n"); + return chatParts; +} +function collectTools(tool, namespacePrefix, out, customToolNames, namespaceMap, convertibleToolNames, signal2) { + const type2 = tool.type ?? ""; + if (type2 === "function") { + const name2 = tool.name; + const flatName = namespacePrefix ? `${namespacePrefix}__${name2}` : name2; + if (convertibleToolNames.has(flatName)) { + throw new ToolTranslationError(`duplicate tool name after flattening: "${flatName}"`); } - }); - const reader = source.pipeThrough(gunzip).getReader(); - const parts = []; - let total = 0; - try { - for (; ; ) { - const { done, value: value2 } = await reader.read(); - if (done) break; - total += value2.byteLength; - if (total > MAX_INFLATED_BODY_BYTES) { - await reader.cancel().catch(() => { - }); - throw new InflatedBodyTooLargeError(MAX_INFLATED_BODY_BYTES); + const t = tool; + out.push({ + type: "function", + function: { + name: flatName, + ...t.description ? { description: t.description } : {}, + ...t.parameters ? { parameters: t.parameters } : {} } - parts.push(value2); + }); + convertibleToolNames.add(flatName); + if (namespacePrefix) namespaceMap.set(flatName, { namespace: namespacePrefix, name: name2 }); + return; + } + if (type2 === "custom") { + const name2 = tool.name; + const flatName = namespacePrefix ? `${namespacePrefix}__${name2}` : name2; + if (convertibleToolNames.has(flatName)) { + throw new ToolTranslationError(`duplicate tool name after flattening: "${flatName}"`); } - } catch (err) { - if (err instanceof InflatedBodyTooLargeError) throw err; - throw new Error(`request body is marked content-encoding: gzip but failed to decompress: ${err.message}`); - } finally { - reader.releaseLock?.(); + const t = tool; + out.push({ + type: "function", + function: { + name: flatName, + ...t.description ? { description: t.description } : {}, + parameters: CUSTOM_TOOL_SCHEMA + } + }); + convertibleToolNames.add(flatName); + customToolNames.add(flatName); + if (namespacePrefix) namespaceMap.set(flatName, { namespace: namespacePrefix, name: name2 }); + return; } - return Buffer.concat(parts); -} -function passthroughResponse(upstream, clientAcceptsGzip2, body2) { - const headers2 = new Headers(); - const forwardHeaders = [ - "content-type", - "content-encoding", - "cache-control", - "x-request-id", - "anthropic-ratelimit-requests-limit", - "anthropic-ratelimit-requests-remaining", - "anthropic-ratelimit-requests-reset", - "anthropic-ratelimit-tokens-limit", - "anthropic-ratelimit-tokens-remaining", - "anthropic-ratelimit-tokens-reset" - ]; - for (const h of forwardHeaders) { - const v = upstream.headers.get(h); - if (v) headers2.set(h, v); + if (type2 === "namespace") { + const ns = tool.name; + const children2 = tool.tools ?? tool.children ?? []; + const childPrefix = namespacePrefix ? `${namespacePrefix}__${ns}` : ns; + for (const child of children2) { + collectTools(child, childPrefix, out, customToolNames, namespaceMap, convertibleToolNames, signal2); + } + return; } - const upstreamEncoding = headers2.get("content-encoding")?.toLowerCase() ?? ""; - const source = body2 ?? upstream.body; - if (upstreamEncoding.includes("gzip") && !clientAcceptsGzip2 && source) { - const gunzip = new DecompressionStream("gzip"); - const decompressed = source.pipeThrough(gunzip); - headers2.delete("content-encoding"); - headers2.delete("content-length"); - return new Response(decompressed, { - status: upstream.status, - statusText: upstream.statusText, - headers: headers2 + if (type2 === "tool_search") { + signal2("tool_search"); + if (convertibleToolNames.has("tool_search")) return; + out.push({ + type: "function", + function: { + name: "tool_search", + description: "Search the available tool registry.", + parameters: TOOL_SEARCH_PROXY_SCHEMA + } }); + convertibleToolNames.add("tool_search"); + return; } - return new Response(source, { - status: upstream.status, - statusText: upstream.statusText, - headers: headers2 - }); -} -function errorResponse(status, type2, message) { - const body2 = JSON.stringify({ - error: { type: type2, message } - }); - return new Response(body2, { - status, - headers: { "content-type": "application/json" } - }); -} -function translateOpenAIBody(body2) { - if (body2 === void 0 || body2.length === 0) { - return errorResponse(400, "translation_failed", "OpenAI request body is empty; cannot translate."); + if (isWebSearchTool(tool)) { + signal2("web_search"); + return; } - let parsed; - try { - parsed = JSON.parse(body2); - } catch (err) { - return errorResponse(400, "translation_failed", `OpenAI request body is not valid JSON: ${err.message}`); + if (isHostedTool(tool)) { + return; } - try { - const translated = translateRequestOpenAIToAnthropic(parsed); - return JSON.stringify(translated); - } catch (err) { - return errorResponse(400, "translation_failed", `OpenAI\u2192Anthropic translation failed: ${err.message}`); + const maybeName = tool.name; + const maybeParams = tool.parameters; + if (typeof maybeName === "string" && maybeParams && typeof maybeParams === "object") { + const flatName = namespacePrefix ? `${namespacePrefix}__${maybeName}` : maybeName; + if (!convertibleToolNames.has(flatName)) { + out.push({ type: "function", function: { name: flatName, parameters: maybeParams } }); + convertibleToolNames.add(flatName); + } } } -function clientAcceptsGzip(req) { - const ae = req.headers.get("accept-encoding"); - if (!ae) return false; - return /\bgzip\b(?!\s*;\s*q=0(?:\.0+)?\s*(?:,|$))/i.test(ae); -} -async function translatedBatchResponse(clientReq, upstream, model, reqId, format, meta, started, headersAt) { - const raw = await upstream.text(); - let parsedAnthropic; - try { - parsedAnthropic = JSON.parse(raw); - } catch (err) { - printRow(reqId, format, meta, 502, started, headersAt, 0, 0, 0); - return errorResponse(502, "translation_failed", `upstream returned non-JSON body: ${err.message}`); +function mapToolChoice(raw, convertible, hasToolSearch) { + if (raw === void 0 || raw === null) return void 0; + if (typeof raw === "string") { + return raw; } - if (!isAnthropicMessagesResponse(parsedAnthropic)) { - printRow(reqId, format, meta, 502, started, headersAt, 0, 0, 0); - return errorResponse(502, "translation_failed", `upstream returned invalid Anthropic message: ${raw.slice(0, 200)}`); + if (typeof raw !== "object") return void 0; + const obj = raw; + const type2 = obj.type ?? ""; + if (type2 === "web_search" || type2 === "web_search_preview") return void 0; + if (type2 === "file_search" || type2 === "code_interpreter" || type2 === "computer_use_preview" || type2 === "image_generation" || type2 === "mcp") { + return void 0; } - const openaiResp = translateResponseAnthropicToOpenAI(parsedAnthropic, model); - const json = JSON.stringify(openaiResp); - const payload = new TextEncoder().encode(json); - const respHeaders = new Headers(); - respHeaders.set("content-type", "application/json"); - for (const h of forwardedUpstreamHeaders()) { - const v = upstream.headers.get(h); - if (v) respHeaders.set(h, v); + if (type2 === "tool_search") { + return hasToolSearch ? { type: "function", function: { name: "tool_search" } } : void 0; } - if (clientAcceptsGzip(clientReq)) { - respHeaders.set("content-encoding", "gzip"); - printRow(reqId, format, meta, upstream.status, started, headersAt, openaiResp.usage?.completion_tokens ?? 0, 0, 0); - return new Response((0, import_node_zlib.gzipSync)(payload), { - status: upstream.status, - headers: respHeaders - }); + if (type2 === "custom" || type2 === "function") { + const name2 = obj.name ?? obj.function?.name; + if (typeof name2 !== "string" || name2.length === 0) return void 0; + if (!convertible.has(name2)) return void 0; + return { type: "function", function: { name: name2 } }; } - printRow(reqId, format, meta, upstream.status, started, headersAt, openaiResp.usage?.completion_tokens ?? 0, 0, 0); - return new Response(payload, { - status: upstream.status, - headers: respHeaders - }); + return void 0; } -async function translatedOpenAIToAnthropicBatchResponse(clientReq, upstream, reqId, format, meta, started, headersAt) { - const raw = await upstream.text(); - let parsedOpenAI; - try { - parsedOpenAI = JSON.parse(raw); - } catch (err) { - printRow(reqId, format, meta, 502, started, headersAt, 0, 0, 0); - return errorResponse(502, "translation_failed", `upstream returned non-JSON body: ${err.message}`); +var CUSTOM_TOOL_SCHEMA, TOOL_SEARCH_PROXY_SCHEMA, ToolTranslationError; +var init_responses_to_chat = __esm({ + "src/translator/responses-to-chat.ts"() { + "use strict"; + init_responses_types(); + CUSTOM_TOOL_SCHEMA = { + type: "object", + properties: { input: { type: "string" } }, + required: ["input"], + additionalProperties: false + }; + TOOL_SEARCH_PROXY_SCHEMA = { + type: "object", + properties: { query: { type: "string" }, limit: { type: "number" } }, + additionalProperties: false + }; + ToolTranslationError = class extends Error { + constructor(message) { + super(message); + this.name = "ToolTranslationError"; + } + }; } - const anthropicResp = translateResponseOpenAIToAnthropic(parsedOpenAI); - const json = JSON.stringify(anthropicResp); - const payload = new TextEncoder().encode(json); - const respHeaders = new Headers(); - respHeaders.set("content-type", "application/json"); - for (const h of forwardedUpstreamHeaders()) { - const v = upstream.headers.get(h); - if (v) respHeaders.set(h, v); +}); + +// src/translator/chat-to-responses.ts +function chatCompletionsToResponses(resp, model, opts = {}) { + const id2 = opts.responseId ?? generateResponsesId(); + const choice = resp.choices?.[0]; + const output = []; + if (choice) { + const items2 = chatChoiceToOutputItems(choice, opts.meta); + output.push(...items2); } - if (clientAcceptsGzip(clientReq)) { - respHeaders.set("content-encoding", "gzip"); - printRow(reqId, format, meta, upstream.status, started, headersAt, anthropicResp.usage.output_tokens, 0, 0); - return new Response((0, import_node_zlib.gzipSync)(payload), { - status: upstream.status, - headers: respHeaders - }); + if (output.length === 0) { + output.push(emptyMessageOutput()); } - printRow(reqId, format, meta, upstream.status, started, headersAt, anthropicResp.usage.output_tokens, 0, 0); - return new Response(payload, { - status: upstream.status, - headers: respHeaders - }); + const status = choice?.finish_reason === "length" ? "incomplete" : "completed"; + const incomplete = status === "incomplete" ? { reason: "max_output_tokens" } : void 0; + return { + id: id2, + object: "response", + created_at: Date.now(), + model: model || resp.model || "", + status, + output, + ...incomplete ? { incomplete_details: incomplete } : {}, + ...resp.usage ? { usage: chatUsageToResponsesUsage(resp.usage) } : {}, + ...opts.instructions ? { instructions: opts.instructions } : {}, + ...opts.previousResponseId ? { previous_response_id: opts.previousResponseId } : {} + }; } -function translateAnthropicBody(body2) { - if (body2 === void 0 || body2.length === 0) { - return errorResponse(400, "translation_failed", "Anthropic request body is empty; cannot translate."); +function chatChoiceToOutputItems(choice, meta) { + const items2 = []; + const msg = choice.message; + if (msg?.reasoning_content) { + items2.push({ + type: "reasoning", + id: generateItemId(), + summary: [{ type: "summary_text", text: msg.reasoning_content }], + status: "completed" + }); } - let parsed; - try { - parsed = JSON.parse(body2); - } catch (err) { - return errorResponse(400, "translation_failed", `Anthropic request body is not valid JSON: ${err.message}`); + const text = extractAssistantText(msg); + const toolCalls = msg?.tool_calls ?? []; + const customNames = meta?.customToolNames ?? /* @__PURE__ */ new Set(); + const nsMap = meta?.namespaceMap ?? /* @__PURE__ */ new Map(); + const hasToolSearch = meta?.hasToolSearch === true; + if (text.length > 0 || toolCalls.length === 0) { + items2.push({ + type: "message", + id: generateItemId(), + role: "assistant", + content: [{ type: "output_text", text }], + status: "completed" + }); + } + for (const tc of toolCalls) { + const flatName = tc.function.name; + const args = tc.function.arguments && tc.function.arguments.trim().length > 0 ? tc.function.arguments : "{}"; + if (customNames.has(flatName)) { + const inputStr = extractCustomToolInput(args); + items2.push({ + type: "custom_tool_call", + id: generateItemId(), + call_id: tc.id || generateCallId(), + name: flatName, + input: inputStr, + status: "completed" + }); + continue; + } + if (flatName === "tool_search" && hasToolSearch) { + let argsObj = {}; + try { + argsObj = JSON.parse(args); + } catch { + argsObj = {}; + } + items2.push({ + type: "tool_search_call", + id: generateItemId(), + call_id: tc.id || generateCallId(), + arguments: argsObj, + execution: "client", + status: "completed" + }); + continue; + } + const ns = nsMap.get(flatName); + if (ns) { + items2.push({ + type: "function_call", + id: generateItemId(), + call_id: tc.id || generateCallId(), + name: ns.name, + namespace: ns.namespace, + arguments: args, + status: "completed" + }); + continue; + } + items2.push({ + type: "function_call", + id: generateItemId(), + call_id: tc.id || generateCallId(), + name: flatName, + arguments: args, + status: "completed" + }); + } + return items2; +} +function emptyMessageOutput() { + return { + type: "message", + id: generateItemId(), + role: "assistant", + content: [{ type: "output_text", text: "" }], + status: "completed" + }; +} +function extractAssistantText(msg) { + if (!msg) return ""; + if (typeof msg.content === "string") return msg.content; + if (Array.isArray(msg.content)) { + return msg.content.filter((c) => c.type === "text" && typeof c.text === "string").map((c) => c.text).join("\n"); } + return ""; +} +function extractCustomToolInput(rawArgs) { try { - const translated = translateRequestAnthropicToOpenAI(parsed); - return JSON.stringify(translated); - } catch (err) { - return errorResponse(400, "translation_failed", `Anthropic\u2192OpenAI translation failed: ${err.message}`); + const obj = JSON.parse(rawArgs); + if (typeof obj.input === "string") return obj.input; + } catch { } + return rawArgs; } -function isAnthropicMessagesResponse(value2) { - if (typeof value2 !== "object" || value2 === null) return false; - const candidate = value2; - return candidate.type === "message" && candidate.role === "assistant" && Array.isArray(candidate.content); +function chatUsageToResponsesUsage(u) { + return { + input_tokens: u.prompt_tokens ?? 0, + output_tokens: u.completion_tokens ?? 0, + total_tokens: u.total_tokens ?? (u.prompt_tokens ?? 0) + (u.completion_tokens ?? 0), + ...u.prompt_tokens_details?.cached_tokens ? { input_tokens_details: { cached_tokens: u.prompt_tokens_details.cached_tokens } } : {}, + ...u.output_tokens_details?.reasoning_tokens ? { output_tokens_details: { reasoning_tokens: u.output_tokens_details.reasoning_tokens } } : {} + }; } -function forwardedUpstreamHeaders() { - return [ - "x-request-id", - "anthropic-ratelimit-requests-limit", - "anthropic-ratelimit-requests-remaining", - "anthropic-ratelimit-requests-reset", - "anthropic-ratelimit-tokens-limit", - "anthropic-ratelimit-tokens-remaining", - "anthropic-ratelimit-tokens-reset" - ]; +function newResponsesStreamState(model, opts = {}) { + return { + responseId: opts.responseId ?? generateResponsesId(), + model, + createdAt: Date.now(), + sequenceNumber: 0, + createdSent: false, + completedSent: false, + nextOutputIndex: 0, + reasoningItemId: void 0, + reasoningIndex: -1, + reasoningOpen: false, + reasoningDone: false, + reasoningText: "", + messageItemId: void 0, + messageIndex: -1, + textPartOpen: false, + text: "", + toolCalls: /* @__PURE__ */ new Map(), + finishReason: void 0, + usage: void 0, + meta: opts.meta + }; } -function translatedSseResponse(body2) { - return new Response(body2, { - status: 200, - headers: { - "content-type": "text/event-stream", - "cache-control": "no-cache" +function chatChunkToResponsesEvents(chunk, state2) { + const events = []; + events.push(...ensureCreated(state2)); + if (chunk.model && !state2.model) state2.model = chunk.model; + if (chunk.usage) state2.usage = chatUsageToResponsesUsage(chunk.usage); + for (const choice of chunk.choices ?? []) { + events.push(...handleChoice(choice, state2)); + } + return events; +} +function handleChoice(choice, state2) { + const events = []; + const delta = choice.delta ?? {}; + if (delta.reasoning_content && delta.reasoning_content.length > 0) { + events.push(...ensureReasoningItem(state2)); + state2.reasoningText += delta.reasoning_content; + events.push(seq(state2, { + type: "response.reasoning_summary_text.delta", + output_index: state2.reasoningIndex, + summary_index: 0, + delta: delta.reasoning_content, + item_id: state2.reasoningItemId + })); + } + if (typeof delta.content === "string" && delta.content.length > 0) { + events.push(...closeReasoningItem(state2)); + events.push(...ensureMessageItem(state2)); + events.push(...ensureTextPart(state2)); + state2.text += delta.content; + events.push(seq(state2, { + type: "response.output_text.delta", + output_index: state2.messageIndex, + content_index: 0, + delta: delta.content, + item_id: state2.messageItemId + })); + } + for (const tc of delta.tool_calls ?? []) { + const idx = tc.index ?? 0; + let entry = state2.toolCalls.get(idx); + if (!entry) { + events.push(...closeReasoningItem(state2)); + const itemId = generateItemId(); + const outputIndex = allocIndex(state2); + const callId = tc.id || generateCallId(); + const name2 = tc.function?.name ?? ""; + entry = { id: callId, name: name2, args: "", itemId, outputIndex }; + state2.toolCalls.set(idx, entry); + const initialArgs = tc.function?.arguments ?? ""; + entry.args += initialArgs; + events.push(seq(state2, { + type: "response.output_item.added", + output_index: outputIndex, + item: toolCallAddedItem(entry, state2.meta) + })); + if (initialArgs.length > 0) { + events.push(seq(state2, toolArgsDeltaEvent(entry, initialArgs, state2))); + } + } else { + if (tc.id) entry.id = tc.id; + if (tc.function?.name) entry.name = tc.function.name; + const argDelta = tc.function?.arguments ?? ""; + if (argDelta.length > 0) { + entry.args += argDelta; + events.push(seq(state2, toolArgsDeltaEvent(entry, argDelta, state2))); + } } - }); + } + if (choice.finish_reason) { + state2.finishReason = choice.finish_reason; + } + return events; } -function peekBody(body2) { - if (!body2) return { model: "-", stream: false }; - try { - const p = JSON.parse(body2); +function toolCallAddedItem(entry, meta) { + const customNames = meta?.customToolNames ?? /* @__PURE__ */ new Set(); + const nsMap = meta?.namespaceMap ?? /* @__PURE__ */ new Map(); + const hasToolSearch = meta?.hasToolSearch === true; + if (customNames.has(entry.name)) { return { - model: typeof p.model === "string" ? p.model : "-", - stream: p.stream === true + type: "custom_tool_call", + id: entry.itemId, + call_id: entry.id, + name: entry.name, + input: "", + // final value emitted at output_item.done + status: "in_progress" }; - } catch { - return { model: "-", stream: false }; } + if (entry.name === "tool_search" && hasToolSearch) { + return { + type: "tool_search_call", + id: entry.itemId, + call_id: entry.id, + execution: "client", + status: "in_progress" + }; + } + const ns = nsMap.get(entry.name); + if (ns) { + return { + type: "function_call", + id: entry.itemId, + call_id: entry.id, + name: ns.name, + namespace: ns.namespace, + status: "in_progress" + }; + } + return { + type: "function_call", + id: entry.itemId, + call_id: entry.id, + name: entry.name, + status: "in_progress" + }; } -var reqCounter = 0; -var headerPrinted = false; -function localTime(ms) { - const d = new Date(ms); - const hh = String(d.getHours()).padStart(2, "0"); - const mm = String(d.getMinutes()).padStart(2, "0"); - const ss = String(d.getSeconds()).padStart(2, "0"); - return `${hh}:${mm}:${ss}`; -} -function nextReqId() { - return `#${String(++reqCounter).padStart(3, "0")}`; -} -var DEBUG_BODY_PREVIEW = 200; -var SENSITIVE_HEADERS2 = /* @__PURE__ */ new Set(["authorization", "x-api-key", "cookie", "set-cookie", "proxy-authorization"]); -function debugLine(reqId, msg) { - console.log(`${reqId} debug: ${msg}`); +function toolArgsDeltaEvent(entry, delta, state2) { + const customNames = state2.meta?.customToolNames ?? /* @__PURE__ */ new Set(); + const isCustom = customNames.has(entry.name); + const base = { + output_index: entry.outputIndex, + delta, + item_id: entry.itemId, + call_id: entry.id, + name: entry.name + }; + return seq(state2, isCustom ? { type: "response.custom_tool_call_input.delta", ...base } : { type: "response.function_call_arguments.delta", ...base }); } -function debugError(reqId, kind2, msg) { - console.log(`${reqId} debug: ERROR ${kind2}: ${msg}`); +function finalizeResponsesStream(state2) { + if (state2.completedSent) return []; + const events = []; + events.push(...ensureCreated(state2)); + events.push(...closeReasoningItem(state2)); + events.push(...synthesizeReasoningFallbackMessage(state2)); + events.push(...closeMessageItem(state2)); + events.push(...closeToolItems(state2)); + const status = state2.finishReason === "length" ? "incomplete" : "completed"; + const incomplete = status === "incomplete" ? { reason: "max_output_tokens" } : void 0; + state2.completedSent = true; + events.push(seq(state2, { + type: status === "incomplete" ? "response.incomplete" : "response.completed", + response: { + id: state2.responseId, + object: "response", + created_at: state2.createdAt, + model: state2.model, + status, + output: buildFinalOutput(state2), + ...incomplete ? { incomplete_details: incomplete } : {}, + ...state2.usage ? { usage: state2.usage } : {} + } + })); + return events; } -function redactHeaderVal(key, val) { - const k = key.toLowerCase(); - if (!SENSITIVE_HEADERS2.has(k)) return val; - if (k === "authorization") { - const sp = val.indexOf(" "); - return sp > 0 ? `${val.slice(0, sp)} ` : ""; - } - if (val.length <= 10) return ""; - return `${val.slice(0, 6)}...${val.slice(-4)}`; +function ensureCreated(state2) { + if (state2.createdSent) return []; + state2.createdSent = true; + return [seq(state2, { + type: "response.created", + response: { + id: state2.responseId, + object: "response", + created_at: state2.createdAt, + model: state2.model, + status: "in_progress", + output: [] + } + })]; } -function formatHeaderPairs(headers2) { - const pairs = []; - for (const [k, v] of headers2.entries()) { - pairs.push(`${k}=${redactHeaderVal(k, v)}`); - } - return pairs.join(" "); +function ensureReasoningItem(state2) { + if (state2.reasoningOpen || state2.reasoningDone) return []; + state2.reasoningOpen = true; + state2.reasoningItemId = generateItemId(); + state2.reasoningIndex = allocIndex(state2); + return [ + seq(state2, { + type: "response.output_item.added", + output_index: state2.reasoningIndex, + item: { type: "reasoning", id: state2.reasoningItemId, status: "in_progress" } + }), + seq(state2, { + type: "response.reasoning_summary_part.added", + output_index: state2.reasoningIndex, + summary_index: 0, + item_id: state2.reasoningItemId, + part: { type: "summary_text" } + }) + ]; } -function formatResponseHeaders(headers2) { - const interesting = [ - "content-type", - "content-encoding", - "content-length", - "x-request-id", - "anthropic-ratelimit-requests-remaining", - "anthropic-ratelimit-tokens-remaining" +function closeReasoningItem(state2) { + if (!state2.reasoningOpen) return []; + state2.reasoningOpen = false; + state2.reasoningDone = true; + const text = state2.reasoningText; + return [ + seq(state2, { + type: "response.reasoning_summary_text.done", + output_index: state2.reasoningIndex, + summary_index: 0, + text, + item_id: state2.reasoningItemId + }), + seq(state2, { + type: "response.reasoning_summary_part.done", + output_index: state2.reasoningIndex, + summary_index: 0, + item_id: state2.reasoningItemId, + part: { type: "summary_text", text } + }), + seq(state2, { + type: "response.output_item.done", + output_index: state2.reasoningIndex, + item: { + type: "reasoning", + id: state2.reasoningItemId, + status: "completed", + summary: [{ type: "summary_text", text }] + } + }) ]; - const pairs = []; - for (const h of interesting) { - const v = headers2.get(h); - if (v) pairs.push(`${h}=${v}`); +} +function synthesizeReasoningFallbackMessage(state2) { + if (state2.messageItemId || state2.text.length > 0 || state2.reasoningText.length === 0 || state2.toolCalls.size > 0) { + return []; } - return pairs.length > 0 ? pairs.join(" ") : "(no notable headers)"; + const text = state2.reasoningText; + if (text.trim().length === 0) return []; + const events = []; + events.push(...ensureMessageItem(state2)); + events.push(...ensureTextPart(state2)); + state2.text = text; + events.push(seq(state2, { + type: "response.output_text.delta", + output_index: state2.messageIndex, + content_index: 0, + delta: text, + item_id: state2.messageItemId + })); + return events; } -function previewBody(body2) { - const flat = body2.replace(/\s+/g, " ").trim(); - if (flat.length <= DEBUG_BODY_PREVIEW) return flat; - return `${flat.slice(0, DEBUG_BODY_PREVIEW)}\u2026(${flat.length} bytes total)`; +function ensureMessageItem(state2) { + if (state2.messageItemId) return []; + state2.messageItemId = generateItemId(); + state2.messageIndex = allocIndex(state2); + return [seq(state2, { + type: "response.output_item.added", + output_index: state2.messageIndex, + item: { + type: "message", + id: state2.messageItemId, + role: "assistant", + status: "in_progress", + content: [{ type: "output_text" }] + } + })]; } -var COMPACT_LOG = process.env.ZCODE_LOG_FORMAT === "compact"; -function printHeader() { - if (headerPrinted) return; - headerPrinted = true; - if (COMPACT_LOG) return; - console.log( - "| # | Time | Fmt | Model | Mode | Stat | TTFB | Tok | tok/s | Total |" - ); - console.log( - "|------|------------|-----|-------------|--------|------|---------|-------|--------|---------|" - ); +function ensureTextPart(state2) { + if (state2.textPartOpen) return []; + state2.textPartOpen = true; + return [seq(state2, { + type: "response.content_part.added", + output_index: state2.messageIndex, + content_index: 0, + item_id: state2.messageItemId, + part: { type: "output_text", text: "" } + })]; } -function printRow(reqId, format, meta, status, started, headersAt, tokens, avgTps, streamEndAt) { - printHeader(); - const tag = format === "anthropic" ? "ANT" : "OAI"; - const mode2 = meta.stream ? "stream" : "batch"; - if (COMPACT_LOG) { - const ttfbMs = headersAt - started; - const totalMs = streamEndAt > started ? streamEndAt - started : ttfbMs; - const ttfbStr = fmtMs(ttfbMs); - const tokStr = tokens > 0 ? `${tokens}tok` : ""; - const tpsStr = avgTps > 0 ? `${avgTps.toFixed(0)}t/s` : ""; - const parts = [reqId, tag, meta.model, String(status), mode2]; - if (meta.stream && streamEndAt > started) { - parts.push(`${ttfbStr}\u2192${fmtMs(totalMs)}`); - } else { - parts.push(ttfbStr); - } - if (tokStr) parts.push(tokStr); - if (tpsStr) parts.push(tpsStr); - console.log(parts.join(" ")); - return; +function closeMessageItem(state2) { + if (!state2.messageItemId) return []; + const events = []; + if (state2.textPartOpen) { + events.push(seq(state2, { + type: "response.output_text.done", + output_index: state2.messageIndex, + content_index: 0, + text: state2.text, + item_id: state2.messageItemId + })); + events.push(seq(state2, { + type: "response.content_part.done", + output_index: state2.messageIndex, + content_index: 0, + item_id: state2.messageItemId, + part: { type: "output_text", text: state2.text } + })); } - const ts = localTime(started); - const ttfb = `${headersAt - started}ms`; - const total = streamEndAt > started ? `${streamEndAt - started}ms` : "-"; - const tok = tokens > 0 ? String(tokens) : "-"; - const tps = avgTps > 0 ? avgTps.toFixed(1) : "-"; - console.log( - `| ${reqId.padEnd(4)} | ${ts.padEnd(10)} | ${tag} | ${meta.model.padEnd(11)} | ${mode2.padEnd(6)} | ${String(status).padStart(4)} | ${ttfb.padStart(7)} | ${tok.padStart(5)} | ${tps.padStart(6)} | ${total.padStart(7)} |` - ); -} -function fmtMs(ms) { - if (ms < 1e3) return `${ms}ms`; - if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`; - return `${Math.floor(ms / 6e4)}m${Math.floor(ms % 6e4 / 1e3)}s`; + events.push(seq(state2, { + type: "response.output_item.done", + output_index: state2.messageIndex, + item: { + type: "message", + id: state2.messageItemId, + role: "assistant", + status: "completed", + content: [{ type: "output_text", text: state2.text }] + } + })); + return events; } -function observeStream(reqId, format, meta, status, requestSentAt, body2, contentEncoding) { - const compressed = contentEncoding !== null; - const dumpOn = dumpEnabled(); - let tokens = 0; - let sseBuffer = ""; - let firstChunkAt = 0; - let totalBytes = 0; - let firstBytesSample = ""; - function parseSse(text) { - for (const line of text.split("\n")) { - if (!line.startsWith("data:") || line.includes("[DONE]")) continue; - try { - const j = JSON.parse(line.slice(5).trim()); - if (j.usage?.completion_tokens) { - tokens = j.usage.completion_tokens; - continue; - } - if (j.usage?.output_tokens) { - tokens = j.usage.output_tokens; - continue; - } - const oai = j.choices?.[0]?.delta?.content; - if (typeof oai === "string" && oai.length > 0) { - tokens++; - continue; - } - if (j.type === "content_block_delta" && j.delta?.type === "text_delta") { - const t = j.delta?.text; - if (typeof t === "string" && t.length > 0) tokens++; +function closeToolItems(state2) { + const events = []; + const sortedKeys = [...state2.toolCalls.keys()].sort((a, b) => a - b); + for (const idx of sortedKeys) { + const entry = state2.toolCalls.get(idx); + const customNames = state2.meta?.customToolNames ?? /* @__PURE__ */ new Set(); + const nsMap = state2.meta?.namespaceMap ?? /* @__PURE__ */ new Map(); + const hasToolSearch = state2.meta?.hasToolSearch === true; + const isCustom = customNames.has(entry.name); + const isToolSearch = entry.name === "tool_search" && hasToolSearch; + const ns = nsMap.get(entry.name); + const finalArgs = entry.args.trim().length === 0 ? "{}" : entry.args; + if (isCustom) { + const inputStr = extractCustomToolInput(finalArgs); + events.push(seq(state2, { + type: "response.custom_tool_call_input.done", + output_index: entry.outputIndex, + input: inputStr, + item_id: entry.itemId, + call_id: entry.id, + name: entry.name + })); + events.push(seq(state2, { + type: "response.output_item.done", + output_index: entry.outputIndex, + item: { + type: "custom_tool_call", + id: entry.itemId, + call_id: entry.id, + name: entry.name, + input: inputStr, + status: "completed" } + })); + } else if (isToolSearch) { + let argsObj = {}; + try { + argsObj = JSON.parse(finalArgs); } catch { + argsObj = {}; } - } - } - (async () => { - const reader = body2.getReader(); - const decoder = new TextDecoder(); - try { - while (true) { - const { done, value: value2 } = await reader.read(); - if (done) break; - if (firstChunkAt === 0) firstChunkAt = Date.now(); - if (dumpOn && value2) { - totalBytes += value2.byteLength; - if (firstBytesSample.length < 4096) { - firstBytesSample += decoder.decode(value2.slice(0, 4096 - firstBytesSample.length), { stream: true }); - } + events.push(seq(state2, { + type: "response.function_call_arguments.done", + output_index: entry.outputIndex, + arguments: finalArgs, + item_id: entry.itemId, + call_id: entry.id, + name: entry.name + })); + events.push(seq(state2, { + type: "response.output_item.done", + output_index: entry.outputIndex, + item: { + type: "tool_search_call", + id: entry.itemId, + call_id: entry.id, + arguments: argsObj, + execution: "client", + status: "completed" } - if (!compressed) { - sseBuffer += decoder.decode(value2, { stream: true }); - const idx = sseBuffer.lastIndexOf("\n"); - if (idx >= 0) { - parseSse(sseBuffer.slice(0, idx)); - sseBuffer = sseBuffer.slice(idx + 1); - } + })); + } else { + events.push(seq(state2, { + type: "response.function_call_arguments.done", + output_index: entry.outputIndex, + arguments: finalArgs, + item_id: entry.itemId, + call_id: entry.id, + name: entry.name + })); + events.push(seq(state2, { + type: "response.output_item.done", + output_index: entry.outputIndex, + item: ns ? { + type: "function_call", + id: entry.itemId, + call_id: entry.id, + name: ns.name, + namespace: ns.namespace, + arguments: finalArgs, + status: "completed" + } : { + type: "function_call", + id: entry.itemId, + call_id: entry.id, + name: entry.name, + arguments: finalArgs, + status: "completed" } + })); + } + } + return events; +} +function buildFinalOutput(state2) { + const out = []; + if (state2.reasoningDone && state2.reasoningText.length > 0) { + out.push({ + type: "reasoning", + id: state2.reasoningItemId, + summary: [{ type: "summary_text", text: state2.reasoningText }], + status: "completed" + }); + } + if (state2.messageItemId || state2.toolCalls.size === 0) { + out.push({ + type: "message", + id: state2.messageItemId ?? generateItemId(), + role: "assistant", + content: [{ type: "output_text", text: state2.text }], + status: "completed" + }); + } + const sortedKeys = [...state2.toolCalls.keys()].sort((a, b) => a - b); + for (const idx of sortedKeys) { + const entry = state2.toolCalls.get(idx); + const customNames = state2.meta?.customToolNames ?? /* @__PURE__ */ new Set(); + const nsMap = state2.meta?.namespaceMap ?? /* @__PURE__ */ new Map(); + const hasToolSearch = state2.meta?.hasToolSearch === true; + const isCustom = customNames.has(entry.name); + const isToolSearch = entry.name === "tool_search" && hasToolSearch; + const ns = nsMap.get(entry.name); + const finalArgs = entry.args.trim().length === 0 ? "{}" : entry.args; + if (isCustom) { + out.push({ + type: "custom_tool_call", + id: entry.itemId, + call_id: entry.id, + name: entry.name, + input: extractCustomToolInput(finalArgs), + status: "completed" + }); + } else if (isToolSearch) { + let argsObj = {}; + try { + argsObj = JSON.parse(finalArgs); + } catch { + argsObj = {}; } - if (!compressed && sseBuffer) parseSse(sseBuffer); - } catch { - } - const endAt = Date.now(); - const ttfbMs = (firstChunkAt > 0 ? firstChunkAt : endAt) - requestSentAt; - const totalMs = endAt - requestSentAt; - const avgTps = tokens > 0 && totalMs > 0 ? tokens / (totalMs / 1e3) : 0; - printRow(reqId, format, meta, status, requestSentAt, requestSentAt + ttfbMs, tokens, avgTps, endAt); - if (dumpOn) { - dumpPhase(reqId, "upstream_stream_summary", { - status, - contentEncoding, - compressed, - totalBytes, - tokensObserved: tokens, - ttfbMs, - totalMs, - firstBytesSample: firstBytesSample.length > 0 ? firstBytesSample.slice(0, 4096) : "(empty stream)" + out.push({ + type: "tool_search_call", + id: entry.itemId, + call_id: entry.id, + arguments: argsObj, + execution: "client", + status: "completed" + }); + } else if (ns) { + out.push({ + type: "function_call", + id: entry.itemId, + call_id: entry.id, + name: ns.name, + namespace: ns.namespace, + arguments: finalArgs, + status: "completed" + }); + } else { + out.push({ + type: "function_call", + id: entry.itemId, + call_id: entry.id, + name: entry.name, + arguments: finalArgs, + status: "completed" }); } - })().catch(() => { - }); -} - -// src/server/routes-openai.ts -async function handleChatCompletions(req, opts) { - return proxyRequest(req, "openai", opts); + } + return out; } -function handleListModels() { - const list = { - object: "list", - data: MODELS.map((m) => ({ - id: m.id, - object: "model", - owned_by: "zcode-proxy" - })) - }; - return new Response(JSON.stringify(list), { - status: 200, - headers: { "content-type": "application/json" } - }); +function allocIndex(state2) { + return state2.nextOutputIndex++; } - -// src/server/routes-anthropic.ts -async function handleMessages(req, opts) { - return proxyRequest(req, "anthropic", opts); +function seq(state2, evt) { + const n = state2.sequenceNumber++; + return { ...evt, sequence_number: n }; } +function responsesEventToSse(evt) { + return `event: ${evt.type} +data: ${JSON.stringify(evt)} -// src/translator/responses-types.ts -function generateResponsesId(prefix2 = "resp_") { - const bytes = new Uint8Array(16); - crypto.getRandomValues(bytes); - const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(""); - return `${prefix2}${hex}`; -} -function generateItemId() { - return generateResponsesId("item_"); -} -function generateCallId() { - return generateResponsesId("call_"); -} -function isHostedTool(t) { - return t.type === "file_search" || t.type === "code_interpreter" || t.type === "computer_use_preview" || t.type === "image_generation" || t.type === "mcp"; -} -function isWebSearchTool(t) { - return t.type === "web_search" || t.type === "web_search_preview"; +`; } - -// src/translator/responses-to-chat.ts -var CUSTOM_TOOL_SCHEMA = { - type: "object", - properties: { input: { type: "string" } }, - required: ["input"], - additionalProperties: false -}; -var TOOL_SEARCH_PROXY_SCHEMA = { - type: "object", - properties: { query: { type: "string" }, limit: { type: "number" } }, - additionalProperties: false -}; -function responsesToChatCompletions(req) { - const messages = []; - if (typeof req.instructions === "string" && req.instructions.trim().length > 0) { - messages.push({ role: "system", content: req.instructions }); +var init_chat_to_responses = __esm({ + "src/translator/chat-to-responses.ts"() { + "use strict"; + init_responses_types(); } - const inputItems = normaliseInput(req.input); - const built = buildMessagesFromItems(inputItems); - messages.push(...built); - const customToolNames = /* @__PURE__ */ new Set(); - const namespaceMap = /* @__PURE__ */ new Map(); - const convertibleToolNames = /* @__PURE__ */ new Set(); - let hasWebSearch = false; - let hasToolSearch = false; - const tools = []; - if (Array.isArray(req.tools)) { - for (const tool of req.tools) { - collectTools(tool, "", tools, customToolNames, namespaceMap, convertibleToolNames, (ref) => { - if (ref === "web_search") hasWebSearch = true; - if (ref === "tool_search") hasToolSearch = true; - }); +}); + +// src/proxy/responses-handler.ts +async function handleResponses(clientReq, opts) { + const fetchImpl = opts.fetchImpl ?? fetch; + const debug = opts.debug === true; + const start2 = Date.now(); + let rawBody; + try { + rawBody = await readBody(clientReq) ?? ""; + } catch (err) { + if (err instanceof InflatedBodyTooLargeError) { + return errorResponse(413, "request_too_large", err.message); } + return errorResponse(400, "invalid_request", `could not read request body: ${err.message}`); } - const chatRequest = { - model: req.model, - messages, - ...req.max_output_tokens !== void 0 ? { max_tokens: req.max_output_tokens } : {}, - ...req.temperature !== void 0 ? { temperature: req.temperature } : {}, - ...req.top_p !== void 0 ? { top_p: req.top_p } : {}, - ...req.stream !== void 0 ? { stream: req.stream } : {}, - ...req.user !== void 0 ? { user: req.user } : {} - }; - if (tools.length > 0) chatRequest.tools = tools; - if (tools.length > 0 && req.tool_choice !== void 0) { - const mapped = mapToolChoice(req.tool_choice, convertibleToolNames, hasToolSearch); - if (mapped !== void 0) chatRequest.tool_choice = mapped; + let req; + try { + req = JSON.parse(rawBody); + } catch (err) { + return errorResponse(400, "invalid_request", `request body is not valid JSON: ${err.message}`); } - if (tools.length > 0 && req.parallel_tool_calls !== void 0) { - chatRequest.parallel_tool_calls = req.parallel_tool_calls; + if (typeof req.input !== "string" && !Array.isArray(req.input)) { + return errorResponse(400, "invalid_request", "`input` must be a string or an array"); } - if (req.reasoning?.effort) { - chatRequest.reasoning_effort = req.reasoning.effort; + if (typeof req.model !== "string" || req.model.length === 0) { + return errorResponse(400, "invalid_request", "`model` is required"); } - return { - chatRequest, - customToolNames, - namespaceMap, - hasWebSearch, - hasToolSearch, - convertibleToolNames + const stream = req.stream === true; + let historyItems = []; + let prevId; + if (typeof req.previous_response_id === "string" && req.previous_response_id.length > 0) { + if (!opts.responseStore) { + return errorResponse(404, "response_store_disabled", "`previous_response_id` was supplied but the response store is not configured"); + } + const prev = opts.responseStore.get(req.previous_response_id); + if (!prev) { + return errorResponse(404, "response_not_found", `previous_response_id ${req.previous_response_id} not found (response store is in-memory; entries are lost on restart and after the TTL)`); + } + prevId = req.previous_response_id; + historyItems = [...prev.input, ...outputItemsAsInputItems(prev.output)]; + } + const input = typeof req.input === "string" ? [...historyItems, { type: "message", role: "user", content: req.input }] : [...historyItems, ...req.input]; + const reqWithHistory = { + ...req, + input }; -} -function normaliseInput(input) { - if (typeof input === "string") { - return [{ type: "message", role: "user", content: input }]; + let translated; + try { + translated = responsesToChatCompletions(reqWithHistory); + } catch (err) { + if (err instanceof ToolTranslationError) { + return errorResponse(400, "tool_translation_error", err.message); + } + throw err; } - if (!Array.isArray(input)) return []; - return input.filter((x3) => x3 !== null && typeof x3 === "object"); -} -function buildMessagesFromItems(items2) { - const out = []; - let pendingReasoning = ""; - for (const item of items2) { - const type2 = item.type ?? ""; - switch (type2) { - case "message": { - const role = item.role; - const chatRole = role === "assistant" ? "assistant" : role === "developer" || role === "system" ? "system" : "user"; - const content2 = contentPartsToChat(item.content, chatRole); - out.push({ role: chatRole, content: content2 }); - if (chatRole !== "assistant") pendingReasoning = ""; - continue; - } - case "reasoning": { - const text = extractReasoningText(item); - if (text) pendingReasoning = text; - continue; - } - case "function_call": { - const fc = item; - const args = (fc.arguments ?? "").trim().length === 0 ? "{}" : fc.arguments; - const toolCall = { - id: fc.call_id, - type: "function", - function: { name: fc.name, arguments: args } - }; - mergeToolCallIntoAssistant(out, toolCall, pendingReasoning); - pendingReasoning = ""; - continue; - } - case "custom_tool_call": { - const ct = item; - const argObj = JSON.stringify({ input: ct.input ?? "" }); - const toolCall = { - id: ct.call_id, - type: "function", - function: { name: ct.name, arguments: argObj } - }; - mergeToolCallIntoAssistant(out, toolCall, pendingReasoning); - pendingReasoning = ""; - continue; - } - case "function_call_output": - case "custom_tool_call_output": { - const fco = item; - out.push({ - role: "tool", - tool_call_id: fco.call_id, - content: fco.output ?? "" + const { chatRequest, customToolNames, namespaceMap, hasToolSearch } = translated; + let cred; + try { + cred = await opts.auth.getCredential(); + } catch (err) { + return errorResponse(503, "credential_unavailable", err.message); + } + const providerDef = resolveProviderDef(opts.config); + const startPlan = opts.config.plan === "start-plan"; + const upstreamFormat = "anthropic"; + let upstreamRequestBody; + { + let anthropicReq; + try { + anthropicReq = translateRequestOpenAIToAnthropic(chatRequest); + } catch (err) { + return errorResponse(400, "translation_failed", `Chat\u2192Anthropic translation failed: ${err.message}`); + } + upstreamRequestBody = transformRequestBody(JSON.stringify(anthropicReq), { + format: "anthropic", + userId: cred.userId, + startPlan + }) ?? JSON.stringify(anthropicReq); + } + const transformedBody = upstreamRequestBody; + const upstreamHeaders = buildUpstreamHeaderPairs(clientReq, upstreamFormat, cred, opts.config.identity, opts.config.plan, void 0, void 0); + const upstreamReq = buildUpstreamRequest(clientReq, upstreamFormat, providerDef, cred, transformedBody, opts.config.identity, opts.config.plan, void 0, void 0); + if (debug) console.log(`[responses] \u2192 POST ${upstreamReq.url}`); + let upstreamResp; + try { + const routing = opts.endpointRouting !== void 0 ? opts.endpointRouting : getDefaultEndpointRouting(opts.config); + const routed = routing ? await routing.resolve(upstreamReq.url, credentialString(cred)) : null; + const sendUrl = routed?.routed ? routed.url : upstreamReq.url; + if (debug && routed?.routed) console.log(`[responses] endpoint routing: ${upstreamReq.url} -> ${sendUrl}`); + const signer = opts.clientSigning !== void 0 ? opts.clientSigning : getDefaultClientSigning(opts.config); + upstreamResp = await sendWithClientSigning(signer, { + url: upstreamReq.url, + headerPairs: upstreamHeaders, + credential: credentialString(cred), + appVersion: opts.config.identity.appVersion, + debug: debug ? (message) => console.log(`[responses] ${message}`) : void 0, + send: (finalPairs) => { + const req2 = new Request(sendUrl, { + method: "POST", + headers: Object.fromEntries(finalPairs), + body: transformedBody ?? void 0 }); - pendingReasoning = ""; - continue; + return fetchImpl(req2, { method: "POST", headers: Object.fromEntries(finalPairs), body: transformedBody ?? void 0, signal: clientReq.signal }); } - case "tool_search_call": { - const tsc = item; - const argStr = typeof tsc.arguments === "string" ? tsc.arguments : JSON.stringify(tsc.arguments ?? {}); - const toolCall = { - id: tsc.call_id ?? "", - type: "function", - function: { name: "tool_search", arguments: argStr } - }; - mergeToolCallIntoAssistant(out, toolCall, pendingReasoning); - pendingReasoning = ""; - continue; + }); + } catch (err) { + return errorResponse(502, "upstream_unreachable", err.message); + } + if (!upstreamResp.ok) { + const errText = await upstreamResp.text().catch(() => ""); + return errorResponse(upstreamResp.status, "upstream_error", errText.slice(0, 500) || `upstream returned ${upstreamResp.status}`); + } + if (upstreamFormat === "anthropic") { + if (stream) { + if (!upstreamResp.body) { + return errorResponse(502, "translation_failed", "upstream returned no body for stream"); } - case "tool_search_output": { - const tso = item; - out.push({ - role: "tool", - tool_call_id: tso.call_id ?? "", - content: typeof tso.output === "string" ? tso.output : JSON.stringify(tso.output ?? {}) - }); - pendingReasoning = ""; - continue; + upstreamResp = new Response(anthropicSseToOpenaiSse(upstreamResp.body, req.model), { + status: upstreamResp.status, + headers: { "content-type": "text/event-stream" } + }); + } else { + const rawAnthropic = await upstreamResp.text(); + let parsedAnthropic; + try { + parsedAnthropic = JSON.parse(rawAnthropic); + } catch (err) { + return errorResponse(502, "translation_failed", `upstream returned non-JSON body: ${err.message}`); } - case "additional_tools": - continue; - default: - if (type2 !== "") pendingReasoning = ""; - continue; + const openaiResp = translateResponseAnthropicToOpenAI(parsedAnthropic, req.model); + upstreamResp = new Response(JSON.stringify(openaiResp), { + status: upstreamResp.status, + headers: { "content-type": "application/json" } + }); } } - return out; + const responseId = generateResponsesId(); + const meta = { customToolNames, namespaceMap, hasToolSearch }; + if (stream) { + return streamResponse(upstreamResp, { responseId, model: req.model, meta, request: req, input, options: opts }); + } + const rawChatResp = await upstreamResp.text(); + let chatRespJson; + try { + chatRespJson = JSON.parse(rawChatResp); + } catch (err) { + return errorResponse(502, "translation_failed", `upstream returned non-JSON body: ${err.message}`); + } + const responsesResp = chatCompletionsToResponses(chatRespJson, req.model, { + responseId, + meta, + ...typeof req.instructions === "string" ? { instructions: req.instructions } : {}, + ...prevId ? { previousResponseId: prevId } : {} + }); + if (req.store !== false && opts.responseStore) { + const stored = buildStoredResponse(responsesResp, input, req.instructions); + opts.responseStore.set(stored); + } + if (debug) console.log(`[responses] \u2190 ${responsesResp.status} (${Date.now() - start2}ms)`); + return new Response(JSON.stringify(responsesResp), { + status: 200, + headers: { "content-type": "application/json" } + }); } -function mergeToolCallIntoAssistant(out, toolCall, reasoning) { - const last = out[out.length - 1]; - if (last && last.role === "assistant" && Array.isArray(last.tool_calls)) { - last.tool_calls.push(toolCall); - if (!last.reasoning_content && reasoning) last.reasoning_content = reasoning; - } else { - out.push({ - role: "assistant", - content: null, - tool_calls: [toolCall], - ...reasoning ? { reasoning_content: reasoning } : {} - }); +function streamResponse(upstreamResp, context2) { + if (!upstreamResp.body) { + return errorResponse(502, "translation_failed", "upstream returned no body for stream"); + } + const state2 = newResponsesStreamState(context2.model, { meta: context2.meta, responseId: context2.responseId }); + const stream = new ReadableStream({ + async start(controller) { + const encoder2 = new TextEncoder(); + const send = (evt) => controller.enqueue(encoder2.encode(responsesEventToSse(evt))); + try { + const reader = upstreamResp.body.getReader(); + const decoder = new TextDecoder(); + let buffer2 = ""; + let errored = false; + for (; ; ) { + if (errored) break; + const { done, value: value2 } = await reader.read(); + if (done) break; + buffer2 += decoder.decode(value2, { stream: true }); + let nl; + while ((nl = buffer2.indexOf("\n\n")) >= 0) { + const frame = buffer2.slice(0, nl); + buffer2 = buffer2.slice(nl + 2); + const dataLine = extractSseData(frame); + if (!dataLine || dataLine === "[DONE]") continue; + try { + const chunk = JSON.parse(dataLine); + for (const evt of chatChunkToResponsesEvents(chunk, state2)) send(evt); + } catch (err) { + errored = true; + controller.error(err); + return; + } + } + } + const finalEvents = finalizeResponsesStream(state2); + for (const evt of finalEvents) send(evt); + const finalEvent = finalEvents.find((evt) => evt.type === "response.completed" || evt.type === "response.incomplete"); + if (finalEvent && context2.request.store !== false && context2.options.responseStore) { + context2.options.responseStore.set(buildStoredResponse(finalEvent.response, context2.input, context2.request.instructions)); + } + try { + controller.close(); + } catch { + } + } catch (err) { + try { + controller.error(err); + } catch { + } + } + }, + cancel(reason2) { + context2.options.debug === true && console.log(`[responses] stream cancelled: ${String(reason2)}`); + try { + upstreamResp.body?.cancel(); + } catch { + } + } + }); + return new Response(stream, { + status: 200, + headers: { + "content-type": "text/event-stream", + "cache-control": "no-cache", + connection: "keep-alive" + } + }); +} +function extractSseData(frame) { + for (const line of frame.split(/\r?\n/)) { + if (line.startsWith("data:")) return line.slice(5).replace(/^\s/, ""); } + return null; } -function extractReasoningText(item) { - const r2 = item; - const parts = Array.isArray(r2.summary) && r2.summary.length > 0 ? r2.summary : r2.content; - if (!Array.isArray(parts)) return ""; - return parts.map((p) => typeof p.text === "string" ? p.text : "").filter((t) => t.length > 0).join("\n"); +function resolveProviderDef(config) { + const base = getProvider(config.provider); + const endpoints = config.providers[config.provider]; + return { + ...base, + anthropicBaseURL: endpoints.anthropicBase, + openaiBaseURL: endpoints.openaiBase + }; } -function contentPartsToChat(content2, role) { - if (typeof content2 === "string") return content2; - if (!Array.isArray(content2)) return ""; - const textParts = []; - const chatParts = []; - let hasImage = false; - for (const part of content2) { - if ((part.type === "input_text" || part.type === "output_text" || part.type === "text") && typeof part.text === "string") { - if (part.text.length === 0) continue; - textParts.push(part.text); - chatParts.push({ type: "text", text: part.text }); - } else if (part.type === "input_image" || part.type === "image_url") { - const url2 = typeof part.image_url === "string" ? part.image_url : part.image_url?.url; - if (!url2) continue; - hasImage = true; - chatParts.push({ type: "image_url", image_url: { url: url2 } }); - } +function outputItemsAsInputItems(outputs) { + return outputs; +} +function buildStoredResponse(resp, input, instructions) { + return { + id: resp.id, + model: resp.model, + status: resp.status === "completed" || resp.status === "incomplete" || resp.status === "failed" ? resp.status : "completed", + input, + output: resp.output, + usage: resp.usage, + instructions, + createdAt: Date.now(), + lastAccessedAt: Date.now() + }; +} +var init_responses_handler = __esm({ + "src/proxy/responses-handler.ts"() { + "use strict"; + init_body_transformer(); + init_providers(); + init_upstream(); + init_endpoint_routing(); + init_client_signing(); + init_types(); + init_openai_to_anthropic(); + init_sse_translator(); + init_responses_to_chat(); + init_chat_to_responses(); + init_responses_types(); + init_handler(); } - if (!hasImage) return textParts.join("\n"); - if (role !== "user") return textParts.join("\n"); - return chatParts; +}); + +// src/server/routes-responses.ts +async function handleResponsesRoute(req, opts) { + return handleResponses(req, opts); } -function collectTools(tool, namespacePrefix, out, customToolNames, namespaceMap, convertibleToolNames, signal2) { - const type2 = tool.type ?? ""; - if (type2 === "function") { - const name2 = tool.name; - const flatName = namespacePrefix ? `${namespacePrefix}__${name2}` : name2; - if (convertibleToolNames.has(flatName)) { - throw new ToolTranslationError(`duplicate tool name after flattening: "${flatName}"`); - } - const t = tool; - out.push({ - type: "function", - function: { - name: flatName, - ...t.description ? { description: t.description } : {}, - ...t.parameters ? { parameters: t.parameters } : {} - } - }); - convertibleToolNames.add(flatName); - if (namespacePrefix) namespaceMap.set(flatName, { namespace: namespacePrefix, name: name2 }); - return; +var init_routes_responses = __esm({ + "src/server/routes-responses.ts"() { + "use strict"; + init_responses_handler(); } - if (type2 === "custom") { - const name2 = tool.name; - const flatName = namespacePrefix ? `${namespacePrefix}__${name2}` : name2; - if (convertibleToolNames.has(flatName)) { - throw new ToolTranslationError(`duplicate tool name after flattening: "${flatName}"`); +}); + +// src/async/openai-stream-adapter.ts +function anthropicSseToOpenaiSseWithKeepalive(upstream, model = "glm-4.6") { + const encoder2 = new TextEncoder(); + const decoder = new TextDecoder(); + const state2 = initState(model); + let doneSent = false; + let errored = false; + function emit(out) { + if (errored) return; + try { + controller0.enqueue(encoder2.encode(out)); + } catch { } - const t = tool; - out.push({ - type: "function", - function: { - name: flatName, - ...t.description ? { description: t.description } : {}, - parameters: CUSTOM_TOOL_SCHEMA - } - }); - convertibleToolNames.add(flatName); - customToolNames.add(flatName); - if (namespacePrefix) namespaceMap.set(flatName, { namespace: namespacePrefix, name: name2 }); - return; } - if (type2 === "namespace") { - const ns = tool.name; - const children2 = tool.tools ?? tool.children ?? []; - const childPrefix = namespacePrefix ? `${namespacePrefix}__${ns}` : ns; - for (const child of children2) { - collectTools(child, childPrefix, out, customToolNames, namespaceMap, convertibleToolNames, signal2); + let controller0; + return new ReadableStream({ + start(controller) { + controller0 = controller; + const reader = upstream.getReader(); + let buffer2 = ""; + reader.read().then(function pump({ done, value: value2 }) { + if (done) { + if (buffer2.trim()) processBlock(buffer2, state2); + buffer2 = ""; + emitDone(); + try { + controller.close(); + } catch { + } + return; + } + buffer2 += decoder.decode(value2, { stream: true }); + const blocks = buffer2.split("\n\n"); + buffer2 = blocks.pop() ?? ""; + for (const block of blocks) { + processBlock(block, state2); + if (errored) { + try { + controller.close(); + } catch { + } + return; + } + } + return reader.read().then(pump); + }).catch((err) => { + if (!errored) { + const errPayload = JSON.stringify({ error: { message: `async stream error: ${err.message}`, type: "server_error" } }); + emit(`data: ${errPayload} + +`); + emitDone(); + } + try { + controller.close(); + } catch { + } + }).finally(() => { + reader.releaseLock?.(); + }); } - return; - } - if (type2 === "tool_search") { - signal2("tool_search"); - if (convertibleToolNames.has("tool_search")) return; - out.push({ - type: "function", - function: { - name: "tool_search", - description: "Search the available tool registry.", - parameters: TOOL_SEARCH_PROXY_SCHEMA + }); + function processBlock(block, st) { + const trimmed = block.trim(); + if (trimmed === "") return; + if (trimmed.startsWith(":")) { + emit(block + "\n\n"); + return; + } + if (trimmed.startsWith("event: error") || trimmed.startsWith("event:error")) { + const dataLine = block.split("\n").find((l) => l.startsWith("data:")); + let anthropicMsg = "unknown error"; + let anthropicType = "api_error"; + if (dataLine) { + try { + const data2 = JSON.parse(dataLine.slice(5).trim()); + if (data2?.error?.message) anthropicMsg = String(data2.error.message); + if (data2?.error?.type) anthropicType = String(data2.error.type); + } catch { + } } - }); - convertibleToolNames.add("tool_search"); - return; - } - if (isWebSearchTool(tool)) { - signal2("web_search"); - return; - } - if (isHostedTool(tool)) { - return; - } - const maybeName = tool.name; - const maybeParams = tool.parameters; - if (typeof maybeName === "string" && maybeParams && typeof maybeParams === "object") { - const flatName = namespacePrefix ? `${namespacePrefix}__${maybeName}` : maybeName; - if (!convertibleToolNames.has(flatName)) { - out.push({ type: "function", function: { name: flatName, parameters: maybeParams } }); - convertibleToolNames.add(flatName); + const oaiPayload = JSON.stringify({ error: { message: anthropicMsg, type: anthropicType } }); + emit(`data: ${oaiPayload} + +`); + emitDone(); + errored = true; + return; + } + const parsed = parseSSEChunk(block); + for (const p of parsed) { + const out = translateEvent(st, p); + if (out) emit(out); } } -} -function mapToolChoice(raw, convertible, hasToolSearch) { - if (raw === void 0 || raw === null) return void 0; - if (typeof raw === "string") { - return raw; - } - if (typeof raw !== "object") return void 0; - const obj = raw; - const type2 = obj.type ?? ""; - if (type2 === "web_search" || type2 === "web_search_preview") return void 0; - if (type2 === "file_search" || type2 === "code_interpreter" || type2 === "computer_use_preview" || type2 === "image_generation" || type2 === "mcp") { - return void 0; - } - if (type2 === "tool_search") { - return hasToolSearch ? { type: "function", function: { name: "tool_search" } } : void 0; - } - if (type2 === "custom" || type2 === "function") { - const name2 = obj.name ?? obj.function?.name; - if (typeof name2 !== "string" || name2.length === 0) return void 0; - if (!convertible.has(name2)) return void 0; - return { type: "function", function: { name: name2 } }; + function emitDone() { + if (doneSent) return; + doneSent = true; + emit("data: [DONE]\n\n"); } - return void 0; } -var ToolTranslationError = class extends Error { - constructor(message) { - super(message); - this.name = "ToolTranslationError"; +var init_openai_stream_adapter = __esm({ + "src/async/openai-stream-adapter.ts"() { + "use strict"; + init_sse_translator(); } -}; +}); -// src/translator/chat-to-responses.ts -function chatCompletionsToResponses(resp, model, opts = {}) { - const id2 = opts.responseId ?? generateResponsesId(); - const choice = resp.choices?.[0]; - const output = []; - if (choice) { - const items2 = chatChoiceToOutputItems(choice, opts.meta); - output.push(...items2); - } - if (output.length === 0) { - output.push(emptyMessageOutput()); - } - const status = choice?.finish_reason === "length" ? "incomplete" : "completed"; - const incomplete = status === "incomplete" ? { reason: "max_output_tokens" } : void 0; - return { - id: id2, - object: "response", - created_at: Date.now(), - model: model || resp.model || "", - status, - output, - ...incomplete ? { incomplete_details: incomplete } : {}, - ...resp.usage ? { usage: chatUsageToResponsesUsage(resp.usage) } : {}, - ...opts.instructions ? { instructions: opts.instructions } : {}, - ...opts.previousResponseId ? { previous_response_id: opts.previousResponseId } : {} - }; +// src/async/types.ts +function isTicketReady(s) { + return s === "ready" || s === "active"; } -function chatChoiceToOutputItems(choice, meta) { - const items2 = []; - const msg = choice.message; - if (msg?.reasoning_content) { - items2.push({ - type: "reasoning", - id: generateItemId(), - summary: [{ type: "summary_text", text: msg.reasoning_content }], - status: "completed" - }); +function isTicketExpired(s) { + return s === "expired" || s === "not_found"; +} +var OffPeakServerError; +var init_types2 = __esm({ + "src/async/types.ts"() { + "use strict"; + OffPeakServerError = class extends Error { + httpStatus; + bizCode; + constructor(message, httpStatus, bizCode) { + super(message); + this.name = "OffPeakServerError"; + this.httpStatus = httpStatus; + this.bizCode = bizCode; + } + }; } - const text = extractAssistantText(msg); - const toolCalls = msg?.tool_calls ?? []; - const customNames = meta?.customToolNames ?? /* @__PURE__ */ new Set(); - const nsMap = meta?.namespaceMap ?? /* @__PURE__ */ new Map(); - const hasToolSearch = meta?.hasToolSearch === true; - if (text.length > 0 || toolCalls.length === 0) { - items2.push({ - type: "message", - id: generateItemId(), - role: "assistant", - content: [{ type: "output_text", text }], - status: "completed" - }); +}); + +// src/async/client.ts +function createOffPeakClient(opts) { + const origin = opts.origin.replace(/\/+$/, ""); + const credentials2 = opts.credentials; + const controlTimeoutMs = opts.controlTimeoutMs ?? DEFAULT_CONTROL_TIMEOUT_MS; + const settleTimeoutMs = opts.settleTimeoutMs ?? controlTimeoutMs; + const fetchImpl = opts.fetchImpl ?? globalThis.fetch; + function buildHeaders(hasBody) { + const h = { + authorization: `Bearer ${credentials2.jwt}`, + "x-coding-plan-api-key": credentials2.codingPlanApiKey + }; + if (hasBody) h["content-type"] = "application/json"; + if (credentials2.bigmodelOrganization) h["bigmodel-organization"] = credentials2.bigmodelOrganization; + if (credentials2.bigmodelProject) h["bigmodel-project"] = credentials2.bigmodelProject; + return h; } - for (const tc of toolCalls) { - const flatName = tc.function.name; - const args = tc.function.arguments && tc.function.arguments.trim().length > 0 ? tc.function.arguments : "{}"; - if (customNames.has(flatName)) { - const inputStr = extractCustomToolInput(args); - items2.push({ - type: "custom_tool_call", - id: generateItemId(), - call_id: tc.id || generateCallId(), - name: flatName, - input: inputStr, - status: "completed" - }); - continue; + async function request(method2, path2, body2, timeoutMs, externalSignal, isSettle, settleAsSuccess) { + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), timeoutMs); + const onExternalAbort = () => controller.abort(); + if (externalSignal) { + if (externalSignal.aborted) controller.abort(); + else externalSignal.addEventListener("abort", onExternalAbort, { once: true }); } - if (flatName === "tool_search" && hasToolSearch) { - let argsObj = {}; + const url2 = `${origin}/api/v1/off-peak${path2}`; + const init = { + method: method2, + headers: buildHeaders(body2 !== void 0), + signal: controller.signal + }; + if (body2 !== void 0) init.body = JSON.stringify(body2); + let resp; + let raw = ""; + try { try { - argsObj = JSON.parse(args); + resp = await fetchImpl(url2, init); + } catch (err) { + const msg = err?.message ?? String(err); + if (/abort/i.test(msg)) throw new OffPeakServerError(`off-peak request aborted: ${method2} ${path2}`, 0); + throw new OffPeakServerError(`off-peak network error: ${method2} ${path2}: ${msg}`, 0); + } + raw = await resp.text(); + } finally { + clearTimeout(timer); + externalSignal?.removeEventListener("abort", onExternalAbort); + } + if (!resp.ok) { + if (isSettle && settleAsSuccess && resp.status >= 400 && resp.status < 500) { + return void 0; + } + let bizCode; + let serverMsg = `HTTP ${resp.status}`; + try { + const parsed = JSON.parse(raw); + bizCode = parsed?.code !== void 0 ? String(parsed.code) : void 0; + if (parsed?.msg) serverMsg = String(parsed.msg); + else if (parsed?.message) serverMsg = String(parsed.message); } catch { - argsObj = {}; + if (raw.length > 0 && raw.length < 200) serverMsg = raw; } - items2.push({ - type: "tool_search_call", - id: generateItemId(), - call_id: tc.id || generateCallId(), - arguments: argsObj, - execution: "client", - status: "completed" - }); - continue; + throw new OffPeakServerError( + `off-peak ${method2} ${path2} failed: ${serverMsg}`, + resp.status, + bizCode + ); } - const ns = nsMap.get(flatName); - if (ns) { - items2.push({ - type: "function_call", - id: generateItemId(), - call_id: tc.id || generateCallId(), - name: ns.name, - namespace: ns.namespace, - arguments: args, - status: "completed" - }); - continue; + if (raw.length === 0) return void 0; + let parsedJson; + try { + parsedJson = JSON.parse(raw); + } catch { + return void 0; } - items2.push({ - type: "function_call", - id: generateItemId(), - call_id: tc.id || generateCallId(), - name: flatName, - arguments: args, - status: "completed" - }); - } - return items2; -} -function emptyMessageOutput() { - return { - type: "message", - id: generateItemId(), - role: "assistant", - content: [{ type: "output_text", text: "" }], - status: "completed" - }; -} -function extractAssistantText(msg) { - if (!msg) return ""; - if (typeof msg.content === "string") return msg.content; - if (Array.isArray(msg.content)) { - return msg.content.filter((c) => c.type === "text" && typeof c.text === "string").map((c) => c.text).join("\n"); - } - return ""; -} -function extractCustomToolInput(rawArgs) { - try { - const obj = JSON.parse(rawArgs); - if (typeof obj.input === "string") return obj.input; - } catch { + if (parsedJson && typeof parsedJson === "object") { + const obj = parsedJson; + if ("code" in obj || "data" in obj) { + const code = obj.code; + if (code !== 0) { + if (code === void 0) { + } else { + const msg = obj.msg ?? obj.message ?? `biz code ${String(code)}`; + throw new OffPeakServerError( + `off-peak ${method2} ${path2} biz error: ${msg}`, + resp?.status ?? 0, + String(code) + ); + } + } else if (obj.data !== void 0) { + return obj.data; + } + } + } + return parsedJson; } - return rawArgs; -} -function chatUsageToResponsesUsage(u) { - return { - input_tokens: u.prompt_tokens ?? 0, - output_tokens: u.completion_tokens ?? 0, - total_tokens: u.total_tokens ?? (u.prompt_tokens ?? 0) + (u.completion_tokens ?? 0), - ...u.prompt_tokens_details?.cached_tokens ? { input_tokens_details: { cached_tokens: u.prompt_tokens_details.cached_tokens } } : {}, - ...u.output_tokens_details?.reasoning_tokens ? { output_tokens_details: { reasoning_tokens: u.output_tokens_details.reasoning_tokens } } : {} - }; -} -function newResponsesStreamState(model, opts = {}) { return { - responseId: opts.responseId ?? generateResponsesId(), - model, - createdAt: Date.now(), - sequenceNumber: 0, - createdSent: false, - completedSent: false, - nextOutputIndex: 0, - reasoningItemId: void 0, - reasoningIndex: -1, - reasoningOpen: false, - reasoningDone: false, - reasoningText: "", - messageItemId: void 0, - messageIndex: -1, - textPartOpen: false, - text: "", - toolCalls: /* @__PURE__ */ new Map(), - finishReason: void 0, - usage: void 0, - meta: opts.meta + async getAvailability(signal2) { + const data2 = await request("GET", "/ticket/availability", void 0, controlTimeoutMs, signal2, false, false); + if (!data2) throw new OffPeakServerError("off-peak availability empty response", 0); + const canTakeNumber = data2.can_take_number === true; + if (!canTakeNumber && data2.next_take_at === void 0) { + throw new OffPeakServerError("off-peak availability missing next_take_at while unavailable", 0); + } + const result3 = { canTakeNumber }; + if (data2.next_take_at !== void 0) result3.nextTakeAt = data2.next_take_at; + return result3; + }, + async takeTicket(taskId, signal2) { + if (!taskId || typeof taskId !== "string") { + throw new Error("takeTicket: taskId must be a non-empty string"); + } + const data2 = await request("POST", "/ticket", { task_id: taskId }, controlTimeoutMs, signal2, false, false); + if (!data2 || typeof data2.ticket_id !== "string" || typeof data2.state !== "string") { + throw new OffPeakServerError("off-peak takeTicket malformed response", 0); + } + const state2 = data2.state; + const result3 = { + ticketId: data2.ticket_id, + state: state2, + registeredAt: Date.now() + }; + if (data2.position != null) result3.position = data2.position; + if (data2.next_poll_after !== void 0) result3.nextPollAfterMs = data2.next_poll_after * 1e3; + return result3; + }, + async batchStatus(ticketIds, signal2) { + if (ticketIds.length === 0) return { tickets: [] }; + const truncated = ticketIds.slice(0, MAX_BATCH_STATUS); + const data2 = await request( + "POST", + "/ticket/status", + { ticket_ids: truncated }, + controlTimeoutMs, + signal2, + false, + false + ); + if (!data2 || !Array.isArray(data2.tickets)) { + throw new OffPeakServerError("off-peak batchStatus malformed response", 0); + } + const result3 = { + tickets: data2.tickets.map((t) => { + if (typeof t.ticket_id !== "string" || typeof t.state !== "string") { + throw new OffPeakServerError("off-peak batchStatus ticket entry malformed", 0); + } + const item = { + ticketId: t.ticket_id, + state: t.state + }; + if (t.position != null) item.position = t.position; + if (t.active_deadline !== void 0) item.activeDeadline = t.active_deadline; + return item; + }) + }; + if (data2.next_poll_after !== void 0) result3.nextPollAfterMs = data2.next_poll_after * 1e3; + return result3; + }, + async settle(ticketId, opts2 = {}) { + const settleAsSuccess = opts2.settleAsSuccess !== false; + await request( + "POST", + `/ticket/${encodeURIComponent(ticketId)}/settle`, + void 0, + settleTimeoutMs, + opts2.signal, + true, + settleAsSuccess + ); + } }; } -function chatChunkToResponsesEvents(chunk, state2) { - const events = []; - events.push(...ensureCreated(state2)); - if (chunk.model && !state2.model) state2.model = chunk.model; - if (chunk.usage) state2.usage = chatUsageToResponsesUsage(chunk.usage); - for (const choice of chunk.choices ?? []) { - events.push(...handleChoice(choice, state2)); +var DEFAULT_CONTROL_TIMEOUT_MS, MAX_BATCH_STATUS; +var init_client = __esm({ + "src/async/client.ts"() { + "use strict"; + init_types2(); + DEFAULT_CONTROL_TIMEOUT_MS = 15e3; + MAX_BATCH_STATUS = 100; } - return events; +}); + +// src/async/keepalive.ts +function keepaliveFrame(text = "keepalive") { + const clean = text.replace(/[\r\n]/g, " "); + return new TextEncoder().encode(`: ${clean} + +`); } -function handleChoice(choice, state2) { - const events = []; - const delta = choice.delta ?? {}; - if (delta.reasoning_content && delta.reasoning_content.length > 0) { - events.push(...ensureReasoningItem(state2)); - state2.reasoningText += delta.reasoning_content; - events.push(seq(state2, { - type: "response.reasoning_summary_text.delta", - output_index: state2.reasoningIndex, - summary_index: 0, - delta: delta.reasoning_content, - item_id: state2.reasoningItemId - })); +var init_keepalive = __esm({ + "src/async/keepalive.ts"() { + "use strict"; } - if (typeof delta.content === "string" && delta.content.length > 0) { - events.push(...closeReasoningItem(state2)); - events.push(...ensureMessageItem(state2)); - events.push(...ensureTextPart(state2)); - state2.text += delta.content; - events.push(seq(state2, { - type: "response.output_text.delta", - output_index: state2.messageIndex, - content_index: 0, - delta: delta.content, - item_id: state2.messageItemId - })); +}); + +// src/async/bridge.ts +function runAsyncBridge(opts) { + const fetchImpl = opts.fetchImpl ?? globalThis.fetch; + const encoder2 = new TextEncoder(); + let outcomeResolve; + const outcome = new Promise((r2) => { + outcomeResolve = r2; + }); + let outcomeResolved = false; + function resolveOutcome(o) { + if (outcomeResolved) return; + outcomeResolved = true; + outcomeResolve(o); } - for (const tc of delta.tool_calls ?? []) { - const idx = tc.index ?? 0; - let entry = state2.toolCalls.get(idx); - if (!entry) { - events.push(...closeReasoningItem(state2)); - const itemId = generateItemId(); - const outputIndex = allocIndex(state2); - const callId = tc.id || generateCallId(); - const name2 = tc.function?.name ?? ""; - entry = { id: callId, name: name2, args: "", itemId, outputIndex }; - state2.toolCalls.set(idx, entry); - const initialArgs = tc.function?.arguments ?? ""; - entry.args += initialArgs; - events.push(seq(state2, { - type: "response.output_item.added", - output_index: outputIndex, - item: toolCallAddedItem(entry, state2.meta) - })); - if (initialArgs.length > 0) { - events.push(seq(state2, toolArgsDeltaEvent(entry, initialArgs, state2))); - } - } else { - if (tc.id) entry.id = tc.id; - if (tc.function?.name) entry.name = tc.function.name; - const argDelta = tc.function?.arguments ?? ""; - if (argDelta.length > 0) { - entry.args += argDelta; - events.push(seq(state2, toolArgsDeltaEvent(entry, argDelta, state2))); - } + let aborted2 = false; + const settledTickets = /* @__PURE__ */ new Set(); + function settleOnce(ticketId) { + if (settledTickets.has(ticketId)) return; + settledTickets.add(ticketId); + void opts.client.settle(ticketId).catch(() => { + }); + } + function log(info) { + try { + opts.onTransition?.(info); + } catch { } } - if (choice.finish_reason) { - state2.finishReason = choice.finish_reason; + function emitKeepalive(controller) { + if (aborted2) return; + try { + controller.enqueue(keepaliveFrame()); + } catch { + } } - return events; -} -function toolCallAddedItem(entry, meta) { - const customNames = meta?.customToolNames ?? /* @__PURE__ */ new Set(); - const nsMap = meta?.namespaceMap ?? /* @__PURE__ */ new Map(); - const hasToolSearch = meta?.hasToolSearch === true; - if (customNames.has(entry.name)) { - return { - type: "custom_tool_call", - id: entry.itemId, - call_id: entry.id, - name: entry.name, - input: "", - // final value emitted at output_item.done - status: "in_progress" - }; + function emitTerminalError(controller, message, type2 = "api_error") { + if (aborted2) return; + const payload = JSON.stringify({ type: "error", error: { type: type2, message } }); + try { + controller.enqueue(encoder2.encode(`event: error +data: ${payload} + +`)); + } catch { + } } - if (entry.name === "tool_search" && hasToolSearch) { - return { - type: "tool_search_call", - id: entry.itemId, - call_id: entry.id, - execution: "client", - status: "in_progress" - }; + async function waitForReady(ticketId, deadlineAt) { + while (true) { + if (aborted2) return { state: "expired" }; + const result3 = await opts.client.batchStatus([ticketId], opts.clientSignal); + if (aborted2) return { state: "expired" }; + const ticket = result3.tickets[0]; + if (!ticket) return { state: "not_found" }; + if (isTicketReady(ticket.state)) return { state: ticket.state }; + if (ticket.state !== "queued") return { state: "expired" }; + const delay = result3.nextPollAfterMs ?? opts.pollIntervalMs; + if (opts.maxWaitMs > 0 && Date.now() + delay > deadlineAt) { + return { state: "expired" }; + } + await sleep(delay, opts.clientSignal); + } } - const ns = nsMap.get(entry.name); - if (ns) { - return { - type: "function_call", - id: entry.itemId, - call_id: entry.id, - name: ns.name, - namespace: ns.namespace, - status: "in_progress" + async function forwardLLM(ticketId) { + const url2 = `${opts.origin.replace(/\/+$/, "")}/api/v1/off-peak/anthropic/v1/messages`; + const headers2 = { + "content-type": "application/json", + authorization: `Bearer ${opts.credentials.jwt}`, + "x-coding-plan-api-key": opts.credentials.codingPlanApiKey, + "x-off-peak-ticket-id": ticketId, + ...buildIdentityHeaders(opts.identity) }; - } - return { - type: "function_call", - id: entry.itemId, - call_id: entry.id, - name: entry.name, - status: "in_progress" - }; -} -function toolArgsDeltaEvent(entry, delta, state2) { - const customNames = state2.meta?.customToolNames ?? /* @__PURE__ */ new Set(); - const isCustom = customNames.has(entry.name); - const base = { - output_index: entry.outputIndex, - delta, - item_id: entry.itemId, - call_id: entry.id, - name: entry.name - }; - return seq(state2, isCustom ? { type: "response.custom_tool_call_input.delta", ...base } : { type: "response.function_call_arguments.delta", ...base }); -} -function finalizeResponsesStream(state2) { - if (state2.completedSent) return []; - const events = []; - events.push(...ensureCreated(state2)); - events.push(...closeReasoningItem(state2)); - events.push(...synthesizeReasoningFallbackMessage(state2)); - events.push(...closeMessageItem(state2)); - events.push(...closeToolItems(state2)); - const status = state2.finishReason === "length" ? "incomplete" : "completed"; - const incomplete = status === "incomplete" ? { reason: "max_output_tokens" } : void 0; - state2.completedSent = true; - events.push(seq(state2, { - type: status === "incomplete" ? "response.incomplete" : "response.completed", - response: { - id: state2.responseId, - object: "response", - created_at: state2.createdAt, - model: state2.model, - status, - output: buildFinalOutput(state2), - ...incomplete ? { incomplete_details: incomplete } : {}, - ...state2.usage ? { usage: state2.usage } : {} + if (opts.credentials.bigmodelOrganization) headers2["bigmodel-organization"] = opts.credentials.bigmodelOrganization; + if (opts.credentials.bigmodelProject) headers2["bigmodel-project"] = opts.credentials.bigmodelProject; + const resp = await fetchImpl(url2, { + method: "POST", + headers: headers2, + body: opts.llmRequestBody, + signal: opts.clientSignal + }); + if (!resp.ok) { + const bodyText = await resp.text().catch(() => ""); + if (bodyText.includes(EXPIRED_MARKER)) { + return { response: new Response(bodyText, { status: resp.status, headers: resp.headers }), expiredInBody: true }; + } + return { response: new Response(bodyText, { status: resp.status, headers: resp.headers }), expiredInBody: false }; } - })); - return events; -} -function ensureCreated(state2) { - if (state2.createdSent) return []; - state2.createdSent = true; - return [seq(state2, { - type: "response.created", - response: { - id: state2.responseId, - object: "response", - created_at: state2.createdAt, - model: state2.model, - status: "in_progress", - output: [] + return { response: resp, expiredInBody: false }; + } + const stream = new ReadableStream({ + async start(controller) { + if (opts.clientSignal) { + if (opts.clientSignal.aborted) aborted2 = true; + else opts.clientSignal.addEventListener("abort", () => { + aborted2 = true; + }, { once: true }); + } + let keepAliveTimer; + function startKeepalive() { + if (keepAliveTimer) return; + keepAliveTimer = setInterval(() => emitKeepalive(controller), opts.keepAliveIntervalMs); + } + function stopKeepalive() { + if (keepAliveTimer) { + clearInterval(keepAliveTimer); + keepAliveTimer = void 0; + } + } + const requestStartedAt = Date.now(); + const deadlineAt = opts.maxWaitMs > 0 ? requestStartedAt + opts.maxWaitMs : Number.MAX_SAFE_INTEGER; + let currentTicket = opts.initialTicket; + let attempt = 0; + try { + while (true) { + if (aborted2) { + log({ phase: "abort", attempt, ticketId: currentTicket.ticketId }); + settleOnce(currentTicket.ticketId); + return; + } + if (!isTicketReady(currentTicket.state)) { + log({ phase: "wait", attempt, ticketId: currentTicket.ticketId, state: currentTicket.state }); + startKeepalive(); + const wait = await waitForReady(currentTicket.ticketId, deadlineAt); + if (aborted2) { + stopKeepalive(); + log({ phase: "abort", attempt, ticketId: currentTicket.ticketId }); + settleOnce(currentTicket.ticketId); + return; + } + if (isTicketExpired(wait.state)) { + stopKeepalive(); + settleOnce(currentTicket.ticketId); + if (opts.maxWaitMs > 0 && Date.now() >= deadlineAt) { + emitTerminalError(controller, `async max wait timeout (${opts.maxWaitMs}ms exceeded)`, "timeout"); + resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + log({ phase: "expired", attempt, ticketId: currentTicket.ticketId, state: wait.state, message: "expired in queue" }); + attempt++; + if (attempt > opts.maxRetries) { + emitTerminalError(controller, `async upstream exhausted retries (ticket expired in queue ${attempt}x)`, "api_error"); + resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + try { + currentTicket = await opts.client.takeTicket(opts.taskId, opts.clientSignal); + } catch (takeErr) { + emitTerminalError(controller, `async retake failed: ${takeErr.message}`, "api_error"); + resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + continue; + } + stopKeepalive(); + } + log({ phase: "ready", attempt, ticketId: currentTicket.ticketId }); + let resp; + let expiredInBody; + try { + const forward = await forwardLLM(currentTicket.ticketId); + resp = forward.response; + expiredInBody = forward.expiredInBody; + } catch (err) { + if (aborted2) { + settleOnce(currentTicket.ticketId); + return; + } + emitTerminalError(controller, `async upstream network error: ${err.message}`, "api_error"); + settleOnce(currentTicket.ticketId); + resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + if (!resp.ok || expiredInBody) { + const bodyText = await resp.text().catch(() => ""); + if (expiredInBody || bodyText.includes(EXPIRED_MARKER)) { + log({ phase: "expired", attempt, ticketId: currentTicket.ticketId, message: "expired during LLM (pre-stream)" }); + settleOnce(currentTicket.ticketId); + attempt++; + if (attempt > opts.maxRetries) { + emitTerminalError(controller, `async upstream exhausted retries (ticket expired during LLM ${attempt}x)`, "api_error"); + resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + try { + currentTicket = await opts.client.takeTicket(opts.taskId, opts.clientSignal); + } catch (takeErr) { + emitTerminalError(controller, `async retake failed: ${takeErr.message}`, "api_error"); + resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + continue; + } + emitTerminalError(controller, `async upstream HTTP ${resp.status}`, "api_error"); + settleOnce(currentTicket.ticketId); + resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + let midStreamExpiredPreCommit = false; + let midStreamExpiredPostCommit = false; + let committed = false; + if (resp.body) { + const reader = resp.body.getReader(); + const streamDecoder = new TextDecoder(); + let pending = ""; + const MAX_PENDING_FRAME_BYTES = 1 * 1024 * 1024; + try { + while (true) { + if (aborted2) { + await reader.cancel().catch(() => { + }); + settleOnce(currentTicket.ticketId); + return; + } + const { done, value: value2 } = await reader.read(); + if (done) { + if (pending.length > 0 && !aborted2 && !midStreamExpiredPreCommit && !midStreamExpiredPostCommit) { + if (pending.includes(EXPIRED_MARKER)) { + if (!committed) midStreamExpiredPreCommit = true; + else midStreamExpiredPostCommit = true; + } else if (pending.endsWith("\n\n")) { + try { + controller.enqueue(encoder2.encode(pending)); + } catch { + } + } + pending = ""; + } + break; + } + if (aborted2) break; + pending += streamDecoder.decode(value2, { stream: true }).replace(/\r\n/g, "\n").replace(/\r/g, "\n"); + if (pending.length > MAX_PENDING_FRAME_BYTES) { + await reader.cancel().catch(() => { + }); + emitTerminalError(controller, "async upstream SSE frame exceeded 1 MiB boundary", "api_error"); + settleOnce(currentTicket.ticketId); + resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + let frameBoundaryFound = false; + while (true) { + const idx = pending.indexOf("\n\n"); + if (idx === -1) break; + const frame = pending.slice(0, idx + 2); + pending = pending.slice(idx + 2); + if (frame.includes(EXPIRED_MARKER)) { + if (!committed) { + midStreamExpiredPreCommit = true; + } else { + midStreamExpiredPostCommit = true; + } + await reader.cancel().catch(() => { + }); + frameBoundaryFound = true; + break; + } + try { + controller.enqueue(encoder2.encode(frame)); + committed = true; + } catch { + await reader.cancel().catch(() => { + }); + frameBoundaryFound = true; + break; + } + } + if (midStreamExpiredPreCommit || midStreamExpiredPostCommit || frameBoundaryFound) break; + } + streamDecoder.decode(); + } finally { + reader.releaseLock?.(); + } + } + if (midStreamExpiredPreCommit && !aborted2) { + log({ phase: "expired", attempt, ticketId: currentTicket.ticketId, message: "expired during LLM (mid-stream, pre-commit)" }); + settleOnce(currentTicket.ticketId); + attempt++; + if (attempt > opts.maxRetries) { + emitTerminalError(controller, `async upstream exhausted retries (ticket expired mid-stream ${attempt}x)`, "api_error"); + resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + try { + currentTicket = await opts.client.takeTicket(opts.taskId, opts.clientSignal); + } catch (takeErr) { + emitTerminalError(controller, `async retake failed: ${takeErr.message}`, "api_error"); + resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + continue; + } + if (midStreamExpiredPostCommit && !aborted2) { + log({ phase: "error", attempt, ticketId: currentTicket.ticketId, message: "expired mid-stream after commit; cannot retry" }); + settleOnce(currentTicket.ticketId); + emitTerminalError(controller, "async upstream ticket expired mid-stream after output started", "api_error"); + resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + return; + } + if (aborted2) { + log({ phase: "abort", attempt, ticketId: currentTicket.ticketId }); + settleOnce(currentTicket.ticketId); + resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "abort" }); + return; + } + log({ phase: "done", attempt, ticketId: currentTicket.ticketId }); + settleOnce(currentTicket.ticketId); + resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "done" }); + return; + } + } catch (err) { + if (!aborted2) { + emitTerminalError(controller, `async bridge internal error: ${err.message}`, "api_error"); + } + settleOnce(currentTicket.ticketId); + resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + } finally { + stopKeepalive(); + try { + controller.close(); + } catch { + } + resolveOutcome({ + attempts: attempt + 1, + finalTicketId: currentTicket.ticketId, + terminalPhase: aborted2 ? "abort" : "error" + }); + } + }, + cancel() { + aborted2 = true; } - })]; -} -function ensureReasoningItem(state2) { - if (state2.reasoningOpen || state2.reasoningDone) return []; - state2.reasoningOpen = true; - state2.reasoningItemId = generateItemId(); - state2.reasoningIndex = allocIndex(state2); - return [ - seq(state2, { - type: "response.output_item.added", - output_index: state2.reasoningIndex, - item: { type: "reasoning", id: state2.reasoningItemId, status: "in_progress" } - }), - seq(state2, { - type: "response.reasoning_summary_part.added", - output_index: state2.reasoningIndex, - summary_index: 0, - item_id: state2.reasoningItemId, - part: { type: "summary_text" } - }) - ]; + }); + return { stream, outcome }; } -function closeReasoningItem(state2) { - if (!state2.reasoningOpen) return []; - state2.reasoningOpen = false; - state2.reasoningDone = true; - const text = state2.reasoningText; - return [ - seq(state2, { - type: "response.reasoning_summary_text.done", - output_index: state2.reasoningIndex, - summary_index: 0, - text, - item_id: state2.reasoningItemId - }), - seq(state2, { - type: "response.reasoning_summary_part.done", - output_index: state2.reasoningIndex, - summary_index: 0, - item_id: state2.reasoningItemId, - part: { type: "summary_text", text } - }), - seq(state2, { - type: "response.output_item.done", - output_index: state2.reasoningIndex, - item: { - type: "reasoning", - id: state2.reasoningItemId, - status: "completed", - summary: [{ type: "summary_text", text }] - } - }) - ]; +function sleep(ms, signal2) { + return new Promise((resolve) => { + if (signal2?.aborted) { + resolve(); + return; + } + const t = setTimeout(() => { + signal2?.removeEventListener("abort", onAbort); + resolve(); + }, ms); + const onAbort = () => { + clearTimeout(t); + resolve(); + }; + signal2?.addEventListener("abort", onAbort, { once: true }); + }); } -function synthesizeReasoningFallbackMessage(state2) { - if (state2.messageItemId || state2.text.length > 0 || state2.reasoningText.length === 0 || state2.toolCalls.size > 0) { - return []; +var EXPIRED_MARKER; +var init_bridge = __esm({ + "src/async/bridge.ts"() { + "use strict"; + init_types2(); + init_keepalive(); + init_identity(); + EXPIRED_MARKER = "off-peak-ticket-expired"; } - const text = state2.reasoningText; - if (text.trim().length === 0) return []; - const events = []; - events.push(...ensureMessageItem(state2)); - events.push(...ensureTextPart(state2)); - state2.text = text; - events.push(seq(state2, { - type: "response.output_text.delta", - output_index: state2.messageIndex, - content_index: 0, - delta: text, - item_id: state2.messageItemId - })); - return events; +}); + +// src/async/handler.ts +function buildCredentials(cred) { + return { + jwt: cred.jwt ?? "", + codingPlanApiKey: credentialString(cred) + }; } -function ensureMessageItem(state2) { - if (state2.messageItemId) return []; - state2.messageItemId = generateItemId(); - state2.messageIndex = allocIndex(state2); - return [seq(state2, { - type: "response.output_item.added", - output_index: state2.messageIndex, - item: { - type: "message", - id: state2.messageItemId, - role: "assistant", - status: "in_progress", - content: [{ type: "output_text" }] - } - })]; +function generateTaskId() { + return `proxy-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`; } -function ensureTextPart(state2) { - if (state2.textPartOpen) return []; - state2.textPartOpen = true; - return [seq(state2, { - type: "response.content_part.added", - output_index: state2.messageIndex, - content_index: 0, - item_id: state2.messageItemId, - part: { type: "output_text", text: "" } - })]; +function resolveModel(req, config) { + const explicit = typeof req.model === "string" ? req.model.trim() : ""; + if (explicit) return explicit; + if (config.async.defaultModel && config.async.defaultModel.trim()) return config.async.defaultModel.trim(); + return config.defaultModel; } -function closeMessageItem(state2) { - if (!state2.messageItemId) return []; - const events = []; - if (state2.textPartOpen) { - events.push(seq(state2, { - type: "response.output_text.done", - output_index: state2.messageIndex, - content_index: 0, - text: state2.text, - item_id: state2.messageItemId - })); - events.push(seq(state2, { - type: "response.content_part.done", - output_index: state2.messageIndex, - content_index: 0, - item_id: state2.messageItemId, - part: { type: "output_text", text: state2.text } - })); - } - events.push(seq(state2, { - type: "response.output_item.done", - output_index: state2.messageIndex, - item: { - type: "message", - id: state2.messageItemId, - role: "assistant", - status: "completed", - content: [{ type: "output_text", text: state2.text }] +async function readBody2(req) { + const contentLength2 = req.headers.get("content-length"); + if (contentLength2) { + const cl = parseInt(contentLength2, 10); + if (Number.isFinite(cl) && cl > MAX_REQUEST_BODY_BYTES) { + req.body?.cancel().catch(() => { + }); + return { ok: false, response: errorResponse(413, "request_too_large", `body exceeds ${MAX_REQUEST_BODY_BYTES} byte cap`) }; } - })); - return events; -} -function closeToolItems(state2) { - const events = []; - const sortedKeys = [...state2.toolCalls.keys()].sort((a, b) => a - b); - for (const idx of sortedKeys) { - const entry = state2.toolCalls.get(idx); - const customNames = state2.meta?.customToolNames ?? /* @__PURE__ */ new Set(); - const nsMap = state2.meta?.namespaceMap ?? /* @__PURE__ */ new Map(); - const hasToolSearch = state2.meta?.hasToolSearch === true; - const isCustom = customNames.has(entry.name); - const isToolSearch = entry.name === "tool_search" && hasToolSearch; - const ns = nsMap.get(entry.name); - const finalArgs = entry.args.trim().length === 0 ? "{}" : entry.args; - if (isCustom) { - const inputStr = extractCustomToolInput(finalArgs); - events.push(seq(state2, { - type: "response.custom_tool_call_input.done", - output_index: entry.outputIndex, - input: inputStr, - item_id: entry.itemId, - call_id: entry.id, - name: entry.name - })); - events.push(seq(state2, { - type: "response.output_item.done", - output_index: entry.outputIndex, - item: { - type: "custom_tool_call", - id: entry.itemId, - call_id: entry.id, - name: entry.name, - input: inputStr, - status: "completed" - } - })); - } else if (isToolSearch) { - let argsObj = {}; - try { - argsObj = JSON.parse(finalArgs); - } catch { - argsObj = {}; + } + if (!req.body) { + return { ok: false, response: errorResponse(400, "invalid_request_error", "missing request body") }; + } + const reader = req.body.getReader(); + const chunks = []; + let total = 0; + try { + while (true) { + const { done, value: value2 } = await reader.read(); + if (done) break; + total += value2.byteLength; + if (total > MAX_REQUEST_BODY_BYTES) { + await reader.cancel().catch(() => { + }); + return { ok: false, response: errorResponse(413, "request_too_large", `body exceeds ${MAX_REQUEST_BODY_BYTES} byte cap`) }; } - events.push(seq(state2, { - type: "response.function_call_arguments.done", - output_index: entry.outputIndex, - arguments: finalArgs, - item_id: entry.itemId, - call_id: entry.id, - name: entry.name - })); - events.push(seq(state2, { - type: "response.output_item.done", - output_index: entry.outputIndex, - item: { - type: "tool_search_call", - id: entry.itemId, - call_id: entry.id, - arguments: argsObj, - execution: "client", - status: "completed" - } - })); - } else { - events.push(seq(state2, { - type: "response.function_call_arguments.done", - output_index: entry.outputIndex, - arguments: finalArgs, - item_id: entry.itemId, - call_id: entry.id, - name: entry.name - })); - events.push(seq(state2, { - type: "response.output_item.done", - output_index: entry.outputIndex, - item: ns ? { - type: "function_call", - id: entry.itemId, - call_id: entry.id, - name: ns.name, - namespace: ns.namespace, - arguments: finalArgs, - status: "completed" - } : { - type: "function_call", - id: entry.itemId, - call_id: entry.id, - name: entry.name, - arguments: finalArgs, - status: "completed" - } - })); + chunks.push(value2); } + } catch { + return { ok: false, response: errorResponse(400, "invalid_request_error", "could not read request body") }; + } finally { + reader.releaseLock?.(); } - return events; -} -function buildFinalOutput(state2) { - const out = []; - if (state2.reasoningDone && state2.reasoningText.length > 0) { - out.push({ - type: "reasoning", - id: state2.reasoningItemId, - summary: [{ type: "summary_text", text: state2.reasoningText }], - status: "completed" - }); - } - if (state2.messageItemId || state2.toolCalls.size === 0) { - out.push({ - type: "message", - id: state2.messageItemId ?? generateItemId(), - role: "assistant", - content: [{ type: "output_text", text: state2.text }], - status: "completed" + const encoding = req.headers.get("content-encoding")?.toLowerCase().trim() ?? ""; + let bytes = Buffer.concat(chunks); + if (encoding === "gzip" || encoding === "x-gzip") { + const gunzip = new DecompressionStream("gzip"); + const source = new ReadableStream({ + start(controller) { + controller.enqueue(bytes); + controller.close(); + } }); - } - const sortedKeys = [...state2.toolCalls.keys()].sort((a, b) => a - b); - for (const idx of sortedKeys) { - const entry = state2.toolCalls.get(idx); - const customNames = state2.meta?.customToolNames ?? /* @__PURE__ */ new Set(); - const nsMap = state2.meta?.namespaceMap ?? /* @__PURE__ */ new Map(); - const hasToolSearch = state2.meta?.hasToolSearch === true; - const isCustom = customNames.has(entry.name); - const isToolSearch = entry.name === "tool_search" && hasToolSearch; - const ns = nsMap.get(entry.name); - const finalArgs = entry.args.trim().length === 0 ? "{}" : entry.args; - if (isCustom) { - out.push({ - type: "custom_tool_call", - id: entry.itemId, - call_id: entry.id, - name: entry.name, - input: extractCustomToolInput(finalArgs), - status: "completed" - }); - } else if (isToolSearch) { - let argsObj = {}; - try { - argsObj = JSON.parse(finalArgs); - } catch { - argsObj = {}; + const inflateReader = source.pipeThrough(gunzip).getReader(); + const inflated = []; + let inflatedTotal = 0; + try { + for (; ; ) { + const { done, value: value2 } = await inflateReader.read(); + if (done) break; + inflatedTotal += value2.byteLength; + if (inflatedTotal > MAX_REQUEST_BODY_BYTES) { + await inflateReader.cancel().catch(() => { + }); + return { ok: false, response: errorResponse(413, "request_too_large", `decompressed body exceeds ${MAX_REQUEST_BODY_BYTES} byte cap`) }; + } + inflated.push(value2); } - out.push({ - type: "tool_search_call", - id: entry.itemId, - call_id: entry.id, - arguments: argsObj, - execution: "client", - status: "completed" - }); - } else if (ns) { - out.push({ - type: "function_call", - id: entry.itemId, - call_id: entry.id, - name: ns.name, - namespace: ns.namespace, - arguments: finalArgs, - status: "completed" - }); - } else { - out.push({ - type: "function_call", - id: entry.itemId, - call_id: entry.id, - name: entry.name, - arguments: finalArgs, - status: "completed" - }); + bytes = Buffer.concat(inflated); + } catch { + return { ok: false, response: errorResponse(400, "invalid_request_error", "could not decompress gzip request body") }; + } finally { + inflateReader.releaseLock?.(); } } - return out; -} -function allocIndex(state2) { - return state2.nextOutputIndex++; -} -function seq(state2, evt) { - const n = state2.sequenceNumber++; - return { ...evt, sequence_number: n }; -} -function responsesEventToSse(evt) { - return `event: ${evt.type} -data: ${JSON.stringify(evt)} - -`; -} - -// src/proxy/responses-handler.ts -async function handleResponses(clientReq, opts) { - const fetchImpl = opts.fetchImpl ?? fetch; - const debug = opts.debug === true; - const start2 = Date.now(); - let rawBody; - try { - rawBody = await readBody(clientReq) ?? ""; - } catch (err) { - if (err instanceof InflatedBodyTooLargeError) { - return errorResponse(413, "request_too_large", err.message); - } - return errorResponse(400, "invalid_request", `could not read request body: ${err.message}`); + const body2 = new TextDecoder().decode(bytes); + if (!body2 || body2.length === 0) { + return { ok: false, response: errorResponse(400, "invalid_request_error", "empty request body") }; } - let req; + return { ok: true, body: body2 }; +} +async function resolveCredential(opts) { + let cred; try { - req = JSON.parse(rawBody); + cred = await opts.auth.getCredential(); } catch (err) { - return errorResponse(400, "invalid_request", `request body is not valid JSON: ${err.message}`); - } - if (typeof req.input !== "string" && !Array.isArray(req.input)) { - return errorResponse(400, "invalid_request", "`input` must be a string or an array"); - } - if (typeof req.model !== "string" || req.model.length === 0) { - return errorResponse(400, "invalid_request", "`model` is required"); + return { ok: false, response: errorResponse(401, "authentication_error", `credential resolution failed: ${err.message}`) }; } - const stream = req.stream === true; - let historyItems = []; - let prevId; - if (typeof req.previous_response_id === "string" && req.previous_response_id.length > 0) { - if (!opts.responseStore) { - return errorResponse(404, "response_store_disabled", "`previous_response_id` was supplied but the response store is not configured"); - } - const prev = opts.responseStore.get(req.previous_response_id); - if (!prev) { - return errorResponse(404, "response_not_found", `previous_response_id ${req.previous_response_id} not found (response store is in-memory; entries are lost on restart and after the TTL)`); - } - prevId = req.previous_response_id; - historyItems = [...prev.input, ...outputItemsAsInputItems(prev.output)]; + if (!cred.jwt) { + return { + ok: false, + response: errorResponse( + 400, + "async_credentials_unavailable", + "async endpoints require a logged-in oauth credential (JWT missing). Re-run `auth login` or use sync /v1/* endpoints." + ) + }; } - const input = typeof req.input === "string" ? [...historyItems, { type: "message", role: "user", content: req.input }] : [...historyItems, ...req.input]; - const reqWithHistory = { - ...req, - input - }; - let translated; + return { ok: true, cred, credentials: buildCredentials(cred) }; +} +function buildClient(opts, credentials2) { + return createOffPeakClient({ + origin: opts.config.async.origin, + credentials: credentials2, + controlTimeoutMs: opts.config.async.controlTimeoutMs, + settleTimeoutMs: opts.config.async.settleTimeoutMs, + fetchImpl: opts.fetchImpl + }); +} +async function takeTicketOr502(client, taskId, opts, signal2) { try { - translated = responsesToChatCompletions(reqWithHistory); + const ticket = await client.takeTicket(taskId, signal2); + return { ok: true, ticket }; } catch (err) { - if (err instanceof ToolTranslationError) { - return errorResponse(400, "tool_translation_error", err.message); - } - throw err; + return { ok: false, response: errorResponse(502, "async_take_ticket_failed", `off-peak takeTicket failed: ${err.message}`) }; } - const { chatRequest, customToolNames, namespaceMap, hasToolSearch } = translated; - let cred; +} +function buildBridge(opts, client, credentials2, llmRequestBody, initialTicket, taskId, req) { + return runAsyncBridge({ + client, + credentials: credentials2, + origin: opts.config.async.origin, + identity: opts.config.identity, + llmRequestBody, + initialTicket, + taskId, + pollIntervalMs: opts.config.async.pollIntervalMs, + keepAliveIntervalMs: opts.config.async.keepAliveIntervalMs, + maxRetries: opts.config.async.maxRetries, + maxWaitMs: opts.config.async.maxWaitMs, + clientSignal: req.signal, + fetchImpl: opts.fetchImpl, + onTransition: opts.debug ? (info) => { + console.log(`[async] task=${taskId} ticket=${info.ticketId} phase=${info.phase} attempt=${info.attempt}${info.state ? ` state=${info.state}` : ""}${info.message ? ` msg=${info.message}` : ""}`); + } : void 0 + }); +} +function sseHeaders() { + return { + "content-type": "text/event-stream; charset=utf-8", + "cache-control": "no-cache", + connection: "keep-alive" + }; +} +async function handleAsyncMessages(req, opts) { + const cred = await resolveCredential(opts); + if (!cred.ok) return cred.response; + const bodyResult = await readBody2(req); + if (!bodyResult.ok) return bodyResult.response; + let parsedBody; try { - cred = await opts.auth.getCredential(); - } catch (err) { - return errorResponse(503, "credential_unavailable", err.message); - } - const providerDef = resolveProviderDef(opts.config); - const startPlan = opts.config.plan === "start-plan"; - const upstreamFormat = "anthropic"; - let upstreamRequestBody; - { - let anthropicReq; - try { - anthropicReq = translateRequestOpenAIToAnthropic(chatRequest); - } catch (err) { - return errorResponse(400, "translation_failed", `Chat\u2192Anthropic translation failed: ${err.message}`); + const raw = JSON.parse(bodyResult.body); + if (raw === null || typeof raw !== "object" || Array.isArray(raw)) { + return errorResponse(400, "invalid_request_error", "request body must be a JSON object"); } - upstreamRequestBody = transformRequestBody(JSON.stringify(anthropicReq), { - format: "anthropic", - userId: cred.userId, - startPlan - }) ?? JSON.stringify(anthropicReq); + parsedBody = raw; + } catch { + return errorResponse(400, "invalid_request_error", "request body is not valid JSON"); } - const transformedBody = upstreamRequestBody; - const upstreamHeaders = buildUpstreamHeaderPairs(clientReq, upstreamFormat, cred, opts.config.identity, opts.config.plan, void 0, void 0); - const upstreamReq = buildUpstreamRequest(clientReq, upstreamFormat, providerDef, cred, transformedBody, opts.config.identity, opts.config.plan, void 0, void 0); - if (debug) console.log(`[responses] \u2192 POST ${upstreamReq.url}`); - let upstreamResp; - try { - const routing = opts.endpointRouting !== void 0 ? opts.endpointRouting : getDefaultEndpointRouting(opts.config); - const routed = routing ? await routing.resolve(upstreamReq.url, credentialString(cred)) : null; - const sendUrl = routed?.routed ? routed.url : upstreamReq.url; - if (debug && routed?.routed) console.log(`[responses] endpoint routing: ${upstreamReq.url} -> ${sendUrl}`); - const signer = opts.clientSigning !== void 0 ? opts.clientSigning : getDefaultClientSigning(opts.config); - upstreamResp = await sendWithClientSigning(signer, { - url: upstreamReq.url, - headerPairs: upstreamHeaders, - credential: credentialString(cred), - appVersion: opts.config.identity.appVersion, - debug: debug ? (message) => console.log(`[responses] ${message}`) : void 0, - send: (finalPairs) => { - const req2 = new Request(sendUrl, { - method: "POST", - headers: Object.fromEntries(finalPairs), - body: transformedBody ?? void 0 - }); - return fetchImpl(req2, { method: "POST", headers: Object.fromEntries(finalPairs), body: transformedBody ?? void 0, signal: clientReq.signal }); - } - }); - } catch (err) { - return errorResponse(502, "upstream_unreachable", err.message); + if (!Array.isArray(parsedBody.messages) || parsedBody.messages.length === 0) { + return errorResponse(400, "invalid_request_error", "missing or invalid `messages` field"); } - if (!upstreamResp.ok) { - const errText = await upstreamResp.text().catch(() => ""); - return errorResponse(upstreamResp.status, "upstream_error", errText.slice(0, 500) || `upstream returned ${upstreamResp.status}`); + const clientWantsStream = parsedBody.stream === true; + const modelStr = typeof parsedBody.model === "string" ? parsedBody.model : void 0; + const upstreamBody = { + ...parsedBody, + model: resolveModel({ model: modelStr }, opts.config), + stream: true + }; + const upstreamBodyText = transformRequestBody(JSON.stringify(upstreamBody), { format: "anthropic", userId: cred.cred.userId }) ?? JSON.stringify(upstreamBody); + const client = buildClient(opts, cred.credentials); + const taskId = generateTaskId(); + const ticket = await takeTicketOr502(client, taskId, opts, req.signal); + if (!ticket.ok) return ticket.response; + const { stream, outcome } = buildBridge(opts, client, cred.credentials, upstreamBodyText, ticket.ticket, taskId, req); + void outcome; + if (clientWantsStream) { + return new Response(stream, { status: 200, headers: sseHeaders() }); } - if (upstreamFormat === "anthropic") { - if (stream) { - if (!upstreamResp.body) { - return errorResponse(502, "translation_failed", "upstream returned no body for stream"); - } - upstreamResp = new Response(anthropicSseToOpenaiSse(upstreamResp.body, req.model), { - status: upstreamResp.status, - headers: { "content-type": "text/event-stream" } - }); - } else { - const rawAnthropic = await upstreamResp.text(); - let parsedAnthropic; - try { - parsedAnthropic = JSON.parse(rawAnthropic); - } catch (err) { - return errorResponse(502, "translation_failed", `upstream returned non-JSON body: ${err.message}`); - } - const openaiResp = translateResponseAnthropicToOpenAI(parsedAnthropic, req.model); - upstreamResp = new Response(JSON.stringify(openaiResp), { - status: upstreamResp.status, - headers: { "content-type": "application/json" } - }); - } + return new Response(nonStreamChunkedJson(stream), { + status: 200, + headers: { "content-type": "application/json; charset=utf-8", "cache-control": "no-cache", "transfer-encoding": "chunked" } + }); +} +async function handleAsyncChat(req, opts) { + const cred = await resolveCredential(opts); + if (!cred.ok) return cred.response; + const bodyResult = await readBody2(req); + if (!bodyResult.ok) return bodyResult.response; + let openaiReq; + try { + openaiReq = JSON.parse(bodyResult.body); + } catch { + return errorResponse(400, "invalid_request_error", "request body is not valid JSON"); } - const responseId = generateResponsesId(); - const meta = { customToolNames, namespaceMap, hasToolSearch }; - if (stream) { - return streamResponse(upstreamResp, { responseId, model: req.model, meta, request: req, input, options: opts }); + if (!Array.isArray(openaiReq.messages) || openaiReq.messages.length === 0) { + return errorResponse(400, "invalid_request_error", "missing or invalid `messages` field"); } - const rawChatResp = await upstreamResp.text(); - let chatRespJson; + openaiReq.model = resolveModel(openaiReq, opts.config); + const clientWantsStream = openaiReq.stream === true; + let anthropicReq; try { - chatRespJson = JSON.parse(rawChatResp); + anthropicReq = translateRequestOpenAIToAnthropic(openaiReq); } catch (err) { - return errorResponse(502, "translation_failed", `upstream returned non-JSON body: ${err.message}`); + return errorResponse(400, "invalid_request_error", `OpenAI\u2192Anthropic translation failed: ${err.message}`); } - const responsesResp = chatCompletionsToResponses(chatRespJson, req.model, { - responseId, - meta, - ...typeof req.instructions === "string" ? { instructions: req.instructions } : {}, - ...prevId ? { previousResponseId: prevId } : {} - }); - if (req.store !== false && opts.responseStore) { - const stored = buildStoredResponse(responsesResp, input, req.instructions); - opts.responseStore.set(stored); + anthropicReq.stream = true; + const upstreamBodyText = transformRequestBody(JSON.stringify(anthropicReq), { format: "anthropic", userId: cred.cred.userId }) ?? JSON.stringify(anthropicReq); + const client = buildClient(opts, cred.credentials); + const taskId = generateTaskId(); + const ticket = await takeTicketOr502(client, taskId, opts, req.signal); + if (!ticket.ok) return ticket.response; + const { stream: rawStream, outcome } = buildBridge(opts, client, cred.credentials, upstreamBodyText, ticket.ticket, taskId, req); + void outcome; + if (clientWantsStream) { + const openaiStream = anthropicSseToOpenaiSseWithKeepalive(rawStream, openaiReq.model); + return new Response(openaiStream, { status: 200, headers: sseHeaders() }); } - if (debug) console.log(`[responses] \u2190 ${responsesResp.status} (${Date.now() - start2}ms)`); - return new Response(JSON.stringify(responsesResp), { + return new Response(nonStreamChunkedJson(rawStream, { translate: "openai", model: openaiReq.model }), { status: 200, - headers: { "content-type": "application/json" } + headers: { "content-type": "application/json; charset=utf-8", "cache-control": "no-cache", "transfer-encoding": "chunked" } }); } -function streamResponse(upstreamResp, context2) { - if (!upstreamResp.body) { - return errorResponse(502, "translation_failed", "upstream returned no body for stream"); +async function handleAsyncHealth(_req, opts) { + const cred = await resolveCredential(opts); + if (!cred.ok) return cred.response; + const client = buildClient(opts, cred.credentials); + try { + const avail = await client.getAvailability(); + return new Response(JSON.stringify(avail), { status: 200, headers: { "content-type": "application/json" } }); + } catch (err) { + return errorResponse(502, "async_health_failed", err.message); } - const state2 = newResponsesStreamState(context2.model, { meta: context2.meta, responseId: context2.responseId }); - const stream = new ReadableStream({ +} +function nonStreamChunkedJson(bridgeStream, translateOpts) { + const encoder2 = new TextEncoder(); + return new ReadableStream({ async start(controller) { - const encoder2 = new TextEncoder(); - const send = (evt) => controller.enqueue(encoder2.encode(responsesEventToSse(evt))); + const reader = bridgeStream.getReader(); + const decoder = new TextDecoder(); + let sseBuffer = ""; try { - const reader = upstreamResp.body.getReader(); - const decoder = new TextDecoder(); - let buffer2 = ""; - let errored = false; - for (; ; ) { - if (errored) break; + while (true) { const { done, value: value2 } = await reader.read(); if (done) break; - buffer2 += decoder.decode(value2, { stream: true }); - let nl; - while ((nl = buffer2.indexOf("\n\n")) >= 0) { - const frame = buffer2.slice(0, nl); - buffer2 = buffer2.slice(nl + 2); - const dataLine = extractSseData(frame); - if (!dataLine || dataLine === "[DONE]") continue; - try { - const chunk = JSON.parse(dataLine); - for (const evt of chatChunkToResponsesEvents(chunk, state2)) send(evt); - } catch (err) { - errored = true; - controller.error(err); - return; - } + try { + controller.enqueue(SINGLE_SPACE); + } catch { + return; } + sseBuffer += decoder.decode(value2, { stream: true }); } - const finalEvents = finalizeResponsesStream(state2); - for (const evt of finalEvents) send(evt); - const finalEvent = finalEvents.find((evt) => evt.type === "response.completed" || evt.type === "response.incomplete"); - if (finalEvent && context2.request.store !== false && context2.options.responseStore) { - context2.options.responseStore.set(buildStoredResponse(finalEvent.response, context2.input, context2.request.instructions)); - } - try { - controller.close(); - } catch { - } - } catch (err) { + sseBuffer += decoder.decode(); + } finally { + reader.releaseLock?.(); + } + const anthropicMsg = reconstructAnthropicBatch(sseBuffer); + if (!anthropicMsg) { + const errPayload = { error: { type: "async_aggregation_failed", message: "could not reconstruct response from bridge stream" } }; try { - controller.error(err); + controller.enqueue(encoder2.encode(JSON.stringify(errPayload))); } catch { } + controller.close(); + return; } - }, - cancel(reason2) { - context2.options.debug === true && console.log(`[responses] stream cancelled: ${String(reason2)}`); + const finalJson = translateOpts?.translate === "openai" ? JSON.stringify(translateResponseAnthropicToOpenAI(anthropicMsg, translateOpts.model)) : JSON.stringify(anthropicMsg); try { - upstreamResp.body?.cancel(); + controller.enqueue(encoder2.encode(finalJson)); } catch { } + controller.close(); } }); - return new Response(stream, { - status: 200, - headers: { - "content-type": "text/event-stream", - "cache-control": "no-cache", - connection: "keep-alive" - } - }); -} -function extractSseData(frame) { - for (const line of frame.split(/\r?\n/)) { - if (line.startsWith("data:")) return line.slice(5).replace(/^\s/, ""); - } - return null; -} -function resolveProviderDef(config) { - const base = getProvider(config.provider); - const endpoints = config.providers[config.provider]; - return { - ...base, - anthropicBaseURL: endpoints.anthropicBase, - openaiBaseURL: endpoints.openaiBase - }; -} -function outputItemsAsInputItems(outputs) { - return outputs; -} -function buildStoredResponse(resp, input, instructions) { - return { - id: resp.id, - model: resp.model, - status: resp.status === "completed" || resp.status === "incomplete" || resp.status === "failed" ? resp.status : "completed", - input, - output: resp.output, - usage: resp.usage, - instructions, - createdAt: Date.now(), - lastAccessedAt: Date.now() - }; -} - -// src/server/routes-responses.ts -async function handleResponsesRoute(req, opts) { - return handleResponses(req, opts); } - -// src/async/openai-stream-adapter.ts -function anthropicSseToOpenaiSseWithKeepalive(upstream, model = "glm-4.6") { - const encoder2 = new TextEncoder(); - const decoder = new TextDecoder(); - const state2 = initState(model); - let doneSent = false; - let errored = false; - function emit(out) { - if (errored) return; +function reconstructAnthropicBatch(sseText) { + const blocks = sseText.split("\n\n"); + let message = null; + const content2 = []; + let currentBlock = null; + let currentToolJson = ""; + let sawMessageStop = false; + let sawError = false; + for (const block of blocks) { + const lines = block.split("\n"); + let eventType; + let data2; + for (const line of lines) { + if (line.startsWith("event:")) eventType = line.slice(6).trim(); + else if (line.startsWith("data:")) data2 = line.slice(5).trim(); + } + if (!data2) continue; + let parsed; try { - controller0.enqueue(encoder2.encode(out)); + parsed = JSON.parse(data2); } catch { + continue; } - } - let controller0; - return new ReadableStream({ - start(controller) { - controller0 = controller; - const reader = upstream.getReader(); - let buffer2 = ""; - reader.read().then(function pump({ done, value: value2 }) { - if (done) { - if (buffer2.trim()) processBlock(buffer2, state2); - buffer2 = ""; - emitDone(); - try { - controller.close(); - } catch { - } - return; + const type2 = eventType ?? parsed.type; + switch (type2) { + case "message_start": { + const msg = parsed.message; + message = { ...msg ?? {} }; + break; + } + case "content_block_start": { + const cb = parsed.content_block; + if (!cb || !cb.type) break; + if (cb.type === "text") currentBlock = { type: "text", text: "" }; + else if (cb.type === "thinking") currentBlock = { type: "thinking", thinking: "" }; + else if (cb.type === "tool_use" && typeof cb.id === "string" && typeof cb.name === "string") { + currentBlock = { type: "tool_use", id: cb.id, name: cb.name, input: {} }; + currentToolJson = ""; } - buffer2 += decoder.decode(value2, { stream: true }); - const blocks = buffer2.split("\n\n"); - buffer2 = blocks.pop() ?? ""; - for (const block of blocks) { - processBlock(block, state2); - if (errored) { + break; + } + case "content_block_delta": { + const delta = parsed.delta; + if (!currentBlock || !delta) break; + if (delta.type === "text_delta" && currentBlock.type === "text" && typeof delta.text === "string") { + currentBlock.text += delta.text; + } else if (delta.type === "thinking_delta" && currentBlock.type === "thinking" && typeof delta.thinking === "string") { + currentBlock.thinking += delta.thinking; + } else if (delta.type === "signature_delta" && currentBlock.type === "thinking" && typeof delta.signature === "string") { + currentBlock.signature = (currentBlock.signature ?? "") + delta.signature; + } else if (delta.type === "input_json_delta" && currentBlock.type === "tool_use" && typeof delta.partial_json === "string") { + currentToolJson += delta.partial_json; + } + break; + } + case "content_block_stop": { + if (currentBlock) { + if (currentBlock.type === "tool_use") { try { - controller.close(); + currentBlock.input = JSON.parse(currentToolJson || "{}"); } catch { + currentBlock.input = {}; } - return; + currentToolJson = ""; } + content2.push(currentBlock); + currentBlock = null; } - return reader.read().then(pump); - }).catch((err) => { - if (!errored) { - const errPayload = JSON.stringify({ error: { message: `async stream error: ${err.message}`, type: "server_error" } }); - emit(`data: ${errPayload} + break; + } + case "message_delta": { + const delta = parsed.delta; + const usage = parsed.usage; + if (delta && message) Object.assign(message, delta); + if (usage && message) message.usage = { ...message.usage ?? { input_tokens: 0, output_tokens: 0 }, ...usage }; + break; + } + case "message_stop": + sawMessageStop = true; + break; + case "error": + sawError = true; + break; + default: + break; + } + } + if (sawError || !sawMessageStop || !message) return null; + message.content = content2; + if (!message.stop_reason) message.stop_reason = "end_turn"; + if (!message.role) message.role = "assistant"; + if (!message.usage) message.usage = { input_tokens: 0, output_tokens: 0 }; + return message; +} +var MAX_REQUEST_BODY_BYTES, SINGLE_SPACE; +var init_handler2 = __esm({ + "src/async/handler.ts"() { + "use strict"; + init_types(); + init_handler(); + init_body_transformer(); + init_openai_to_anthropic(); + init_openai_stream_adapter(); + init_client(); + init_bridge(); + MAX_REQUEST_BODY_BYTES = 4 * 1024 * 1024; + SINGLE_SPACE = new Uint8Array([32]); + } +}); -`); - emitDone(); - } - try { - controller.close(); - } catch { - } - }).finally(() => { - reader.releaseLock?.(); +// src/server/routes-async.ts +async function handleAsyncMessagesRoute(req, opts) { + return handleAsyncMessages(req, opts); +} +async function handleAsyncChatRoute(req, opts) { + return handleAsyncChat(req, opts); +} +async function handleAsyncHealthRoute(req, opts) { + return handleAsyncHealth(req, opts); +} +var init_routes_async = __esm({ + "src/server/routes-async.ts"() { + "use strict"; + init_handler2(); + } +}); + +// src/server/server.ts +function createFetchHandler(opts) { + const { config, auth } = opts; + const proxyOpts = { config, auth, fetchImpl: opts.fetchImpl, debug: opts.debug === true }; + const responsesOpts = { + config, + auth, + fetchImpl: opts.fetchImpl, + debug: opts.debug === true, + ...opts.responseStore ? { responseStore: opts.responseStore } : {} + }; + const asyncOpts = { + config, + auth, + fetchImpl: opts.fetchImpl, + debug: opts.debug === true + }; + return async (req) => { + const url2 = new URL(req.url); + const path2 = url2.pathname; + const method2 = req.method; + if (method2 === "OPTIONS") { + return corsResponse(); + } + if (method2 === "GET" && (path2 === "/webui" || path2.startsWith("/webui/"))) { + return new Response(webui_default, { + status: 200, + headers: { "content-type": "text/html; charset=utf-8", "cache-control": "no-cache" } }); } - }); - function processBlock(block, st) { - const trimmed = block.trim(); - if (trimmed === "") return; - if (trimmed.startsWith(":")) { - emit(block + "\n\n"); - return; + if (config.auth.proxyApiKey) { + const authHeader = req.headers.get("authorization") ?? req.headers.get("x-api-key"); + if (!authHeader || !checkProxyKey(authHeader, config.auth.proxyApiKey)) { + return errorResponse(401, "authentication_error", "Invalid or missing proxy API key"); + } + } + if (path2 === "/v1/chat/completions" && method2 === "POST") { + return handleChatCompletions(req, proxyOpts); + } + if (config.responses.enabled && path2 === "/v1/responses" && method2 === "POST") { + return handleResponsesRoute(req, responsesOpts); + } + if (path2 === "/v1/models" && method2 === "GET") { + return handleListModels(); + } + if (path2 === "/v1/messages" && method2 === "POST") { + return handleMessages(req, proxyOpts); + } + if (config.async.enabled) { + if (path2 === "/async/v1/messages" && method2 === "POST") { + return handleAsyncMessagesRoute(req, asyncOpts); + } + if (path2 === "/async/v1/chat/completions" && method2 === "POST") { + return handleAsyncChatRoute(req, asyncOpts); + } + if (path2 === "/async/v1/health" && method2 === "GET") { + return handleAsyncHealthRoute(req, asyncOpts); + } + } + if (path2 === "/health" || path2 === "/") { + return new Response(JSON.stringify({ status: "ok", provider: config.provider }), { + status: 200, + headers: { "content-type": "application/json" } + }); + } + return errorResponse(404, "not_found_error", `No route for ${method2} ${path2}`); + }; +} +function startServer(opts) { + const handler = createFetchHandler(opts); + const { port: requestedPort, host: host2 } = opts.config.server; + const server = (0, import_node_http.createServer)(async (req, res) => { + const abortController = new AbortController(); + const onClientClose = () => { + if (!res.writableEnded) abortController.abort(); + }; + res.on("close", onClientClose); + if ((req.url ?? "").startsWith("/async/")) { + req.setTimeout(24 * 60 * 60 * 1e3); } - if (trimmed.startsWith("event: error") || trimmed.startsWith("event:error")) { - const dataLine = block.split("\n").find((l) => l.startsWith("data:")); - let anthropicMsg = "unknown error"; - let anthropicType = "api_error"; - if (dataLine) { + try { + const webReq = nodeReqToWebRequest(req, abortController.signal); + const resp = await handler(webReq).then((r2) => addCorsHeaders(r2)); + await writeWebResponseToNodeResp(resp, res, abortController.signal); + } catch (err) { + if (abortController.signal.aborted) return; + if (!res.headersSent) { + res.writeHead(500, { "content-type": "application/json" }); + res.end(JSON.stringify({ error: { type: "internal_error", message: err.message } })); + } else { try { - const data2 = JSON.parse(dataLine.slice(5).trim()); - if (data2?.error?.message) anthropicMsg = String(data2.error.message); - if (data2?.error?.type) anthropicType = String(data2.error.type); + res.end(); } catch { } } - const oaiPayload = JSON.stringify({ error: { message: anthropicMsg, type: anthropicType } }); - emit(`data: ${oaiPayload} - -`); - emitDone(); - errored = true; - return; } - const parsed = parseSSEChunk(block); - for (const p of parsed) { - const out = translateEvent(st, p); - if (out) emit(out); + }); + server.requestTimeout = 6e5; + server.keepAliveTimeout = 12e4; + server.headersTimeout = 6e5; + return new Promise((resolve, reject) => { + server.on("error", reject); + server.listen(requestedPort, host2, () => { + const addr = server.address(); + const actualPort = typeof addr === "object" && addr ? addr.port : requestedPort; + resolve({ + hostname: host2, + port: actualPort, + stop: (exit) => { + server.close(); + if (exit) process.exit(0); + }, + close: () => new Promise((r2) => server.close(() => r2())) + }); + }); + }); +} +function nodeReqToWebRequest(req, signal2) { + const headers2 = new Headers(); + for (const [key, val] of Object.entries(req.headers)) { + if (val == null) continue; + if (Array.isArray(val)) { + for (const v of val) headers2.append(key, v); + } else { + headers2.set(key, val); } } - function emitDone() { - if (doneSent) return; - doneSent = true; - emit("data: [DONE]\n\n"); + const host2 = headers2.get("host") ?? "localhost"; + const url2 = `http://${host2}${req.url ?? "/"}`; + const method2 = req.method ?? "GET"; + if (method2 === "GET" || method2 === "HEAD") { + return new Request(url2, { method: method2, headers: headers2, signal: signal2 }); } + const bodyStream = import_node_stream.Readable.toWeb(req); + const init = { + method: method2, + headers: headers2, + body: bodyStream, + duplex: "half", + signal: signal2 + }; + return new Request(url2, init); } - -// src/async/types.ts -function isTicketReady(s) { - return s === "ready" || s === "active"; -} -function isTicketExpired(s) { - return s === "expired" || s === "not_found"; -} -var OffPeakServerError = class extends Error { - httpStatus; - bizCode; - constructor(message, httpStatus, bizCode) { - super(message); - this.name = "OffPeakServerError"; - this.httpStatus = httpStatus; - this.bizCode = bizCode; - } -}; - -// src/async/client.ts -var DEFAULT_CONTROL_TIMEOUT_MS = 15e3; -var MAX_BATCH_STATUS = 100; -function createOffPeakClient(opts) { - const origin = opts.origin.replace(/\/+$/, ""); - const credentials2 = opts.credentials; - const controlTimeoutMs = opts.controlTimeoutMs ?? DEFAULT_CONTROL_TIMEOUT_MS; - const settleTimeoutMs = opts.settleTimeoutMs ?? controlTimeoutMs; - const fetchImpl = opts.fetchImpl ?? globalThis.fetch; - function buildHeaders(hasBody) { - const h = { - authorization: `Bearer ${credentials2.jwt}`, - "x-coding-plan-api-key": credentials2.codingPlanApiKey - }; - if (hasBody) h["content-type"] = "application/json"; - if (credentials2.bigmodelOrganization) h["bigmodel-organization"] = credentials2.bigmodelOrganization; - if (credentials2.bigmodelProject) h["bigmodel-project"] = credentials2.bigmodelProject; - return h; - } - async function request(method2, path2, body2, timeoutMs, externalSignal, isSettle, settleAsSuccess) { - const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), timeoutMs); - const onExternalAbort = () => controller.abort(); - if (externalSignal) { - if (externalSignal.aborted) controller.abort(); - else externalSignal.addEventListener("abort", onExternalAbort, { once: true }); +async function writeWebResponseToNodeResp(resp, res, abortSignal) { + const headers2 = {}; + resp.headers.forEach((value2, key) => { + const existing = headers2[key]; + if (existing === void 0) { + headers2[key] = value2; + } else if (typeof existing === "string") { + headers2[key] = [existing, value2]; + } else { + existing.push(value2); } - const url2 = `${origin}/api/v1/off-peak${path2}`; - const init = { - method: method2, - headers: buildHeaders(body2 !== void 0), - signal: controller.signal - }; - if (body2 !== void 0) init.body = JSON.stringify(body2); - let resp; - let raw = ""; - try { - try { - resp = await fetchImpl(url2, init); - } catch (err) { - const msg = err?.message ?? String(err); - if (/abort/i.test(msg)) throw new OffPeakServerError(`off-peak request aborted: ${method2} ${path2}`, 0); - throw new OffPeakServerError(`off-peak network error: ${method2} ${path2}: ${msg}`, 0); + }); + res.writeHead(resp.status, resp.statusText, headers2); + if (resp.body == null) { + res.end(); + return; + } + const reader = resp.body.getReader(); + const onAbort = () => { + reader.cancel().catch(() => { + }); + }; + abortSignal?.addEventListener("abort", onAbort); + try { + while (true) { + const { done, value: value2 } = await reader.read(); + if (done) break; + if (!res.write(Buffer.from(value2))) { + await new Promise((resolve) => res.once("drain", () => resolve())); } - raw = await resp.text(); - } finally { - clearTimeout(timer); - externalSignal?.removeEventListener("abort", onExternalAbort); } - if (!resp.ok) { - if (isSettle && settleAsSuccess && resp.status >= 400 && resp.status < 500) { - return void 0; - } - let bizCode; - let serverMsg = `HTTP ${resp.status}`; + res.end(); + } catch (err) { + if (abortSignal?.aborted) { try { - const parsed = JSON.parse(raw); - bizCode = parsed?.code !== void 0 ? String(parsed.code) : void 0; - if (parsed?.msg) serverMsg = String(parsed.msg); - else if (parsed?.message) serverMsg = String(parsed.message); + res.end(); } catch { - if (raw.length > 0 && raw.length < 200) serverMsg = raw; } - throw new OffPeakServerError( - `off-peak ${method2} ${path2} failed: ${serverMsg}`, - resp.status, - bizCode - ); - } - if (raw.length === 0) return void 0; - let parsedJson; - try { - parsedJson = JSON.parse(raw); - } catch { - return void 0; - } - if (parsedJson && typeof parsedJson === "object") { - const obj = parsedJson; - if ("code" in obj || "data" in obj) { - const code = obj.code; - if (code !== 0) { - if (code === void 0) { - } else { - const msg = obj.msg ?? obj.message ?? `biz code ${String(code)}`; - throw new OffPeakServerError( - `off-peak ${method2} ${path2} biz error: ${msg}`, - resp?.status ?? 0, - String(code) - ); - } - } else if (obj.data !== void 0) { - return obj.data; - } + } else { + try { + res.destroy(err); + } catch { } } - return parsedJson; + } finally { + abortSignal?.removeEventListener("abort", onAbort); } - return { - async getAvailability(signal2) { - const data2 = await request("GET", "/ticket/availability", void 0, controlTimeoutMs, signal2, false, false); - if (!data2) throw new OffPeakServerError("off-peak availability empty response", 0); - const canTakeNumber = data2.can_take_number === true; - if (!canTakeNumber && data2.next_take_at === void 0) { - throw new OffPeakServerError("off-peak availability missing next_take_at while unavailable", 0); - } - const result3 = { canTakeNumber }; - if (data2.next_take_at !== void 0) result3.nextTakeAt = data2.next_take_at; - return result3; - }, - async takeTicket(taskId, signal2) { - if (!taskId || typeof taskId !== "string") { - throw new Error("takeTicket: taskId must be a non-empty string"); - } - const data2 = await request("POST", "/ticket", { task_id: taskId }, controlTimeoutMs, signal2, false, false); - if (!data2 || typeof data2.ticket_id !== "string" || typeof data2.state !== "string") { - throw new OffPeakServerError("off-peak takeTicket malformed response", 0); - } - const state2 = data2.state; - const result3 = { - ticketId: data2.ticket_id, - state: state2, - registeredAt: Date.now() - }; - if (data2.position != null) result3.position = data2.position; - if (data2.next_poll_after !== void 0) result3.nextPollAfterMs = data2.next_poll_after * 1e3; - return result3; - }, - async batchStatus(ticketIds, signal2) { - if (ticketIds.length === 0) return { tickets: [] }; - const truncated = ticketIds.slice(0, MAX_BATCH_STATUS); - const data2 = await request( - "POST", - "/ticket/status", - { ticket_ids: truncated }, - controlTimeoutMs, - signal2, - false, - false - ); - if (!data2 || !Array.isArray(data2.tickets)) { - throw new OffPeakServerError("off-peak batchStatus malformed response", 0); - } - const result3 = { - tickets: data2.tickets.map((t) => { - if (typeof t.ticket_id !== "string" || typeof t.state !== "string") { - throw new OffPeakServerError("off-peak batchStatus ticket entry malformed", 0); - } - const item = { - ticketId: t.ticket_id, - state: t.state - }; - if (t.position != null) item.position = t.position; - if (t.active_deadline !== void 0) item.activeDeadline = t.active_deadline; - return item; - }) - }; - if (data2.next_poll_after !== void 0) result3.nextPollAfterMs = data2.next_poll_after * 1e3; - return result3; - }, - async settle(ticketId, opts2 = {}) { - const settleAsSuccess = opts2.settleAsSuccess !== false; - await request( - "POST", - `/ticket/${encodeURIComponent(ticketId)}/settle`, - void 0, - settleTimeoutMs, - opts2.signal, - true, - settleAsSuccess - ); - } - }; } - -// src/async/keepalive.ts -function keepaliveFrame(text = "keepalive") { - const clean = text.replace(/[\r\n]/g, " "); - return new TextEncoder().encode(`: ${clean} - -`); +function checkProxyKey(authHeader, expected) { + const trimmed = authHeader.trim(); + if (trimmed.startsWith("Bearer ")) { + return trimmed.slice(7).trim() === expected; + } + return trimmed === expected; } - -// src/async/bridge.ts -init_identity(); -var EXPIRED_MARKER = "off-peak-ticket-expired"; -function runAsyncBridge(opts) { - const fetchImpl = opts.fetchImpl ?? globalThis.fetch; - const encoder2 = new TextEncoder(); - let outcomeResolve; - const outcome = new Promise((r2) => { - outcomeResolve = r2; +function corsResponse() { + return new Response(null, { + status: 204, + headers: corsHeaders() }); - let outcomeResolved = false; - function resolveOutcome(o) { - if (outcomeResolved) return; - outcomeResolved = true; - outcomeResolve(o); - } - let aborted2 = false; - const settledTickets = /* @__PURE__ */ new Set(); - function settleOnce(ticketId) { - if (settledTickets.has(ticketId)) return; - settledTickets.add(ticketId); - void opts.client.settle(ticketId).catch(() => { - }); - } - function log(info) { - try { - opts.onTransition?.(info); - } catch { - } +} +function addCorsHeaders(resp) { + const headers2 = new Headers(resp.headers); + for (const [k, v] of Object.entries(corsHeaders())) { + headers2.set(k, v); } - function emitKeepalive(controller) { - if (aborted2) return; - try { - controller.enqueue(keepaliveFrame()); - } catch { - } + return new Response(resp.body, { + status: resp.status, + statusText: resp.statusText, + headers: headers2 + }); +} +function corsHeaders() { + return { + "access-control-allow-origin": "*", + "access-control-allow-methods": "GET, POST, OPTIONS", + "access-control-allow-headers": "Content-Type, Authorization, x-api-key, anthropic-version, anthropic-beta", + "access-control-max-age": "86400" + }; +} +var import_node_http, import_node_stream; +var init_server = __esm({ + "src/server/server.ts"() { + "use strict"; + import_node_http = require("node:http"); + import_node_stream = require("node:stream"); + init_webui(); + init_routes_openai(); + init_routes_anthropic(); + init_routes_responses(); + init_routes_async(); + init_handler(); } - function emitTerminalError(controller, message, type2 = "api_error") { - if (aborted2) return; - const payload = JSON.stringify({ type: "error", error: { type: type2, message } }); - try { - controller.enqueue(encoder2.encode(`event: error -data: ${payload} +}); -`)); - } catch { - } +// src/auth/oauth.ts +async function requestZcodeEnvelope(fetchImpl, url2, init, label2) { + const resp = await fetchImpl(url2, init); + const raw = safeJsonParse(await resp.text()); + if (!raw || typeof raw.code !== "number") { + throw new Error(`${label2}: invalid response envelope (status=${resp.status})`); } - async function waitForReady(ticketId, deadlineAt) { - while (true) { - if (aborted2) return { state: "expired" }; - const result3 = await opts.client.batchStatus([ticketId], opts.clientSignal); - if (aborted2) return { state: "expired" }; - const ticket = result3.tickets[0]; - if (!ticket) return { state: "not_found" }; - if (isTicketReady(ticket.state)) return { state: ticket.state }; - if (ticket.state !== "queued") return { state: "expired" }; - const delay = result3.nextPollAfterMs ?? opts.pollIntervalMs; - if (opts.maxWaitMs > 0 && Date.now() + delay > deadlineAt) { - return { state: "expired" }; - } - await sleep(delay, opts.clientSignal); - } + if (!resp.ok || raw.code !== 0) { + throw new Error(`${label2} failed: status=${resp.status} msg=${raw.msg ?? "(none)"}`); } - async function forwardLLM(ticketId) { - const url2 = `${opts.origin.replace(/\/+$/, "")}/api/v1/off-peak/anthropic/v1/messages`; - const headers2 = { - "content-type": "application/json", - authorization: `Bearer ${opts.credentials.jwt}`, - "x-coding-plan-api-key": opts.credentials.codingPlanApiKey, - "x-off-peak-ticket-id": ticketId, - ...buildIdentityHeaders(opts.identity) - }; - if (opts.credentials.bigmodelOrganization) headers2["bigmodel-organization"] = opts.credentials.bigmodelOrganization; - if (opts.credentials.bigmodelProject) headers2["bigmodel-project"] = opts.credentials.bigmodelProject; - const resp = await fetchImpl(url2, { - method: "POST", - headers: headers2, - body: opts.llmRequestBody, - signal: opts.clientSignal - }); - if (!resp.ok) { - const bodyText = await resp.text().catch(() => ""); - if (bodyText.includes(EXPIRED_MARKER)) { - return { response: new Response(bodyText, { status: resp.status, headers: resp.headers }), expiredInBody: true }; - } - return { response: new Response(bodyText, { status: resp.status, headers: resp.headers }), expiredInBody: false }; - } - return { response: resp, expiredInBody: false }; + return raw.data; +} +function defaultSleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} +function safeJsonParse(text) { + try { + return JSON.parse(text); + } catch { + return null; } - const stream = new ReadableStream({ - async start(controller) { - if (opts.clientSignal) { - if (opts.clientSignal.aborted) aborted2 = true; - else opts.clientSignal.addEventListener("abort", () => { - aborted2 = true; - }, { once: true }); - } - let keepAliveTimer; - function startKeepalive() { - if (keepAliveTimer) return; - keepAliveTimer = setInterval(() => emitKeepalive(controller), opts.keepAliveIntervalMs); - } - function stopKeepalive() { - if (keepAliveTimer) { - clearInterval(keepAliveTimer); - keepAliveTimer = void 0; - } - } - const requestStartedAt = Date.now(); - const deadlineAt = opts.maxWaitMs > 0 ? requestStartedAt + opts.maxWaitMs : Number.MAX_SAFE_INTEGER; - let currentTicket = opts.initialTicket; - let attempt = 0; - try { - while (true) { - if (aborted2) { - log({ phase: "abort", attempt, ticketId: currentTicket.ticketId }); - settleOnce(currentTicket.ticketId); - return; - } - if (!isTicketReady(currentTicket.state)) { - log({ phase: "wait", attempt, ticketId: currentTicket.ticketId, state: currentTicket.state }); - startKeepalive(); - const wait = await waitForReady(currentTicket.ticketId, deadlineAt); - if (aborted2) { - stopKeepalive(); - log({ phase: "abort", attempt, ticketId: currentTicket.ticketId }); - settleOnce(currentTicket.ticketId); - return; - } - if (isTicketExpired(wait.state)) { - stopKeepalive(); - settleOnce(currentTicket.ticketId); - if (opts.maxWaitMs > 0 && Date.now() >= deadlineAt) { - emitTerminalError(controller, `async max wait timeout (${opts.maxWaitMs}ms exceeded)`, "timeout"); - resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - return; - } - log({ phase: "expired", attempt, ticketId: currentTicket.ticketId, state: wait.state, message: "expired in queue" }); - attempt++; - if (attempt > opts.maxRetries) { - emitTerminalError(controller, `async upstream exhausted retries (ticket expired in queue ${attempt}x)`, "api_error"); - resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - return; - } - try { - currentTicket = await opts.client.takeTicket(opts.taskId, opts.clientSignal); - } catch (takeErr) { - emitTerminalError(controller, `async retake failed: ${takeErr.message}`, "api_error"); - resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - return; - } - continue; - } - stopKeepalive(); - } - log({ phase: "ready", attempt, ticketId: currentTicket.ticketId }); - let resp; - let expiredInBody; - try { - const forward = await forwardLLM(currentTicket.ticketId); - resp = forward.response; - expiredInBody = forward.expiredInBody; - } catch (err) { - if (aborted2) { - settleOnce(currentTicket.ticketId); - return; - } - emitTerminalError(controller, `async upstream network error: ${err.message}`, "api_error"); - settleOnce(currentTicket.ticketId); - resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - return; +} +var import_node_http2, import_node_crypto3, ZCODE_API_BASE, ZCODE_TOKEN_ENDPOINT, BIGMODEL_HOST, BIGMODEL_APP_ID, LOGIN_TIMEOUT_MS, OAuthFlowClient, ZaiOAuthClient, AuthCodeOAuthClient, BIGMODEL_AUTH_CODE_CONFIG, BigmodelOAuthClient; +var init_oauth = __esm({ + "src/auth/oauth.ts"() { + "use strict"; + import_node_http2 = require("node:http"); + import_node_crypto3 = require("node:crypto"); + ZCODE_API_BASE = "https://zcode.z.ai/api/v1"; + ZCODE_TOKEN_ENDPOINT = `${ZCODE_API_BASE}/oauth/token`; + BIGMODEL_HOST = "https://bigmodel.cn"; + BIGMODEL_APP_ID = "zcode"; + LOGIN_TIMEOUT_MS = 3e5; + OAuthFlowClient = class { + constructor(provider, fetchImpl) { + this.provider = provider; + this.fetchImpl = fetchImpl; + } + provider; + fetchImpl; + /** Run the full flow end-to-end: surface authorize URL, wait, close. */ + async authorize(onAuthorizeUrl, timeoutMs = LOGIN_TIMEOUT_MS) { + const started = await this.start(); + onAuthorizeUrl?.(started.authorizeUrl); + try { + const tokens = await this.complete(started, timeoutMs); + return { accessToken: tokens.accessToken, provider: this.provider, userId: tokens.userId, jwt: tokens.jwt }; + } finally { + await this.close(); + } + } + }; + ZaiOAuthClient = class extends OAuthFlowClient { + constructor(fetchImpl = fetch, sleep2 = defaultSleep) { + super("zai", fetchImpl); + this.sleep = sleep2; + } + sleep; + flow = null; + pollToken = ""; + start() { + this.flow = null; + this.pollToken = (0, import_node_crypto3.randomBytes)(32).toString("hex"); + return (async () => { + const data2 = await requestZcodeEnvelope( + this.fetchImpl, + `${ZCODE_API_BASE}/oauth/cli/init`, + { + method: "POST", + headers: { authorization: `Bearer ${this.pollToken}`, "content-type": "application/json" }, + body: JSON.stringify({ provider: this.provider }) + }, + "Z.AI login init" + ); + if (!data2 || typeof data2.flow_id !== "string" || typeof data2.authorize_url !== "string" || typeof data2.expires_at !== "number" || typeof data2.poll_interval_sec !== "number") { + throw new Error("Z.AI login init: invalid response data"); } - if (!resp.ok || expiredInBody) { - const bodyText = await resp.text().catch(() => ""); - if (expiredInBody || bodyText.includes(EXPIRED_MARKER)) { - log({ phase: "expired", attempt, ticketId: currentTicket.ticketId, message: "expired during LLM (pre-stream)" }); - settleOnce(currentTicket.ticketId); - attempt++; - if (attempt > opts.maxRetries) { - emitTerminalError(controller, `async upstream exhausted retries (ticket expired during LLM ${attempt}x)`, "api_error"); - resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - return; - } - try { - currentTicket = await opts.client.takeTicket(opts.taskId, opts.clientSignal); - } catch (takeErr) { - emitTerminalError(controller, `async retake failed: ${takeErr.message}`, "api_error"); - resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - return; - } - continue; + this.flow = data2; + return { authorizeUrl: this.flow.authorize_url, callbackUrl: "", state: this.flow.flow_id }; + })(); + } + async complete(_started, timeoutMs = LOGIN_TIMEOUT_MS) { + const flow = this.flow; + if (!flow) throw new Error("Z.AI login not started"); + const deadlineMs = Math.min(Date.now() + timeoutMs, flow.expires_at * 1e3); + const intervalMs = Math.max(1e3, flow.poll_interval_sec * 1e3); + for (; ; ) { + if (Date.now() >= deadlineMs) { + throw new Error("Authorization timed out. Please retry login."); + } + const data2 = await requestZcodeEnvelope( + this.fetchImpl, + `${ZCODE_API_BASE}/oauth/cli/poll/${encodeURIComponent(flow.flow_id)}`, + { method: "GET", headers: { authorization: `Bearer ${this.pollToken}` } }, + "Z.AI login poll" + ); + if (data2?.status === "ready") { + const accessToken = typeof data2.zai?.access_token === "string" ? data2.zai.access_token.trim() : ""; + if (!accessToken) { + throw new Error("Z.AI login poll: response missing data.zai.access_token"); } - emitTerminalError(controller, `async upstream HTTP ${resp.status}`, "api_error"); - settleOnce(currentTicket.ticketId); - resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - return; + return { + accessToken, + jwt: typeof data2.token === "string" ? data2.token.trim() : void 0, + userId: typeof data2.user?.user_id === "string" ? data2.user.user_id : void 0 + }; } - let midStreamExpiredPreCommit = false; - let midStreamExpiredPostCommit = false; - let committed = false; - if (resp.body) { - const reader = resp.body.getReader(); - const streamDecoder = new TextDecoder(); - let pending = ""; - const MAX_PENDING_FRAME_BYTES = 1 * 1024 * 1024; - try { - while (true) { - if (aborted2) { - await reader.cancel().catch(() => { - }); - settleOnce(currentTicket.ticketId); - return; - } - const { done, value: value2 } = await reader.read(); - if (done) { - if (pending.length > 0 && !aborted2 && !midStreamExpiredPreCommit && !midStreamExpiredPostCommit) { - if (pending.includes(EXPIRED_MARKER)) { - if (!committed) midStreamExpiredPreCommit = true; - else midStreamExpiredPostCommit = true; - } else if (pending.endsWith("\n\n")) { - try { - controller.enqueue(encoder2.encode(pending)); - } catch { - } - } - pending = ""; - } - break; - } - if (aborted2) break; - pending += streamDecoder.decode(value2, { stream: true }).replace(/\r\n/g, "\n").replace(/\r/g, "\n"); - if (pending.length > MAX_PENDING_FRAME_BYTES) { - await reader.cancel().catch(() => { - }); - emitTerminalError(controller, "async upstream SSE frame exceeded 1 MiB boundary", "api_error"); - settleOnce(currentTicket.ticketId); - resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - return; - } - let frameBoundaryFound = false; - while (true) { - const idx = pending.indexOf("\n\n"); - if (idx === -1) break; - const frame = pending.slice(0, idx + 2); - pending = pending.slice(idx + 2); - if (frame.includes(EXPIRED_MARKER)) { - if (!committed) { - midStreamExpiredPreCommit = true; - } else { - midStreamExpiredPostCommit = true; - } - await reader.cancel().catch(() => { - }); - frameBoundaryFound = true; - break; - } - try { - controller.enqueue(encoder2.encode(frame)); - committed = true; - } catch { - await reader.cancel().catch(() => { - }); - frameBoundaryFound = true; - break; - } - } - if (midStreamExpiredPreCommit || midStreamExpiredPostCommit || frameBoundaryFound) break; - } - streamDecoder.decode(); - } finally { - reader.releaseLock?.(); - } + if (data2?.status === "failed") { + throw new Error("Authorization failed. Please retry login."); } - if (midStreamExpiredPreCommit && !aborted2) { - log({ phase: "expired", attempt, ticketId: currentTicket.ticketId, message: "expired during LLM (mid-stream, pre-commit)" }); - settleOnce(currentTicket.ticketId); - attempt++; - if (attempt > opts.maxRetries) { - emitTerminalError(controller, `async upstream exhausted retries (ticket expired mid-stream ${attempt}x)`, "api_error"); - resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - return; - } - try { - currentTicket = await opts.client.takeTicket(opts.taskId, opts.clientSignal); - } catch (takeErr) { - emitTerminalError(controller, `async retake failed: ${takeErr.message}`, "api_error"); - resolveOutcome({ attempts: attempt, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); + if (data2?.status !== "pending") { + throw new Error(`Z.AI login poll: unexpected status ${String(data2?.status ?? "(none)")}`); + } + await this.sleep(Math.min(intervalMs, Math.max(0, deadlineMs - Date.now()))); + } + } + async close() { + this.flow = null; + } + }; + AuthCodeOAuthClient = class extends OAuthFlowClient { + server = null; + callbackResult = null; + callbackWaiters = []; + constructor(config, fetchImpl = fetch) { + super(config.provider, fetchImpl); + this.config = config; + } + config; + /** Build the provider authorize URL with the localhost redirect + state. */ + buildAuthorizeUrl(callbackUrl, state2) { + const params = new URLSearchParams({ + appId: this.config.appId, + redirect: callbackUrl, + state: state2 + }); + return `${this.config.authorizeUrl}?${params.toString()}`; + } + /** + * Start the localhost callback server and return the authorize URL. + * Call `waitForCallback()` (or `authorize()`) afterwards, then `close()`. + * + * The bind port is `0` (OS-assigned random) unless the env var + * `ZCODE_OAUTH_CALLBACK_PORT` is set, in which case that exact port is used. + * The Android entry sets the env var so the Custom Tabs redirect URL is + * predictable across launches. + */ + start() { + const state2 = (0, import_node_crypto3.randomBytes)(32).toString("hex"); + const requestedPort = Number(process.env.ZCODE_OAUTH_CALLBACK_PORT ?? 0) || 0; + return new Promise((resolve, reject) => { + this.server = (0, import_node_http2.createServer)((req, res) => { + this.handleCallback(req, res, state2); + }); + this.server.on("error", (err) => { + this.server = null; + reject(err); + }); + this.server.listen(requestedPort, "127.0.0.1", () => { + const addr = this.server.address(); + if (!addr || typeof addr !== "object") { + reject(new Error("Failed to bind localhost callback server")); return; } - continue; - } - if (midStreamExpiredPostCommit && !aborted2) { - log({ phase: "error", attempt, ticketId: currentTicket.ticketId, message: "expired mid-stream after commit; cannot retry" }); - settleOnce(currentTicket.ticketId); - emitTerminalError(controller, "async upstream ticket expired mid-stream after output started", "api_error"); - resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - return; - } - if (aborted2) { - log({ phase: "abort", attempt, ticketId: currentTicket.ticketId }); - settleOnce(currentTicket.ticketId); - resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "abort" }); - return; + const callbackUrl = `http://127.0.0.1:${addr.port}${this.config.callbackPath}`; + const authorizeUrl = this.buildAuthorizeUrl(callbackUrl, state2); + resolve({ authorizeUrl, callbackUrl, state: state2 }); + }); + }); + } + handleCallback(req, res, expectedState) { + const url2 = new URL(req.url ?? "/", "http://127.0.0.1"); + if (url2.pathname !== this.config.callbackPath) { + res.writeHead(404, { "Content-Type": "text/plain" }); + res.end("Not found"); + return; + } + const state2 = url2.searchParams.get("state") ?? ""; + const code = url2.searchParams.get("authCode") ?? url2.searchParams.get("code") ?? ""; + if (state2 !== expectedState || !code) { + res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" }); + res.end("Authorization failed: state mismatch or missing code."); + if (!this.callbackResult) { + this.callbackResult = { code: "", error: "OAuth callback state mismatch or missing code." }; + this.callbackWaiters.forEach((fn) => fn(this.callbackResult)); } - log({ phase: "done", attempt, ticketId: currentTicket.ticketId }); - settleOnce(currentTicket.ticketId); - resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "done" }); return; } - } catch (err) { - if (!aborted2) { - emitTerminalError(controller, `async bridge internal error: ${err.message}`, "api_error"); + res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" }); + res.end("Authorization successful! You may close this window and return to the CLI."); + if (!this.callbackResult) { + this.callbackResult = { code, error: null }; + this.callbackWaiters.forEach((fn) => fn(this.callbackResult)); } - settleOnce(currentTicket.ticketId); - resolveOutcome({ attempts: attempt + 1, finalTicketId: currentTicket.ticketId, terminalPhase: "error" }); - } finally { - stopKeepalive(); + } + /** Wait for the OAuth callback redirect. Resolves with the auth code. */ + waitForCallback(timeoutMs = LOGIN_TIMEOUT_MS) { + if (this.callbackResult?.code) { + return Promise.resolve(this.callbackResult.code); + } + if (this.callbackResult?.error) { + return Promise.reject(new Error(this.callbackResult.error)); + } + return new Promise((resolve, reject) => { + const timer = setTimeout(() => { + reject(new Error("Authorization timed out. Please retry login.")); + }, timeoutMs); + this.callbackWaiters.push((result3) => { + clearTimeout(timer); + if (result3.error) { + reject(new Error(result3.error)); + } else { + resolve(result3.code); + } + }); + }); + } + /** + * Exchange the auth code at the shared zcode.z.ai token endpoint. + * The ZCode server holds the app secret and performs the real provider exchange. + * Returns `{ accessToken, userId, jwt }`. + */ + async exchangeCode(authCode, redirectUri, state2) { + const resp = await this.fetchImpl(this.config.tokenUrl, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ + provider: this.config.provider, + code: authCode, + redirect_uri: redirectUri, + state: state2 + }) + }); + const raw = safeJsonParse(await resp.text()); + if (!resp.ok || raw && typeof raw.code === "number" && raw.code !== 0) { + const label2 = this.config.provider; + throw new Error( + `${label2} token exchange failed: status=${resp.status} msg=${raw?.msg ?? "(none)"}` + ); + } + const providerToken = raw?.data?.[this.config.accessTokenField]; + const accessToken = providerToken?.access_token?.trim() ?? ""; + if (!accessToken) { + throw new Error(`${this.config.provider} token response missing data.${this.config.accessTokenField}.access_token`); + } + const userId = raw?.data?.user?.user_id; + const jwt = raw?.data?.token?.trim() ?? void 0; + return { accessToken, userId: typeof userId === "string" ? userId : void 0, jwt }; + } + /** Wait for the browser callback, then exchange the code. */ + async complete(started, timeoutMs = LOGIN_TIMEOUT_MS) { + const code = await this.waitForCallback(timeoutMs); + return this.exchangeCode(code, started.callbackUrl, started.state); + } + async close() { + if (this.server) { + const server = this.server; + this.server = null; + server.closeAllConnections?.(); + await new Promise((resolve) => { + server.close(() => resolve()); + }); + } + } + }; + BIGMODEL_AUTH_CODE_CONFIG = { + provider: "bigmodel", + authorizeUrl: `${BIGMODEL_HOST}/login`, + appId: BIGMODEL_APP_ID, + tokenUrl: ZCODE_TOKEN_ENDPOINT, + callbackPath: "/oauth/callback/bigmodel", + accessTokenField: "bigmodel" + }; + BigmodelOAuthClient = class extends AuthCodeOAuthClient { + constructor(fetchImpl = fetch, host2 = BIGMODEL_HOST, appId = BIGMODEL_APP_ID) { + super( + { ...BIGMODEL_AUTH_CODE_CONFIG, authorizeUrl: `${host2}/login`, appId }, + fetchImpl + ); + } + }; + } +}); + +// src/auth/resolver.ts +async function requestBizApi(fetchImpl, url2, authorization, init) { + const resp = await fetchImpl(url2, { + ...init, + headers: { + Authorization: authorization, + "Content-Type": "application/json", + ...init?.headers ?? {} + } + }); + if (!resp.ok) { + throw new Error(`Biz API ${url2} failed: ${resp.status}`); + } + const body2 = await resp.json(); + const code = body2.code ?? body2.status; + if (code != null && code !== 0 && code !== 200 && code !== "0" && code !== "200") { + throw new Error(body2.msg ?? `Biz API error ${code}`); + } + return body2.data ?? body2; +} +var ZAI_API_KEY_NAME, DEFAULT_ORG_MARKER, DEFAULT_PROJECT_MARKER, KeyResolver; +var init_resolver = __esm({ + "src/auth/resolver.ts"() { + "use strict"; + ZAI_API_KEY_NAME = "zcode-api-key"; + DEFAULT_ORG_MARKER = "\u9ED8\u8BA4\u673A\u6784"; + DEFAULT_PROJECT_MARKER = "\u9ED8\u8BA4\u9879\u76EE"; + KeyResolver = class { + constructor(fetchImpl = fetch) { + this.fetchImpl = fetchImpl; + } + fetchImpl; + async resolveZaiBizToken(accessToken) { + const resp = await this.fetchImpl("https://api.z.ai/api/auth/z/login", { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify({ token: accessToken }) + }); + if (!resp.ok) { + throw new Error(`z/login failed: ${resp.status}`); + } + const data2 = await resp.json(); + return data2.access_token ?? data2.accessToken ?? data2.data?.access_token; + } + async resolveCustomerInfo(host2, authorization) { + const data2 = await requestBizApi( + this.fetchImpl, + `${host2}/api/biz/customer/getCustomerInfo`, + authorization, + { method: "GET" } + ); + const orgs = data2.organizations ?? data2.orgs ?? []; + if (!Array.isArray(orgs) || orgs.length === 0) { + throw new Error("No organizations found"); + } + const org = orgs.find( + (o) => (o.organizationName ?? o.name ?? "").includes(DEFAULT_ORG_MARKER) + ) ?? orgs[0]; + const orgId = org.organizationId ?? org.id ?? org.orgId; + const projects = org.projects ?? []; + if (!Array.isArray(projects) || projects.length === 0) { + throw new Error("No projects found in default organization"); + } + const project = projects.find( + (p) => (p.projectName ?? p.name ?? "").includes(DEFAULT_PROJECT_MARKER) + ) ?? projects[0]; + const projectId = project.projectId ?? project.id; + return { orgId, projectId }; + } + async findOrCreateApiKey(host2, authorization, orgId, projectId) { + const listUrl = `${host2}/api/biz/v1/organization/${orgId}/projects/${projectId}/api_keys`; + let existing = []; try { - controller.close(); + existing = await requestBizApi(this.fetchImpl, listUrl, authorization, { method: "GET" }) ?? []; } catch { } - resolveOutcome({ - attempts: attempt + 1, - finalTicketId: currentTicket.ticketId, - terminalPhase: aborted2 ? "abort" : "error" + if (Array.isArray(existing)) { + const found = existing.find((k) => k.name === ZAI_API_KEY_NAME); + if (found?.apiKey) { + return { apiKey: found.apiKey }; + } + } + const created = await requestBizApi(this.fetchImpl, listUrl, authorization, { + method: "POST", + body: JSON.stringify({ name: ZAI_API_KEY_NAME }) }); + return { apiKey: created.apiKey }; + } + async getSecretKey(host2, authorization, orgId, projectId, apiKey) { + const url2 = `${host2}/api/biz/v1/organization/${orgId}/projects/${projectId}/api_keys/copy/${encodeURIComponent(apiKey)}`; + const data2 = await requestBizApi(this.fetchImpl, url2, authorization, { method: "GET" }); + return data2.secretKey ?? data2.secret_key ?? ""; + } + async resolveCodingPlanCredential(accessToken, provider, userId) { + if (provider === "zai") { + const bizToken = await this.resolveZaiBizToken(accessToken); + const host3 = "https://api.z.ai"; + const authorization2 = `Bearer ${bizToken}`; + const { orgId: orgId2, projectId: projectId2 } = await this.resolveCustomerInfo(host3, authorization2); + const { apiKey: apiKey2 } = await this.findOrCreateApiKey(host3, authorization2, orgId2, projectId2); + let secret; + try { + secret = await this.getSecretKey(host3, authorization2, orgId2, projectId2, apiKey2); + } catch { + } + return { apiKey: apiKey2, secret: secret || void 0, provider: "zai", userId }; + } + const host2 = "https://bigmodel.cn"; + const authorization = accessToken; + const { orgId, projectId } = await this.resolveCustomerInfo(host2, authorization); + const { apiKey } = await this.findOrCreateApiKey(host2, authorization, orgId, projectId); + let fullKey = apiKey; + try { + const secret = await this.getSecretKey(host2, authorization, orgId, projectId, apiKey); + if (secret) fullKey = `${apiKey}.${secret}`; + } catch { + } + return { apiKey: fullKey, provider: "bigmodel", userId }; } - }, - cancel() { - aborted2 = true; + }; + } +}); + +// src/auth/store.ts +function getEncryptionKey() { + const hash = new Uint8Array(new ArrayBuffer(32)); + const encoder2 = new TextEncoder(); + const seed2 = process.env[ENV_SECRET] ?? `${(0, import_node_os4.homedir)()}-${process.platform}-${process.arch}`; + const seedBytes = encoder2.encode(seed2); + for (let i = 0; i < seedBytes.length; i++) { + hash[i % 32] ^= seedBytes[i]; + } + return hash; +} +async function encrypt(plaintext) { + const key = await crypto.subtle.importKey( + "raw", + getEncryptionKey(), + { name: "AES-GCM" }, + false, + ["encrypt", "decrypt"] + ); + const iv = crypto.getRandomValues(new Uint8Array(12)); + const encoder2 = new TextEncoder(); + const encrypted = await crypto.subtle.encrypt( + { name: "AES-GCM", iv }, + key, + encoder2.encode(plaintext) + ); + const combined = new Uint8Array(iv.length + encrypted.byteLength); + combined.set(iv, 0); + combined.set(new Uint8Array(encrypted), iv.length); + return Buffer.from(combined).toString("base64"); +} +async function decrypt(ciphertext) { + const key = await crypto.subtle.importKey( + "raw", + getEncryptionKey(), + { name: "AES-GCM" }, + false, + ["encrypt", "decrypt"] + ); + const combined = Buffer.from(ciphertext, "base64"); + const iv = combined.slice(0, 12); + const data2 = combined.slice(12); + const decrypted = await crypto.subtle.decrypt( + { name: "AES-GCM", iv }, + key, + data2 + ); + return new TextDecoder().decode(decrypted); +} +async function saveCredential(cred) { + (0, import_node_fs4.mkdirSync)((0, import_node_path2.dirname)(STORE_FILE), { recursive: true }); + const json = JSON.stringify(cred); + const encrypted = await encrypt(json); + (0, import_node_fs4.writeFileSync)(STORE_FILE, JSON.stringify({ encrypted }), { mode: 384 }); +} +async function loadCredential() { + if (!(0, import_node_fs4.existsSync)(STORE_FILE)) return null; + const raw = (0, import_node_fs4.readFileSync)(STORE_FILE, "utf-8"); + const parsed = JSON.parse(raw); + if (!parsed.encrypted) return null; + try { + const json = await decrypt(parsed.encrypted); + return JSON.parse(json); + } catch (e) { + console.warn(`Ignoring corrupted or stale credentials at ${STORE_FILE}: ${e.message}`); + return null; + } +} +function clearCredential() { + if ((0, import_node_fs4.existsSync)(STORE_FILE)) { + (0, import_node_fs4.unlinkSync)(STORE_FILE); + } +} +function getStorePath() { + return STORE_FILE; +} +var import_node_fs4, import_node_path2, import_node_os4, STORE_DIR, STORE_FILE, ENV_SECRET; +var init_store = __esm({ + "src/auth/store.ts"() { + "use strict"; + import_node_fs4 = require("node:fs"); + import_node_path2 = require("node:path"); + import_node_os4 = require("node:os"); + STORE_DIR = (0, import_node_path2.join)((0, import_node_os4.homedir)(), ".zcode-proxy"); + STORE_FILE = (0, import_node_path2.join)(STORE_DIR, "credentials.json"); + ENV_SECRET = "ZCODE_PROXY_CREDENTIAL_SECRET"; + } +}); + +// src/android/control.ts +function startControlListener(opts) { + const logBuffer = opts.logBuffer ?? new LogBuffer(); + const server = (0, import_node_http3.createServer)(async (req, res) => { + try { + const result3 = await handleControlRequest(req, opts.state, { + onStartProxy: opts.onStartProxy, + onStopProxy: opts.onStopProxy, + onSetConfig: opts.onSetConfig, + onShutdown: opts.onShutdown, + logBuffer + }); + writeJson(res, result3.status, result3.body); + } catch (err) { + writeJson(res, 500, { ok: false, error: `internal_error: ${err.message}` }); } }); - return { stream, outcome }; + return new Promise((resolve, reject) => { + server.on("error", reject); + server.listen(opts.port, "127.0.0.1", () => resolve({ + close: () => new Promise((r2) => server.close(() => r2())) + })); + }); } -function sleep(ms, signal2) { - return new Promise((resolve) => { - if (signal2?.aborted) { - resolve(); - return; +async function handleControlRequest(req, state2, ctx) { + if (!isLoopback(req.socket.remoteAddress)) { + return { status: 403, body: { ok: false, error: "forbidden: non-loopback remote address" } }; + } + const parsed = new URL(req.url ?? "/", "http://127.0.0.1"); + if (req.method !== "POST" || parsed.pathname !== "/control") { + return { status: 404, body: { ok: false, error: `not_found: ${req.method} ${parsed.pathname}` } }; + } + const body2 = await readBody3(req); + let cmd; + try { + cmd = JSON.parse(body2); + } catch { + return { status: 400, body: { ok: false, error: "invalid_json" } }; + } + const result3 = await dispatch(cmd, state2, ctx); + return { status: 200, body: result3 }; +} +async function dispatch(cmd, state2, ctx) { + switch (cmd.cmd) { + case "status": { + const cred = await loadCredential().catch(() => null); + return { + ok: true, + state: "running", + provider: state2.provider, + plan: state2.plan, + proxyPort: state2.proxyPort, + loggedIn: cred != null + }; } - const t = setTimeout(() => { - signal2?.removeEventListener("abort", onAbort); - resolve(); - }, ms); - const onAbort = () => { - clearTimeout(t); - resolve(); - }; - signal2?.addEventListener("abort", onAbort, { once: true }); - }); + case "startOAuth": { + if (state2.activeOauth) { + await state2.activeOauth.client.close().catch(() => { + }); + state2.activeOauth = void 0; + } + const client = cmd.provider === "bigmodel" ? new BigmodelOAuthClient() : new ZaiOAuthClient(); + const started = await client.start(); + const callbackPort = started.callbackUrl ? Number(new URL(started.callbackUrl).port) || 80 : 0; + state2.activeOauth = { + client, + callbackUrl: started.callbackUrl, + state: started.state + }; + client.complete(started).then(async (tokens) => { + const resolver = new KeyResolver(); + const cred = await resolver.resolveCodingPlanCredential(tokens.accessToken, cmd.provider, tokens.userId); + if (tokens.jwt) cred.jwt = tokens.jwt; + await saveCredential(cred); + console.log(`OAuth completed for ${cmd.provider}`); + }).catch((err) => { + console.error(`OAuth flow ended without success: ${err?.message ?? String(err)}`); + }).finally(() => { + void client.close().catch(() => { + }); + if (state2.activeOauth?.state === started.state) state2.activeOauth = void 0; + }); + return { + ok: true, + event: "oauthUrl", + authorizeUrl: started.authorizeUrl, + callbackPort + }; + } + case "deliverOAuthCode": { + const active = state2.activeOauth; + if (!(active?.client instanceof AuthCodeOAuthClient) || active.state !== cmd.state) { + return { ok: false, error: "no_matching_oauth_flow" }; + } + try { + const { accessToken, userId, jwt } = await active.client.exchangeCode( + cmd.code, + active.callbackUrl, + cmd.state + ); + const resolver = new KeyResolver(); + const cred = await resolver.resolveCodingPlanCredential(accessToken, cmd.provider, userId); + if (jwt) cred.jwt = jwt; + await saveCredential(cred); + state2.activeOauth = void 0; + await active.client.close().catch(() => { + }); + return { ok: true, event: "loginOk", provider: cmd.provider }; + } catch (err) { + state2.activeOauth = void 0; + await active.client.close().catch(() => { + }); + return { ok: false, error: `oauth_exchange_failed: ${err.message}` }; + } + } + case "logout": { + await clearCredential(); + return { ok: true, event: "loggedOut" }; + } + case "setConfig": { + if (!ctx.onSetConfig) return { ok: false, error: "config_update_unavailable" }; + const result3 = await ctx.onSetConfig({ provider: cmd.provider, plan: cmd.plan }); + if (!result3.ok) return result3; + state2.provider = result3.provider; + state2.plan = result3.plan; + return { ok: true, event: "configUpdated", provider: result3.provider, plan: result3.plan }; + } + case "startProxy": { + if (!ctx.onStartProxy) return { ok: false, error: "proxy_lifecycle_unavailable" }; + const result3 = await ctx.onStartProxy(); + if (!result3.ok) return result3; + state2.proxyPort = result3.port; + return { ok: true, event: "proxyStarted", port: result3.port }; + } + case "stopProxy": { + if (!ctx.onStopProxy) return { ok: false, error: "proxy_lifecycle_unavailable" }; + const result3 = await ctx.onStopProxy(); + if (!result3.ok) return result3; + state2.proxyPort = 0; + return { ok: true, event: "proxyStopped" }; + } + case "getLogs": { + const since = typeof cmd.since === "number" ? cmd.since : 0; + const { nextSince, lines } = ctx.logBuffer.since(since); + return { ok: true, event: "logs", nextSince, lines: [...lines] }; + } + case "shutdown": { + if (ctx.onShutdown) await ctx.onShutdown(); + return { ok: true, event: "shuttingDown" }; + } + default: + return { ok: false, error: `unknown_cmd: ${cmd.cmd}` }; + } } - -// src/async/handler.ts -var MAX_REQUEST_BODY_BYTES = 4 * 1024 * 1024; -var SINGLE_SPACE = new Uint8Array([32]); -function buildCredentials(cred) { - return { - jwt: cred.jwt ?? "", - codingPlanApiKey: credentialString(cred) - }; +function isLoopback(addr) { + return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1"; } -function generateTaskId() { - return `proxy-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`; +function writeJson(res, status, body2) { + const json = JSON.stringify(body2); + res.writeHead(status, { + "content-type": "application/json; charset=utf-8", + "content-length": Buffer.byteLength(json) + }); + res.end(json); } -function resolveModel(req, config) { - const explicit = typeof req.model === "string" ? req.model.trim() : ""; - if (explicit) return explicit; - if (config.async.defaultModel && config.async.defaultModel.trim()) return config.async.defaultModel.trim(); - return config.defaultModel; +function readBody3(req) { + return new Promise((resolve, reject) => { + const chunks = []; + req.on("data", (c) => chunks.push(c)); + req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8"))); + req.on("error", reject); + }); } -async function readBody2(req) { - const contentLength2 = req.headers.get("content-length"); - if (contentLength2) { - const cl = parseInt(contentLength2, 10); - if (Number.isFinite(cl) && cl > MAX_REQUEST_BODY_BYTES) { - req.body?.cancel().catch(() => { - }); - return { ok: false, response: errorResponse(413, "request_too_large", `body exceeds ${MAX_REQUEST_BODY_BYTES} byte cap`) }; - } +var import_node_http3, LogBuffer; +var init_control = __esm({ + "src/android/control.ts"() { + "use strict"; + import_node_http3 = require("node:http"); + init_oauth(); + init_resolver(); + init_store(); + LogBuffer = class { + lines = []; + capacity; + nextSeq = 0; + constructor(capacity = 500) { + this.capacity = capacity; + } + push(line) { + this.lines.push(line); + this.nextSeq++; + if (this.lines.length > this.capacity) { + this.lines.splice(0, this.lines.length - this.capacity); + } + } + /** + * Returns lines whose logical sequence number is `>= since`, plus the + * next-since cursor (use as the next `since` value for incremental polling). + */ + since(since) { + const baseSeq = Math.max(0, this.nextSeq - this.lines.length); + const wantStart = Math.max(since, baseSeq); + const offset2 = wantStart - baseSeq; + if (offset2 >= this.lines.length) { + return { nextSince: this.nextSeq, lines: [] }; + } + return { nextSince: this.nextSeq, lines: this.lines.slice(offset2) }; + } + /** Returns all lines currently in the buffer. */ + snapshot() { + return this.lines; + } + /** Monotonic cursor; safe to expose externally. */ + get cursor() { + return this.nextSeq; + } + }; } - if (!req.body) { - return { ok: false, response: errorResponse(400, "invalid_request_error", "missing request body") }; +}); + +// src/config/edit.ts +function updateConfigYaml(path2, fields) { + const raw = (0, import_node_fs5.readFileSync)(path2, "utf-8"); + const parsed = (0, import_yaml2.parse)(raw) ?? {}; + parsed.provider = fields.provider; + parsed.plan = fields.plan; + (0, import_node_fs5.writeFileSync)(path2, (0, import_yaml2.stringify)(parsed), "utf-8"); +} +var import_yaml2, import_node_fs5; +var init_edit = __esm({ + "src/config/edit.ts"() { + "use strict"; + import_yaml2 = __toESM(require_dist(), 1); + import_node_fs5 = require("node:fs"); } - const reader = req.body.getReader(); - const chunks = []; - let total = 0; +}); + +// src/runtime/open-browser.ts +function openBrowser(url2) { try { - while (true) { - const { done, value: value2 } = await reader.read(); - if (done) break; - total += value2.byteLength; - if (total > MAX_REQUEST_BODY_BYTES) { - await reader.cancel().catch(() => { - }); - return { ok: false, response: errorResponse(413, "request_too_large", `body exceeds ${MAX_REQUEST_BODY_BYTES} byte cap`) }; - } - chunks.push(value2); + if (process.platform === "win32") { + (0, import_node_child_process.spawn)("cmd.exe", ["/c", `start "" "${url2}"`], { + detached: true, + stdio: "ignore", + windowsHide: true, + windowsVerbatimArguments: true + }).unref(); + } else if (process.platform === "darwin") { + (0, import_node_child_process.spawn)("open", [url2], { detached: true, stdio: "ignore" }).unref(); + } else { + (0, import_node_child_process.spawn)("xdg-open", [url2], { detached: true, stdio: "ignore" }).unref(); } } catch { - return { ok: false, response: errorResponse(400, "invalid_request_error", "could not read request body") }; - } finally { - reader.releaseLock?.(); } - const encoding = req.headers.get("content-encoding")?.toLowerCase().trim() ?? ""; - let bytes = Buffer.concat(chunks); - if (encoding === "gzip" || encoding === "x-gzip") { - const gunzip = new DecompressionStream("gzip"); - const source = new ReadableStream({ - start(controller) { - controller.enqueue(bytes); - controller.close(); +} +var import_node_child_process; +var init_open_browser = __esm({ + "src/runtime/open-browser.ts"() { + "use strict"; + import_node_child_process = require("node:child_process"); + } +}); + +// src/responses/store.ts +var DEFAULT_MAX_ENTRIES, DEFAULT_TTL_MS, ResponseStore; +var init_store2 = __esm({ + "src/responses/store.ts"() { + "use strict"; + DEFAULT_MAX_ENTRIES = 1e3; + DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3; + ResponseStore = class { + maxEntries; + ttlMs; + map = /* @__PURE__ */ new Map(); + constructor(opts = {}) { + this.maxEntries = opts.maxEntries ?? DEFAULT_MAX_ENTRIES; + this.ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS; } - }); - const inflateReader = source.pipeThrough(gunzip).getReader(); - const inflated = []; - let inflatedTotal = 0; - try { - for (; ; ) { - const { done, value: value2 } = await inflateReader.read(); - if (done) break; - inflatedTotal += value2.byteLength; - if (inflatedTotal > MAX_REQUEST_BODY_BYTES) { - await inflateReader.cancel().catch(() => { - }); - return { ok: false, response: errorResponse(413, "request_too_large", `decompressed body exceeds ${MAX_REQUEST_BODY_BYTES} byte cap`) }; + /** Store a response. Overwrites on duplicate id. Evicts LRU entries on overflow. */ + set(entry) { + const now = Date.now(); + entry.createdAt = now; + entry.lastAccessedAt = now; + if (this.map.has(entry.id)) this.map.delete(entry.id); + this.map.set(entry.id, entry); + while (this.map.size > this.maxEntries) { + const oldestKey = this.map.keys().next().value; + if (oldestKey === void 0) break; + this.map.delete(oldestKey); } - inflated.push(value2); } - bytes = Buffer.concat(inflated); - } catch { - return { ok: false, response: errorResponse(400, "invalid_request_error", "could not decompress gzip request body") }; - } finally { - inflateReader.releaseLock?.(); - } + /** + * Fetch a stored response. Returns `undefined` when missing or stale. + * Refreshes LRU position on hit. + */ + get(id2) { + const entry = this.map.get(id2); + if (!entry) return void 0; + const now = Date.now(); + if (now - entry.createdAt > this.ttlMs) { + this.map.delete(id2); + return void 0; + } + entry.lastAccessedAt = now; + this.map.delete(id2); + this.map.set(id2, entry); + return entry; + } + delete(id2) { + return this.map.delete(id2); + } + clear() { + this.map.clear(); + } + size() { + return this.map.size; + } + }; } - const body2 = new TextDecoder().decode(bytes); - if (!body2 || body2.length === 0) { - return { ok: false, response: errorResponse(400, "invalid_request_error", "empty request body") }; +}); + +// src/server/server-options.ts +function buildServerOptions(config, auth, debug) { + const opts = { config, auth, debug }; + if (config.responses.enabled) { + opts.responseStore = new ResponseStore({ maxEntries: config.responses.storeMaxEntries, ttlMs: config.responses.storeTtlMs }); } - return { ok: true, body: body2 }; + return opts; } -async function resolveCredential(opts) { - let cred; +var init_server_options = __esm({ + "src/server/server-options.ts"() { + "use strict"; + init_store2(); + } +}); + +// src/runtime/node-fetch-compat.ts +async function ensureNodeFetchNoTimeouts() { + if (typeof Bun !== "undefined") return; + if (applied) return; + applied = true; try { - cred = await opts.auth.getCredential(); + const { Agent, setGlobalDispatcher: setGlobalDispatcher2 } = await Promise.resolve().then(() => __toESM(require_undici(), 1)); + setGlobalDispatcher2(new Agent({ headersTimeout: 0, bodyTimeout: 0 })); } catch (err) { - return { ok: false, response: errorResponse(401, "authentication_error", `credential resolution failed: ${err.message}`) }; + console.error(`zcode-proxy: could not disable Node fetch default timeouts: ${err.message}`); } - if (!cred.jwt) { - return { - ok: false, - response: errorResponse( - 400, - "async_credentials_unavailable", - "async endpoints require a logged-in oauth credential (JWT missing). Re-run `auth login` or use sync /v1/* endpoints." - ) - }; +} +var applied; +var init_node_fetch_compat = __esm({ + "src/runtime/node-fetch-compat.ts"() { + "use strict"; + applied = false; } - return { ok: true, cred, credentials: buildCredentials(cred) }; +}); + +// src/tui/width.ts +function inRanges(cp, ranges) { + let lo = 0; + let hi = ranges.length - 1; + while (lo <= hi) { + const mid = lo + hi >> 1; + const [a, b] = ranges[mid]; + if (cp < a) hi = mid - 1; + else if (cp > b) lo = mid + 1; + else return true; + } + return false; } -function buildClient(opts, credentials2) { - return createOffPeakClient({ - origin: opts.config.async.origin, - credentials: credentials2, - controlTimeoutMs: opts.config.async.controlTimeoutMs, - settleTimeoutMs: opts.config.async.settleTimeoutMs, - fetchImpl: opts.fetchImpl - }); +function codePointWidth(cp) { + if (cp === 0) return 0; + if (cp < 32 || cp >= 127 && cp < 160) return 0; + if (inRanges(cp, ZERO_RANGES)) return 0; + if (inRanges(cp, WIDE_RANGES)) return 2; + return 1; } -async function takeTicketOr502(client, taskId, opts, signal2) { - try { - const ticket = await client.takeTicket(taskId, signal2); - return { ok: true, ticket }; - } catch (err) { - return { ok: false, response: errorResponse(502, "async_take_ticket_failed", `off-peak takeTicket failed: ${err.message}`) }; +function stripAnsi(s) { + return s.replace(ANSI_RE, ""); +} +function displayWidth(s) { + let w2 = 0; + for (const ch of stripAnsi(s)) { + w2 += codePointWidth(ch.codePointAt(0)); } + return w2; } -function buildBridge(opts, client, credentials2, llmRequestBody, initialTicket, taskId, req) { - return runAsyncBridge({ - client, - credentials: credentials2, - origin: opts.config.async.origin, - identity: opts.config.identity, - llmRequestBody, - initialTicket, - taskId, - pollIntervalMs: opts.config.async.pollIntervalMs, - keepAliveIntervalMs: opts.config.async.keepAliveIntervalMs, - maxRetries: opts.config.async.maxRetries, - maxWaitMs: opts.config.async.maxWaitMs, - clientSignal: req.signal, - fetchImpl: opts.fetchImpl, - onTransition: opts.debug ? (info) => { - console.log(`[async] task=${taskId} ticket=${info.ticketId} phase=${info.phase} attempt=${info.attempt}${info.state ? ` state=${info.state}` : ""}${info.message ? ` msg=${info.message}` : ""}`); - } : void 0 - }); +function truncateToWidth(s, max, ellipsis = "\u2026") { + if (max <= 0) return ""; + const plain = stripAnsi(s); + if (displayWidth(plain) <= max) return plain; + const ellWidth = displayWidth(ellipsis); + let w2 = 0; + let out = ""; + for (const ch of plain) { + const cw = codePointWidth(ch.codePointAt(0)); + if (w2 + cw > max - ellWidth) break; + out += ch; + w2 += cw; + } + return out + ellipsis; } -function sseHeaders() { - return { - "content-type": "text/event-stream; charset=utf-8", - "cache-control": "no-cache", - connection: "keep-alive" - }; +var ANSI_RE, WIDE_RANGES, ZERO_RANGES; +var init_width = __esm({ + "src/tui/width.ts"() { + "use strict"; + ANSI_RE = /\x1b(?:\[[0-9;?<=>! ]*[A-Za-z~@`\\]|\][^\x07\x1b]*(?:\x07|\x1b\\)?|[@-Z\\-_=>])/g; + WIDE_RANGES = [ + [4352, 4447], + [11904, 12350], + [12353, 13311], + [13312, 19903], + [19968, 40959], + [40960, 42182], + [43360, 43388], + [44032, 55203], + [63744, 64255], + [65040, 65049], + [65072, 65106], + [65108, 65126], + [65128, 65131], + [65281, 65376], + [65504, 65510], + [127744, 128591], + [128640, 128767], + [129280, 129535], + [131072, 196605], + [196608, 262141] + ]; + ZERO_RANGES = [ + [768, 879], + [8203, 8207], + [8400, 8447], + [65024, 65039] + ]; + } +}); + +// src/tui/log-pane.ts +var LogPane; +var init_log_pane = __esm({ + "src/tui/log-pane.ts"() { + "use strict"; + init_width(); + LogPane = class { + constructor(capacity = 2e3) { + this.capacity = capacity; + } + capacity; + lines = []; + nextSeq = 0; + /** Lines hidden below the viewport. 0 = follow the tail. */ + offset = 0; + /** + * Append a log record. ANSI escape sequences are stripped (proxy logs carry + * color codes; the pane applies its own) and embedded newlines split into + * separate rows so multi-line records scroll naturally. + */ + push(text, level = "info") { + const clean = stripAnsi(String(text)).replace(/\r/g, ""); + const parts = clean.split("\n"); + if (parts.length > 1 && parts[parts.length - 1] === "") parts.pop(); + for (const part of parts) { + this.lines.push({ seq: this.nextSeq++, level, text: part }); + } + if (this.lines.length > this.capacity) { + this.lines.splice(0, this.lines.length - this.capacity); + } + } + get count() { + return this.lines.length; + } + /** True when the viewport is pinned to the newest lines. */ + get following() { + return this.offset === 0; + } + scrollUp(n) { + this.offset = Math.min(this.lines.length, this.offset + Math.max(0, n)); + } + scrollDown(n) { + this.offset = Math.max(0, this.offset - Math.max(0, n)); + } + /** Jump back to the tail (re-enable following). */ + followBottom() { + this.offset = 0; + } + clear() { + this.lines = []; + this.offset = 0; + } + /** Slice of lines currently visible in a viewport `height` rows tall. */ + view(height2) { + const rows2 = Math.max(1, height2); + const end2 = Math.max(Math.min(rows2, this.lines.length), this.lines.length - this.offset); + const start2 = Math.max(0, end2 - rows2); + return { + lines: this.lines.slice(start2, end2), + total: this.lines.length, + fromBottom: this.lines.length - end2 + }; + } + }; + } +}); + +// src/tui/keys.ts +function csiAction(final, params) { + if (params.startsWith("<")) return mouseAction(params.slice(1), final); + switch (final) { + case "A": + return { type: "up" }; + case "B": + return { type: "down" }; + case "H": + return { type: "home" }; + case "F": + return { type: "end" }; + case "~": + if (params === "5" || params === "5;5") return { type: "pageup" }; + if (params === "6" || params === "6;5") return { type: "pagedown" }; + if (params === "1" || params === "7") return { type: "home" }; + if (params === "4" || params === "8") return { type: "end" }; + return { type: "ignore" }; + default: + return { type: "ignore" }; + } } -async function handleAsyncMessages(req, opts) { - const cred = await resolveCredential(opts); - if (!cred.ok) return cred.response; - const bodyResult = await readBody2(req); - if (!bodyResult.ok) return bodyResult.response; - let parsedBody; - try { - const raw = JSON.parse(bodyResult.body); - if (raw === null || typeof raw !== "object" || Array.isArray(raw)) { - return errorResponse(400, "invalid_request_error", "request body must be a JSON object"); - } - parsedBody = raw; - } catch { - return errorResponse(400, "invalid_request_error", "request body is not valid JSON"); +function mouseAction(params, final) { + if (final !== "M") return { type: "ignore" }; + const parts = params.split(";"); + const button = Number(parts[0]); + const x3 = Number(parts[1]); + const y3 = Number(parts[2]); + if (!Number.isFinite(button) || !Number.isFinite(x3) || !Number.isFinite(y3)) { + return { type: "ignore" }; + } + if (button === 0) return { type: "click", x: x3 - 1, y: y3 - 1 }; + if (button === 64) return { type: "wheel-up" }; + if (button === 65) return { type: "wheel-down" }; + return { type: "ignore" }; +} +var KeyParser; +var init_keys = __esm({ + "src/tui/keys.ts"() { + "use strict"; + KeyParser = class { + pending = ""; + /** Consume a raw stdin chunk and return the actions it completes. */ + feed(chunk) { + const buf = this.pending + chunk; + const actions = []; + let i = 0; + while (i < buf.length) { + const ch = buf[i]; + if (ch === "\x1B") { + if (i + 1 >= buf.length) break; + if (buf[i + 1] === "[") { + let j = i + 2; + while (j < buf.length && !/[A-Za-z~]/.test(buf[j])) j++; + if (j >= buf.length) break; + actions.push(csiAction(buf[j], buf.slice(i + 2, j))); + i = j + 1; + continue; + } + if (buf[i + 1] === "O") { + if (i + 2 >= buf.length) break; + actions.push(csiAction(buf[i + 2], "")); + i += 3; + continue; + } + actions.push({ type: "ignore" }); + i += 2; + continue; + } + if (ch === "") { + actions.push({ type: "ctrl-c" }); + i++; + continue; + } + if (ch < " " || ch === "\x7F") { + actions.push({ type: "ignore" }); + i++; + continue; + } + actions.push({ type: "char", key: ch }); + i++; + } + this.pending = buf.slice(i); + return actions; + } + }; } - if (!Array.isArray(parsedBody.messages) || parsedBody.messages.length === 0) { - return errorResponse(400, "invalid_request_error", "missing or invalid `messages` field"); +}); + +// src/tui/frame.ts +function findRegion(regions, row, col) { + for (const r2 of regions) { + if (r2.row === row && col >= r2.col && col < r2.col + r2.width) return r2.action; } - const clientWantsStream = parsedBody.stream === true; - const modelStr = typeof parsedBody.model === "string" ? parsedBody.model : void 0; - const upstreamBody = { - ...parsedBody, - model: resolveModel({ model: modelStr }, opts.config), - stream: true + return null; +} +function paint(code, t) { + return `\x1B[${code}m${t}\x1B[0m`; +} +function segWidth(segs) { + let w2 = 0; + for (const s of segs) w2 += displayWidth(s.t); + return w2; +} +function paintSegs(segs) { + return segs.map((s) => s.c ? paint(s.c, s.t) : s.t).join(""); +} +function segPlain(segs) { + return segs.map((s) => s.t).join(""); +} +function renderTopBorder(w2, left, right = []) { + let l = left; + let r2 = right; + if (r2.length === 0) { + if (5 + segWidth(l) > w2 - 1) l = [{ t: truncateToWidth(segPlain(l), Math.max(0, w2 - 7)) }]; + const fill2 = Math.max(1, w2 - 5 - segWidth(l)); + return paint(DIM, "\u256D\u2500 ") + paintSegs(l) + paint(DIM, ` ${"\u2500".repeat(fill2)}\u256E`); + } + const lw = segWidth(l); + const rw = segWidth(r2); + let fill = w2 - 8 - lw - rw; + if (fill < 1) { + const budget = Math.max(0, w2 - 9 - lw); + r2 = [{ t: truncateToWidth(segPlain(r2), budget) }]; + fill = Math.max(1, w2 - 8 - lw - segWidth(r2)); + if (fill < 1) { + l = [{ t: truncateToWidth(segPlain(l), Math.max(0, w2 - 8 - segWidth(r2))) }]; + fill = Math.max(1, w2 - 8 - segWidth(l) - segWidth(r2)); + } + } + return paint(DIM, "\u256D\u2500 ") + paintSegs(l) + paint(DIM, ` ${"\u2500".repeat(fill)} `) + paintSegs(r2) + paint(DIM, " \u2500\u256E"); +} +function renderBottomBorder(w2) { + return paint(DIM, `\u2570${"\u2500".repeat(Math.max(0, w2 - 2))}\u256F`); +} +function composeRow(w2, row, label2, parts, opts = {}) { + const chrome = opts.chrome !== false; + const contentW = Math.max(0, w2 - (chrome ? 4 : 2)); + const prefixPlain = label2 !== null ? " ".repeat(2) + label2.padEnd(LABEL_W - 2) : " ".repeat(2); + const prefixW = displayWidth(prefixPlain); + const prefixPainted = label2 !== null ? paint(DIM, prefixPlain) : prefixPlain; + const regions = []; + const painted = []; + let col = prefixW; + for (const p of parts) { + const pw = displayWidth(p.t); + if (col + pw > contentW) break; + if (p.action) regions.push({ row, col: (chrome ? 2 : 0) + col, width: pw, action: p.action }); + painted.push(p.c ? paint(p.c, p.t) : p.t); + col += pw; + } + if (!chrome) { + return { line: prefixPainted + painted.join(""), regions }; + } + const pad = " ".repeat(Math.max(0, contentW - col)); + return { + line: `${paint(DIM, "\u2502")} ${prefixPainted}${painted.join("")}${pad} ${paint(DIM, "\u2502")}`, + regions }; - const upstreamBodyText = transformRequestBody(JSON.stringify(upstreamBody), { format: "anthropic", userId: cred.cred.userId }) ?? JSON.stringify(upstreamBody); - const client = buildClient(opts, cred.credentials); - const taskId = generateTaskId(); - const ticket = await takeTicketOr502(client, taskId, opts, req.signal); - if (!ticket.ok) return ticket.response; - const { stream, outcome } = buildBridge(opts, client, cred.credentials, upstreamBodyText, ticket.ticket, taskId, req); - void outcome; - if (clientWantsStream) { - return new Response(stream, { status: 200, headers: sseHeaders() }); - } - return new Response(nonStreamChunkedJson(stream), { - status: 200, - headers: { "content-type": "application/json; charset=utf-8", "cache-control": "no-cache", "transfer-encoding": "chunked" } +} +function optionParts(slots, selected, makeAction, disabled2) { + const parts = []; + slots.forEach((v, i) => { + if (i > 0) parts.push({ t: " " }); + parts.push({ + t: ` ${v} `, + c: disabled2 ? DIM : v === selected ? BTN_SELECTED : BTN_GRAY, + action: disabled2 ? void 0 : makeAction(v) + }); }); + if (disabled2) parts.push({ t: " " }, { t: "(stop to switch)", c: AMBER }); + return parts; } -async function handleAsyncChat(req, opts) { - const cred = await resolveCredential(opts); - if (!cred.ok) return cred.response; - const bodyResult = await readBody2(req); - if (!bodyResult.ok) return bodyResult.response; - let openaiReq; - try { - openaiReq = JSON.parse(bodyResult.body); - } catch { - return errorResponse(400, "invalid_request_error", "request body is not valid JSON"); +function logLineCode(level) { + if (level === "error") return RED; + if (level === "warn") return AMBER; + return void 0; +} +function buildFrame(s) { + const w2 = s.width; + const h = s.height; + const regions = []; + const lines = []; + const emit = (line) => { + lines.push(line + "\x1B[0m\x1B[K"); + return lines.length - 1; + }; + if (w2 < 40 || h < 14) { + emit("zcode-proxy: terminal too small for the TUI."); + emit(` need >= 40x14, got ${w2}x${h}`); + return { text: lines.join("\n") + "\x1B[0m\x1B[J", regions }; + } + const pill = s.loginInFlight ? [{ t: "\u25CF logging in\u2026", c: AMBER }] : s.loggedIn ? [{ t: "\u25CF ready", c: GREEN }] : [{ t: "\u25CF logged out", c: AMBER }]; + const busy = s.serverStatus === "running" || s.serverStatus === "starting"; + emit(renderTopBorder(w2, [{ t: "Settings & Login", c: BOLD }], pill)); + const providerRow = composeRow( + w2, + lines.length, + "Provider", + optionParts( + ["zai", "bigmodel"], + s.provider, + (v) => ({ kind: "provider", value: v }), + busy + ) + ); + emit(providerRow.line); + regions.push(...providerRow.regions); + const planRow = composeRow( + w2, + lines.length, + "Plan", + optionParts( + ["coding-plan", "start-plan"], + s.plan, + (v) => ({ kind: "plan", value: v }), + busy + ) + ); + emit(planRow.line); + regions.push(...planRow.regions); + const authSegs = s.loggedIn ? [{ t: "\u25CF ", c: GREEN }, { t: `logged in \xB7 ${s.apiKeyPreview}` }] : [{ t: "\u25CB not logged in", c: AMBER }]; + emit(composeRow(w2, lines.length, "Auth", authSegs.map((g) => ({ t: g.t, c: g.c }))).line); + const loginRow = composeRow(w2, lines.length, "", s.loginInFlight ? [{ t: " Logging in\u2026 ", c: DIM }] : s.loggedIn ? [ + { t: " Logged In ", c: DIM }, + { t: " " }, + { t: " Logout ", c: BTN_GRAY, action: { kind: "key", key: "o" } } + ] : [ + { t: " OAuth Login ", c: BTN_GREEN, action: { kind: "key", key: "l" } }, + { t: " " }, + { t: " Logout ", c: DIM } + ]); + emit(loginRow.line); + regions.push(...loginRow.regions); + if (s.loginInFlight && s.loginHint) { + emit(composeRow(w2, lines.length, "Login", [{ t: `\xBB ${s.loginHint}`, c: AMBER }]).line); + } + emit(renderBottomBorder(w2)); + emit(""); + emit(renderTopBorder(w2, [{ t: "Proxy Server", c: BOLD }])); + const statusSegs = s.serverStatus === "running" ? [{ t: "\u25CF running", c: GREEN }, { t: " " + s.serverUrl, c: CYAN }] : s.serverStatus === "starting" ? [{ t: "\u25CF starting\u2026", c: AMBER }] : s.serverStatus === "error" ? [{ t: "\u2717 failed", c: RED }] : [{ t: "\u25CB stopped", c: DIM }]; + emit(composeRow(w2, lines.length, "Status", statusSegs.map((g) => ({ t: g.t, c: g.c }))).line); + const configText = [ + `${s.provider} \xB7 ${s.plan} \xB7 ${s.modelCount} models`, + s.responsesEnabled ? "/v1/responses" : "", + s.claimAuto ? "claim:auto" : "", + `v${s.version}` + ].filter(Boolean).join(" \xB7 "); + emit(composeRow(w2, lines.length, "Config", [{ t: configText, c: DIM }]).line); + const startEnabled = s.serverStatus === "stopped" || s.serverStatus === "error"; + const stopEnabled = s.serverStatus === "running"; + const serverButtonsRow = composeRow(w2, lines.length, "", [ + { t: " Start ", c: startEnabled ? BTN_GREEN : DIM, action: startEnabled ? { kind: "key", key: "s" } : void 0 }, + { t: " " }, + { t: " Stop ", c: stopEnabled ? BTN_RED : DIM, action: stopEnabled ? { kind: "key", key: "s" } : void 0 } + ]); + emit(serverButtonsRow.line); + regions.push(...serverButtonsRow.regions); + if (s.serverStatus === "error" && s.serverError) { + emit(composeRow(w2, lines.length, "Error", [{ t: s.serverError, c: RED }]).line); + } + emit(renderBottomBorder(w2)); + emit(""); + const logRight = s.logFollowing ? [{ t: "following", c: GREEN }] : [{ t: `\u25BC ${s.logFromBottom} more \xB7 g follow`, c: AMBER }]; + const fixed = lines.length + 2 + 1 + (s.toast ? 1 : 0); + const logRows = Math.max(1, h - fixed); + const logBorderRow = emit(renderTopBorder(w2, [{ t: "Logs", c: BOLD }, { t: ` (${s.logTotal})`, c: DIM }], logRight)); + if (!s.logFollowing) { + regions.push({ row: logBorderRow, col: 0, width: w2, action: { kind: "follow" } }); + } + if (s.logView.length === 0) { + emit(composeRow(w2, lines.length, null, [{ t: "(no logs yet \u2014 start the server and send requests)", c: DIM }]).line); + } else { + for (const line of s.logView.slice(-logRows)) { + emit(composeRow(w2, lines.length, null, [{ t: truncateToWidth(line.text, w2 - 6), c: logLineCode(line.level) }]).line); + } + } + emit(renderBottomBorder(w2)); + if (s.toast) { + const color = s.toast.kind === "ok" ? GREEN : s.toast.kind === "err" ? RED : CYAN; + emit(" " + paint(color, truncateToWidth(`\u25B8 ${s.toast.text}`, w2 - 2))); + } + const footerRow = lines.length; + const footerParts = []; + const footerItems = [ + ["s", "start/stop"], + ["l", "login"], + ["o", "logout"], + ["g", "follow"], + ["q", "quit"], + ["p", "provider"], + ["t", "plan"], + ["c", "clear"] + ]; + footerParts.push({ t: "\u2191\u2193 scroll", c: DIM }); + for (const [key, label2] of footerItems) { + footerParts.push({ t: " \xB7 ", c: DIM }); + footerParts.push({ t: `[${key}] ${label2}`, c: DIM, action: { kind: "key", key } }); + } + const footer = composeRow(w2, footerRow, null, footerParts, { chrome: false }); + emit(footer.line); + regions.push(...footer.regions); + return { text: lines.join("\n") + "\x1B[0m\x1B[J", regions }; +} +var DIM, RED, GREEN, AMBER, CYAN, BOLD, LABEL_W, BTN_GREEN, BTN_RED, BTN_BLUE, BTN_GRAY, BTN_SELECTED; +var init_frame = __esm({ + "src/tui/frame.ts"() { + "use strict"; + init_width(); + DIM = "90"; + RED = "31"; + GREEN = "32"; + AMBER = "33"; + CYAN = "36"; + BOLD = "1"; + LABEL_W = 12; + BTN_GREEN = "38;2;255;255;255;48;2;35;134;54"; + BTN_RED = "38;2;255;255;255;48;2;218;54;51"; + BTN_BLUE = "38;2;255;255;255;48;2;31;111;235"; + BTN_GRAY = "38;2;201;209;217;48;2;48;54;61"; + BTN_SELECTED = BTN_BLUE; } - if (!Array.isArray(openaiReq.messages) || openaiReq.messages.length === 0) { - return errorResponse(400, "invalid_request_error", "missing or invalid `messages` field"); +}); + +// src/claim/types.ts +function classifyClaimCode(code) { + switch (typeof code === "string" ? Number.parseInt(code, 10) : code) { + case 1001: + return "not_found"; + case 1002: + return "unavailable"; + case 1003: + return "already_claimed"; + case 1004: + return "ineligible"; + case 1005: + return "quota_exhausted"; + case 3001: + return "invalid_request"; + case 3007: + return "captcha"; + case 401: + return "login_required"; + default: + return "unknown"; } - openaiReq.model = resolveModel(openaiReq, opts.config); - const clientWantsStream = openaiReq.stream === true; - let anthropicReq; - try { - anthropicReq = translateRequestOpenAIToAnthropic(openaiReq); - } catch (err) { - return errorResponse(400, "invalid_request_error", `OpenAI\u2192Anthropic translation failed: ${err.message}`); +} +var init_types3 = __esm({ + "src/claim/types.ts"() { + "use strict"; } - anthropicReq.stream = true; - const upstreamBodyText = transformRequestBody(JSON.stringify(anthropicReq), { format: "anthropic", userId: cred.cred.userId }) ?? JSON.stringify(anthropicReq); - const client = buildClient(opts, cred.credentials); - const taskId = generateTaskId(); - const ticket = await takeTicketOr502(client, taskId, opts, req.signal); - if (!ticket.ok) return ticket.response; - const { stream: rawStream, outcome } = buildBridge(opts, client, cred.credentials, upstreamBodyText, ticket.ticket, taskId, req); - void outcome; - if (clientWantsStream) { - const openaiStream = anthropicSseToOpenaiSseWithKeepalive(rawStream, openaiReq.model); - return new Response(openaiStream, { status: 200, headers: sseHeaders() }); +}); + +// src/claim/client.ts +function createClaimClient(opts) { + const origin = opts.origin.replace(/\/+$/, ""); + const jwt = opts.jwt?.trim() || void 0; + const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS; + const fetchImpl = opts.fetchImpl ?? globalThis.fetch; + const identityHeaders = opts.identity ? Object.fromEntries( + Object.entries(buildIdentityHeaders(opts.identity)).filter(([name2]) => name2 !== "X-ZCode-Agent") + ) : { "X-ZCode-App-Version": opts.appVersion, "X-Platform": opts.platform }; + function parseEntitlement(c) { + const entitlementId = c.entitlement_id?.trim() ?? ""; + if (!entitlementId) return null; + const e = { + entitlementId, + showName: c.show_name?.trim() ?? "", + meter: c.meter?.trim() ?? "", + unitType: c.unit_type?.trim() ?? "", + capabilities: Array.isArray(c.capabilities) ? c.capabilities : [], + grantUnits: Number.isFinite(c.grant_units) ? c.grant_units : 0, + period: c.period?.trim() ?? "", + priority: Number.isFinite(c.priority) ? c.priority : 0 + }; + if (Number.isFinite(c.effective_at)) e.effectiveAt = c.effective_at; + return e; } - return new Response(nonStreamChunkedJson(rawStream, { translate: "openai", model: openaiReq.model }), { - status: 200, - headers: { "content-type": "application/json; charset=utf-8", "cache-control": "no-cache", "transfer-encoding": "chunked" } - }); -} -async function handleAsyncHealth(_req, opts) { - const cred = await resolveCredential(opts); - if (!cred.ok) return cred.response; - const client = buildClient(opts, cred.credentials); - try { - const avail = await client.getAvailability(); - return new Response(JSON.stringify(avail), { status: 200, headers: { "content-type": "application/json" } }); - } catch (err) { - return errorResponse(502, "async_health_failed", err.message); + function parsePlan(p) { + const planId = p.plan_id?.trim() ?? ""; + if (!planId) return null; + const plan = { + planId, + name: p.name?.trim() || planId, + description: p.description?.trim() ?? "", + priority: Number.isFinite(p.priority) ? p.priority : 0, + entitlements: (p.entitlements ?? []).flatMap((c) => { + const e = parseEntitlement(c); + return e ? [e] : []; + }) + }; + if (Number.isFinite(p.starts_at)) plan.startsAt = p.starts_at; + if (Number.isFinite(p.ends_at)) plan.endsAt = p.ends_at; + return plan; } -} -function nonStreamChunkedJson(bridgeStream, translateOpts) { - const encoder2 = new TextEncoder(); - return new ReadableStream({ - async start(controller) { - const reader = bridgeStream.getReader(); - const decoder = new TextDecoder(); - let sseBuffer = ""; + async function request(method2, path2, init) { + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), timeoutMs); + const onExternalAbort = () => controller.abort(); + if (init.signal) { + if (init.signal.aborted) controller.abort(); + else init.signal.addEventListener("abort", onExternalAbort, { once: true }); + } + let resp; + try { + resp = await fetchImpl(`${origin}${path2}`, { + method: method2, + headers: init.headers, + body: init.body === void 0 ? void 0 : JSON.stringify(init.body), + signal: controller.signal + }); + const text = await resp.text(); + let json; try { - while (true) { - const { done, value: value2 } = await reader.read(); - if (done) break; - try { - controller.enqueue(SINGLE_SPACE); - } catch { - return; - } - sseBuffer += decoder.decode(value2, { stream: true }); - } - sseBuffer += decoder.decode(); - } finally { - reader.releaseLock?.(); + const parsed = JSON.parse(text); + if (parsed && typeof parsed === "object") json = parsed; + } catch { } - const anthropicMsg = reconstructAnthropicBatch(sseBuffer); - if (!anthropicMsg) { - const errPayload = { error: { type: "async_aggregation_failed", message: "could not reconstruct response from bridge stream" } }; - try { - controller.enqueue(encoder2.encode(JSON.stringify(errPayload))); - } catch { - } - controller.close(); - return; + return { status: resp.status, json, text }; + } finally { + clearTimeout(timer); + init.signal?.removeEventListener("abort", onExternalAbort); + } + } + function unwrapError(json, status, text) { + const code = json?.code !== void 0 ? json.code : status >= 400 ? status : -1; + const rawMsg = json?.msg ?? json?.message; + const message = typeof rawMsg === "string" && rawMsg.trim() ? rawMsg.trim() : text.length > 0 && text.length < 200 ? text : `HTTP ${status}`; + return { code, message }; + } + return { + async getPreviews(signal2) { + const url2 = `/api/v1/zcode-plan/billing/preview?app_version=${encodeURIComponent(opts.appVersion)}&platform=${encodeURIComponent(opts.platform)}`; + const headers2 = { ...identityHeaders }; + if (jwt) headers2.authorization = `Bearer ${jwt}`; + const { status, json, text } = await request("GET", url2, { headers: headers2, signal: signal2 }); + if (status < 200 || status >= 300 || json?.code !== void 0 && json.code !== 0 || json?.data === void 0) { + const { code, message } = unwrapError(json, status, text); + throw new ClaimPreviewError(`claim preview failed (${code}): ${message}`, status, code); } - const finalJson = translateOpts?.translate === "openai" ? JSON.stringify(translateResponseAnthropicToOpenAI(anthropicMsg, translateOpts.model)) : JSON.stringify(anthropicMsg); - try { - controller.enqueue(encoder2.encode(finalJson)); - } catch { + const data2 = json.data; + return (data2.plans ?? []).flatMap((p) => { + const plan = parsePlan(p); + return plan ? [plan] : []; + }); + }, + async claim(planId, captcha, signal2) { + if (!jwt) return { ok: false, planId, failureKind: "login_required", code: 401, message: "manual_claim_login_required" }; + const headers2 = { + ...identityHeaders, + authorization: `Bearer ${jwt}`, + "content-type": "application/json", + "X-Aliyun-Captcha-Verify-Param": captcha.verifyParam + }; + if (captcha.region) headers2["X-Aliyun-Captcha-Verify-Region"] = captcha.region; + const { status, json, text } = await request("POST", "/api/v1/zcode-plan/billing/claim", { body: { plan_id: planId }, headers: headers2, signal: signal2 }); + const data2 = json?.data; + const bizCode = json?.code !== void 0 ? json.code : void 0; + const plan = data2?.plan; + if (status >= 200 && status < 300 && bizCode === 0 && plan) { + const out = { ok: true, planId }; + if (Number.isFinite(plan.starts_at)) out.startsAt = plan.starts_at; + if (Number.isFinite(plan.ends_at)) out.endsAt = plan.ends_at; + return out; } - controller.close(); + const { code, message } = unwrapError(json, status, text); + const failureEndsAt = Number.isFinite(plan?.ends_at) ? plan?.ends_at : void 0; + const httpDerived = status >= 400 && bizCode === void 0; + return { + ok: false, + planId, + failureKind: httpDerived ? status === 401 ? "login_required" : "http_error" : classifyClaimCode(code), + code, + message, + ...failureEndsAt !== void 0 ? { failureEndsAt } : {} + }; } - }); + }; } -function reconstructAnthropicBatch(sseText) { - const blocks = sseText.split("\n\n"); - let message = null; - const content2 = []; - let currentBlock = null; - let currentToolJson = ""; - let sawMessageStop = false; - let sawError = false; - for (const block of blocks) { - const lines = block.split("\n"); - let eventType; - let data2; - for (const line of lines) { - if (line.startsWith("event:")) eventType = line.slice(6).trim(); - else if (line.startsWith("data:")) data2 = line.slice(5).trim(); - } - if (!data2) continue; - let parsed; - try { - parsed = JSON.parse(data2); - } catch { - continue; - } - const type2 = eventType ?? parsed.type; - switch (type2) { - case "message_start": { - const msg = parsed.message; - message = { ...msg ?? {} }; - break; +var DEFAULT_TIMEOUT_MS, ClaimPreviewError; +var init_client2 = __esm({ + "src/claim/client.ts"() { + "use strict"; + init_types3(); + init_identity(); + DEFAULT_TIMEOUT_MS = 15e3; + ClaimPreviewError = class extends Error { + status; + code; + constructor(message, status, code) { + super(message); + this.name = "ClaimPreviewError"; + this.status = status; + this.code = code; } - case "content_block_start": { - const cb = parsed.content_block; - if (!cb || !cb.type) break; - if (cb.type === "text") currentBlock = { type: "text", text: "" }; - else if (cb.type === "thinking") currentBlock = { type: "thinking", thinking: "" }; - else if (cb.type === "tool_use" && typeof cb.id === "string" && typeof cb.name === "string") { - currentBlock = { type: "tool_use", id: cb.id, name: cb.name, input: {} }; - currentToolJson = ""; - } - break; + }; + } +}); + +// src/claim/scheduler.ts +var ClaimScheduler; +var init_scheduler = __esm({ + "src/claim/scheduler.ts"() { + "use strict"; + init_client2(); + ClaimScheduler = class { + constructor(deps) { + this.deps = deps; + this.now = deps.now ?? Date.now; + this.log = deps.log ?? (() => { + }); } - case "content_block_delta": { - const delta = parsed.delta; - if (!currentBlock || !delta) break; - if (delta.type === "text_delta" && currentBlock.type === "text" && typeof delta.text === "string") { - currentBlock.text += delta.text; - } else if (delta.type === "thinking_delta" && currentBlock.type === "thinking" && typeof delta.thinking === "string") { - currentBlock.thinking += delta.thinking; - } else if (delta.type === "signature_delta" && currentBlock.type === "thinking" && typeof delta.signature === "string") { - currentBlock.signature = (currentBlock.signature ?? "") + delta.signature; - } else if (delta.type === "input_json_delta" && currentBlock.type === "tool_use" && typeof delta.partial_json === "string") { - currentToolJson += delta.partial_json; + deps; + stopped = false; + holdUntil = 0; + timer = null; + now; + log; + isStopped() { + return this.stopped; + } + start() { + if (this.stopped) return; + this.scheduleNext(0); + } + stop() { + this.stopped = true; + if (this.timer !== null) { + clearTimeout(this.timer); + this.timer = null; } - break; } - case "content_block_stop": { - if (currentBlock) { - if (currentBlock.type === "tool_use") { - try { - currentBlock.input = JSON.parse(currentToolJson || "{}"); - } catch { - currentBlock.input = {}; - } - currentToolJson = ""; + /** One poll→claim cycle. Exposed for tests; `start()` drives it on a timer. */ + async tick() { + if (this.stopped) return { action: "stopped" }; + const nowMs = this.now(); + if (nowMs < this.holdUntil) return { action: "skipped_hold" }; + let jwt; + try { + jwt = await this.deps.getJwt(); + } catch (err) { + return this.errorBackoff(`credential resolution failed: ${err.message}`); + } + if (!jwt) { + return this.errorBackoff("no JWT available (oauth login pending)"); + } + const client = this.deps.createClient(jwt); + let plans; + try { + plans = await client.getPreviews(); + } catch (err) { + if (err instanceof ClaimPreviewError && err.status === 404) { + this.holdUntil = nowMs + this.deps.config.pollIntervalMs; + return { action: "idle" }; } - content2.push(currentBlock); - currentBlock = null; + return this.errorBackoff(`preview failed: ${err.message}`); } - break; + if (plans.length === 0) { + this.holdUntil = nowMs + this.deps.config.pollIntervalMs; + return { action: "idle" }; + } + const target2 = this.pickPlan(plans); + if (!target2) { + this.holdUntil = nowMs + this.deps.config.pollIntervalMs; + return { action: "idle" }; + } + let captcha; + try { + captcha = await this.deps.getCaptcha(); + } catch (err) { + return this.errorBackoff(`captcha token failed: ${err.message}`); + } + let outcome; + try { + outcome = await client.claim(target2.planId, captcha); + } catch (err) { + return this.errorBackoff(`claim request failed: ${err.message}`); + } + if (outcome.ok) { + const endsAtMs = outcome.endsAt !== void 0 ? outcome.endsAt * 1e3 : void 0; + this.holdUntil = endsAtMs ?? nowMs + this.deps.config.pollIntervalMs; + this.log(`claim: claimed plan ${target2.planId}${outcome.startsAt !== void 0 ? ` (activates ${new Date(outcome.startsAt * 1e3).toISOString()})` : ""}`); + return { action: "claimed", planId: target2.planId, startsAt: outcome.startsAt, endsAt: outcome.endsAt }; + } + const holdMs = this.holdForFailure(outcome.failureKind, outcome.failureEndsAt, nowMs); + this.holdUntil = nowMs + holdMs; + this.log(`claim: ${outcome.failureKind} (${outcome.code}) \u2014 ${outcome.message}; retry in ${Math.round(holdMs / 1e3)}s`); + if (outcome.failureKind === "login_required") { + this.stop(); + } + return { action: "failed", outcome, holdMs }; } - case "message_delta": { - const delta = parsed.delta; - const usage = parsed.usage; - if (delta && message) Object.assign(message, delta); - if (usage && message) message.usage = { ...message.usage ?? { input_tokens: 0, output_tokens: 0 }, ...usage }; - break; + pickPlan(plans) { + const wanted = this.deps.config.planId?.trim(); + if (wanted) return plans.find((p) => p.planId === wanted) ?? null; + const sorted = [...plans].sort((a, b) => b.priority - a.priority); + return sorted[0] ?? null; } - case "message_stop": - sawMessageStop = true; - break; - case "error": - sawError = true; - break; - default: - break; - } - } - if (sawError || !sawMessageStop || !message) return null; - message.content = content2; - if (!message.stop_reason) message.stop_reason = "end_turn"; - if (!message.role) message.role = "assistant"; - if (!message.usage) message.usage = { input_tokens: 0, output_tokens: 0 }; - return message; -} - -// src/server/routes-async.ts -async function handleAsyncMessagesRoute(req, opts) { - return handleAsyncMessages(req, opts); -} -async function handleAsyncChatRoute(req, opts) { - return handleAsyncChat(req, opts); -} -async function handleAsyncHealthRoute(req, opts) { - return handleAsyncHealth(req, opts); -} - -// src/server/server.ts -function createFetchHandler(opts) { - const { config, auth } = opts; - const proxyOpts = { config, auth, fetchImpl: opts.fetchImpl, debug: opts.debug === true }; - const responsesOpts = { - config, - auth, - fetchImpl: opts.fetchImpl, - debug: opts.debug === true, - ...opts.responseStore ? { responseStore: opts.responseStore } : {} - }; - const asyncOpts = { - config, - auth, - fetchImpl: opts.fetchImpl, - debug: opts.debug === true - }; - return async (req) => { - const url2 = new URL(req.url); - const path2 = url2.pathname; - const method2 = req.method; - if (method2 === "OPTIONS") { - return corsResponse(); - } - if (method2 === "GET" && (path2 === "/webui" || path2.startsWith("/webui/"))) { - return new Response(webui_default, { - status: 200, - headers: { "content-type": "text/html; charset=utf-8", "cache-control": "no-cache" } - }); - } - if (config.auth.proxyApiKey) { - const authHeader = req.headers.get("authorization") ?? req.headers.get("x-api-key"); - if (!authHeader || !checkProxyKey(authHeader, config.auth.proxyApiKey)) { - return errorResponse(401, "authentication_error", "Invalid or missing proxy API key"); + holdForFailure(kind2, failureEndsAtSec, nowMs) { + if ((kind2 === "already_claimed" || kind2 === "quota_exhausted") && Number.isFinite(failureEndsAtSec)) { + const untilMs = failureEndsAtSec * 1e3; + if (untilMs > nowMs) return Math.min(untilMs - nowMs, 24 * 60 * 60 * 1e3); + } + return this.deps.config.cooldownMs; } - } - if (path2 === "/v1/chat/completions" && method2 === "POST") { - return handleChatCompletions(req, proxyOpts); - } - if (config.responses.enabled && path2 === "/v1/responses" && method2 === "POST") { - return handleResponsesRoute(req, responsesOpts); - } - if (path2 === "/v1/models" && method2 === "GET") { - return handleListModels(); - } - if (path2 === "/v1/messages" && method2 === "POST") { - return handleMessages(req, proxyOpts); - } - if (config.async.enabled) { - if (path2 === "/async/v1/messages" && method2 === "POST") { - return handleAsyncMessagesRoute(req, asyncOpts); + errorBackoff(message) { + const holdMs = this.deps.config.cooldownMs; + this.holdUntil = this.now() + holdMs; + this.log(`claim: ${message}; retry in ${Math.round(holdMs / 1e3)}s`); + return { action: "error", message, holdMs }; } - if (path2 === "/async/v1/chat/completions" && method2 === "POST") { - return handleAsyncChatRoute(req, asyncOpts); + scheduleNext(delayMs) { + if (this.stopped) return; + this.timer = setTimeout(() => { + this.timer = null; + void this.tick().finally(() => this.scheduleNext(this.nextDelay())); + }, delayMs); } - if (path2 === "/async/v1/health" && method2 === "GET") { - return handleAsyncHealthRoute(req, asyncOpts); + nextDelay() { + const remaining = this.holdUntil - this.now(); + return remaining > 0 ? remaining : this.deps.config.pollIntervalMs; } - } - if (path2 === "/health" || path2 === "/") { - return new Response(JSON.stringify({ status: "ok", provider: config.provider }), { - status: 200, - headers: { "content-type": "application/json" } - }); - } - return errorResponse(404, "not_found_error", `No route for ${method2} ${path2}`); - }; -} -function startServer(opts) { - const handler = createFetchHandler(opts); - const { port: requestedPort, host: host2 } = opts.config.server; - const server = (0, import_node_http.createServer)(async (req, res) => { - const abortController = new AbortController(); - const onClientClose = () => { - if (!res.writableEnded) abortController.abort(); }; - res.on("close", onClientClose); - if ((req.url ?? "").startsWith("/async/")) { - req.setTimeout(24 * 60 * 60 * 1e3); - } - try { - const webReq = nodeReqToWebRequest(req, abortController.signal); - const resp = await handler(webReq).then((r2) => addCorsHeaders(r2)); - await writeWebResponseToNodeResp(resp, res, abortController.signal); - } catch (err) { - if (abortController.signal.aborted) return; - if (!res.headersSent) { - res.writeHead(500, { "content-type": "application/json" }); - res.end(JSON.stringify({ error: { type: "internal_error", message: err.message } })); - } else { - try { - res.end(); - } catch { - } - } - } - }); - server.requestTimeout = 6e5; - server.keepAliveTimeout = 12e4; - server.headersTimeout = 6e5; - return new Promise((resolve, reject) => { - server.on("error", reject); - server.listen(requestedPort, host2, () => { - const addr = server.address(); - const actualPort = typeof addr === "object" && addr ? addr.port : requestedPort; - resolve({ - hostname: host2, - port: actualPort, - stop: (exit) => { - server.close(); - if (exit) process.exit(0); - }, - close: () => new Promise((r2) => server.close(() => r2())) - }); - }); - }); -} -function nodeReqToWebRequest(req, signal2) { - const headers2 = new Headers(); - for (const [key, val] of Object.entries(req.headers)) { - if (val == null) continue; - if (Array.isArray(val)) { - for (const v of val) headers2.append(key, v); - } else { - headers2.set(key, val); - } - } - const host2 = headers2.get("host") ?? "localhost"; - const url2 = `http://${host2}${req.url ?? "/"}`; - const method2 = req.method ?? "GET"; - if (method2 === "GET" || method2 === "HEAD") { - return new Request(url2, { method: method2, headers: headers2, signal: signal2 }); } - const bodyStream = import_node_stream.Readable.toWeb(req); - const init = { - method: method2, - headers: headers2, - body: bodyStream, - duplex: "half", - signal: signal2 - }; - return new Request(url2, init); +}); + +// src/claim/runtime.ts +var runtime_exports = {}; +__export(runtime_exports, { + claimPlatform: () => claimPlatform, + runClaimCli: () => runClaimCli, + startAutoClaim: () => startAutoClaim +}); +function claimPlatform() { + return `${process.platform}-${process.arch}`; } -async function writeWebResponseToNodeResp(resp, res, abortSignal) { - const headers2 = {}; - resp.headers.forEach((value2, key) => { - const existing = headers2[key]; - if (existing === void 0) { - headers2[key] = value2; - } else if (typeof existing === "string") { - headers2[key] = [existing, value2]; - } else { - existing.push(value2); - } - }); - res.writeHead(resp.status, resp.statusText, headers2); - if (resp.body == null) { - res.end(); - return; - } - const reader = resp.body.getReader(); - const onAbort = () => { - reader.cancel().catch(() => { - }); - }; - abortSignal?.addEventListener("abort", onAbort); - try { - while (true) { - const { done, value: value2 } = await reader.read(); - if (done) break; - if (!res.write(Buffer.from(value2))) { - await new Promise((resolve) => res.once("drain", () => resolve())); - } - } - res.end(); - } catch (err) { - if (abortSignal?.aborted) { - try { - res.end(); - } catch { - } - } else { +function startAutoClaim(config, auth) { + const scheduler = new ClaimScheduler({ + // AuthManager first (fresh), then the encrypted store — on Android the + // login can land in the store after boot while auth hasn't been reloaded. + getJwt: async () => { try { - res.destroy(err); + const cred = await auth.getCredential(); + if (cred.jwt) return cred.jwt; } catch { } - } - } finally { - abortSignal?.removeEventListener("abort", onAbort); - } -} -function checkProxyKey(authHeader, expected) { - const trimmed = authHeader.trim(); - if (trimmed.startsWith("Bearer ")) { - return trimmed.slice(7).trim() === expected; - } - return trimmed === expected; -} -function corsResponse() { - return new Response(null, { - status: 204, - headers: corsHeaders() + const stored = await loadCredential().catch(() => null); + return stored?.jwt; + }, + createClient: (jwt) => createClaimClient({ + origin: config.claim.origin, + jwt, + appVersion: config.identity.appVersion, + platform: claimPlatform(), + identity: config.identity + }), + getCaptcha: async () => { + const { verifyParam, region } = await getCaptchaToken(config.identity.appVersion); + return { verifyParam, region: region || void 0 }; + }, + config: { + planId: config.claim.planId || void 0, + pollIntervalMs: config.claim.pollIntervalMs, + cooldownMs: config.claim.cooldownMs + }, + log: (message) => console.log(`[claim] ${message}`) }); + scheduler.start(); + return scheduler; } -function addCorsHeaders(resp) { - const headers2 = new Headers(resp.headers); - for (const [k, v] of Object.entries(corsHeaders())) { - headers2.set(k, v); +async function runClaimCli(config, mode2) { + const cred = await loadCredential(); + const jwt = cred?.jwt; + if (!jwt) { + console.error("Claim requires a logged-in oauth credential (no JWT stored). Run: zcode-proxy auth login "); + process.exit(1); } - return new Response(resp.body, { - status: resp.status, - statusText: resp.statusText, - headers: headers2 + const client = createClaimClient({ + origin: config.claim.origin, + jwt, + appVersion: config.identity.appVersion, + platform: claimPlatform(), + identity: config.identity }); -} -function corsHeaders() { - return { - "access-control-allow-origin": "*", - "access-control-allow-methods": "GET, POST, OPTIONS", - "access-control-allow-headers": "Content-Type, Authorization, x-api-key, anthropic-version, anthropic-beta", - "access-control-max-age": "86400" - }; -} - -// src/android/control.ts -var import_node_http3 = require("node:http"); - -// src/auth/oauth.ts -var import_node_http2 = require("node:http"); -var import_node_crypto3 = require("node:crypto"); -var ZCODE_API_BASE = "https://zcode.z.ai/api/v1"; -var ZCODE_TOKEN_ENDPOINT = `${ZCODE_API_BASE}/oauth/token`; -var BIGMODEL_HOST = "https://bigmodel.cn"; -var BIGMODEL_APP_ID = "zcode"; -var LOGIN_TIMEOUT_MS = 3e5; -var OAuthFlowClient = class { - constructor(provider, fetchImpl) { - this.provider = provider; - this.fetchImpl = fetchImpl; - } - provider; - fetchImpl; - /** Run the full flow end-to-end: surface authorize URL, wait, close. */ - async authorize(onAuthorizeUrl, timeoutMs = LOGIN_TIMEOUT_MS) { - const started = await this.start(); - onAuthorizeUrl?.(started.authorizeUrl); - try { - const tokens = await this.complete(started, timeoutMs); - return { accessToken: tokens.accessToken, provider: this.provider, userId: tokens.userId, jwt: tokens.jwt }; - } finally { - await this.close(); + let plans; + try { + plans = await client.getPreviews(); + } catch (err) { + if (err instanceof ClaimPreviewError && err.status === 404) { + console.log("No claimable plans: the campaign endpoint is not deployed yet (404)."); + console.log("Weekend campaigns typically go live shortly before the window \u2014 keep the proxy"); + console.log("serving with claim.enabled, or re-run this command later."); + return; } + throw err; } -}; -async function requestZcodeEnvelope(fetchImpl, url2, init, label2) { - const resp = await fetchImpl(url2, init); - const raw = safeJsonParse(await resp.text()); - if (!raw || typeof raw.code !== "number") { - throw new Error(`${label2}: invalid response envelope (status=${resp.status})`); + if (plans.length === 0) { + console.log("No claimable plans right now."); + return; } - if (!resp.ok || raw.code !== 0) { - throw new Error(`${label2} failed: status=${resp.status} msg=${raw.msg ?? "(none)"}`); + printPlans(plans); + if (mode2 === "list") return; + const wanted = config.claim.planId.trim(); + const target2 = wanted ? plans.find((p) => p.planId === wanted) : [...plans].sort((a, b) => b.priority - a.priority)[0]; + if (!target2) { + console.error(`Configured claim.planId "${wanted}" not in the preview list.`); + process.exit(1); } - return raw.data; + if (target2.planId !== plans[0].planId) console.log(`Claiming configured plan: ${target2.planId}`); + const captcha = await getCaptchaToken(config.identity.appVersion); + const outcome = await client.claim(target2.planId, { verifyParam: captcha.verifyParam, region: captcha.region || void 0 }); + printOutcome(outcome); + if (!outcome.ok) process.exit(1); } -var ZaiOAuthClient = class extends OAuthFlowClient { - constructor(fetchImpl = fetch, sleep2 = defaultSleep) { - super("zai", fetchImpl); - this.sleep = sleep2; - } - sleep; - flow = null; - pollToken = ""; - start() { - this.flow = null; - this.pollToken = (0, import_node_crypto3.randomBytes)(32).toString("hex"); - return (async () => { - const data2 = await requestZcodeEnvelope( - this.fetchImpl, - `${ZCODE_API_BASE}/oauth/cli/init`, - { - method: "POST", - headers: { authorization: `Bearer ${this.pollToken}`, "content-type": "application/json" }, - body: JSON.stringify({ provider: this.provider }) - }, - "Z.AI login init" - ); - if (!data2 || typeof data2.flow_id !== "string" || typeof data2.authorize_url !== "string" || typeof data2.expires_at !== "number" || typeof data2.poll_interval_sec !== "number") { - throw new Error("Z.AI login init: invalid response data"); - } - this.flow = data2; - return { authorizeUrl: this.flow.authorize_url, callbackUrl: "", state: this.flow.flow_id }; - })(); - } - async complete(_started, timeoutMs = LOGIN_TIMEOUT_MS) { - const flow = this.flow; - if (!flow) throw new Error("Z.AI login not started"); - const deadlineMs = Math.min(Date.now() + timeoutMs, flow.expires_at * 1e3); - const intervalMs = Math.max(1e3, flow.poll_interval_sec * 1e3); - for (; ; ) { - if (Date.now() >= deadlineMs) { - throw new Error("Authorization timed out. Please retry login."); - } - const data2 = await requestZcodeEnvelope( - this.fetchImpl, - `${ZCODE_API_BASE}/oauth/cli/poll/${encodeURIComponent(flow.flow_id)}`, - { method: "GET", headers: { authorization: `Bearer ${this.pollToken}` } }, - "Z.AI login poll" - ); - if (data2?.status === "ready") { - const accessToken = typeof data2.zai?.access_token === "string" ? data2.zai.access_token.trim() : ""; - if (!accessToken) { - throw new Error("Z.AI login poll: response missing data.zai.access_token"); - } - return { - accessToken, - jwt: typeof data2.token === "string" ? data2.token.trim() : void 0, - userId: typeof data2.user?.user_id === "string" ? data2.user.user_id : void 0 - }; - } - if (data2?.status === "failed") { - throw new Error("Authorization failed. Please retry login."); - } - if (data2?.status !== "pending") { - throw new Error(`Z.AI login poll: unexpected status ${String(data2?.status ?? "(none)")}`); - } - await this.sleep(Math.min(intervalMs, Math.max(0, deadlineMs - Date.now()))); - } - } - async close() { - this.flow = null; - } -}; -var AuthCodeOAuthClient = class extends OAuthFlowClient { - server = null; - callbackResult = null; - callbackWaiters = []; - constructor(config, fetchImpl = fetch) { - super(config.provider, fetchImpl); - this.config = config; - } - config; - /** Build the provider authorize URL with the localhost redirect + state. */ - buildAuthorizeUrl(callbackUrl, state2) { - const params = new URLSearchParams({ - appId: this.config.appId, - redirect: callbackUrl, - state: state2 - }); - return `${this.config.authorizeUrl}?${params.toString()}`; - } - /** - * Start the localhost callback server and return the authorize URL. - * Call `waitForCallback()` (or `authorize()`) afterwards, then `close()`. - * - * The bind port is `0` (OS-assigned random) unless the env var - * `ZCODE_OAUTH_CALLBACK_PORT` is set, in which case that exact port is used. - * The Android entry sets the env var so the Custom Tabs redirect URL is - * predictable across launches. - */ - start() { - const state2 = (0, import_node_crypto3.randomBytes)(32).toString("hex"); - const requestedPort = Number(process.env.ZCODE_OAUTH_CALLBACK_PORT ?? 0) || 0; - return new Promise((resolve, reject) => { - this.server = (0, import_node_http2.createServer)((req, res) => { - this.handleCallback(req, res, state2); - }); - this.server.on("error", (err) => { - this.server = null; - reject(err); - }); - this.server.listen(requestedPort, "127.0.0.1", () => { - const addr = this.server.address(); - if (!addr || typeof addr !== "object") { - reject(new Error("Failed to bind localhost callback server")); - return; - } - const callbackUrl = `http://127.0.0.1:${addr.port}${this.config.callbackPath}`; - const authorizeUrl = this.buildAuthorizeUrl(callbackUrl, state2); - resolve({ authorizeUrl, callbackUrl, state: state2 }); - }); - }); - } - handleCallback(req, res, expectedState) { - const url2 = new URL(req.url ?? "/", "http://127.0.0.1"); - if (url2.pathname !== this.config.callbackPath) { - res.writeHead(404, { "Content-Type": "text/plain" }); - res.end("Not found"); - return; - } - const state2 = url2.searchParams.get("state") ?? ""; - const code = url2.searchParams.get("authCode") ?? url2.searchParams.get("code") ?? ""; - if (state2 !== expectedState || !code) { - res.writeHead(400, { "Content-Type": "text/plain; charset=utf-8" }); - res.end("Authorization failed: state mismatch or missing code."); - if (!this.callbackResult) { - this.callbackResult = { code: "", error: "OAuth callback state mismatch or missing code." }; - this.callbackWaiters.forEach((fn) => fn(this.callbackResult)); - } - return; - } - res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" }); - res.end("Authorization successful! You may close this window and return to the CLI."); - if (!this.callbackResult) { - this.callbackResult = { code, error: null }; - this.callbackWaiters.forEach((fn) => fn(this.callbackResult)); - } - } - /** Wait for the OAuth callback redirect. Resolves with the auth code. */ - waitForCallback(timeoutMs = LOGIN_TIMEOUT_MS) { - if (this.callbackResult?.code) { - return Promise.resolve(this.callbackResult.code); - } - if (this.callbackResult?.error) { - return Promise.reject(new Error(this.callbackResult.error)); +function printPlans(plans) { + console.log(`Claimable plans (${plans.length}):`); + for (const p of plans) { + const window2 = [fmtTime(p.startsAt), fmtTime(p.endsAt)].filter(Boolean).join(" \u2192 "); + console.log(` - ${p.planId} "${p.name}" priority=${p.priority}${window2 ? ` ${window2}` : ""}`); + for (const e of p.entitlements) { + const quota = e.grantUnits > 0 ? ` ${e.grantUnits} ${e.unitType}` : ""; + const activate = e.effectiveAt !== void 0 ? ` (activates ${new Date(e.effectiveAt * 1e3).toISOString()})` : ""; + console.log(` \xB7 ${e.showName || e.entitlementId}${quota}${activate}`); } - return new Promise((resolve, reject) => { - const timer = setTimeout(() => { - reject(new Error("Authorization timed out. Please retry login.")); - }, timeoutMs); - this.callbackWaiters.push((result3) => { - clearTimeout(timer); - if (result3.error) { - reject(new Error(result3.error)); - } else { - resolve(result3.code); - } - }); - }); } - /** - * Exchange the auth code at the shared zcode.z.ai token endpoint. - * The ZCode server holds the app secret and performs the real provider exchange. - * Returns `{ accessToken, userId, jwt }`. - */ - async exchangeCode(authCode, redirectUri, state2) { - const resp = await this.fetchImpl(this.config.tokenUrl, { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ - provider: this.config.provider, - code: authCode, - redirect_uri: redirectUri, - state: state2 - }) - }); - const raw = safeJsonParse(await resp.text()); - if (!resp.ok || raw && typeof raw.code === "number" && raw.code !== 0) { - const label2 = this.config.provider; - throw new Error( - `${label2} token exchange failed: status=${resp.status} msg=${raw?.msg ?? "(none)"}` - ); - } - const providerToken = raw?.data?.[this.config.accessTokenField]; - const accessToken = providerToken?.access_token?.trim() ?? ""; - if (!accessToken) { - throw new Error(`${this.config.provider} token response missing data.${this.config.accessTokenField}.access_token`); - } - const userId = raw?.data?.user?.user_id; - const jwt = raw?.data?.token?.trim() ?? void 0; - return { accessToken, userId: typeof userId === "string" ? userId : void 0, jwt }; - } - /** Wait for the browser callback, then exchange the code. */ - async complete(started, timeoutMs = LOGIN_TIMEOUT_MS) { - const code = await this.waitForCallback(timeoutMs); - return this.exchangeCode(code, started.callbackUrl, started.state); - } - async close() { - if (this.server) { - const server = this.server; - this.server = null; - server.closeAllConnections?.(); - await new Promise((resolve) => { - server.close(() => resolve()); - }); - } +} +function printOutcome(outcome) { + if (outcome.ok) { + console.log(` +Claimed: ${outcome.planId}`); + if (outcome.startsAt !== void 0) console.log(` activates: ${new Date(outcome.startsAt * 1e3).toISOString()}`); + if (outcome.endsAt !== void 0) console.log(` expires: ${new Date(outcome.endsAt * 1e3).toISOString()}`); + if (outcome.startsAt === void 0 && outcome.endsAt === void 0) console.log(" active immediately"); + return; } -}; -var BIGMODEL_AUTH_CODE_CONFIG = { - provider: "bigmodel", - authorizeUrl: `${BIGMODEL_HOST}/login`, - appId: BIGMODEL_APP_ID, - tokenUrl: ZCODE_TOKEN_ENDPOINT, - callbackPath: "/oauth/callback/bigmodel", - accessTokenField: "bigmodel" -}; -var BigmodelOAuthClient = class extends AuthCodeOAuthClient { - constructor(fetchImpl = fetch, host2 = BIGMODEL_HOST, appId = BIGMODEL_APP_ID) { - super( - { ...BIGMODEL_AUTH_CODE_CONFIG, authorizeUrl: `${host2}/login`, appId }, - fetchImpl - ); + const label2 = FAILURE_LABELS[outcome.failureKind] ?? FAILURE_LABELS.unknown; + console.error(` +Claim failed: ${label2} (code ${String(outcome.code)}) \u2014 ${outcome.message}`); + if (outcome.failureEndsAt !== void 0) { + console.error(` retry window opens: ${new Date(outcome.failureEndsAt * 1e3).toISOString()}`); } -}; -function defaultSleep(ms) { - return new Promise((resolve) => setTimeout(resolve, ms)); } -function safeJsonParse(text) { - try { - return JSON.parse(text); - } catch { - return null; - } +function fmtTime(sec) { + return sec === void 0 ? "" : new Date(sec * 1e3).toISOString(); } - -// src/auth/resolver.ts -var ZAI_API_KEY_NAME = "zcode-api-key"; -var DEFAULT_ORG_MARKER = "\u9ED8\u8BA4\u673A\u6784"; -var DEFAULT_PROJECT_MARKER = "\u9ED8\u8BA4\u9879\u76EE"; -async function requestBizApi(fetchImpl, url2, authorization, init) { - const resp = await fetchImpl(url2, { - ...init, - headers: { - Authorization: authorization, - "Content-Type": "application/json", - ...init?.headers ?? {} - } - }); - if (!resp.ok) { - throw new Error(`Biz API ${url2} failed: ${resp.status}`); - } - const body2 = await resp.json(); - const code = body2.code ?? body2.status; - if (code != null && code !== 0 && code !== 200 && code !== "0" && code !== "200") { - throw new Error(body2.msg ?? `Biz API error ${code}`); +var FAILURE_LABELS; +var init_runtime = __esm({ + "src/claim/runtime.ts"() { + "use strict"; + init_client2(); + init_scheduler(); + init_captcha(); + init_store(); + FAILURE_LABELS = { + not_found: "plan does not exist", + unavailable: "campaign ended or not claimable yet", + already_claimed: "already claimed on this account", + ineligible: "account or client version not eligible (needs appVersion >= campaign minimum)", + quota_exhausted: "daily claim quota exhausted", + invalid_request: "invalid request", + captcha: "captcha verification failed", + login_required: "not logged in", + http_error: "HTTP error", + unknown: "unknown failure" + }; } - return body2.data ?? body2; -} -var KeyResolver = class { - constructor(fetchImpl = fetch) { - this.fetchImpl = fetchImpl; +}); + +// src/tui/app.ts +var app_exports = {}; +__export(app_exports, { + runTui: () => runTui +}); +async function runTui(args) { + if (!process.stdout.isTTY || !process.stdin.isTTY) { + process.stderr.write("zcode-proxy: tui requires an interactive terminal (TTY).\n"); + process.exit(1); } - fetchImpl; - async resolveZaiBizToken(accessToken) { - const resp = await this.fetchImpl("https://api.z.ai/api/auth/z/login", { - method: "POST", - headers: { "content-type": "application/json" }, - body: JSON.stringify({ token: accessToken }) - }); - if (!resp.ok) { - throw new Error(`z/login failed: ${resp.status}`); + const path2 = args.configPath ?? process.env.ZCODE_PROXY_CONFIG ?? "config.yaml"; + let config; + try { + if (!(0, import_node_fs6.existsSync)(path2)) { + (0, import_node_fs6.writeFileSync)(path2, EXAMPLE_CONFIG_YAML, "utf-8"); + ensureDeviceMidInConfig(path2); + process.stderr.write(`Created ${path2} from bundled template. +`); } - const data2 = await resp.json(); - return data2.access_token ?? data2.accessToken ?? data2.data?.access_token; + config = loadConfig(path2); + } catch (err) { + process.stderr.write(`zcode-proxy: config error: ${err.message} +`); + process.exit(1); } - async resolveCustomerInfo(host2, authorization) { - const data2 = await requestBizApi( - this.fetchImpl, - `${host2}/api/biz/customer/getCustomerInfo`, - authorization, - { method: "GET" } - ); - const orgs = data2.organizations ?? data2.orgs ?? []; - if (!Array.isArray(orgs) || orgs.length === 0) { - throw new Error("No organizations found"); - } - const org = orgs.find( - (o) => (o.organizationName ?? o.name ?? "").includes(DEFAULT_ORG_MARKER) - ) ?? orgs[0]; - const orgId = org.organizationId ?? org.id ?? org.orgId; - const projects = org.projects ?? []; - if (!Array.isArray(projects) || projects.length === 0) { - throw new Error("No projects found in default organization"); - } - const project = projects.find( - (p) => (p.projectName ?? p.name ?? "").includes(DEFAULT_PROJECT_MARKER) - ) ?? projects[0]; - const projectId = project.projectId ?? project.id; - return { orgId, projectId }; - } - async findOrCreateApiKey(host2, authorization, orgId, projectId) { - const listUrl = `${host2}/api/biz/v1/organization/${orgId}/projects/${projectId}/api_keys`; - let existing = []; + const auth = new AuthManager(); + const pane = new LogPane(2e3); + const serverRef = { current: null }; + const state2 = { + provider: config.provider, + plan: config.plan, + loggedIn: false, + apiKeyPreview: "", + serverStatus: "stopped", + serverUrl: "", + serverError: "", + loginInFlight: false, + loginHint: "", + toast: null + }; + const stdout = process.stdout; + const stdin = process.stdin; + stdout.write("\x1B[?1049h\x1B[?25l\x1B[?1000h\x1B[?1006h\x1B[2J"); + const restore = () => { try { - existing = await requestBizApi(this.fetchImpl, listUrl, authorization, { method: "GET" }) ?? []; + stdout.write("\x1B[0m\x1B[?1006l\x1B[?1000l\x1B[?25h\x1B[?1049l"); } catch { } - if (Array.isArray(existing)) { - const found = existing.find((k) => k.name === ZAI_API_KEY_NAME); - if (found?.apiKey) { - return { apiKey: found.apiKey }; - } - } - const created = await requestBizApi(this.fetchImpl, listUrl, authorization, { - method: "POST", - body: JSON.stringify({ name: ZAI_API_KEY_NAME }) - }); - return { apiKey: created.apiKey }; - } - async getSecretKey(host2, authorization, orgId, projectId, apiKey) { - const url2 = `${host2}/api/biz/v1/organization/${orgId}/projects/${projectId}/api_keys/copy/${encodeURIComponent(apiKey)}`; - const data2 = await requestBizApi(this.fetchImpl, url2, authorization, { method: "GET" }); - return data2.secretKey ?? data2.secret_key ?? ""; - } - async resolveCodingPlanCredential(accessToken, provider, userId) { - if (provider === "zai") { - const bizToken = await this.resolveZaiBizToken(accessToken); - const host3 = "https://api.z.ai"; - const authorization2 = `Bearer ${bizToken}`; - const { orgId: orgId2, projectId: projectId2 } = await this.resolveCustomerInfo(host3, authorization2); - const { apiKey: apiKey2 } = await this.findOrCreateApiKey(host3, authorization2, orgId2, projectId2); - let secret; + }; + const origConsole = {}; + const origError = console.error; + const logFile = process.env.ZCODE_TUI_LOGFILE; + const emit = (text, level) => { + pane.push(text, level); + if (logFile) { try { - secret = await this.getSecretKey(host3, authorization2, orgId2, projectId2, apiKey2); + (0, import_node_fs6.appendFileSync)(logFile, text + "\n", "utf-8"); } catch { } - return { apiKey: apiKey2, secret: secret || void 0, provider: "zai", userId }; } - const host2 = "https://bigmodel.cn"; - const authorization = accessToken; - const { orgId, projectId } = await this.resolveCustomerInfo(host2, authorization); - const { apiKey } = await this.findOrCreateApiKey(host2, authorization, orgId, projectId); - let fullKey = apiKey; + scheduleRender(); + }; + const consoleOwner = console; + for (const key of Object.keys(console)) { + const fn = consoleOwner[key]; + if (typeof fn !== "function") continue; + origConsole[key] = fn; + consoleOwner[key] = (...a) => { + const level = key === "error" ? "error" : key === "warn" ? "warn" : "info"; + const prefix2 = key === "error" ? "[error] " : key === "warn" ? "[warn] " : ""; + emit(prefix2 + a.map(String).join(" "), level); + }; + } + const restoreConsole = () => { + for (const [key, fn] of Object.entries(origConsole)) consoleOwner[key] = fn; + }; + let renderTimer = null; + let activeRegions = []; + function renderNow() { + renderTimer = null; + const width2 = stdout.columns || 80; + const height2 = stdout.rows || 24; + const view = pane.view(Math.max(4, height2 - 14)); + const frame = buildFrame({ + version: VERSION, + configPath: path2, + provider: state2.provider, + plan: state2.plan, + loggedIn: state2.loggedIn, + apiKeyPreview: state2.apiKeyPreview, + loginInFlight: state2.loginInFlight, + loginHint: state2.loginHint, + serverStatus: state2.serverStatus, + serverUrl: state2.serverUrl, + serverError: state2.serverError, + modelCount: config.models.length, + responsesEnabled: config.responses.enabled, + claimAuto: config.claim.enabled && config.claim.auto, + logTotal: view.total, + logView: view.lines, + logFollowing: pane.following, + logFromBottom: view.fromBottom, + toast: state2.toast, + width: width2, + height: height2 + }); + activeRegions = frame.regions; try { - const secret = await this.getSecretKey(host2, authorization, orgId, projectId, apiKey); - if (secret) fullKey = `${apiKey}.${secret}`; + stdout.write("\x1B[H" + frame.text); } catch { } - return { apiKey: fullKey, provider: "bigmodel", userId }; } -}; - -// src/android/control.ts -init_store(); -var LogBuffer = class { - lines = []; - capacity; - nextSeq = 0; - constructor(capacity = 500) { - this.capacity = capacity; - } - push(line) { - this.lines.push(line); - this.nextSeq++; - if (this.lines.length > this.capacity) { - this.lines.splice(0, this.lines.length - this.capacity); - } - } - /** - * Returns lines whose logical sequence number is `>= since`, plus the - * next-since cursor (use as the next `since` value for incremental polling). - */ - since(since) { - const baseSeq = Math.max(0, this.nextSeq - this.lines.length); - const wantStart = Math.max(since, baseSeq); - const offset2 = wantStart - baseSeq; - if (offset2 >= this.lines.length) { - return { nextSince: this.nextSeq, lines: [] }; - } - return { nextSince: this.nextSeq, lines: this.lines.slice(offset2) }; - } - /** Returns all lines currently in the buffer. */ - snapshot() { - return this.lines; - } - /** Monotonic cursor; safe to expose externally. */ - get cursor() { - return this.nextSeq; + function scheduleRender() { + if (renderTimer) return; + renderTimer = setTimeout(renderNow, RENDER_MS); + if (typeof renderTimer.unref === "function") renderTimer.unref(); + } + let toastTimer = null; + function setToast(text, kind2) { + state2.toast = { text, kind: kind2 }; + if (toastTimer) clearTimeout(toastTimer); + toastTimer = setTimeout(() => { + state2.toast = null; + toastTimer = null; + scheduleRender(); + }, TOAST_MS); + if (typeof toastTimer.unref === "function") toastTimer.unref(); + scheduleRender(); + } + async function refreshAuth() { + const cred = await loadCredential().catch(() => null); + state2.loggedIn = cred != null; + state2.apiKeyPreview = cred ? `${cred.apiKey.slice(0, 8)}\u2026` : ""; + scheduleRender(); } -}; -function startControlListener(opts) { - const logBuffer = opts.logBuffer ?? new LogBuffer(); - const server = (0, import_node_http3.createServer)(async (req, res) => { + async function startProxy() { + if (state2.serverStatus === "running" || state2.serverStatus === "starting") return; + state2.serverStatus = "starting"; + state2.serverError = ""; + scheduleRender(); + const cred = await loadCredential().catch(() => null); + if (!cred) { + state2.serverStatus = "stopped"; + setToast("not logged in \u2014 press l to login", "err"); + return; + } + auth.setOAuthCredential(cred); try { - const result3 = await handleControlRequest(req, opts.state, { - onStartProxy: opts.onStartProxy, - onStopProxy: opts.onStopProxy, - onSetConfig: opts.onSetConfig, - onShutdown: opts.onShutdown, - logBuffer - }); - writeJson(res, result3.status, result3.body); + const s = await startServer(buildServerOptions(config, auth, args.debug)); + serverRef.current = s; + state2.serverStatus = "running"; + state2.serverUrl = `http://${s.hostname}:${s.port}`; + setToast(`proxy started on ${state2.serverUrl}`, "ok"); + startBackgroundJobsOnce(); } catch (err) { - writeJson(res, 500, { ok: false, error: `internal_error: ${err.message}` }); + state2.serverStatus = "error"; + state2.serverError = err.message; + setToast(`start failed: ${err.message}`, "err"); } - }); - return new Promise((resolve, reject) => { - server.on("error", reject); - server.listen(opts.port, "127.0.0.1", () => resolve({ - close: () => new Promise((r2) => server.close(() => r2())) - })); - }); -} -async function handleControlRequest(req, state2, ctx) { - if (!isLoopback(req.socket.remoteAddress)) { - return { status: 403, body: { ok: false, error: "forbidden: non-loopback remote address" } }; } - const parsed = new URL(req.url ?? "/", "http://127.0.0.1"); - if (req.method !== "POST" || parsed.pathname !== "/control") { - return { status: 404, body: { ok: false, error: `not_found: ${req.method} ${parsed.pathname}` } }; + function stopProxy() { + const s = serverRef.current; + if (!s) return; + try { + s.stop(false); + } catch (err) { + setToast(`stop failed: ${err.message}`, "err"); + return; + } + serverRef.current = null; + state2.serverStatus = "stopped"; + state2.serverUrl = ""; + setToast("proxy stopped", "info"); } - const body2 = await readBody3(req); - let cmd; - try { - cmd = JSON.parse(body2); - } catch { - return { status: 400, body: { ok: false, error: "invalid_json" } }; + function toggleProxy() { + if (state2.serverStatus === "running" || state2.serverStatus === "starting") stopProxy(); + else void startProxy(); } - const result3 = await dispatch(cmd, state2, ctx); - return { status: 200, body: result3 }; -} -async function dispatch(cmd, state2, ctx) { - switch (cmd.cmd) { - case "status": { - const cred = await loadCredential().catch(() => null); - return { - ok: true, - state: "running", - provider: state2.provider, - plan: state2.plan, - proxyPort: state2.proxyPort, - loggedIn: cred != null - }; - } - case "startOAuth": { - if (state2.activeOauth) { - await state2.activeOauth.client.close().catch(() => { - }); - state2.activeOauth = void 0; - } - const client = cmd.provider === "bigmodel" ? new BigmodelOAuthClient() : new ZaiOAuthClient(); - const started = await client.start(); - const callbackPort = started.callbackUrl ? Number(new URL(started.callbackUrl).port) || 80 : 0; - state2.activeOauth = { - client, - callbackUrl: started.callbackUrl, - state: started.state - }; - client.complete(started).then(async (tokens) => { - const resolver = new KeyResolver(); - const cred = await resolver.resolveCodingPlanCredential(tokens.accessToken, cmd.provider, tokens.userId); - if (tokens.jwt) cred.jwt = tokens.jwt; - await saveCredential(cred); - console.log(`OAuth completed for ${cmd.provider}`); - }).catch((err) => { - console.error(`OAuth flow ended without success: ${err?.message ?? String(err)}`); - }).finally(() => { - void client.close().catch(() => { - }); - if (state2.activeOauth?.state === started.state) state2.activeOauth = void 0; - }); - return { - ok: true, - event: "oauthUrl", - authorizeUrl: started.authorizeUrl, - callbackPort - }; + let backgroundJobsStarted = false; + function startBackgroundJobsOnce() { + if (backgroundJobsStarted) return; + backgroundJobsStarted = true; + if (config.plan === "start-plan") { + Promise.resolve().then(() => (init_captcha(), captcha_exports)).then((m) => m.startCaptchaPool(config.identity.appVersion)).catch((err) => console.error(`[captcha] pool warmup failed: ${err.message}`)); } - case "deliverOAuthCode": { - const active = state2.activeOauth; - if (!(active?.client instanceof AuthCodeOAuthClient) || active.state !== cmd.state) { - return { ok: false, error: "no_matching_oauth_flow" }; - } - try { - const { accessToken, userId, jwt } = await active.client.exchangeCode( - cmd.code, - active.callbackUrl, - cmd.state - ); - const resolver = new KeyResolver(); - const cred = await resolver.resolveCodingPlanCredential(accessToken, cmd.provider, userId); - if (jwt) cred.jwt = jwt; - await saveCredential(cred); - state2.activeOauth = void 0; - await active.client.close().catch(() => { - }); - return { ok: true, event: "loginOk", provider: cmd.provider }; - } catch (err) { - state2.activeOauth = void 0; - await active.client.close().catch(() => { - }); - return { ok: false, error: `oauth_exchange_failed: ${err.message}` }; - } + if (config.claim.enabled && config.claim.auto) { + Promise.resolve().then(() => (init_runtime(), runtime_exports)).then((m) => { + m.startAutoClaim(config, auth); + console.log(`[claim] auto ON (poll ${Math.round(config.claim.pollIntervalMs / 1e3)}s)`); + }).catch((err) => console.error(`[claim] scheduler failed to start: ${err.message}`)); } - case "logout": { - await clearCredential(); - return { ok: true, event: "loggedOut" }; + } + function switchProvider() { + const next = state2.provider === "zai" ? "bigmodel" : "zai"; + applyConfigChange(next, state2.plan, `provider \u2192 ${next}`); + } + function switchPlan() { + const next = state2.plan === "coding-plan" ? "start-plan" : "coding-plan"; + applyConfigChange(state2.provider, next, `plan \u2192 ${next}`); + } + function applyConfigChange(provider, plan, message) { + if (state2.serverStatus === "running" || state2.serverStatus === "starting") { + setToast("stop the proxy before switching (press s)", "err"); + return; } - case "setConfig": { - if (!ctx.onSetConfig) return { ok: false, error: "config_update_unavailable" }; - const result3 = await ctx.onSetConfig({ provider: cmd.provider, plan: cmd.plan }); - if (!result3.ok) return result3; - state2.provider = result3.provider; - state2.plan = result3.plan; - return { ok: true, event: "configUpdated", provider: result3.provider, plan: result3.plan }; + config.provider = provider; + config.plan = plan; + try { + updateConfigYaml(path2, { provider, plan }); + state2.provider = provider; + state2.plan = plan; + setToast(message, "ok"); + console.log(`config updated: provider=${provider} plan=${plan}`); + } catch (err) { + setToast(`config update failed: ${err.message}`, "err"); } - case "startProxy": { - if (!ctx.onStartProxy) return { ok: false, error: "proxy_lifecycle_unavailable" }; - const result3 = await ctx.onStartProxy(); - if (!result3.ok) return result3; - state2.proxyPort = result3.port; - return { ok: true, event: "proxyStarted", port: result3.port }; + scheduleRender(); + } + let activeOauth = null; + async function startLogin() { + if (state2.loginInFlight) { + setToast("login already in progress", "info"); + return; } - case "stopProxy": { - if (!ctx.onStopProxy) return { ok: false, error: "proxy_lifecycle_unavailable" }; - const result3 = await ctx.onStopProxy(); - if (!result3.ok) return result3; - state2.proxyPort = 0; - return { ok: true, event: "proxyStopped" }; + const provider = state2.provider; + const client = provider === "bigmodel" ? new BigmodelOAuthClient() : new ZaiOAuthClient(); + let started; + try { + started = await client.start(); + } catch (err) { + void client.close().catch(() => { + }); + setToast(`login failed: ${err.message}`, "err"); + return; } - case "getLogs": { - const since = typeof cmd.since === "number" ? cmd.since : 0; - const { nextSince, lines } = ctx.logBuffer.since(since); - return { ok: true, event: "logs", nextSince, lines: [...lines] }; + activeOauth = { client, provider }; + state2.loginInFlight = true; + state2.loginHint = "waiting for browser authorization\u2026"; + console.log(`OAuth: opening ${started.authorizeUrl}`); + console.log("If the browser did not open, copy the URL above into a browser."); + openBrowser(started.authorizeUrl); + scheduleRender(); + client.complete(started).then(async (tokens) => { + const resolver = new KeyResolver(); + const cred = await resolver.resolveCodingPlanCredential(tokens.accessToken, provider, tokens.userId); + if (tokens.jwt) cred.jwt = tokens.jwt; + await saveCredential(cred); + if (serverRef.current) auth.setOAuthCredential(cred); + console.log(`OAuth completed for ${provider}`); + setToast("logged in", "ok"); + }).catch((err) => { + const msg = err?.message ?? String(err); + console.error(`OAuth flow ended without success: ${msg}`); + setToast(`login failed: ${msg}`, "err"); + }).finally(() => { + void client.close().catch(() => { + }); + if (activeOauth?.client === client) activeOauth = null; + state2.loginInFlight = false; + state2.loginHint = ""; + void refreshAuth(); + }); + } + async function logout() { + if (activeOauth) { + void activeOauth.client.close().catch(() => { + }); + activeOauth = null; + state2.loginInFlight = false; + state2.loginHint = ""; } - case "shutdown": { - if (ctx.onShutdown) await ctx.onShutdown(); - return { ok: true, event: "shuttingDown" }; + try { + clearCredential(); + } catch { } - default: - return { ok: false, error: `unknown_cmd: ${cmd.cmd}` }; + await refreshAuth(); + if (serverRef.current) setToast("logged out \u2014 restart the proxy to apply", "info"); + else setToast("logged out", "ok"); } -} -function isLoopback(addr) { - return addr === "127.0.0.1" || addr === "::1" || addr === "::ffff:127.0.0.1"; -} -function writeJson(res, status, body2) { - const json = JSON.stringify(body2); - res.writeHead(status, { - "content-type": "application/json; charset=utf-8", - "content-length": Buffer.byteLength(json) - }); - res.end(json); -} -function readBody3(req) { - return new Promise((resolve, reject) => { - const chunks = []; - req.on("data", (c) => chunks.push(c)); - req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8"))); - req.on("error", reject); + const parser = new KeyParser(); + stdin.setEncoding("utf8"); + if (typeof stdin.setRawMode !== "function") { + restore(); + origError("zcode-proxy: tui requires a terminal with raw-mode input.\n"); + process.exit(1); + } + stdin.setRawMode(true); + stdin.resume(); + stdin.on("data", (chunk) => { + for (const action of parser.feed(chunk)) handleKey(action); }); -} - -// src/responses/store.ts -var DEFAULT_MAX_ENTRIES = 1e3; -var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3; -var ResponseStore = class { - maxEntries; - ttlMs; - map = /* @__PURE__ */ new Map(); - constructor(opts = {}) { - this.maxEntries = opts.maxEntries ?? DEFAULT_MAX_ENTRIES; - this.ttlMs = opts.ttlMs ?? DEFAULT_TTL_MS; - } - /** Store a response. Overwrites on duplicate id. Evicts LRU entries on overflow. */ - set(entry) { - const now = Date.now(); - entry.createdAt = now; - entry.lastAccessedAt = now; - if (this.map.has(entry.id)) this.map.delete(entry.id); - this.map.set(entry.id, entry); - while (this.map.size > this.maxEntries) { - const oldestKey = this.map.keys().next().value; - if (oldestKey === void 0) break; - this.map.delete(oldestKey); - } - } - /** - * Fetch a stored response. Returns `undefined` when missing or stale. - * Refreshes LRU position on hit. - */ - get(id2) { - const entry = this.map.get(id2); - if (!entry) return void 0; - const now = Date.now(); - if (now - entry.createdAt > this.ttlMs) { - this.map.delete(id2); - return void 0; + function scrollUp(n) { + pane.scrollUp(n); + scheduleRender(); + } + function scrollDown(n) { + pane.scrollDown(n); + scheduleRender(); + } + function handleKey(action) { + switch (action.type) { + case "ctrl-c": + quit(); + return; + case "click": { + const hit = findRegion(activeRegions, action.y, action.x); + if (hit) dispatchClick(hit); + return; + } + case "wheel-up": + scrollUp(3); + return; + case "wheel-down": + scrollDown(3); + return; + case "char": { + switch (action.key.toLowerCase()) { + case "q": + quit(); + return; + case "s": + toggleProxy(); + return; + case "l": + void startLogin(); + return; + case "o": + void logout(); + return; + case "p": + switchProvider(); + return; + case "t": + switchPlan(); + return; + case "c": + pane.clear(); + scheduleRender(); + return; + case "g": + pane.followBottom(); + scheduleRender(); + return; + case "k": + scrollUp(1); + return; + case "j": + scrollDown(1); + return; + default: + return; + } + } + case "up": + scrollUp(1); + return; + case "down": + scrollDown(1); + return; + case "pageup": + scrollUp(PAGE_LINES); + return; + case "pagedown": + scrollDown(PAGE_LINES); + return; + case "home": + scrollUp(pane.count); + return; + case "end": + pane.followBottom(); + scheduleRender(); + return; + default: + return; } - entry.lastAccessedAt = now; - this.map.delete(id2); - this.map.set(id2, entry); - return entry; } - delete(id2) { - return this.map.delete(id2); + function dispatchClick(action) { + switch (action.kind) { + case "key": + handleKey({ type: "char", key: action.key }); + return; + case "provider": + applyConfigChange(action.value, state2.plan, `provider \u2192 ${action.value}`); + return; + case "plan": + applyConfigChange(state2.provider, action.value, `plan \u2192 ${action.value}`); + return; + case "follow": + pane.followBottom(); + scheduleRender(); + return; + } } - clear() { - this.map.clear(); + function quit() { + cleanup(); + process.exit(0); } - size() { - return this.map.size; + function cleanup() { + restore(); + restoreConsole(); + try { + serverRef.current?.stop(false); + } catch { + } } -}; - -// src/index.ts -init_store(); -var import_yaml2 = __toESM(require_dist(), 1); -var import_node_child_process = require("node:child_process"); -var import_node_fs5 = require("node:fs"); -var import_node_path3 = require("node:path"); -var import_node_os5 = require("node:os"); -var import_node_crypto4 = require("node:crypto"); - -// src/runtime/node-fetch-compat.ts -var applied = false; -async function ensureNodeFetchNoTimeouts() { - if (typeof Bun !== "undefined") return; - if (applied) return; - applied = true; - try { - const { Agent, setGlobalDispatcher: setGlobalDispatcher2 } = await Promise.resolve().then(() => __toESM(require_undici(), 1)); - setGlobalDispatcher2(new Agent({ headersTimeout: 0, bodyTimeout: 0 })); - } catch (err) { - console.error(`zcode-proxy: could not disable Node fetch default timeouts: ${err.message}`); + process.on("SIGINT", quit); + process.on("SIGTERM", quit); + process.on("exit", restore); + stdout.on("resize", scheduleRender); + process.on("uncaughtException", (err) => { + cleanup(); + origError(`zcode-proxy: tui crashed: ${err.stack ?? String(err)}`); + process.exit(1); + }); + console.log(`zcode-proxy TUI \u2014 config: ${path2}`); + console.log(`provider: ${state2.provider} \xB7 plan: ${state2.plan}`); + await refreshAuth(); + renderNow(); + if (!state2.loggedIn) { + setToast("not logged in \u2014 press l to login", "err"); + } else { + await startProxy(); } } +var import_node_fs6, RENDER_MS, PAGE_LINES, TOAST_MS; +var init_app = __esm({ + "src/tui/app.ts"() { + "use strict"; + init_loader(); + init_template(); + init_edit(); + init_manager(); + init_server(); + init_server_options(); + init_store(); + init_oauth(); + init_resolver(); + init_open_browser(); + init_index(); + import_node_fs6 = require("node:fs"); + init_log_pane(); + init_keys(); + init_frame(); + RENDER_MS = 33; + PAGE_LINES = 10; + TOAST_MS = 2600; + } +}); // src/index.ts -var VERSION = "2.6.0"; -if (require.main === module) main(); +var index_exports = {}; +__export(index_exports, { + VERSION: () => VERSION, + applyAndroidIdentityDefaults: () => applyAndroidIdentityDefaults, + ensureDeviceMidInConfig: () => ensureDeviceMidInConfig, + main: () => main, + parseServeArgs: () => parseServeArgs +}); +module.exports = __toCommonJS(index_exports); function parseServeArgs(args) { const debug = args.includes("debug"); const configPath = args.find((a) => a !== "debug"); @@ -118825,6 +120136,13 @@ function runCli() { } else if (cmd === "android") { runAndroid().catch((err) => { process.stderr.write(`zcode-proxy: android entry failed: ${err.stack ?? String(err)} +`); + process.exit(1); + }); + } else if (cmd === "tui") { + const tuiArgs = parseServeArgs(args.slice(1)); + Promise.resolve().then(() => (init_app(), app_exports)).then((m) => m.runTui(tuiArgs)).catch((err) => { + process.stderr.write(`zcode-proxy: tui failed: ${err.stack ?? String(err)} `); process.exit(1); }); @@ -118849,6 +120167,7 @@ Usage: zcode-proxy serve [config.yaml] Start the proxy server (default) zcode-proxy serve debug [config.yaml] Start with verbose per-request diagnostics + zcode-proxy tui [config.yaml] Interactive terminal UI (login / start-stop / live logs) zcode-proxy android Android entry: proxy + localhost control listener zcode-proxy auth login Login via OAuth (provider: zai | bigmodel) zcode-proxy auth login --import @@ -118862,6 +120181,7 @@ Usage: Examples: zcode-proxy Start server with default config.yaml zcode-proxy serve debug Start with extra debug logging + zcode-proxy tui Terminal UI: login, start/stop, live logs zcode-proxy auth login bigmodel OAuth login for Bigmodel zcode-proxy auth login bigmodel --import Import existing key from ZCode config @@ -118870,8 +120190,8 @@ Examples: } async function serve(configPath, debug) { const path2 = configPath ?? process.env.ZCODE_PROXY_CONFIG ?? "config.yaml"; - if (!(0, import_node_fs5.existsSync)(path2)) { - (0, import_node_fs5.writeFileSync)(path2, EXAMPLE_CONFIG_YAML, "utf-8"); + if (!(0, import_node_fs7.existsSync)(path2)) { + (0, import_node_fs7.writeFileSync)(path2, EXAMPLE_CONFIG_YAML, "utf-8"); ensureDeviceMidInConfig(path2); console.log(`Created ${path2} from bundled template.`); console.log(`Run: zcode-proxy auth login @@ -118911,13 +120231,6 @@ async function serve(configPath, debug) { server.stop(true); }); } -function buildServerOptions(config, auth, debug) { - const opts = { config, auth, debug }; - if (config.responses.enabled) { - opts.responseStore = new ResponseStore({ maxEntries: config.responses.storeMaxEntries, ttlMs: config.responses.storeTtlMs }); - } - return opts; -} function applyAndroidIdentityDefaults() { process.env.ZCODE_IDENTITY_PLATFORM = process.env.ZCODE_IDENTITY_PLATFORM ?? "linux"; process.env.ZCODE_IDENTITY_ARCH = process.env.ZCODE_IDENTITY_ARCH ?? "x64"; @@ -118926,8 +120239,8 @@ function applyAndroidIdentityDefaults() { async function runAndroid() { applyAndroidIdentityDefaults(); const path2 = process.env.ZCODE_PROXY_CONFIG ?? "config.yaml"; - if (!(0, import_node_fs5.existsSync)(path2)) { - (0, import_node_fs5.writeFileSync)(path2, EXAMPLE_CONFIG_YAML, "utf-8"); + if (!(0, import_node_fs7.existsSync)(path2)) { + (0, import_node_fs7.writeFileSync)(path2, EXAMPLE_CONFIG_YAML, "utf-8"); } const config = loadConfig(path2); const logBuffer = new LogBuffer(); @@ -119016,13 +120329,6 @@ async function runAndroid() { void controlListener.close().then(() => serverRef.current?.stop(true)); }); } -function updateConfigYaml(path2, fields) { - const raw = (0, import_node_fs5.readFileSync)(path2, "utf-8"); - const parsed = (0, import_yaml2.parse)(raw) ?? {}; - parsed.provider = fields.provider; - parsed.plan = fields.plan; - (0, import_node_fs5.writeFileSync)(path2, (0, import_yaml2.stringify)(parsed), "utf-8"); -} function printDebugBanner(config, path2, cred) { const credShape = cred ? `${cred.apiKey.slice(0, 6)}...${cred.apiKey.slice(-4)} (${cred.apiKey.length} chars)` : "(none)"; const active = config.providers[config.provider]; @@ -119061,7 +120367,7 @@ async function claimCommand(args) { process.exit(1); } const path2 = process.env.ZCODE_PROXY_CONFIG ?? "config.yaml"; - if (!(0, import_node_fs5.existsSync)(path2)) { + if (!(0, import_node_fs7.existsSync)(path2)) { console.error(`Config file not found: ${path2} (run serve once or create it).`); process.exit(1); } @@ -119104,8 +120410,8 @@ Logged in as ${provider}.`); } function ensureConfigWithDeviceMid() { const path2 = process.env.ZCODE_PROXY_CONFIG ?? "config.yaml"; - if (!(0, import_node_fs5.existsSync)(path2)) { - (0, import_node_fs5.writeFileSync)(path2, EXAMPLE_CONFIG_YAML, "utf-8"); + if (!(0, import_node_fs7.existsSync)(path2)) { + (0, import_node_fs7.writeFileSync)(path2, EXAMPLE_CONFIG_YAML, "utf-8"); console.log(`Created ${path2} from bundled template.`); } return ensureDeviceMidInConfig(path2); @@ -119113,7 +120419,7 @@ function ensureConfigWithDeviceMid() { function ensureDeviceMidInConfig(path2) { const deviceMidLine = /^(\s*)deviceMid:\s*(.*)$/m; const identityBlockLine = /^identity:\s*$/m; - const raw = (0, import_node_fs5.readFileSync)(path2, "utf-8"); + const raw = (0, import_node_fs7.readFileSync)(path2, "utf-8"); const existing = deviceMidLine.exec(raw); if (existing) { const value2 = existing[2].trim().replace(/^"|"$/g, ""); @@ -119132,12 +120438,12 @@ function ensureDeviceMidInConfig(path2) { `; updated = raw.endsWith("\n") || raw.length === 0 ? raw + block : raw + "\n" + block; } - (0, import_node_fs5.writeFileSync)(path2, updated, "utf-8"); + (0, import_node_fs7.writeFileSync)(path2, updated, "utf-8"); console.log(`Device identity generated: ${mid.slice(0, 8)}\u2026 (stored in ${path2})`); return mid; } function authLogout() { - if (!(0, import_node_fs5.existsSync)(getStorePath())) { + if (!(0, import_node_fs7.existsSync)(getStorePath())) { console.log("Not logged in."); return; } @@ -119181,7 +120487,7 @@ function importFromZCodeConfig(provider) { const configPath = (0, import_node_path3.join)((0, import_node_os5.homedir)(), ".zcode", "v2", "config.json"); let raw; try { - raw = (0, import_node_fs5.readFileSync)(configPath, "utf-8"); + raw = (0, import_node_fs7.readFileSync)(configPath, "utf-8"); } catch { console.error(`Cannot read ${configPath}.`); console.error("Make sure ZCode is installed and you've logged in at least once."); @@ -119201,25 +120507,33 @@ function importFromZCodeConfig(provider) { if (jwt) console.log(` Start-plan JWT: ${jwt.slice(0, 12)}...`); return { apiKey, provider, jwt }; } -function openBrowser(url2) { - try { - if (process.platform === "win32") { - (0, import_node_child_process.spawn)("cmd.exe", ["/c", `start "" "${url2}"`], { - detached: true, - stdio: "ignore", - windowsHide: true, - windowsVerbatimArguments: true - }).unref(); - } else if (process.platform === "darwin") { - (0, import_node_child_process.spawn)("open", [url2], { detached: true, stdio: "ignore" }).unref(); - } else { - (0, import_node_child_process.spawn)("xdg-open", [url2], { detached: true, stdio: "ignore" }).unref(); - } - } catch { - } -} +var import_node_fs7, import_node_path3, import_node_os5, import_node_crypto4, VERSION; +var init_index = __esm({ + "src/index.ts"() { + init_loader(); + init_template(); + init_manager(); + init_server(); + init_control(); + init_store(); + init_oauth(); + init_resolver(); + init_edit(); + init_open_browser(); + init_server_options(); + import_node_fs7 = require("node:fs"); + import_node_path3 = require("node:path"); + import_node_os5 = require("node:os"); + import_node_crypto4 = require("node:crypto"); + init_node_fetch_compat(); + VERSION = "2.6.0"; + if (require.main === module) main(); + } +}); +init_index(); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { + VERSION, applyAndroidIdentityDefaults, ensureDeviceMidInConfig, main, diff --git a/README.md b/README.md index 05b458e..9772f0d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,9 @@ bun install # Copy and edit config cp config.example.yaml config.yaml -# Default auth is OAuth — log in first (see Authentication below) + +# Log in (OAuth, browser-based) +bun run src/index.ts auth login zai # or: bigmodel # Start the proxy bun run src/index.ts @@ -196,6 +198,34 @@ upload (auto-enabled for models whose id contains `v`), MCP HTTP servers, markdown + code-highlight rendering, light/dark theme, and per-browser multi-session autosave (localStorage). Open Settings (⚙) to configure. +### Terminal UI (TUI) + +```bash +bun run src/index.ts tui # same as serve, plus an interactive panel +bun run src/index.ts tui debug # with per-request debug diagnostics +``` + +A PC terminal control panel mirroring the Android app's layout — three cards +(Settings & Login / Proxy Server / Logs) rendered in the alternate screen with +zero extra dependencies. The proxy auto-starts on launch when credentials are +available; the log card shows live per-request rows (console output is +captured in-process) with scrollback and tail-following. + +| Key | Action | +|-----|--------| +| `s` | Start / stop the proxy server | +| `l` | OAuth login for the current provider (opens the browser) | +| `o` | Logout (cancels an in-flight login and releases its callback port) | +| `p` / `t` | Switch provider (`zai` ↔ `bigmodel`) / plan (`coding-plan` ↔ `start-plan`) — requires the proxy stopped, persisted to `config.yaml` | +| `↑↓` / `PgUp`/`PgDn` / `Home`/`End` | Scroll the log pane | +| `g` | Jump back to the tail (re-enable following) | +| `c` | Clear the log pane | +| `q` / `Ctrl+C` | Quit | + +Set `ZCODE_TUI_LOGFILE=/path/to/file.log` to also tee every captured line to a +file (best-effort; never affects handling). Requires a TTY with at least +40x14 cells; Windows Terminal, mintty and common Unix terminals are supported. + ## Configuration | Field | Env Var | Default | Description | diff --git a/src/config/edit.test.ts b/src/config/edit.test.ts new file mode 100644 index 0000000..e4d7597 --- /dev/null +++ b/src/config/edit.test.ts @@ -0,0 +1,38 @@ +import { describe, expect, test } from "bun:test"; +import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { updateConfigYaml } from "./edit.js"; + +describe("updateConfigYaml", () => { + test("rewrites top-level provider and plan, preserving other keys", () => { + const dir = mkdtempSync(join(tmpdir(), "zcode-tui-test-")); + const path = join(dir, "config.yaml"); + writeFileSync( + path, + [ + "server:", + " host: 127.0.0.1", + " port: 8080", + "provider: zai", + "plan: coding-plan", + "models:", + " - glm-4.6", + " - glm-5.3", + "", + ].join("\n"), + "utf-8", + ); + + try { + updateConfigYaml(path, { provider: "bigmodel", plan: "start-plan" }); + const updated = readFileSync(path, "utf-8"); + expect(updated).toContain("provider: bigmodel"); + expect(updated).toContain("plan: start-plan"); + expect(updated).toContain("port: 8080"); + expect(updated).toContain("- glm-5.3"); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); +}); diff --git a/src/config/edit.ts b/src/config/edit.ts new file mode 100644 index 0000000..145638e --- /dev/null +++ b/src/config/edit.ts @@ -0,0 +1,19 @@ +/** + * Targeted YAML config editing helpers shared by the CLI entries (serve / + * android / tui) and the TUI runtime. + */ +import { parse, stringify } from "yaml"; +import { readFileSync, writeFileSync } from "node:fs"; +import type { ProviderId } from "../provider/types.js"; + +/** Targeted YAML update of top-level `provider` and `plan` keys. */ +export function updateConfigYaml( + path: string, + fields: { provider: ProviderId; plan: "coding-plan" | "start-plan" }, +): void { + const raw = readFileSync(path, "utf-8"); + const parsed = parse(raw) ?? {}; + parsed.provider = fields.provider; + parsed.plan = fields.plan; + writeFileSync(path, stringify(parsed), "utf-8"); +} diff --git a/src/index.ts b/src/index.ts index 1b32ea2..91cb237 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,22 +7,22 @@ import { EXAMPLE_CONFIG_YAML } from "./config/template.js"; import { AuthManager } from "./auth/manager.js"; import { startServer, type ProxyServer } from "./server/server.js"; import { startControlListener, LogBuffer, type ControlState } from "./android/control.js"; -import { ResponseStore } from "./responses/store.js"; import { loadCredential, saveCredential, clearCredential, getStorePath } from "./auth/store.js"; import { ZaiOAuthClient, BigmodelOAuthClient } from "./auth/oauth.js"; import { KeyResolver } from "./auth/resolver.js"; import type { Credential } from "./auth/types.js"; import type { ProviderId } from "./provider/types.js"; import type { ProxyConfig } from "./config/types.js"; -import { parse, stringify } from "yaml"; -import { spawn } from "node:child_process"; +import { updateConfigYaml } from "./config/edit.js"; +import { openBrowser } from "./runtime/open-browser.js"; +import { buildServerOptions } from "./server/server-options.js"; import { readFileSync, existsSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { homedir } from "node:os"; import { randomUUID } from "node:crypto"; import { ensureNodeFetchNoTimeouts } from "./runtime/node-fetch-compat.js"; -const VERSION = "2.6.0"; +export const VERSION = "2.6.0"; if (require.main === module) main(); @@ -74,6 +74,16 @@ function runCli(): void { process.stderr.write(`zcode-proxy: android entry failed: ${(err as Error).stack ?? String(err)}\n`); process.exit(1); }); + } else if (cmd === "tui") { + // Dynamic import: the TUI module imports helpers back from this file, so a + // static edge would create a load-time cycle (same pattern as claimCommand). + const tuiArgs = parseServeArgs(args.slice(1)); + import("./tui/app.js") + .then((m) => m.runTui(tuiArgs)) + .catch((err: unknown) => { + process.stderr.write(`zcode-proxy: tui failed: ${(err as Error).stack ?? String(err)}\n`); + process.exit(1); + }); } else if (cmd === "serve" || cmd.endsWith(".yaml") || cmd.endsWith(".yml")) { const serveArgs = cmd === "serve" ? parseServeArgs(args.slice(1)) @@ -97,6 +107,7 @@ Usage: zcode-proxy serve [config.yaml] Start the proxy server (default) zcode-proxy serve debug [config.yaml] Start with verbose per-request diagnostics + zcode-proxy tui [config.yaml] Interactive terminal UI (login / start-stop / live logs) zcode-proxy android Android entry: proxy + localhost control listener zcode-proxy auth login Login via OAuth (provider: zai | bigmodel) zcode-proxy auth login --import @@ -110,6 +121,7 @@ Usage: Examples: zcode-proxy Start server with default config.yaml zcode-proxy serve debug Start with extra debug logging + zcode-proxy tui Terminal UI: login, start/stop, live logs zcode-proxy auth login bigmodel OAuth login for Bigmodel zcode-proxy auth login bigmodel --import Import existing key from ZCode config @@ -170,15 +182,6 @@ async function serve(configPath: string | undefined, debug: boolean): Promise { }); } -/** Targeted YAML update of top-level `provider` and `plan` keys. */ -function updateConfigYaml(path: string, fields: { provider: ProviderId; plan: "coding-plan" | "start-plan" }): void { - const raw = readFileSync(path, "utf-8"); - const parsed = parse(raw) ?? {}; - parsed.provider = fields.provider; - parsed.plan = fields.plan; - writeFileSync(path, stringify(parsed), "utf-8"); -} - function printDebugBanner(config: ProxyConfig, path: string, cred: Credential | null): void { const credShape = cred ? `${cred.apiKey.slice(0, 6)}...${cred.apiKey.slice(-4)} (${cred.apiKey.length} chars)` @@ -529,17 +523,3 @@ function importFromZCodeConfig(provider: ProviderId): Credential { if (jwt) console.log(` Start-plan JWT: ${jwt.slice(0, 12)}...`); return { apiKey, provider, jwt }; } - -function openBrowser(url: string): void { - try { - if (process.platform === "win32") { - spawn("cmd.exe", ["/c", `start "" "${url}"`], { - detached: true, stdio: "ignore", windowsHide: true, windowsVerbatimArguments: true, - }).unref(); - } else if (process.platform === "darwin") { - spawn("open", [url], { detached: true, stdio: "ignore" }).unref(); - } else { - spawn("xdg-open", [url], { detached: true, stdio: "ignore" }).unref(); - } - } catch { /* user copies URL manually */ } -} diff --git a/src/proxy/captcha-happy.test.ts b/src/proxy/captcha-happy.test.ts new file mode 100644 index 0000000..0e72eb4 --- /dev/null +++ b/src/proxy/captcha-happy.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, test } from "bun:test"; +import { makeDualConsole } from "./captcha-happy.js"; + +describe("dual console (guest spam guard)", () => { + test("drops every console method's call while the guest predicate holds", () => { + const seen: string[] = []; + const recorder: Record = {}; + for (const m of ["log", "debug", "info", "dir", "table", "group", "warn", "error"]) { + recorder[m] = (...a: unknown[]) => { seen.push(m + ": " + a.join(" ")); }; + } + const orig = console as unknown as Record; + const saved = Object.fromEntries( + Object.keys(recorder).map((k) => [k, orig[k]]), + ); + Object.assign(orig, recorder); + + try { + // Build the dual console against the recorder and route calls through + // it with the guest predicate forced on — the FeiLin spam condition. + const dual = makeDualConsole(() => true) as Record void>; + dual.log!("%c%d", "font-size:0;color:transparent", "Error"); + dual.debug!("anything"); + dual.dir!({ an: "object" }); + dual.table!([1, 2]); + expect(seen).toEqual([]); + + // Host condition — identical calls must forward untouched. + const forward = makeDualConsole(() => false) as Record void>; + forward.log!("hello", 42); + forward.error!("[real] failure"); + expect(seen).toEqual(["log: hello 42", "error: [real] failure"]); + } finally { + Object.assign(orig, saved); + } + }); +}); diff --git a/src/proxy/captcha-happy.ts b/src/proxy/captcha-happy.ts index d904ff7..baadd25 100644 --- a/src/proxy/captcha-happy.ts +++ b/src/proxy/captcha-happy.ts @@ -1789,8 +1789,60 @@ const EXTRA_WINDOW_PROPS = [ // destroyDom() pulls `window` out from under a sibling mid-solve. let _aliasRefCount = 0; +// Under Bun, guest scripts run in the HOST realm — a bare `console` inside +// SDK code resolves to the HOST console (that is the FeiLin spam channel: +// invisible devtools-format lines probed across every console method, ~1/sec +// while solving). While the aliases are installed, `console` on globalThis is +// replaced with a DUAL console: calls whose stack originates from guest SDK +// script URLs are dropped, everything else forwards to the console that was +// live at install time (the TUI's interception or the serve terminal — so +// host logging keeps working untouched). Restored on the last destroyDom. +// Skipped under CAPTCHA_DEBUG so guest logs stay inspectable. +let _savedConsoleDescriptor: PropertyDescriptor | undefined; +let _dualConsole: Record | null = null; + +function isGuestConsoleCall(): boolean { + const stack = new Error().stack ?? ""; + return /alicdn\.com|aliyuncs\.com/i.test(stack); +} + +/** Build a console facade that drops calls while `isGuest()` holds (test seam). */ +export function makeDualConsole(isGuest: () => boolean = isGuestConsoleCall): Record { + // Capture the console OBJECT at build time — methods must keep their + // original receiver (looking up `console` again inside the closure would + // resolve to the dual getter itself and recurse). + const host = console as unknown as Record; + const dual: Record = {}; + for (const key of Object.keys(host)) { + const fn = host[key]; + if (typeof fn !== "function") { + dual[key] = fn; + continue; + } + dual[key] = (...args: unknown[]) => { + if (isGuest()) return; + return (fn as (...a: unknown[]) => void).apply(host, args); + }; + } + return dual; +} + function installGlobalWindowAlias(g, w) { _aliasRefCount += 1; + if (_aliasRefCount === 1 && !process.env.CAPTCHA_DEBUG) { + _dualConsole = makeDualConsole(); _savedConsoleDescriptor = Object.getOwnPropertyDescriptor(g, "console"); + try { + Object.defineProperty(g, "console", { + get() { + return _dualConsole; + }, + set(v) { + try { w.console = v; } catch (_) {} + }, + configurable: true, + }); + } catch (_) {} + } const props = new Set(Object.getOwnPropertyNames(w)); for (const name of EXTRA_WINDOW_PROPS) props.add(name); // also walk the prototype chain one level (BrowserWindow getters like @@ -1852,6 +1904,16 @@ function removeGlobalWindowAlias(g, w) { for (const prop of ["window", "self", "top", "parent"]) { try { delete g[prop]; } catch (_) {} } + // Restore the pre-alias console descriptor — `delete g.console` above (the + // getter installed for the dual console) would otherwise leave globalThis + // without a console at all. + if (_savedConsoleDescriptor) { + try { + Object.defineProperty(g, "console", _savedConsoleDescriptor); + } catch (_) {} + _savedConsoleDescriptor = undefined; + _dualConsole = null; + } } function destroyDom(win) { diff --git a/src/runtime/open-browser.ts b/src/runtime/open-browser.ts new file mode 100644 index 0000000..21b0e17 --- /dev/null +++ b/src/runtime/open-browser.ts @@ -0,0 +1,20 @@ +/** + * Cross-platform default-browser launcher, shared by the CLI auth flows and + * the TUI login action. Best-effort: a failure leaves the URL on screen for + * the user to copy manually. + */ +import { spawn } from "node:child_process"; + +export function openBrowser(url: string): void { + try { + if (process.platform === "win32") { + spawn("cmd.exe", ["/c", `start "" "${url}"`], { + detached: true, stdio: "ignore", windowsHide: true, windowsVerbatimArguments: true, + }).unref(); + } else if (process.platform === "darwin") { + spawn("open", [url], { detached: true, stdio: "ignore" }).unref(); + } else { + spawn("xdg-open", [url], { detached: true, stdio: "ignore" }).unref(); + } + } catch { /* user copies URL manually */ } +} diff --git a/src/server/server-options.ts b/src/server/server-options.ts new file mode 100644 index 0000000..93aa64b --- /dev/null +++ b/src/server/server-options.ts @@ -0,0 +1,20 @@ +/** + * `startServer` option assembly shared by every entry that boots the proxy + * in-process (serve / android / tui). + */ +import type { ProxyConfig } from "../config/types.js"; +import type { AuthManager } from "../auth/manager.js"; +import { ResponseStore } from "../responses/store.js"; + +/** Build `startServer` options, wiring the Responses store when its config gate is on. */ +export function buildServerOptions( + config: ProxyConfig, + auth: AuthManager, + debug: boolean, +): { config: ProxyConfig; auth: AuthManager; debug: boolean; responseStore?: ResponseStore } { + const opts: { config: ProxyConfig; auth: AuthManager; debug: boolean; responseStore?: ResponseStore } = { config, auth, debug }; + if (config.responses.enabled) { + opts.responseStore = new ResponseStore({ maxEntries: config.responses.storeMaxEntries, ttlMs: config.responses.storeTtlMs }); + } + return opts; +} diff --git a/src/tui/app.ts b/src/tui/app.ts new file mode 100644 index 0000000..275aaaf --- /dev/null +++ b/src/tui/app.ts @@ -0,0 +1,451 @@ +/** + * PC terminal UI (`zcode-proxy tui`) — an in-process control panel mirroring + * the Android app's three-card layout: Settings & Login / Proxy Server / Logs. + * + * The TUI owns the terminal (alternate screen + raw mode) and, like the + * Android entry, intercepts console.log/warn/error into a ring buffer so the + * per-request log rows land in the Logs card. Zero new dependencies: the + * renderer, input parser and width math are hand-rolled ANSI/VT (Bun- and + * Node-compatible, bundles into both release artifacts). + * + * index.ts dispatches here via dynamic import (this module imports helpers + * back from index.js), mirroring the claimCommand pattern. + */ +import { loadConfig } from "../config/loader.js"; +import { EXAMPLE_CONFIG_YAML } from "../config/template.js"; +import { updateConfigYaml } from "../config/edit.js"; +import { AuthManager } from "../auth/manager.js"; +import { startServer, type ProxyServer } from "../server/server.js"; +import { buildServerOptions } from "../server/server-options.js"; +import { loadCredential, saveCredential, clearCredential } from "../auth/store.js"; +import { ZaiOAuthClient, BigmodelOAuthClient, type OAuthFlowClient } from "../auth/oauth.js"; +import { KeyResolver } from "../auth/resolver.js"; +import { openBrowser } from "../runtime/open-browser.js"; +import { ensureDeviceMidInConfig, VERSION, type ServeArgs } from "../index.js"; +import { writeFileSync, existsSync, appendFileSync } from "node:fs"; +import type { ProxyConfig } from "../config/types.js"; +import type { ProviderId } from "../provider/types.js"; +import { LogPane } from "./log-pane.js"; +import { KeyParser, type KeyAction } from "./keys.js"; +import { buildFrame, findRegion, type ClickAction, type ClickRegion } from "./frame.js"; + +type PlanTier = "coding-plan" | "start-plan"; +type ServerStatus = "stopped" | "starting" | "running" | "error"; + +const RENDER_MS = 33; +const PAGE_LINES = 10; +const TOAST_MS = 2600; + +export async function runTui(args: ServeArgs): Promise { + if (!process.stdout.isTTY || !process.stdin.isTTY) { + process.stderr.write("zcode-proxy: tui requires an interactive terminal (TTY).\n"); + process.exit(1); + } + + const path = args.configPath ?? process.env.ZCODE_PROXY_CONFIG ?? "config.yaml"; + let config: ProxyConfig; + try { + if (!existsSync(path)) { + writeFileSync(path, EXAMPLE_CONFIG_YAML, "utf-8"); + ensureDeviceMidInConfig(path); + process.stderr.write(`Created ${path} from bundled template.\n`); + } + config = loadConfig(path); + } catch (err) { + process.stderr.write(`zcode-proxy: config error: ${(err as Error).message}\n`); + process.exit(1); + } + + const auth = new AuthManager(); + const pane = new LogPane(2000); + const serverRef: { current: ProxyServer | null } = { current: null }; + + const state = { + provider: config.provider as ProviderId, + plan: config.plan as PlanTier, + loggedIn: false, + apiKeyPreview: "", + serverStatus: "stopped" as ServerStatus, + serverUrl: "", + serverError: "", + loginInFlight: false, + loginHint: "", + toast: null as { text: string; kind: "ok" | "err" | "info" } | null, + }; + + // --- terminal setup ------------------------------------------------------ + const stdout = process.stdout; + const stdin = process.stdin; + // Alt screen + hide cursor + SGR mouse tracking (buttons clickable, wheel scrolls). + stdout.write("\x1b[?1049h\x1b[?25l\x1b[?1000h\x1b[?1006h\x1b[2J"); + + const restore = (): void => { + try { stdout.write("\x1b[0m\x1b[?1006l\x1b[?1000l\x1b[?25h\x1b[?1049l"); } catch { /* terminal gone */ } + }; + + // --- console interception → log pane (Android-entry pattern) ------------ + // ALL console methods are intercepted, not just log/warn/error: guest + // scripts (the captcha SDK) probe the full console surface, and anything + // left unpatched would bypass the pane and write raw into the alt-screen + // frame. Originals are kept for the pre-TUI error path and restore. + const origConsole: Record void> = {}; + const origError = console.error; + const logFile = process.env.ZCODE_TUI_LOGFILE; + const emit = (text: string, level: "info" | "warn" | "error"): void => { + pane.push(text, level); + if (logFile) { + try { appendFileSync(logFile, text + "\n", "utf-8"); } catch { /* best-effort tee */ } + } + scheduleRender(); + }; + const consoleOwner = console as unknown as Record; + for (const key of Object.keys(console)) { + const fn = consoleOwner[key]; + if (typeof fn !== "function") continue; + origConsole[key] = fn as (...a: unknown[]) => void; + consoleOwner[key] = (...a: unknown[]) => { + const level = key === "error" ? "error" : key === "warn" ? "warn" : "info"; + const prefix = key === "error" ? "[error] " : key === "warn" ? "[warn] " : ""; + emit(prefix + a.map(String).join(" "), level); + }; + } + const restoreConsole = (): void => { + for (const [key, fn] of Object.entries(origConsole)) consoleOwner[key] = fn; + }; + + // --- rendering ----------------------------------------------------------- + let renderTimer: ReturnType | null = null; + let activeRegions: ClickRegion[] = []; + function renderNow(): void { + renderTimer = null; + const width = stdout.columns || 80; + const height = stdout.rows || 24; + const view = pane.view(Math.max(4, height - 14)); + const frame = buildFrame({ + version: VERSION, + configPath: path, + provider: state.provider, + plan: state.plan, + loggedIn: state.loggedIn, + apiKeyPreview: state.apiKeyPreview, + loginInFlight: state.loginInFlight, + loginHint: state.loginHint, + serverStatus: state.serverStatus, + serverUrl: state.serverUrl, + serverError: state.serverError, + modelCount: config.models.length, + responsesEnabled: config.responses.enabled, + claimAuto: config.claim.enabled && config.claim.auto, + logTotal: view.total, + logView: view.lines, + logFollowing: pane.following, + logFromBottom: view.fromBottom, + toast: state.toast, + width, + height, + }); + activeRegions = frame.regions; + try { stdout.write("\x1b[H" + frame.text); } catch { /* terminal gone */ } + } + function scheduleRender(): void { + if (renderTimer) return; + renderTimer = setTimeout(renderNow, RENDER_MS); + if (typeof renderTimer.unref === "function") renderTimer.unref(); + } + let toastTimer: ReturnType | null = null; + function setToast(text: string, kind: "ok" | "err" | "info"): void { + state.toast = { text, kind }; + if (toastTimer) clearTimeout(toastTimer); + toastTimer = setTimeout(() => { + state.toast = null; + toastTimer = null; + scheduleRender(); + }, TOAST_MS); + if (typeof toastTimer.unref === "function") toastTimer.unref(); + scheduleRender(); + } + + // --- auth ---------------------------------------------------------------- + async function refreshAuth(): Promise { + const cred = await loadCredential().catch(() => null); + state.loggedIn = cred != null; + state.apiKeyPreview = cred ? `${cred.apiKey.slice(0, 8)}…` : ""; + scheduleRender(); + } + + // --- proxy lifecycle (mirrors the Android startProxy/stopProxy hooks) ---- + async function startProxy(): Promise { + if (state.serverStatus === "running" || state.serverStatus === "starting") return; + state.serverStatus = "starting"; + state.serverError = ""; + scheduleRender(); + const cred = await loadCredential().catch(() => null); + if (!cred) { + state.serverStatus = "stopped"; + setToast("not logged in — press l to login", "err"); + return; + } + auth.setOAuthCredential(cred); + try { + const s = await startServer(buildServerOptions(config, auth, args.debug)); + serverRef.current = s; + state.serverStatus = "running"; + state.serverUrl = `http://${s.hostname}:${s.port}`; + setToast(`proxy started on ${state.serverUrl}`, "ok"); + startBackgroundJobsOnce(); + } catch (err) { + state.serverStatus = "error"; + state.serverError = (err as Error).message; + setToast(`start failed: ${(err as Error).message}`, "err"); + } + } + + function stopProxy(): void { + const s = serverRef.current; + if (!s) return; + try { + s.stop(false); // NOT stop(true) — must not kill the process (anti-pattern #19) + } catch (err) { + setToast(`stop failed: ${(err as Error).message}`, "err"); + return; + } + serverRef.current = null; + state.serverStatus = "stopped"; + state.serverUrl = ""; + setToast("proxy stopped", "info"); + } + + function toggleProxy(): void { + if (state.serverStatus === "running" || state.serverStatus === "starting") stopProxy(); + else void startProxy(); + } + + // Captcha warmup + claim scheduler start once per process, even across + // proxy stop/start cycles — the pools and scheduler are process-global. + let backgroundJobsStarted = false; + function startBackgroundJobsOnce(): void { + if (backgroundJobsStarted) return; + backgroundJobsStarted = true; + if (config.plan === "start-plan") { + import("../proxy/captcha.js") + .then((m) => m.startCaptchaPool(config.identity.appVersion)) + .catch((err) => console.error(`[captcha] pool warmup failed: ${(err as Error).message}`)); + } + if (config.claim.enabled && config.claim.auto) { + import("../claim/runtime.js") + .then((m) => { + m.startAutoClaim(config, auth); + console.log(`[claim] auto ON (poll ${Math.round(config.claim.pollIntervalMs / 1000)}s)`); + }) + .catch((err) => console.error(`[claim] scheduler failed to start: ${(err as Error).message}`)); + } + } + + // --- provider / plan switching (mirrors the Android setConfig command) --- + function switchProvider(): void { + const next: ProviderId = state.provider === "zai" ? "bigmodel" : "zai"; + applyConfigChange(next, state.plan, `provider → ${next}`); + } + + function switchPlan(): void { + const next: PlanTier = state.plan === "coding-plan" ? "start-plan" : "coding-plan"; + applyConfigChange(state.provider, next, `plan → ${next}`); + } + + function applyConfigChange(provider: ProviderId, plan: PlanTier, message: string): void { + if (state.serverStatus === "running" || state.serverStatus === "starting") { + setToast("stop the proxy before switching (press s)", "err"); + return; + } + config.provider = provider; + config.plan = plan; + try { + updateConfigYaml(path, { provider, plan }); + state.provider = provider; + state.plan = plan; + setToast(message, "ok"); + console.log(`config updated: provider=${provider} plan=${plan}`); + } catch (err) { + setToast(`config update failed: ${(err as Error).message}`, "err"); + } + scheduleRender(); + } + + // --- login / logout (mirrors the control-listener startOAuth/logout) ----- + let activeOauth: { client: OAuthFlowClient; provider: ProviderId } | null = null; + + async function startLogin(): Promise { + if (state.loginInFlight) { + setToast("login already in progress", "info"); + return; + } + const provider = state.provider; + const client: OAuthFlowClient = provider === "bigmodel" ? new BigmodelOAuthClient() : new ZaiOAuthClient(); + let started: Awaited>; + try { + started = await client.start(); + } catch (err) { + void client.close().catch(() => {}); + setToast(`login failed: ${(err as Error).message}`, "err"); + return; + } + activeOauth = { client, provider }; + state.loginInFlight = true; + state.loginHint = "waiting for browser authorization…"; + console.log(`OAuth: opening ${started.authorizeUrl}`); + console.log("If the browser did not open, copy the URL above into a browser."); + openBrowser(started.authorizeUrl); + scheduleRender(); + + client.complete(started).then(async (tokens) => { + const resolver = new KeyResolver(); + const cred = await resolver.resolveCodingPlanCredential(tokens.accessToken, provider, tokens.userId); + if (tokens.jwt) cred.jwt = tokens.jwt; + await saveCredential(cred); + if (serverRef.current) auth.setOAuthCredential(cred); + console.log(`OAuth completed for ${provider}`); + setToast("logged in", "ok"); + }).catch((err: unknown) => { + const msg = (err as Error)?.message ?? String(err); + console.error(`OAuth flow ended without success: ${msg}`); + setToast(`login failed: ${msg}`, "err"); + }).finally(() => { + // MUST run on rejection too — otherwise the callback port leaks + // (fixed Android bug 5746857, same discipline applies here). + void client.close().catch(() => {}); + if (activeOauth?.client === client) activeOauth = null; + state.loginInFlight = false; + state.loginHint = ""; + void refreshAuth(); + }); + } + + async function logout(): Promise { + if (activeOauth) { + void activeOauth.client.close().catch(() => {}); + activeOauth = null; + state.loginInFlight = false; + state.loginHint = ""; + } + try { + clearCredential(); + } catch { /* best-effort logout */ } + await refreshAuth(); + if (serverRef.current) setToast("logged out — restart the proxy to apply", "info"); + else setToast("logged out", "ok"); + } + + // --- input loop ------------------------------------------------------------ + const parser = new KeyParser(); + stdin.setEncoding("utf8"); + if (typeof (stdin as { setRawMode?: (m: boolean) => void }).setRawMode !== "function") { + restore(); + origError("zcode-proxy: tui requires a terminal with raw-mode input.\n"); + process.exit(1); + } + (stdin as { setRawMode(m: boolean): void }).setRawMode(true); + stdin.resume(); + stdin.on("data", (chunk: string) => { + for (const action of parser.feed(chunk)) handleKey(action); + }); + + function scrollUp(n: number): void { + pane.scrollUp(n); + scheduleRender(); + } + function scrollDown(n: number): void { + pane.scrollDown(n); + scheduleRender(); + } + + function handleKey(action: KeyAction): void { + switch (action.type) { + case "ctrl-c": + quit(); + return; + case "click": { + const hit = findRegion(activeRegions, action.y, action.x); + if (hit) dispatchClick(hit); + return; + } + case "wheel-up": + scrollUp(3); + return; + case "wheel-down": + scrollDown(3); + return; + case "char": { + switch (action.key.toLowerCase()) { + case "q": quit(); return; + case "s": toggleProxy(); return; + case "l": void startLogin(); return; + case "o": void logout(); return; + case "p": switchProvider(); return; + case "t": switchPlan(); return; + case "c": pane.clear(); scheduleRender(); return; + case "g": pane.followBottom(); scheduleRender(); return; + case "k": scrollUp(1); return; + case "j": scrollDown(1); return; + default: return; + } + } + case "up": scrollUp(1); return; + case "down": scrollDown(1); return; + case "pageup": scrollUp(PAGE_LINES); return; + case "pagedown": scrollDown(PAGE_LINES); return; + case "home": scrollUp(pane.count); return; + case "end": pane.followBottom(); scheduleRender(); return; + default: return; + } + } + + /** Mouse clicks hit the same actions as their keyboard shortcuts. */ + function dispatchClick(action: ClickAction): void { + switch (action.kind) { + case "key": + handleKey({ type: "char", key: action.key }); + return; + case "provider": + applyConfigChange(action.value, state.plan, `provider → ${action.value}`); + return; + case "plan": + applyConfigChange(state.provider, action.value, `plan → ${action.value}`); + return; + case "follow": + pane.followBottom(); + scheduleRender(); + return; + } + } + + // --- teardown --------------------------------------------------------------- + function quit(): void { + cleanup(); + process.exit(0); + } + function cleanup(): void { + restore(); + restoreConsole(); + try { serverRef.current?.stop(false); } catch { /* already closed */ } + } + process.on("SIGINT", quit); + process.on("SIGTERM", quit); + process.on("exit", restore); + stdout.on("resize", scheduleRender); + process.on("uncaughtException", (err: Error) => { + cleanup(); + origError(`zcode-proxy: tui crashed: ${err.stack ?? String(err)}`); + process.exit(1); + }); + + // --- boot --------------------------------------------------------------------- + console.log(`zcode-proxy TUI — config: ${path}`); + console.log(`provider: ${state.provider} · plan: ${state.plan}`); + await refreshAuth(); + renderNow(); + if (!state.loggedIn) { + setToast("not logged in — press l to login", "err"); + } else { + await startProxy(); + } +} diff --git a/src/tui/frame.test.ts b/src/tui/frame.test.ts new file mode 100644 index 0000000..cc8ffa0 --- /dev/null +++ b/src/tui/frame.test.ts @@ -0,0 +1,241 @@ +import { describe, expect, test } from "bun:test"; +import { buildFrame, findRegion, type FrameState } from "./frame.js"; +import { displayWidth, stripAnsi } from "./width.js"; + +function baseState(overrides: Partial = {}): FrameState { + return { + version: "2.6.0", + configPath: "config.yaml", + provider: "zai", + plan: "coding-plan", + loggedIn: false, + apiKeyPreview: "", + loginInFlight: false, + loginHint: "", + serverStatus: "stopped", + serverUrl: "", + serverError: "", + modelCount: 6, + responsesEnabled: true, + claimAuto: false, + logTotal: 0, + logView: [], + logFollowing: true, + logFromBottom: 0, + toast: null, + width: 80, + height: 30, + ...overrides, + }; +} + +function plainLines(state: FrameState): string[] { + return buildFrame(state).text.split("\n").map((l) => stripAnsi(l.replace(/\x1b\[K$/, ""))); +} + +describe("buildFrame", () => { + test("renders the three card titles, mirroring the Android layout", () => { + const lines = plainLines(baseState()); + const text = lines.join("\n"); + expect(text).toContain("Settings & Login"); + expect(text).toContain("Proxy Server"); + expect(text).toContain("Logs"); + }); + + test("shows provider/plan button state and auth status", () => { + const text = plainLines(baseState({ loggedIn: true, apiKeyPreview: "ab12cd34…" })).join("\n"); + expect(text).toContain(" zai "); + expect(text).toContain(" bigmodel "); + expect(text).toContain(" coding-plan "); + expect(text).toContain(" start-plan "); + expect(text).toContain("logged in · ab12cd34…"); + expect(text).toContain(" Logged In "); + expect(text).toContain(" Logout "); + }); + + test("shows a running server with its URL", () => { + const text = plainLines( + baseState({ serverStatus: "running", serverUrl: "http://127.0.0.1:8080" }), + ).join("\n"); + expect(text).toContain("● running"); + expect(text).toContain("http://127.0.0.1:8080"); + }); + + test("shows the error row when startup failed", () => { + const text = plainLines( + baseState({ serverStatus: "error", serverError: "EADDRINUSE: port busy" }), + ).join("\n"); + expect(text).toContain("✗ failed"); + expect(text).toContain("EADDRINUSE: port busy"); + }); + + test("renders log lines newest-last and marks the count", () => { + const text = plainLines( + baseState({ + logTotal: 3, + logView: [ + { level: "info", text: "one" }, + { level: "error", text: "boom" }, + { level: "info", text: "two" }, + ], + }), + ).join("\n"); + expect(text).toContain("(3)"); + expect(text.indexOf("one")).toBeLessThan(text.indexOf("boom")); + expect(text.indexOf("boom")).toBeLessThan(text.indexOf("two")); + }); + + test("shows an empty-log placeholder", () => { + const text = plainLines(baseState()).join("\n"); + expect(text).toContain("(no logs yet"); + }); + + test("scrollback state shows a more-below indicator instead of following", () => { + const text = plainLines(baseState({ logFollowing: false, logFromBottom: 42 })).join("\n"); + expect(text).toContain("▼ 42 more"); + expect(text).not.toContain("following"); + }); + + test("toast line appears above the footer", () => { + const lines = plainLines(baseState({ toast: { text: "proxy started", kind: "ok" } })); + const footerIdx = lines.findIndex((l) => l.includes("[s] start/stop")); + const toastIdx = lines.findIndex((l) => l.includes("proxy started")); + expect(toastIdx).toBeGreaterThan(0); + expect(toastIdx).toBe(footerIdx - 1); + }); + + test("login-in-flight adds a hint row and pill", () => { + const text = plainLines( + baseState({ loginInFlight: true, loginHint: "waiting for browser authorization…" }), + ).join("\n"); + expect(text).toContain("waiting for browser authorization…"); + expect(text).toContain("● logging in…"); + }); + + test("provider switch is locked while the proxy runs", () => { + const text = plainLines(baseState({ serverStatus: "running" })).join("\n"); + expect(text).toContain("(stop to switch)"); + }); + + test("server Start/Stop are clickable in either state (filled buttons row)", () => { + for (const serverStatus of ["stopped", "running"] as const) { + const f = buildFrame(baseState({ serverStatus, loggedIn: true, apiKeyPreview: "ab…" })); + const lines = f.text.split("\n").map((l) => stripAnsi(l.replace(/\x1b\[K$/, ""))); + const serverRow = lines.findIndex((l) => l.includes(" Stop ") && !l.includes("[s]")); + expect(serverRow).toBeGreaterThan(0); + const onRow = f.regions.filter((r) => r.row === serverRow); + expect(onRow.some((r) => r.action.kind === "key" && r.action.key === "s")).toBe(true); + const text = lines.join("\n"); + expect(text).toContain(" Start "); + expect(text).toContain(" Stop "); + } + }); + + test("registers click regions for provider/plan/login/server/footer buttons", () => { + const { regions } = buildFrame(baseState()); + const actions = regions.map((r) => r.action); + expect(actions).toContainEqual({ kind: "provider", value: "zai" }); + expect(actions).toContainEqual({ kind: "provider", value: "bigmodel" }); + expect(actions).toContainEqual({ kind: "plan", value: "coding-plan" }); + expect(actions).toContainEqual({ kind: "plan", value: "start-plan" }); + expect(actions).toContainEqual({ kind: "key", key: "l" }); + expect(actions).toContainEqual({ kind: "key", key: "s" }); + expect(actions).toContainEqual({ kind: "key", key: "q" }); + }); + + test("findRegion hit-tests provider buttons on their row", () => { + const { text, regions } = buildFrame(baseState()); + const lines = text.split("\n").map((l) => stripAnsi(l.replace(/\x1b\[K$/, ""))); + const providerRow = lines.findIndex((l) => l.includes(" zai ")); + expect(providerRow).toBeGreaterThan(0); + const colOfZai = lines[providerRow]!.indexOf(" zai "); + const colOfBigmodel = lines[providerRow]!.indexOf(" bigmodel "); + expect(findRegion(regions, providerRow, colOfZai + 2)).toEqual({ kind: "provider", value: "zai" }); + expect(findRegion(regions, providerRow, colOfBigmodel + 2)).toEqual({ kind: "provider", value: "bigmodel" }); + expect(findRegion(regions, providerRow, colOfBigmodel - 1)).toBeNull(); + }); + + test("provider/plan buttons are locked (no regions) while the proxy runs", () => { + const { regions } = buildFrame(baseState({ serverStatus: "running" })); + const providerRegions = regions.filter((r) => r.action.kind === "provider"); + expect(providerRegions).toEqual([]); + }); + + test("logout is only clickable when logged in (card button, not footer)", () => { + const cardLogoutRegions = (f: { text: string; regions: ReturnType["regions"] }) => { + const lines = f.text.split("\n").map((l) => stripAnsi(l.replace(/\x1b\[K$/, ""))); + const row = lines.findIndex((l) => l.includes(" Logout ")); + return f.regions.filter((r) => r.row === row && r.action.kind === "key" && r.action.key === "o"); + }; + expect(cardLogoutRegions(buildFrame(baseState({ loggedIn: false })))).toEqual([]); + expect(cardLogoutRegions(buildFrame(baseState({ loggedIn: true, apiKeyPreview: "ab12…" })))).toHaveLength(1); + }); + + test("the log title bar is a follow button while scrolled", () => { + const following = buildFrame(baseState({ logFollowing: true })); + expect(following.regions.some((r) => r.action.kind === "follow")).toBe(false); + const scrolled = buildFrame(baseState({ logFollowing: false, logFromBottom: 9 })); + const follow = scrolled.regions.find((r) => r.action.kind === "follow"); + expect(follow).toBeDefined(); + expect(follow!.row).toBeGreaterThan(0); + }); + + test("buttons keep their slots when the selection changes (no jumping)", () => { + // zai is always the first slot, bigmodel the second — regardless of which + // is selected (the user's mouse must not hit a different button twice). + for (const provider of ["zai", "bigmodel"] as const) { + const { text, regions } = buildFrame(baseState({ provider })); + const lines = text.split("\n").map((l) => stripAnsi(l.replace(/\x1b\[K$/, ""))); + const row = lines.findIndex((l) => l.includes(" zai ")); + expect(lines[row]!.indexOf(" zai ")).toBeLessThan(lines[row]!.indexOf(" bigmodel ")); + const bigmodelCol = lines[row]!.indexOf(" bigmodel "); + expect(findRegion(regions, row, bigmodelCol + 2)).toEqual({ kind: "provider", value: "bigmodel" }); + expect(findRegion(regions, row, lines[row]!.indexOf(" zai ") + 2)).toEqual({ kind: "provider", value: "zai" }); + } + for (const plan of ["coding-plan", "start-plan"] as const) { + const { text } = buildFrame(baseState({ plan })); + const lines = text.split("\n").map((l) => stripAnsi(l.replace(/\x1b\[K$/, ""))); + const row = lines.findIndex((l) => l.includes(" coding-plan ")); + expect(lines[row]!.indexOf(" coding-plan ")).toBeLessThan(lines[row]!.indexOf(" start-plan ")); + } + }); + + test("no line exceeds the terminal width (CJK logs included)", () => { + const state = baseState({ + logTotal: 2, + logView: [ + { level: "info", text: "#001 上游连接失败 upstream connect failed after many retries with backoff" }, + { level: "error", text: "🚀 emoji + 日本語テキスト mixing widths for truncation testing 1234567890" }, + ], + }); + for (const raw of buildFrame(state).text.split("\n")) { + expect(displayWidth(raw)).toBeLessThanOrEqual(state.width); + } + }); + + test("box borders span the full width", () => { + const lines = plainLines(baseState()); + const borders = lines.filter((l) => l.startsWith("╭")); + expect(borders.length).toBe(3); + for (const b of borders) expect(displayWidth(b)).toBe(80); + for (const b of lines.filter((l) => l.startsWith("╰"))) { + expect(displayWidth(b)).toBe(80); + } + }); + + test("fills the terminal height: cards + logs + footer", () => { + const state = baseState({ + logTotal: 50, + logView: Array.from({ length: 50 }, (_, i) => ({ level: "info", text: `log ${i}` })), + }); + const lines = plainLines(state); + // every rendered row (before \x1b[J) accounts for one terminal row + expect(lines.length).toBe(30); + }); + + test("too-small terminals get a compact message instead of boxes", () => { + const frame = buildFrame(baseState({ width: 30, height: 10 })).text; + expect(frame).toContain("terminal too small"); + expect(frame).not.toContain("╭"); + }); +}); diff --git a/src/tui/frame.ts b/src/tui/frame.ts new file mode 100644 index 0000000..3645473 --- /dev/null +++ b/src/tui/frame.ts @@ -0,0 +1,379 @@ +/** + * Pure frame renderer for the TUI. Takes a complete view-model and returns + * the full ANSI frame plus the clickable hit regions — interactive rows are + * rendered as bracketed buttons (`[ zai ]`, `[S] Start`) and every button + * registers a row/column span the app hit-tests against mouse clicks (SGR + * mouse tracking, opencode-style). No I/O, no clock — fully deterministic so + * tests can snapshot both the text and the regions. + * + * Layout mirrors the Android app: three stacked cards (Settings & Login / + * Proxy Server / Logs) plus a toast line and a key-hint footer (the hints + * are themselves clickable). The top two cards are fixed-height; the log + * card absorbs the remaining terminal rows. + */ +import { displayWidth, truncateToWidth } from "./width.js"; + +export type Seg = { t: string; c?: string }; + +/** What a mouse click on a button should do. `key` reuses the key bindings. */ +export type ClickAction = + | { kind: "key"; key: string } + | { kind: "provider"; value: "zai" | "bigmodel" } + | { kind: "plan"; value: "coding-plan" | "start-plan" } + | { kind: "follow" }; + +/** 0-based terminal-cell span carrying an action. */ +export interface ClickRegion { + row: number; + col: number; + width: number; + action: ClickAction; +} + +export interface Frame { + text: string; + regions: ClickRegion[]; +} + +/** Hit-test: the action whose button contains (col,row), if any. */ +export function findRegion(regions: readonly ClickRegion[], row: number, col: number): ClickAction | null { + for (const r of regions) { + if (r.row === row && col >= r.col && col < r.col + r.width) return r.action; + } + return null; +} + +export interface FrameState { + version: string; + configPath: string; + provider: string; + plan: string; + loggedIn: boolean; + apiKeyPreview: string; + loginInFlight: boolean; + loginHint: string; + serverStatus: "stopped" | "starting" | "running" | "error"; + serverUrl: string; + serverError: string; + modelCount: number; + responsesEnabled: boolean; + claimAuto: boolean; + logTotal: number; + logView: ReadonlyArray<{ level: string; text: string }>; + logFollowing: boolean; + logFromBottom: number; + toast: { text: string; kind: "ok" | "err" | "info" } | null; + width: number; + height: number; +} + +const DIM = "90"; +const RED = "31"; +const GREEN = "32"; +const AMBER = "33"; +const CYAN = "36"; +const BOLD = "1"; +const LABEL_W = 12; // fixed label column inside cards + +// Solid filled buttons — GitHub dark-theme button palette via 24-bit +// truecolor SGR (Windows Terminal / mintty / modern Unix terminals render it +// natively; a legacy terminal falls back to its defaults with text intact). +// green #238636 success red #da3633 danger +// blue #1f6feb primary gray #30363d secondary (text #c9d1d9) +const BTN_GREEN = "38;2;255;255;255;48;2;35;134;54"; +const BTN_RED = "38;2;255;255;255;48;2;218;54;51"; +const BTN_BLUE = "38;2;255;255;255;48;2;31;111;235"; +const BTN_GRAY = "38;2;201;209;217;48;2;48;54;61"; +const BTN_SELECTED = BTN_BLUE; + +function paint(code: string, t: string): string { + return `\x1b[${code}m${t}\x1b[0m`; +} + +function segWidth(segs: readonly Seg[]): number { + let w = 0; + for (const s of segs) w += displayWidth(s.t); + return w; +} + +function paintSegs(segs: readonly Seg[]): string { + return segs.map((s) => (s.c ? paint(s.c, s.t) : s.t)).join(""); +} + +function segPlain(segs: readonly Seg[]): string { + return segs.map((s) => s.t).join(""); +} + +/** `╭─ title ────…──── pill ─╮` */ +function renderTopBorder(w: number, left: Seg[], right: Seg[] = []): string { + let l = left; + let r = right; + if (r.length === 0) { + // ╭(1) ─(1) sp(1) left sp(1) fill ╮(1) = w + if (5 + segWidth(l) > w - 1) l = [{ t: truncateToWidth(segPlain(l), Math.max(0, w - 7)) }]; + const fill = Math.max(1, w - 5 - segWidth(l)); + return paint(DIM, "╭─ ") + paintSegs(l) + paint(DIM, ` ${"─".repeat(fill)}╮`); + } + // ╭(1) ─(1) sp(1) left sp(1) fill sp(1) right sp(1) ─(1) ╮(1) = w + const lw = segWidth(l); + const rw = segWidth(r); + let fill = w - 8 - lw - rw; + if (fill < 1) { + // Degenerate: shrink the right side, then the left. + const budget = Math.max(0, w - 9 - lw); + r = [{ t: truncateToWidth(segPlain(r), budget) }]; + fill = Math.max(1, w - 8 - lw - segWidth(r)); + if (fill < 1) { + l = [{ t: truncateToWidth(segPlain(l), Math.max(0, w - 8 - segWidth(r))) }]; + fill = Math.max(1, w - 8 - segWidth(l) - segWidth(r)); + } + } + return ( + paint(DIM, "╭─ ") + paintSegs(l) + paint(DIM, ` ${"─".repeat(fill)} `) + + paintSegs(r) + paint(DIM, " ─╮") + ); +} + +function renderBottomBorder(w: number): string { + return paint(DIM, `╰${"─".repeat(Math.max(0, w - 2))}╯`); +} + +interface Part { + t: string; + c?: string; + action?: ClickAction; +} + +/** + * `│ Label [button] [button] … │` for an interactive row: parts are laid + * out left-to-right after the (optional) label column; parts carrying an + * action register a click region spanning exactly their cells. Overflow is + * dropped on the part that crosses the budget (and its region never added). + * With `chrome: false` the card borders/padding are omitted (footer row). + */ +function composeRow( + w: number, + row: number, + label: string | null, + parts: readonly Part[], + opts: { chrome?: boolean } = {}, +): { line: string; regions: ClickRegion[] } { + const chrome = opts.chrome !== false; + const contentW = Math.max(0, w - (chrome ? 4 : 2)); + const prefixPlain = label !== null ? " ".repeat(2) + label.padEnd(LABEL_W - 2) : " ".repeat(2); + const prefixW = displayWidth(prefixPlain); + const prefixPainted = label !== null ? paint(DIM, prefixPlain) : prefixPlain; + + const regions: ClickRegion[] = []; + const painted: string[] = []; + let col = prefixW; + for (const p of parts) { + const pw = displayWidth(p.t); + if (col + pw > contentW) break; + // With chrome the content starts after `│ ` (2 cells); without it the + // prefix itself starts at column 0. + if (p.action) regions.push({ row, col: (chrome ? 2 : 0) + col, width: pw, action: p.action }); + painted.push(p.c ? paint(p.c, p.t) : p.t); + col += pw; + } + if (!chrome) { + return { line: prefixPainted + painted.join(""), regions }; + } + const pad = " ".repeat(Math.max(0, contentW - col)); + return { + line: `${paint(DIM, "│")} ${prefixPainted}${painted.join("")}${pad} ${paint(DIM, "│")}`, + regions, + }; +} + +/** Radio-style option buttons rendered in FIXED slot order — selection only + * changes colors, never positions, so clicking the same spot twice always + * hits the same button. */ +function optionParts( + slots: readonly [string, string], + selected: string, + makeAction: (v: string) => ClickAction, + disabled: boolean, +): Part[] { + const parts: Part[] = []; + slots.forEach((v, i) => { + if (i > 0) parts.push({ t: " " }); + parts.push({ + t: ` ${v} `, + c: disabled ? DIM : v === selected ? BTN_SELECTED : BTN_GRAY, + action: disabled ? undefined : makeAction(v), + }); + }); + if (disabled) parts.push({ t: " " }, { t: "(stop to switch)", c: AMBER }); + return parts; +} + +function logLineCode(level: string): string | undefined { + if (level === "error") return RED; + if (level === "warn") return AMBER; + return undefined; +} + +export function buildFrame(s: FrameState): Frame { + const w = s.width; + const h = s.height; + const regions: ClickRegion[] = []; + const lines: string[] = []; + const emit = (line: string): number => { + lines.push(line + "\x1b[0m\x1b[K"); + return lines.length - 1; + }; + + if (w < 40 || h < 14) { + // Untruncated on purpose: shrinking the diagnostic would defeat it. + emit("zcode-proxy: terminal too small for the TUI."); + emit(` need >= 40x14, got ${w}x${h}`); + return { text: lines.join("\n") + "\x1b[0m\x1b[J", regions }; + } + + const pill: Seg[] = s.loginInFlight + ? [{ t: "● logging in…", c: AMBER }] + : s.loggedIn + ? [{ t: "● ready", c: GREEN }] + : [{ t: "● logged out", c: AMBER }]; + + const busy = s.serverStatus === "running" || s.serverStatus === "starting"; + + // --- Settings & Login card --------------------------------------------- + emit(renderTopBorder(w, [{ t: "Settings & Login", c: BOLD }], pill)); + + const providerRow = composeRow( + w, lines.length, "Provider", + optionParts( + ["zai", "bigmodel"], + s.provider, + (v) => ({ kind: "provider", value: v as "zai" | "bigmodel" }), + busy, + ), + ); + emit(providerRow.line); + regions.push(...providerRow.regions); + + const planRow = composeRow( + w, lines.length, "Plan", + optionParts( + ["coding-plan", "start-plan"], + s.plan, + (v) => ({ kind: "plan", value: v as "coding-plan" | "start-plan" }), + busy, + ), + ); + emit(planRow.line); + regions.push(...planRow.regions); + + const authSegs: Seg[] = s.loggedIn + ? [{ t: "● ", c: GREEN }, { t: `logged in · ${s.apiKeyPreview}` }] + : [{ t: "○ not logged in", c: AMBER }]; + emit((composeRow(w, lines.length, "Auth", authSegs.map((g) => ({ t: g.t, c: g.c })))).line); + + const loginRow = composeRow(w, lines.length, "", s.loginInFlight + ? [{ t: " Logging in… ", c: DIM }] + : s.loggedIn + ? [ + { t: " Logged In ", c: DIM }, + { t: " " }, + { t: " Logout ", c: BTN_GRAY, action: { kind: "key", key: "o" } }, + ] + : [ + { t: " OAuth Login ", c: BTN_GREEN, action: { kind: "key", key: "l" } }, + { t: " " }, + { t: " Logout ", c: DIM }, + ]); + emit(loginRow.line); + regions.push(...loginRow.regions); + + if (s.loginInFlight && s.loginHint) { + emit((composeRow(w, lines.length, "Login", [{ t: `» ${s.loginHint}`, c: AMBER }])).line); + } + + emit(renderBottomBorder(w)); + emit(""); + + // --- Proxy Server card -------------------------------------------------- + emit(renderTopBorder(w, [{ t: "Proxy Server", c: BOLD }])); + + const statusSegs: Seg[] = + s.serverStatus === "running" + ? [{ t: "● running", c: GREEN }, { t: " " + s.serverUrl, c: CYAN }] + : s.serverStatus === "starting" + ? [{ t: "● starting…", c: AMBER }] + : s.serverStatus === "error" + ? [{ t: "✗ failed", c: RED }] + : [{ t: "○ stopped", c: DIM }]; + emit((composeRow(w, lines.length, "Status", statusSegs.map((g) => ({ t: g.t, c: g.c })))).line); + + const configText = [ + `${s.provider} · ${s.plan} · ${s.modelCount} models`, + s.responsesEnabled ? "/v1/responses" : "", + s.claimAuto ? "claim:auto" : "", + `v${s.version}`, + ].filter(Boolean).join(" · "); + emit((composeRow(w, lines.length, "Config", [{ t: configText, c: DIM }])).line); + + const startEnabled = s.serverStatus === "stopped" || s.serverStatus === "error"; + const stopEnabled = s.serverStatus === "running"; + const serverButtonsRow = composeRow(w, lines.length, "", [ + { t: " Start ", c: startEnabled ? BTN_GREEN : DIM, action: startEnabled ? { kind: "key", key: "s" } : undefined }, + { t: " " }, + { t: " Stop ", c: stopEnabled ? BTN_RED : DIM, action: stopEnabled ? { kind: "key", key: "s" } : undefined }, + ]); + emit(serverButtonsRow.line); + regions.push(...serverButtonsRow.regions); + + if (s.serverStatus === "error" && s.serverError) { + emit((composeRow(w, lines.length, "Error", [{ t: s.serverError, c: RED }])).line); + } + emit(renderBottomBorder(w)); + emit(""); + + // --- Logs card (absorbs remaining height) ------------------------------- + const logRight: Seg[] = s.logFollowing + ? [{ t: "following", c: GREEN }] + : [{ t: `▼ ${s.logFromBottom} more · g follow`, c: AMBER }]; + const fixed = + lines.length + 2 /* log card borders */ + 1 /* footer */ + (s.toast ? 1 : 0); + const logRows = Math.max(1, h - fixed); + const logBorderRow = emit(renderTopBorder(w, [{ t: "Logs", c: BOLD }, { t: ` (${s.logTotal})`, c: DIM }], logRight)); + if (!s.logFollowing) { + // Clicking the log title bar jumps back to the tail, like the g key. + regions.push({ row: logBorderRow, col: 0, width: w, action: { kind: "follow" } }); + } + if (s.logView.length === 0) { + emit((composeRow(w, lines.length, null, [{ t: "(no logs yet — start the server and send requests)", c: DIM }])).line); + } else { + for (const line of s.logView.slice(-logRows)) { + emit((composeRow(w, lines.length, null, [{ t: truncateToWidth(line.text, w - 6), c: logLineCode(line.level) }])).line); + } + } + emit(renderBottomBorder(w)); + + // --- Toast + footer ------------------------------------------------------ + if (s.toast) { + const color = s.toast.kind === "ok" ? GREEN : s.toast.kind === "err" ? RED : CYAN; + emit(" " + paint(color, truncateToWidth(`▸ ${s.toast.text}`, w - 2))); + } + const footerRow = lines.length; + const footerParts: Part[] = []; + // Priority order — the footer composes greedily and drops its tail on + // narrow terminals, so the primary actions must come first. + const footerItems: Array<[string, string]> = [ + ["s", "start/stop"], ["l", "login"], ["o", "logout"], ["g", "follow"], ["q", "quit"], + ["p", "provider"], ["t", "plan"], ["c", "clear"], + ]; + footerParts.push({ t: "↑↓ scroll", c: DIM }); + for (const [key, label] of footerItems) { + footerParts.push({ t: " · ", c: DIM }); + footerParts.push({ t: `[${key}] ${label}`, c: DIM, action: { kind: "key", key } }); + } + // The footer lives outside the card borders — no chrome, plain indent. + const footer = composeRow(w, footerRow, null, footerParts, { chrome: false }); + emit(footer.line); + regions.push(...footer.regions); + + return { text: lines.join("\n") + "\x1b[0m\x1b[J", regions }; +} diff --git a/src/tui/keys.test.ts b/src/tui/keys.test.ts new file mode 100644 index 0000000..0646b12 --- /dev/null +++ b/src/tui/keys.test.ts @@ -0,0 +1,108 @@ +import { describe, expect, test } from "bun:test"; +import { KeyParser } from "./keys.js"; + +function types(parser: KeyParser, chunk: string): string[] { + return parser.feed(chunk).map((a) => a.type); +} + +describe("KeyParser", () => { + test("plain characters map to char actions", () => { + const p = new KeyParser(); + const actions = p.feed("qs"); + expect(actions).toEqual([ + { type: "char", key: "q" }, + { type: "char", key: "s" }, + ]); + }); + + test("ctrl-c is recognized", () => { + const p = new KeyParser(); + expect(p.feed("\x03")).toEqual([{ type: "ctrl-c" }]); + }); + + test("arrow keys", () => { + const p = new KeyParser(); + expect(types(p, "\x1b[A\x1b[B")).toEqual(["up", "down"]); + }); + + test("page and home/end keys", () => { + const p = new KeyParser(); + expect(types(p, "\x1b[5~\x1b[6~\x1b[H\x1b[F")).toEqual(["pageup", "pagedown", "home", "end"]); + }); + + test("SS3 application-mode keys (ESC O A)", () => { + const p = new KeyParser(); + expect(types(p, "\x1bOA\x1bOB")).toEqual(["up", "down"]); + }); + + test("enter, tab and backspace are ignored", () => { + const p = new KeyParser(); + expect(types(p, "\r\n\t\x7f")).toEqual(["ignore", "ignore", "ignore", "ignore"]); + }); + + test("alt+key and bare ESC-prefixed sequences are ignored", () => { + const p = new KeyParser(); + expect(types(p, "\x1bq")).toEqual(["ignore"]); + }); + + test("escape sequence split across chunks still completes", () => { + const p = new KeyParser(); + expect(p.feed("\x1b")).toEqual([]); // buffered, nothing yet + expect(p.feed("[B")).toEqual([{ type: "down" }]); + }); + + test("incomplete CSI with params waits for the final byte", () => { + const p = new KeyParser(); + expect(p.feed("\x1b[5")).toEqual([]); + expect(p.feed("~")).toEqual([{ type: "pageup" }]); + }); + + test("a completed sequence followed by chars in one chunk", () => { + const p = new KeyParser(); + const actions = p.feed("\x1b[Aq\x1b[Bs"); + expect(actions.map((a) => a.type)).toEqual(["up", "char", "down", "char"]); + expect(actions[1]).toEqual({ type: "char", key: "q" }); + }); + + test("unknown CSI finals are ignored", () => { + const p = new KeyParser(); + expect(types(p, "\x1b[Z\x1b[3~")).toEqual(["ignore", "ignore"]); + }); + + test("UTF-8 multibyte chars survive as single chars", () => { + const p = new KeyParser(); + const actions = p.feed("日"); + expect(actions).toEqual([{ type: "char", key: "日" }]); + }); + + test("SGR mouse press maps to a 0-based click", () => { + const p = new KeyParser(); + expect(p.feed("\x1b[<0;10;5M")).toEqual([{ type: "click", x: 9, y: 4 }]); + }); + + test("mouse release and drag are ignored", () => { + const p = new KeyParser(); + expect(types(p, "\x1b[<0;10;5m\x1b[<32;10;5M")).toEqual(["ignore", "ignore"]); + }); + + test("wheel buttons map to scroll actions", () => { + const p = new KeyParser(); + expect(types(p, "\x1b[<64;1;1M\x1b[<65;1;1M")).toEqual(["wheel-up", "wheel-down"]); + }); + + test("right/middle button presses are ignored", () => { + const p = new KeyParser(); + expect(types(p, "\x1b[<1;3;3M\x1b[<2;3;3M")).toEqual(["ignore", "ignore"]); + }); + + test("mouse sequence split across chunks still completes", () => { + const p = new KeyParser(); + expect(p.feed("\x1b[<0;")).toEqual([]); + expect(p.feed("12;7M")).toEqual([{ type: "click", x: 11, y: 6 }]); + }); + + test("malformed mouse params are ignored", () => { + const p = new KeyParser(); + expect(types(p, "\x1b[<;5M")).toEqual(["ignore"]); + }); +}); diff --git a/src/tui/keys.ts b/src/tui/keys.ts new file mode 100644 index 0000000..e4eb67c --- /dev/null +++ b/src/tui/keys.ts @@ -0,0 +1,124 @@ +/** + * Incremental VT/ANSI input parser for the TUI keyboard loop. + * + * stdin is read in raw mode as a UTF-8 string stream; `KeyParser.feed` + * converts chunks into actions. A chunk can end in the middle of an escape + * sequence (lone `\x1b` before more bytes arrive), so unconsumed input is + * buffered until the sequence completes on a later chunk. Works identically + * under Bun and Node — no readline keypress events involved. + * + * Mouse: with SGR mouse tracking enabled (`\x1b[?1000h\x1b[?1006h`), the + * terminal reports presses/releases as `ESC [ < b ; x ; y M/m` and wheel + * events as button codes 64/65 — parsed into click/wheel actions so TUI + * buttons are directly clickable (coordinates arrive 1-based, converted + * to 0-based terminal cells). + */ + +export type KeyAction = + | { type: "char"; key: string } + | { type: "up" } + | { type: "down" } + | { type: "pageup" } + | { type: "pagedown" } + | { type: "home" } + | { type: "end" } + | { type: "click"; x: number; y: number } + | { type: "wheel-up" } + | { type: "wheel-down" } + | { type: "ctrl-c" } + /** Recognized but without a binding (Enter, Tab, bare Esc, Alt+key, drag/release, …). */ + | { type: "ignore" }; + +export class KeyParser { + private pending = ""; + + /** Consume a raw stdin chunk and return the actions it completes. */ + feed(chunk: string): KeyAction[] { + const buf = this.pending + chunk; + const actions: KeyAction[] = []; + let i = 0; + + while (i < buf.length) { + const ch = buf[i]!; + + if (ch === "\x1b") { + if (i + 1 >= buf.length) break; // lone ESC at chunk end — wait for the rest + if (buf[i + 1] === "[") { + let j = i + 2; + while (j < buf.length && !/[A-Za-z~]/.test(buf[j]!)) j++; + if (j >= buf.length) break; // incomplete CSI — wait + actions.push(csiAction(buf[j]!, buf.slice(i + 2, j))); + i = j + 1; + continue; + } + if (buf[i + 1] === "O") { + if (i + 2 >= buf.length) break; // incomplete SS3 — wait + actions.push(csiAction(buf[i + 2]!, "")); + i += 3; + continue; + } + // Alt+key or other two-byte sequence — no binding. + actions.push({ type: "ignore" }); + i += 2; + continue; + } + + if (ch === "\x03") { + actions.push({ type: "ctrl-c" }); + i++; + continue; + } + + if (ch < " " || ch === "\x7f") { + // Remaining control bytes (Enter/Tab/backspace/…) carry no binding. + actions.push({ type: "ignore" }); + i++; + continue; + } + + actions.push({ type: "char", key: ch }); + i++; + } + + this.pending = buf.slice(i); + return actions; + } +} + +function csiAction(final: string, params: string): KeyAction { + if (params.startsWith("<")) return mouseAction(params.slice(1), final); + switch (final) { + case "A": + return { type: "up" }; + case "B": + return { type: "down" }; + case "H": + return { type: "home" }; + case "F": + return { type: "end" }; + case "~": + if (params === "5" || params === "5;5") return { type: "pageup" }; + if (params === "6" || params === "6;5") return { type: "pagedown" }; + if (params === "1" || params === "7") return { type: "home" }; + if (params === "4" || params === "8") return { type: "end" }; + return { type: "ignore" }; + default: + return { type: "ignore" }; + } +} + +/** SGR mouse event: ` { + test("push appends and tracks count", () => { + const pane = new LogPane(); + pane.push("one"); + pane.push("two"); + expect(pane.count).toBe(2); + expect(pane.view(10).lines.map((l) => l.text)).toEqual(["one", "two"]); + }); + + test("strips ANSI codes", () => { + const pane = new LogPane(); + pane.push("\x1b[31merror\x1b[0m part"); + expect(pane.view(10).lines[0]!.text).toBe("error part"); + }); + + test("splits embedded newlines into rows", () => { + const pane = new LogPane(); + pane.push("a\nb\nc"); + expect(pane.count).toBe(3); + expect(pane.view(10).lines.map((l) => l.text)).toEqual(["a", "b", "c"]); + }); + + test("trailing newline does not create an empty row", () => { + const pane = new LogPane(); + pane.push("a\n"); + expect(pane.count).toBe(1); + }); + + test("evicts oldest beyond capacity", () => { + const pane = new LogPane(5); + for (let i = 0; i < 8; i++) pane.push(`line-${i}`); + expect(pane.count).toBe(5); + expect(pane.view(10).lines.map((l) => l.text)).toEqual([ + "line-3", "line-4", "line-5", "line-6", "line-7", + ]); + }); + + test("follows the tail by default", () => { + const pane = new LogPane(); + for (let i = 0; i < 20; i++) pane.push(`l${i}`); + expect(pane.following).toBe(true); + expect(pane.view(5).lines.map((l) => l.text)).toEqual(["l15", "l16", "l17", "l18", "l19"]); + expect(pane.view(5).fromBottom).toBe(0); + }); + + test("scrollUp freezes the viewport, scrollDown to 0 resumes following", () => { + const pane = new LogPane(); + for (let i = 0; i < 20; i++) pane.push(`l${i}`); + pane.scrollUp(3); + expect(pane.following).toBe(false); + expect(pane.view(5).lines.map((l) => l.text)).toEqual(["l12", "l13", "l14", "l15", "l16"]); + expect(pane.view(5).fromBottom).toBe(3); + pane.scrollDown(2); + expect(pane.view(5).fromBottom).toBe(1); + pane.scrollDown(10); + expect(pane.following).toBe(true); + expect(pane.view(5).lines.at(-1)!.text).toBe("l19"); + }); + + test("scrollUp is clamped to the buffer length", () => { + const pane = new LogPane(); + for (let i = 0; i < 10; i++) pane.push(`l${i}`); + pane.scrollUp(1000); + expect(pane.view(3).lines.map((l) => l.text)).toEqual(["l0", "l1", "l2"]); + expect(pane.view(3).fromBottom).toBe(7); + }); + + test("clear empties and resumes following", () => { + const pane = new LogPane(); + for (let i = 0; i < 10; i++) pane.push(`l${i}`); + pane.scrollUp(5); + pane.clear(); + expect(pane.count).toBe(0); + expect(pane.following).toBe(true); + expect(pane.view(5).lines).toEqual([]); + }); + + test("keeps levels and monotonic sequence", () => { + const pane = new LogPane(); + pane.push("info line", "info"); + pane.push("warn line", "warn"); + pane.push("error line", "error"); + const view = pane.view(10).lines; + expect(view.map((l) => l.level)).toEqual(["info", "warn", "error"]); + expect(view[0]!.seq < view[1]!.seq && view[1]!.seq < view[2]!.seq).toBe(true); + }); + + test("viewport height is clamped to at least 1", () => { + const pane = new LogPane(); + pane.push("a"); + pane.push("b"); + expect(pane.view(0).lines).toHaveLength(1); + }); +}); diff --git a/src/tui/log-pane.ts b/src/tui/log-pane.ts new file mode 100644 index 0000000..5cf0809 --- /dev/null +++ b/src/tui/log-pane.ts @@ -0,0 +1,91 @@ +/** + * The log pane: a bounded ring of leveled log lines with tail-following and + * scrollback, mirroring the Android app's Logs card (LazyColumn that sticks + * to the newest line). Pure state — the frame renderer and terminal glue + * read it, tests drive it directly. + */ +import { stripAnsi } from "./width.js"; + +export type LogLevel = "info" | "warn" | "error"; + +export interface LogLine { + readonly seq: number; + readonly level: LogLevel; + readonly text: string; +} + +export interface LogView { + /** The lines to draw, oldest first, at most `height` of them. */ + readonly lines: readonly LogLine[]; + /** Total lines retained (for the "Logs (N)" header). */ + readonly total: number; + /** Lines hidden BELOW the viewport toward the tail (0 while following). */ + readonly fromBottom: number; +} + +export class LogPane { + private lines: LogLine[] = []; + private nextSeq = 0; + /** Lines hidden below the viewport. 0 = follow the tail. */ + private offset = 0; + + constructor(private readonly capacity = 2000) {} + + /** + * Append a log record. ANSI escape sequences are stripped (proxy logs carry + * color codes; the pane applies its own) and embedded newlines split into + * separate rows so multi-line records scroll naturally. + */ + push(text: string, level: LogLevel = "info"): void { + const clean = stripAnsi(String(text)).replace(/\r/g, ""); + const parts = clean.split("\n"); + if (parts.length > 1 && parts[parts.length - 1] === "") parts.pop(); + for (const part of parts) { + this.lines.push({ seq: this.nextSeq++, level, text: part }); + } + if (this.lines.length > this.capacity) { + this.lines.splice(0, this.lines.length - this.capacity); + } + } + + get count(): number { + return this.lines.length; + } + + /** True when the viewport is pinned to the newest lines. */ + get following(): boolean { + return this.offset === 0; + } + + scrollUp(n: number): void { + this.offset = Math.min(this.lines.length, this.offset + Math.max(0, n)); + } + + scrollDown(n: number): void { + this.offset = Math.max(0, this.offset - Math.max(0, n)); + } + + /** Jump back to the tail (re-enable following). */ + followBottom(): void { + this.offset = 0; + } + + clear(): void { + this.lines = []; + this.offset = 0; + } + + /** Slice of lines currently visible in a viewport `height` rows tall. */ + view(height: number): LogView { + const rows = Math.max(1, height); + // At max scrollback (offset === length) the viewport pins to the oldest + // rows instead of going empty. + const end = Math.max(Math.min(rows, this.lines.length), this.lines.length - this.offset); + const start = Math.max(0, end - rows); + return { + lines: this.lines.slice(start, end), + total: this.lines.length, + fromBottom: this.lines.length - end, + }; + } +} diff --git a/src/tui/width.test.ts b/src/tui/width.test.ts new file mode 100644 index 0000000..71f6c62 --- /dev/null +++ b/src/tui/width.test.ts @@ -0,0 +1,96 @@ +import { describe, expect, test } from "bun:test"; +import { displayWidth, padEndWidth, stripAnsi, truncateToWidth } from "./width.js"; + +describe("stripAnsi", () => { + test("removes SGR sequences", () => { + expect(stripAnsi("\x1b[31mred\x1b[0m")).toBe("red"); + expect(stripAnsi("\x1b[1;36mbold cyan\x1b[0m ok")).toBe("bold cyan ok"); + }); + + test("removes cursor movement and other CSI", () => { + expect(stripAnsi("\x1b[H\x1b[2J\x1b[Khello")).toBe("hello"); + expect(stripAnsi("a\x1b[?1049hb")).toBe("ab"); + }); + + test("leaves plain text untouched", () => { + expect(stripAnsi("plain text 123")).toBe("plain text 123"); + }); +}); + +describe("displayWidth", () => { + test("ASCII counts one cell per char", () => { + expect(displayWidth("hello world")).toBe(11); + expect(displayWidth("")).toBe(0); + }); + + test("ANSI escapes count as zero", () => { + expect(displayWidth("\x1b[31mab\x1b[0m")).toBe(2); + }); + + test("CJK counts two cells", () => { + expect(displayWidth("日志")).toBe(4); + expect(displayWidth("a日b志")).toBe(6); + }); + + test("fullwidth forms count two cells", () => { + expect(displayWidth("AB")).toBe(4); + }); + + test("emoji count two cells", () => { + expect(displayWidth("🚀x")).toBe(3); + }); + + test("combining marks count zero", () => { + expect(displayWidth("e\u0301x")).toBe(2); + }); +}); + +describe("truncateToWidth", () => { + test("returns short strings unchanged", () => { + expect(truncateToWidth("abc", 10)).toBe("abc"); + expect(truncateToWidth("abc", 3)).toBe("abc"); + }); + + test("truncates ASCII with ellipsis", () => { + const out = truncateToWidth("abcdefghijkl", 8); + expect(displayWidth(out)).toBe(8); + expect(out.endsWith("…")).toBe(true); + expect(out.startsWith("abcdefg")).toBe(true); + }); + + test("never cuts a wide char in half", () => { + const out = truncateToWidth("日志日志日志", 7); + expect(displayWidth(out)).toBe(7); + expect(out).toBe("日志日…"); + }); + + test("handles ANSI-laden input by stripping first", () => { + const out = truncateToWidth("\x1b[31merror message that is quite long\x1b[0m", 10); + expect(displayWidth(out)).toBe(10); + expect(out).not.toContain("\x1b"); + }); + + test("max 0 yields empty string", () => { + expect(truncateToWidth("abc", 0)).toBe(""); + }); + + test("wide ellipsis still fits", () => { + const out = truncateToWidth("日志志", 3); + expect(displayWidth(out)).toBeLessThanOrEqual(3); + }); +}); + +describe("padEndWidth", () => { + test("pads ASCII to exact width", () => { + expect(displayWidth(padEndWidth("ab", 5))).toBe(5); + expect(padEndWidth("ab", 5)).toBe("ab "); + }); + + test("pads CJK correctly", () => { + expect(displayWidth(padEndWidth("日志", 6))).toBe(6); + }); + + test("does not shrink overlong input", () => { + expect(padEndWidth("abcdef", 3)).toBe("abcdef"); + }); +}); diff --git a/src/tui/width.ts b/src/tui/width.ts new file mode 100644 index 0000000..441d185 --- /dev/null +++ b/src/tui/width.ts @@ -0,0 +1,90 @@ +/** + * Display-width helpers for TUI rendering. + * + * Terminal cells are monospace but East-Asian characters, fullwidth forms and + * most emoji occupy 2 cells while combining marks occupy 0 — naive `.length` + * math misaligns box borders the moment a log line contains CJK text (and + * proxy errors regularly do, since upstream bodies are passed through). + * `displayWidth` implements the common subset of wcwidth; width errors on + * exotic content are cosmetic only (a mis-truncated log line), never fatal. + */ + +/** CSI sequences, OSC sequences, and remaining two-byte ESC sequences. */ +const ANSI_RE = /\x1b(?:\[[0-9;?<=>! ]*[A-Za-z~@`\\]|\][^\x07\x1b]*(?:\x07|\x1b\\)?|[@-Z\\-_=>])/g; + +/** Ranges whose code points occupy two terminal cells. */ +const WIDE_RANGES: ReadonlyArray = [ + [0x1100, 0x115f], [0x2e80, 0x303e], [0x3041, 0x33ff], [0x3400, 0x4dbf], + [0x4e00, 0x9fff], [0xa000, 0xa4c6], [0xa960, 0xa97c], [0xac00, 0xd7a3], + [0xf900, 0xfaff], [0xfe10, 0xfe19], [0xfe30, 0xfe52], [0xfe54, 0xfe66], + [0xfe68, 0xfe6b], [0xff01, 0xff60], [0xffe0, 0xffe6], + [0x1f300, 0x1f64f], [0x1f680, 0x1f6ff], [0x1f900, 0x1f9ff], + [0x20000, 0x2fffd], [0x30000, 0x3fffd], +]; + +/** Ranges whose code points occupy zero cells (combining marks, ZW*, variation selectors). */ +const ZERO_RANGES: ReadonlyArray = [ + [0x0300, 0x036f], [0x200b, 0x200f], [0x20d0, 0x20ff], [0xfe00, 0xfe0f], +]; + +function inRanges(cp: number, ranges: ReadonlyArray): boolean { + let lo = 0; + let hi = ranges.length - 1; + while (lo <= hi) { + const mid = (lo + hi) >> 1; + const [a, b] = ranges[mid]!; + if (cp < a) hi = mid - 1; + else if (cp > b) lo = mid + 1; + else return true; + } + return false; +} + +function codePointWidth(cp: number): number { + if (cp === 0) return 0; + if (cp < 32 || (cp >= 0x7f && cp < 0xa0)) return 0; + if (inRanges(cp, ZERO_RANGES)) return 0; + if (inRanges(cp, WIDE_RANGES)) return 2; + return 1; +} + +/** Remove ANSI escape sequences so the result can be measured / compared. */ +export function stripAnsi(s: string): string { + return s.replace(ANSI_RE, ""); +} + +/** Display width in terminal cells (ANSI escape sequences count as 0). */ +export function displayWidth(s: string): number { + let w = 0; + for (const ch of stripAnsi(s)) { + w += codePointWidth(ch.codePointAt(0)!); + } + return w; +} + +/** + * Truncate to `max` display cells, appending `…` when anything was cut. + * ANSI sequences are stripped first — callers that want color re-wrap the + * result themselves. + */ +export function truncateToWidth(s: string, max: number, ellipsis = "…"): string { + if (max <= 0) return ""; + const plain = stripAnsi(s); + if (displayWidth(plain) <= max) return plain; + const ellWidth = displayWidth(ellipsis); + let w = 0; + let out = ""; + for (const ch of plain) { + const cw = codePointWidth(ch.codePointAt(0)!); + if (w + cw > max - ellWidth) break; + out += ch; + w += cw; + } + return out + ellipsis; +} + +/** Pad with spaces (display-width aware) so the string occupies exactly `width` cells. */ +export function padEndWidth(s: string, width: number): string { + const pad = width - displayWidth(s); + return pad > 0 ? s + " ".repeat(pad) : s; +}