{"version":3,"sources":["../src/proxy.ts"],"sourcesContent":["import {\n  DEFAULT_PROXY_PATH,\n  LEGACY_DEV_INSTANCE_SUFFIXES,\n  LOCAL_ENV_SUFFIXES,\n  LOCAL_FAPI_URL,\n  PROD_FAPI_URL,\n  STAGING_ENV_SUFFIXES,\n  STAGING_FAPI_URL,\n} from '@clerk/shared/constants';\nimport { parsePublishableKey } from '@clerk/shared/keys';\n\nexport { DEFAULT_PROXY_PATH } from '@clerk/shared/constants';\n\n/**\n * Options for the Frontend API proxy\n */\nexport interface FrontendApiProxyOptions {\n  /**\n   * The path prefix for proxy requests. Defaults to `/__clerk`.\n   */\n  proxyPath?: string;\n  /**\n   * The Clerk publishable key. Falls back to CLERK_PUBLISHABLE_KEY env var.\n   */\n  publishableKey?: string;\n  /**\n   * The Clerk secret key. Falls back to CLERK_SECRET_KEY env var.\n   */\n  secretKey?: string;\n}\n\n/**\n * Error codes for proxy errors\n */\nexport type ProxyErrorCode = 'proxy_configuration_error' | 'proxy_path_mismatch' | 'proxy_request_failed';\n\n/**\n * Error response structure for proxy errors\n */\nexport interface ProxyError {\n  code: ProxyErrorCode;\n  message: string;\n}\n\n// Hop-by-hop headers that should not be forwarded\nconst HOP_BY_HOP_HEADERS = new Set([\n  'connection',\n  'keep-alive',\n  'proxy-authenticate',\n  'proxy-authorization',\n  'te',\n  'trailer',\n  'transfer-encoding',\n  'upgrade',\n]);\n\n/**\n * Parses the Connection header to extract dynamically-nominated hop-by-hop\n * header names (RFC 7230 Section 6.1). These headers are specific to the\n * current connection and must not be forwarded by proxies.\n */\nfunction getDynamicHopByHopHeaders(headers: Headers): Set<string> {\n  const connectionValue = headers.get('connection');\n  if (!connectionValue) {\n    return new Set();\n  }\n  return new Set(\n    connectionValue\n      .split(',')\n      .map(h => h.trim().toLowerCase())\n      .filter(h => h.length > 0),\n  );\n}\n\n// Headers to strip from proxied responses. fetch() auto-decompresses\n// response bodies, so Content-Encoding no longer describes the body\n// and Content-Length reflects the compressed size. We request identity\n// encoding upstream to avoid the double compression pass, but strip\n// these defensively since servers may ignore Accept-Encoding: identity.\nconst RESPONSE_HEADERS_TO_STRIP = new Set(['content-encoding', 'content-length']);\n\n/**\n * Derives the Frontend API URL from a publishable key.\n * @param publishableKey - The Clerk publishable key\n * @returns The Frontend API URL for the environment\n */\nexport function fapiUrlFromPublishableKey(publishableKey: string): string {\n  const frontendApi = parsePublishableKey(publishableKey)?.frontendApi;\n\n  if (frontendApi?.startsWith('clerk.') && LEGACY_DEV_INSTANCE_SUFFIXES.some(suffix => frontendApi?.endsWith(suffix))) {\n    return PROD_FAPI_URL;\n  }\n\n  if (LOCAL_ENV_SUFFIXES.some(suffix => frontendApi?.endsWith(suffix))) {\n    return LOCAL_FAPI_URL;\n  }\n  if (STAGING_ENV_SUFFIXES.some(suffix => frontendApi?.endsWith(suffix))) {\n    return STAGING_FAPI_URL;\n  }\n  return PROD_FAPI_URL;\n}\n\n/**\n * Removes trailing slashes from a string without using regex\n * to avoid potential ReDoS concerns flagged by security scanners.\n */\nexport function stripTrailingSlashes(str: string): string {\n  while (str.endsWith('/')) {\n    str = str.slice(0, -1);\n  }\n  return str;\n}\n\n/**\n * Checks if a request path matches the proxy path.\n * @param request - The incoming request\n * @param options - Proxy options including the proxy path\n * @returns True if the request matches the proxy path\n */\nexport function matchProxyPath(request: Request, options?: Pick<FrontendApiProxyOptions, 'proxyPath'>): boolean {\n  const proxyPath = stripTrailingSlashes(options?.proxyPath || DEFAULT_PROXY_PATH);\n  const url = new URL(request.url);\n  return url.pathname === proxyPath || url.pathname.startsWith(proxyPath + '/');\n}\n\n/**\n * Creates a JSON error response\n */\nfunction createErrorResponse(code: ProxyErrorCode, message: string, status: number): Response {\n  const error: ProxyError = { code, message };\n  return new Response(JSON.stringify({ errors: [error] }), {\n    status,\n    headers: {\n      'Content-Type': 'application/json',\n      'Cache-Control': 'no-store',\n    },\n  });\n}\n\n/**\n * Derives the public-facing origin from forwarded headers, falling back to the raw request URL.\n * Behind a reverse proxy, request.url is typically localhost, but the Clerk-Proxy-Url header\n * and Location rewrites must use the origin visible to the browser.\n */\nfunction derivePublicOrigin(request: Request, requestUrl: URL): string {\n  const forwardedProto = request.headers.get('x-forwarded-proto')?.split(',')[0]?.trim();\n  const forwardedHost = request.headers.get('x-forwarded-host')?.split(',')[0]?.trim();\n\n  if (forwardedProto && forwardedHost) {\n    return `${forwardedProto}://${forwardedHost}`;\n  }\n\n  return requestUrl.origin;\n}\n\n/**\n * Gets the client IP address from various headers\n */\nfunction getClientIp(request: Request): string | undefined {\n  const cfConnectingIp = request.headers.get('cf-connecting-ip');\n  if (cfConnectingIp) {\n    return cfConnectingIp;\n  }\n\n  const xRealIp = request.headers.get('x-real-ip');\n  if (xRealIp) {\n    return xRealIp;\n  }\n\n  const xForwardedFor = request.headers.get('x-forwarded-for');\n  if (xForwardedFor) {\n    // Take the first IP in the chain\n    return xForwardedFor.split(',')[0]?.trim();\n  }\n\n  return undefined;\n}\n\n/**\n * Proxies a request to Clerk's Frontend API.\n *\n * This function handles forwarding requests from your application to Clerk's\n * Frontend API, enabling scenarios where direct communication with Clerk's API\n * is blocked or needs to go through your application server.\n *\n * @param request - The incoming request to proxy\n * @param options - Proxy configuration options\n * @returns A Response from Clerk's Frontend API\n *\n * @example\n * ```typescript\n * import { clerkFrontendApiProxy } from '@clerk/backend/proxy';\n *\n * // In a route handler\n * const response = await clerkFrontendApiProxy(request, {\n *   proxyPath: '/__clerk',\n *   publishableKey: process.env.CLERK_PUBLISHABLE_KEY,\n *   secretKey: process.env.CLERK_SECRET_KEY,\n * });\n * ```\n */\nexport async function clerkFrontendApiProxy(request: Request, options?: FrontendApiProxyOptions): Promise<Response> {\n  const proxyPath = stripTrailingSlashes(options?.proxyPath || DEFAULT_PROXY_PATH);\n  const publishableKey =\n    options?.publishableKey || (typeof process !== 'undefined' ? process.env?.CLERK_PUBLISHABLE_KEY : undefined);\n  const secretKey = options?.secretKey || (typeof process !== 'undefined' ? process.env?.CLERK_SECRET_KEY : undefined);\n\n  // Validate configuration\n  if (!publishableKey) {\n    return createErrorResponse(\n      'proxy_configuration_error',\n      'Missing publishableKey. Provide it in options or set CLERK_PUBLISHABLE_KEY environment variable.',\n      500,\n    );\n  }\n\n  if (!secretKey) {\n    return createErrorResponse(\n      'proxy_configuration_error',\n      'Missing secretKey. Provide it in options or set CLERK_SECRET_KEY environment variable.',\n      500,\n    );\n  }\n\n  // Get the request URL and validate path\n  const requestUrl = new URL(request.url);\n  const pathMatches = requestUrl.pathname === proxyPath || requestUrl.pathname.startsWith(proxyPath + '/');\n  if (!pathMatches) {\n    return createErrorResponse(\n      'proxy_path_mismatch',\n      `Request path \"${requestUrl.pathname}\" does not match proxy path \"${proxyPath}\"`,\n      400,\n    );\n  }\n\n  // Derive the FAPI URL and construct the target URL.\n  // Use string concatenation instead of `new URL(path, base)` to avoid\n  // protocol-relative resolution (e.g., \"//evil.com\" resolving to a different host).\n  const fapiBaseUrl = fapiUrlFromPublishableKey(publishableKey);\n  const fapiHost = new URL(fapiBaseUrl).host;\n  const targetPath = requestUrl.pathname.slice(proxyPath.length) || '/';\n  const targetUrl = new URL(`${fapiBaseUrl}${targetPath}`);\n  targetUrl.search = requestUrl.search;\n\n  if (targetUrl.host !== fapiHost) {\n    return createErrorResponse('proxy_request_failed', 'Resolved target does not match the expected host', 400);\n  }\n\n  // Build headers for the proxied request\n  const headers = new Headers();\n\n  // Copy original headers, excluding hop-by-hop headers and any\n  // dynamically-nominated hop-by-hop headers listed in the Connection header (RFC 7230 Section 6.1).\n  const dynamicHopByHop = getDynamicHopByHopHeaders(request.headers);\n  request.headers.forEach((value, key) => {\n    const lower = key.toLowerCase();\n    if (!HOP_BY_HOP_HEADERS.has(lower) && !dynamicHopByHop.has(lower)) {\n      headers.set(key, value);\n    }\n  });\n\n  // Set required Clerk proxy headers\n  // Use the public origin (from forwarded headers) so the Clerk-Proxy-Url\n  // points to the browser-visible host, not localhost behind a reverse proxy.\n  const publicOrigin = derivePublicOrigin(request, requestUrl);\n  const proxyUrl = `${publicOrigin}${proxyPath}`;\n  headers.set('Clerk-Proxy-Url', proxyUrl);\n  headers.set('Clerk-Secret-Key', secretKey);\n\n  // Set the host header to the FAPI host\n  headers.set('Host', fapiHost);\n\n  // Request uncompressed responses to avoid a double compression pass.\n  // fetch() auto-decompresses, so without this FAPI compresses → fetch\n  // decompresses → the serving layer re-compresses for the browser.\n  headers.set('Accept-Encoding', 'identity');\n\n  // Set X-Forwarded-* headers for proxy awareness\n  // Only set these if not already present (preserve values from upstream proxies)\n  if (!headers.has('X-Forwarded-Host')) {\n    headers.set('X-Forwarded-Host', requestUrl.host);\n  }\n  if (!headers.has('X-Forwarded-Proto')) {\n    headers.set('X-Forwarded-Proto', requestUrl.protocol.replace(':', ''));\n  }\n\n  // Set X-Forwarded-For to the client IP\n  // In multi-proxy scenarios, we prefer authoritative headers (CF-Connecting-IP, X-Real-IP)\n  // over the existing X-Forwarded-For chain, as they provide the true client IP\n  const clientIp = getClientIp(request);\n  if (clientIp) {\n    headers.set('X-Forwarded-For', clientIp);\n  }\n\n  // Determine if request has a body (handles DELETE-with-body and any other method)\n  const hasBody = request.body !== null;\n\n  try {\n    // Make the proxied request\n    // TODO: Consider adding AbortSignal.timeout(30_000) via AbortSignal.any()\n    const fetchOptions: RequestInit = {\n      method: request.method,\n      headers,\n      redirect: 'manual',\n      signal: request.signal,\n    };\n\n    // Only set duplex when body is present (required for streaming bodies)\n    if (hasBody) {\n      // @ts-expect-error - duplex is required for streaming bodies, but not present on the RequestInit type from undici\n      fetchOptions.duplex = 'half';\n      fetchOptions.body = request.body;\n    }\n\n    const response = await fetch(targetUrl.toString(), fetchOptions);\n\n    // Build response headers, excluding hop-by-hop and encoding headers.\n    // Also strip dynamically-nominated hop-by-hop headers from the response Connection header.\n    const responseDynamicHopByHop = getDynamicHopByHopHeaders(response.headers);\n    const responseHeaders = new Headers();\n    response.headers.forEach((value, key) => {\n      const lower = key.toLowerCase();\n      if (\n        !HOP_BY_HOP_HEADERS.has(lower) &&\n        !RESPONSE_HEADERS_TO_STRIP.has(lower) &&\n        !responseDynamicHopByHop.has(lower)\n      ) {\n        if (lower === 'set-cookie') {\n          responseHeaders.append(key, value);\n        } else {\n          responseHeaders.set(key, value);\n        }\n      }\n    });\n\n    // Rewrite Location header for redirects to go through the proxy\n    const locationHeader = response.headers.get('location');\n    if (locationHeader) {\n      try {\n        const locationUrl = new URL(locationHeader, fapiBaseUrl);\n        // Check if the redirect points to the FAPI host\n        if (locationUrl.host === fapiHost) {\n          // Rewrite to go through the proxy\n          const rewrittenLocation = `${proxyUrl}${locationUrl.pathname}${locationUrl.search}${locationUrl.hash}`;\n          responseHeaders.set('Location', rewrittenLocation);\n        }\n      } catch {\n        // If URL parsing fails, leave the Location header as-is (could be a relative URL)\n      }\n    }\n\n    const proxyResponse = new Response(response.body, {\n      status: response.status,\n      statusText: response.statusText,\n      headers: responseHeaders,\n    });\n\n    // Some runtimes may re-add Content-Length when constructing the Response.\n    // Delete explicitly since fetch() decoded the body and the original values\n    // no longer reflect the actual content.\n    for (const header of RESPONSE_HEADERS_TO_STRIP) {\n      proxyResponse.headers.delete(header);\n    }\n\n    return proxyResponse;\n  } catch (error) {\n    const message = error instanceof Error ? error.message : 'Unknown error';\n    return createErrorResponse('proxy_request_failed', `Failed to proxy request to Clerk FAPI: ${message}`, 502);\n  }\n}\n"],"mappings":";;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,2BAA2B;AAEpC,SAAS,sBAAAA,2BAA0B;AAkCnC,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAOD,SAAS,0BAA0B,SAA+B;AAChE,QAAM,kBAAkB,QAAQ,IAAI,YAAY;AAChD,MAAI,CAAC,iBAAiB;AACpB,WAAO,oBAAI,IAAI;AAAA,EACjB;AACA,SAAO,IAAI;AAAA,IACT,gBACG,MAAM,GAAG,EACT,IAAI,OAAK,EAAE,KAAK,EAAE,YAAY,CAAC,EAC/B,OAAO,OAAK,EAAE,SAAS,CAAC;AAAA,EAC7B;AACF;AAOA,IAAM,4BAA4B,oBAAI,IAAI,CAAC,oBAAoB,gBAAgB,CAAC;AAOzE,SAAS,0BAA0B,gBAAgC;AACxE,QAAM,cAAc,oBAAoB,cAAc,GAAG;AAEzD,MAAI,aAAa,WAAW,QAAQ,KAAK,6BAA6B,KAAK,YAAU,aAAa,SAAS,MAAM,CAAC,GAAG;AACnH,WAAO;AAAA,EACT;AAEA,MAAI,mBAAmB,KAAK,YAAU,aAAa,SAAS,MAAM,CAAC,GAAG;AACpE,WAAO;AAAA,EACT;AACA,MAAI,qBAAqB,KAAK,YAAU,aAAa,SAAS,MAAM,CAAC,GAAG;AACtE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAMO,SAAS,qBAAqB,KAAqB;AACxD,SAAO,IAAI,SAAS,GAAG,GAAG;AACxB,UAAM,IAAI,MAAM,GAAG,EAAE;AAAA,EACvB;AACA,SAAO;AACT;AAQO,SAAS,eAAe,SAAkB,SAA+D;AAC9G,QAAM,YAAY,qBAAqB,SAAS,aAAa,kBAAkB;AAC/E,QAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,SAAO,IAAI,aAAa,aAAa,IAAI,SAAS,WAAW,YAAY,GAAG;AAC9E;AAKA,SAAS,oBAAoB,MAAsB,SAAiB,QAA0B;AAC5F,QAAM,QAAoB,EAAE,MAAM,QAAQ;AAC1C,SAAO,IAAI,SAAS,KAAK,UAAU,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG;AAAA,IACvD;AAAA,IACA,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,IACnB;AAAA,EACF,CAAC;AACH;AAOA,SAAS,mBAAmB,SAAkB,YAAyB;AACrE,QAAM,iBAAiB,QAAQ,QAAQ,IAAI,mBAAmB,GAAG,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK;AACrF,QAAM,gBAAgB,QAAQ,QAAQ,IAAI,kBAAkB,GAAG,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK;AAEnF,MAAI,kBAAkB,eAAe;AACnC,WAAO,GAAG,cAAc,MAAM,aAAa;AAAA,EAC7C;AAEA,SAAO,WAAW;AACpB;AAKA,SAAS,YAAY,SAAsC;AACzD,QAAM,iBAAiB,QAAQ,QAAQ,IAAI,kBAAkB;AAC7D,MAAI,gBAAgB;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,QAAQ,QAAQ,IAAI,WAAW;AAC/C,MAAI,SAAS;AACX,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,QAAQ,QAAQ,IAAI,iBAAiB;AAC3D,MAAI,eAAe;AAEjB,WAAO,cAAc,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK;AAAA,EAC3C;AAEA,SAAO;AACT;AAyBA,eAAsB,sBAAsB,SAAkB,SAAsD;AAClH,QAAM,YAAY,qBAAqB,SAAS,aAAa,kBAAkB;AAC/E,QAAM,iBACJ,SAAS,mBAAmB,OAAO,YAAY,cAAc,QAAQ,KAAK,wBAAwB;AACpG,QAAM,YAAY,SAAS,cAAc,OAAO,YAAY,cAAc,QAAQ,KAAK,mBAAmB;AAG1G,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,aAAa,IAAI,IAAI,QAAQ,GAAG;AACtC,QAAM,cAAc,WAAW,aAAa,aAAa,WAAW,SAAS,WAAW,YAAY,GAAG;AACvG,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,MACL;AAAA,MACA,iBAAiB,WAAW,QAAQ,gCAAgC,SAAS;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AAKA,QAAM,cAAc,0BAA0B,cAAc;AAC5D,QAAM,WAAW,IAAI,IAAI,WAAW,EAAE;AACtC,QAAM,aAAa,WAAW,SAAS,MAAM,UAAU,MAAM,KAAK;AAClE,QAAM,YAAY,IAAI,IAAI,GAAG,WAAW,GAAG,UAAU,EAAE;AACvD,YAAU,SAAS,WAAW;AAE9B,MAAI,UAAU,SAAS,UAAU;AAC/B,WAAO,oBAAoB,wBAAwB,oDAAoD,GAAG;AAAA,EAC5G;AAGA,QAAM,UAAU,IAAI,QAAQ;AAI5B,QAAM,kBAAkB,0BAA0B,QAAQ,OAAO;AACjE,UAAQ,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AACtC,UAAM,QAAQ,IAAI,YAAY;AAC9B,QAAI,CAAC,mBAAmB,IAAI,KAAK,KAAK,CAAC,gBAAgB,IAAI,KAAK,GAAG;AACjE,cAAQ,IAAI,KAAK,KAAK;AAAA,IACxB;AAAA,EACF,CAAC;AAKD,QAAM,eAAe,mBAAmB,SAAS,UAAU;AAC3D,QAAM,WAAW,GAAG,YAAY,GAAG,SAAS;AAC5C,UAAQ,IAAI,mBAAmB,QAAQ;AACvC,UAAQ,IAAI,oBAAoB,SAAS;AAGzC,UAAQ,IAAI,QAAQ,QAAQ;AAK5B,UAAQ,IAAI,mBAAmB,UAAU;AAIzC,MAAI,CAAC,QAAQ,IAAI,kBAAkB,GAAG;AACpC,YAAQ,IAAI,oBAAoB,WAAW,IAAI;AAAA,EACjD;AACA,MAAI,CAAC,QAAQ,IAAI,mBAAmB,GAAG;AACrC,YAAQ,IAAI,qBAAqB,WAAW,SAAS,QAAQ,KAAK,EAAE,CAAC;AAAA,EACvE;AAKA,QAAM,WAAW,YAAY,OAAO;AACpC,MAAI,UAAU;AACZ,YAAQ,IAAI,mBAAmB,QAAQ;AAAA,EACzC;AAGA,QAAM,UAAU,QAAQ,SAAS;AAEjC,MAAI;AAGF,UAAM,eAA4B;AAAA,MAChC,QAAQ,QAAQ;AAAA,MAChB;AAAA,MACA,UAAU;AAAA,MACV,QAAQ,QAAQ;AAAA,IAClB;AAGA,QAAI,SAAS;AAEX,mBAAa,SAAS;AACtB,mBAAa,OAAO,QAAQ;AAAA,IAC9B;AAEA,UAAM,WAAW,MAAM,MAAM,UAAU,SAAS,GAAG,YAAY;AAI/D,UAAM,0BAA0B,0BAA0B,SAAS,OAAO;AAC1E,UAAM,kBAAkB,IAAI,QAAQ;AACpC,aAAS,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AACvC,YAAM,QAAQ,IAAI,YAAY;AAC9B,UACE,CAAC,mBAAmB,IAAI,KAAK,KAC7B,CAAC,0BAA0B,IAAI,KAAK,KACpC,CAAC,wBAAwB,IAAI,KAAK,GAClC;AACA,YAAI,UAAU,cAAc;AAC1B,0BAAgB,OAAO,KAAK,KAAK;AAAA,QACnC,OAAO;AACL,0BAAgB,IAAI,KAAK,KAAK;AAAA,QAChC;AAAA,MACF;AAAA,IACF,CAAC;AAGD,UAAM,iBAAiB,SAAS,QAAQ,IAAI,UAAU;AACtD,QAAI,gBAAgB;AAClB,UAAI;AACF,cAAM,cAAc,IAAI,IAAI,gBAAgB,WAAW;AAEvD,YAAI,YAAY,SAAS,UAAU;AAEjC,gBAAM,oBAAoB,GAAG,QAAQ,GAAG,YAAY,QAAQ,GAAG,YAAY,MAAM,GAAG,YAAY,IAAI;AACpG,0BAAgB,IAAI,YAAY,iBAAiB;AAAA,QACnD;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,UAAM,gBAAgB,IAAI,SAAS,SAAS,MAAM;AAAA,MAChD,QAAQ,SAAS;AAAA,MACjB,YAAY,SAAS;AAAA,MACrB,SAAS;AAAA,IACX,CAAC;AAKD,eAAW,UAAU,2BAA2B;AAC9C,oBAAc,QAAQ,OAAO,MAAM;AAAA,IACrC;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,WAAO,oBAAoB,wBAAwB,0CAA0C,OAAO,IAAI,GAAG;AAAA,EAC7G;AACF;","names":["DEFAULT_PROXY_PATH"]}