import type { Dispatcher } from 'undici' import { Agent, EnvHttpProxyAgent } from 'undici' const PROXY_ENV_KEYS = ['HTTP_PROXY', 'http_proxy', 'HTTPS_PROXY', 'https_proxy'] as const export function hasProxyEnv(): boolean { return PROXY_ENV_KEYS.some((k) => (process.env[k] ?? '') !== '') } export type ProxyDispatcherOptions = { // --insecure on a self-signed https:// host: skip certificate verification // (local-dev only, same flag that allows plain http:// hosts). readonly insecure?: boolean } let resolvedKey: string | undefined let agent: Dispatcher | undefined // Node's global fetch ignores HTTP_PROXY / HTTPS_PROXY / NO_PROXY. When a proxy // var is set, route requests through an EnvHttpProxyAgent (it also reads the // lowercase variants and honours NO_PROXY); when none is set and TLS verification // isn't being skipped, return undefined so fetch keeps Node's default global // dispatcher untouched. Resolved once per (proxy env, insecure) combination — // both are fixed for a single CLI invocation. export function proxyDispatcher(opts: ProxyDispatcherOptions = {}): Dispatcher | undefined { const insecure = opts.insecure ?? false const key = `${hasProxyEnv()}:${insecure}` if (resolvedKey !== key) { const tls = insecure ? { rejectUnauthorized: false } : undefined agent = hasProxyEnv() ? new EnvHttpProxyAgent( tls !== undefined ? { connect: tls, requestTls: tls, proxyTls: tls } : undefined, ) : tls !== undefined ? new Agent({ connect: tls }) : undefined resolvedKey = key } return agent }