{"version":3,"file":"httpUtils-CB_100ND.mjs","names":[],"sources":["../src/getFetch.ts","../src/internals/signals.ts","../src/links/internals/httpUtils.ts"],"sourcesContent":["import type { FetchEsque, NativeFetchEsque } from './internals/types';\n\ntype AnyFn = (...args: any[]) => unknown;\n\nconst isFunction = (fn: unknown): fn is AnyFn => typeof fn === 'function';\n\nexport function getFetch(\n  customFetchImpl?: FetchEsque | NativeFetchEsque,\n): FetchEsque {\n  if (customFetchImpl) {\n    return customFetchImpl as FetchEsque;\n  }\n\n  // eslint-disable-next-line @typescript-eslint/unbound-method\n  if (typeof window !== 'undefined' && isFunction(window.fetch)) {\n    return window.fetch.bind(window);\n  }\n\n  if (typeof globalThis !== 'undefined' && isFunction(globalThis.fetch)) {\n    return globalThis.fetch;\n  }\n\n  throw new Error('No fetch implementation found');\n}\n","import type { Maybe } from '@trpc/server/unstable-core-do-not-import';\n\n/**\n * Like `Promise.all()` but for abort signals\n * - When all signals have been aborted, the merged signal will be aborted\n * - If one signal is `null`, no signal will be aborted\n */\nexport function allAbortSignals(...signals: Maybe<AbortSignal>[]): AbortSignal {\n  const ac = new AbortController();\n\n  const count = signals.length;\n\n  let abortedCount = 0;\n\n  const onAbort = () => {\n    if (++abortedCount === count) {\n      ac.abort();\n    }\n  };\n\n  for (const signal of signals) {\n    if (signal?.aborted) {\n      onAbort();\n    } else {\n      signal?.addEventListener('abort', onAbort, {\n        once: true,\n      });\n    }\n  }\n\n  return ac.signal;\n}\n\n/**\n * Like `Promise.race` but for abort signals\n *\n * Basically, a ponyfill for\n * [`AbortSignal.any`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static).\n */\nexport function raceAbortSignals(\n  ...signals: Maybe<AbortSignal>[]\n): AbortSignal {\n  const ac = new AbortController();\n\n  for (const signal of signals) {\n    if (signal?.aborted) {\n      ac.abort();\n    } else {\n      signal?.addEventListener('abort', () => ac.abort(), { once: true });\n    }\n  }\n\n  return ac.signal;\n}\n\nexport function abortSignalToPromise(signal: AbortSignal): Promise<never> {\n  return new Promise((_, reject) => {\n    if (signal.aborted) {\n      reject(signal.reason);\n      return;\n    }\n    signal.addEventListener(\n      'abort',\n      () => {\n        reject(signal.reason);\n      },\n      { once: true },\n    );\n  });\n}\n","import type {\n  AnyClientTypes,\n  CombinedDataTransformer,\n  Maybe,\n  ProcedureType,\n  TRPCAcceptHeader,\n  TRPCResponse,\n} from '@trpc/server/unstable-core-do-not-import';\nimport { getFetch } from '../../getFetch';\nimport type {\n  FetchEsque,\n  RequestInitEsque,\n  ResponseEsque,\n} from '../../internals/types';\nimport type { TransformerOptions } from '../../unstable-internals';\nimport { getTransformer } from '../../unstable-internals';\nimport type { HTTPHeaders } from '../types';\n\n/**\n * @internal\n */\nexport type HTTPLinkBaseOptions<\n  TRoot extends Pick<AnyClientTypes, 'transformer'>,\n> = {\n  url: string | URL;\n  /**\n   * Add ponyfill for fetch\n   */\n  fetch?: FetchEsque;\n  /**\n   * Send all requests `as POST`s requests regardless of the procedure type\n   * The HTTP handler must separately allow overriding the method. See:\n   * @see https://trpc.io/docs/rpc\n   */\n  methodOverride?: 'POST';\n} & TransformerOptions<TRoot>;\n\nexport interface ResolvedHTTPLinkOptions {\n  url: string;\n  fetch?: FetchEsque;\n  transformer: CombinedDataTransformer;\n  methodOverride?: 'POST';\n}\n\nexport function resolveHTTPLinkOptions(\n  opts: HTTPLinkBaseOptions<AnyClientTypes>,\n): ResolvedHTTPLinkOptions {\n  return {\n    url: opts.url.toString(),\n    fetch: opts.fetch,\n    transformer: getTransformer(opts.transformer),\n    methodOverride: opts.methodOverride,\n  };\n}\n\n// https://github.com/trpc/trpc/pull/669\nfunction arrayToDict(array: unknown[]) {\n  const dict: Record<number, unknown> = {};\n  for (let index = 0; index < array.length; index++) {\n    const element = array[index];\n    dict[index] = element;\n  }\n  return dict;\n}\n\nconst METHOD = {\n  query: 'GET',\n  mutation: 'POST',\n  subscription: 'PATCH',\n} as const;\n\nexport interface HTTPResult {\n  json: TRPCResponse;\n  meta: {\n    response: ResponseEsque;\n    responseJSON?: unknown;\n  };\n}\n\ntype GetInputOptions = {\n  transformer: CombinedDataTransformer;\n} & ({ input: unknown } | { inputs: unknown[] });\n\nexport function getInput(opts: GetInputOptions) {\n  return 'input' in opts\n    ? opts.transformer.input.serialize(opts.input)\n    : arrayToDict(\n        opts.inputs.map((_input) => opts.transformer.input.serialize(_input)),\n      );\n}\n\nexport type HTTPBaseRequestOptions = GetInputOptions &\n  ResolvedHTTPLinkOptions & {\n    type: ProcedureType;\n    path: string;\n    signal: Maybe<AbortSignal>;\n  };\n\ntype GetUrl = (opts: HTTPBaseRequestOptions) => string;\ntype GetBody = (opts: HTTPBaseRequestOptions) => RequestInitEsque['body'];\n\nexport type ContentOptions = {\n  trpcAcceptHeader?: TRPCAcceptHeader;\n  trpcAcceptHeaderKey?: 'trpc-accept' | 'accept';\n  contentTypeHeader?: string;\n  getUrl: GetUrl;\n  getBody: GetBody;\n};\n\nexport const getUrl: GetUrl = (opts) => {\n  const parts = opts.url.split('?') as [string, string?];\n  const base = parts[0].replace(/\\/$/, ''); // Remove any trailing slashes\n\n  let url = base + '/' + opts.path;\n  const queryParts: string[] = [];\n\n  if (parts[1]) {\n    queryParts.push(parts[1]);\n  }\n  if ('inputs' in opts) {\n    queryParts.push('batch=1');\n  }\n  if (opts.type === 'query' || opts.type === 'subscription') {\n    const input = getInput(opts);\n    if (input !== undefined && opts.methodOverride !== 'POST') {\n      queryParts.push(`input=${encodeURIComponent(JSON.stringify(input))}`);\n    }\n  }\n  if (queryParts.length) {\n    url += '?' + queryParts.join('&');\n  }\n  return url;\n};\n\nexport const getBody: GetBody = (opts) => {\n  if (opts.type === 'query' && opts.methodOverride !== 'POST') {\n    return undefined;\n  }\n  const input = getInput(opts);\n  return input !== undefined ? JSON.stringify(input) : undefined;\n};\n\nexport type Requester = (\n  opts: HTTPBaseRequestOptions & {\n    headers: () => HTTPHeaders | Promise<HTTPHeaders>;\n  },\n) => Promise<HTTPResult>;\n\nexport const jsonHttpRequester: Requester = (opts) => {\n  return httpRequest({\n    ...opts,\n    contentTypeHeader: 'application/json',\n    getUrl,\n    getBody,\n  });\n};\n\n/**\n * Polyfill for DOMException with AbortError name\n */\nclass AbortError extends Error {\n  constructor() {\n    const name = 'AbortError';\n    super(name);\n    this.name = name;\n    this.message = name;\n  }\n}\n\nexport type HTTPRequestOptions = ContentOptions &\n  HTTPBaseRequestOptions & {\n    headers: () => HTTPHeaders | Promise<HTTPHeaders>;\n  };\n\n/**\n * Polyfill for `signal.throwIfAborted()`\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/throwIfAborted\n */\nconst throwIfAborted = (signal: Maybe<AbortSignal>) => {\n  if (!signal?.aborted) {\n    return;\n  }\n  // If available, use the native implementation\n  signal.throwIfAborted?.();\n\n  // If we have `DOMException`, use it\n  if (typeof DOMException !== 'undefined') {\n    throw new DOMException('AbortError', 'AbortError');\n  }\n\n  // Otherwise, use our own implementation\n  throw new AbortError();\n};\n\nexport async function fetchHTTPResponse(opts: HTTPRequestOptions) {\n  throwIfAborted(opts.signal);\n\n  const url = opts.getUrl(opts);\n  const body = opts.getBody(opts);\n  const method = opts.methodOverride ?? METHOD[opts.type];\n  const resolvedHeaders = await (async () => {\n    const heads = await opts.headers();\n    if (Symbol.iterator in heads) {\n      return Object.fromEntries(heads);\n    }\n    return heads;\n  })();\n  const headers = {\n    ...(opts.contentTypeHeader && method !== 'GET'\n      ? { 'content-type': opts.contentTypeHeader }\n      : {}),\n    ...(opts.trpcAcceptHeader\n      ? { [opts.trpcAcceptHeaderKey ?? 'trpc-accept']: opts.trpcAcceptHeader }\n      : undefined),\n    ...resolvedHeaders,\n  };\n\n  return getFetch(opts.fetch)(url, {\n    method,\n    signal: opts.signal,\n    body,\n    headers,\n  });\n}\n\nexport async function httpRequest(\n  opts: HTTPRequestOptions,\n): Promise<HTTPResult> {\n  const meta = {} as HTTPResult['meta'];\n\n  const res = await fetchHTTPResponse(opts);\n  meta.response = res;\n\n  const json = await res.json();\n\n  meta.responseJSON = json;\n\n  return {\n    json: json as TRPCResponse,\n    meta,\n  };\n}\n"],"mappings":"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"}