{"version":3,"file":"http-dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/http-dispatcher.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,4BAA4B,SAAU,CAAC;AAEpD,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;EAM5B,CAAC;AAKX,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAgBzE;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAK1E;AA+BD,wBAAgB,uBAAuB,CAAC,SAAS,GAAE,MAAqC,GAAG,IAAI,CA2B9F","sourcesContent":["import { EventEmitter } from \"node:events\";\nimport * as undici from \"undici\";\n\nexport const DEFAULT_HTTP_IDLE_TIMEOUT_MS = 300_000;\n\nexport const HTTP_IDLE_TIMEOUT_CHOICES = [\n\t{ label: \"30 sec\", timeoutMs: 30_000 },\n\t{ label: \"1 min\", timeoutMs: 60_000 },\n\t{ label: \"2 min\", timeoutMs: 120_000 },\n\t{ label: \"5 min\", timeoutMs: 300_000 },\n\t{ label: \"disabled\", timeoutMs: 0 },\n] as const;\n\nconst originalGlobalFetch = globalThis.fetch;\nlet installedGlobalFetch: typeof globalThis.fetch | undefined;\n\nexport function parseHttpIdleTimeoutMs(value: unknown): number | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst trimmed = value.trim();\n\t\tif (trimmed.toLowerCase() === \"disabled\") {\n\t\t\treturn 0;\n\t\t}\n\t\tif (trimmed.length === 0) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn parseHttpIdleTimeoutMs(Number(trimmed));\n\t}\n\n\tif (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n\t\treturn undefined;\n\t}\n\treturn Math.floor(value);\n}\n\nexport function formatHttpIdleTimeoutMs(timeoutMs: number): string {\n\tconst choice = HTTP_IDLE_TIMEOUT_CHOICES.find((item) => item.timeoutMs === timeoutMs);\n\tif (choice) {\n\t\treturn choice.label;\n\t}\n\treturn `${timeoutMs / 1000} sec`;\n}\n\nexport function applyHttpProxySettings(httpProxy: string | undefined): void {\n\tconst proxy = httpProxy?.trim();\n\tif (!proxy) return;\n\tprocess.env.HTTP_PROXY ??= proxy;\n\tprocess.env.HTTPS_PROXY ??= proxy;\n}\n\nconst ignoreUndiciDispatcherError = (_error: unknown): void => {};\n\n// Undici can emit an internal Client \"error\" while terminating a mid-stream\n// fetch body. The body stream still rejects through reader.read(); this listener\n// only prevents EventEmitter's unhandled \"error\" special case from crashing pi.\nfunction withUndiciErrorListener<T extends undici.Dispatcher>(dispatcher: T): T {\n\tif (dispatcher instanceof EventEmitter) {\n\t\tEventEmitter.prototype.on.call(dispatcher, \"error\", ignoreUndiciDispatcherError);\n\t}\n\treturn dispatcher;\n}\n\nfunction createUndiciClient(origin: string | URL, options: object): undici.Dispatcher {\n\treturn withUndiciErrorListener(new undici.Client(origin, options as undici.Client.Options));\n}\n\nfunction createUndiciOriginDispatcher(origin: string | URL, options: object): undici.Dispatcher {\n\tconst dispatcherOptions = options as undici.Pool.Options;\n\tif (dispatcherOptions.connections === 1) {\n\t\treturn createUndiciClient(origin, dispatcherOptions);\n\t}\n\treturn withUndiciErrorListener(\n\t\tnew undici.Pool(origin, {\n\t\t\t...dispatcherOptions,\n\t\t\tfactory: createUndiciClient,\n\t\t}),\n\t);\n}\n\nexport function configureHttpDispatcher(timeoutMs: number = DEFAULT_HTTP_IDLE_TIMEOUT_MS): void {\n\tconst normalizedTimeoutMs = parseHttpIdleTimeoutMs(timeoutMs);\n\tif (normalizedTimeoutMs === undefined) {\n\t\tthrow new Error(`Invalid HTTP idle timeout: ${String(timeoutMs)}`);\n\t}\n\tconst dispatcher = withUndiciErrorListener(\n\t\tnew undici.EnvHttpProxyAgent({\n\t\t\tallowH2: false,\n\t\t\tbodyTimeout: normalizedTimeoutMs,\n\t\t\theadersTimeout: normalizedTimeoutMs,\n\t\t\tclientFactory: createUndiciClient,\n\t\t\tfactory: createUndiciOriginDispatcher,\n\t\t}),\n\t);\n\tundici.setGlobalDispatcher(dispatcher);\n\t// Keep fetch and the dispatcher on the same undici implementation. Node 26.0's\n\t// bundled fetch can otherwise consume compressed responses through npm undici's\n\t// dispatcher without decompressing them, causing response.json() failures.\n\t// If a caller replaced fetch after module load, preserve that deliberate override.\n\tconst shouldInstallGlobals =\n\t\tinstalledGlobalFetch === undefined\n\t\t\t? globalThis.fetch === originalGlobalFetch\n\t\t\t: globalThis.fetch === installedGlobalFetch;\n\tif (shouldInstallGlobals) {\n\t\tundici.install?.();\n\t\tinstalledGlobalFetch = globalThis.fetch;\n\t}\n}\n"]}