{"version":3,"file":"fetchObservable.mjs","names":[],"sources":["../../src/browser/fetchObservable.ts"],"sourcesContent":["import type { ClocksState } from '@openobserve/js-core/time'\nimport { clocksNow } from '@openobserve/js-core/time'\nimport type { InstrumentedMethodCall } from '../tools/instrumentMethod'\nimport { instrumentMethod } from '../tools/instrumentMethod'\nimport { monitorError } from '../tools/monitor'\nimport { Observable } from '../tools/observable'\nimport { normalizeUrl } from '../tools/utils/urlPolyfill'\nimport type { GlobalObject } from '../tools/globalObject'\nimport { globalObject } from '../tools/globalObject'\nimport { readBytesFromStream } from '../tools/readBytesFromStream'\nimport { tryToClone } from '../tools/utils/responseUtils'\n\ninterface FetchContextBase {\n  method: string\n  startClocks: ClocksState\n  input: unknown\n  init?: RequestInit\n  url: string\n  handlingStack?: string\n  isAbortedOnStart: boolean\n}\n\nexport interface FetchStartContext extends FetchContextBase {\n  state: 'start'\n}\n\nexport interface FetchResolveContext extends FetchContextBase {\n  state: 'resolve'\n  status: number\n  response?: Response\n  responseBody?: string\n  responseType?: string\n  isAborted: boolean\n  error?: Error\n}\n\nexport type FetchContext = FetchStartContext | FetchResolveContext\n\ntype ResponseBodyActionGetter = (context: FetchResolveContext) => ResponseBodyAction\n\n/**\n * Action to take with the response body of a fetch request.\n * Values are ordered by priority: higher values take precedence when multiple actions are requested.\n */\nexport const enum ResponseBodyAction {\n  IGNORE = 0,\n  COLLECT = 1,\n}\n\nlet fetchObservable: Observable<FetchContext> | undefined\nconst responseBodyActionGetters: ResponseBodyActionGetter[] = []\n\nexport function initFetchObservable({ responseBodyAction }: { responseBodyAction?: ResponseBodyActionGetter } = {}) {\n  if (responseBodyAction) {\n    responseBodyActionGetters.push(responseBodyAction)\n  }\n  if (!fetchObservable) {\n    fetchObservable = createFetchObservable()\n  }\n  return fetchObservable\n}\n\nexport function resetFetchObservable() {\n  fetchObservable = undefined\n  responseBodyActionGetters.length = 0\n}\n\nfunction createFetchObservable() {\n  return new Observable<FetchContext>((observable) => {\n    // eslint-disable-next-line local-rules/disallow-zone-js-patched-values\n    if (!globalObject.fetch) {\n      return\n    }\n\n    const { stop } = instrumentMethod(globalObject, 'fetch', (call) => beforeSend(call, observable), {\n      computeHandlingStack: true,\n    })\n\n    return stop\n  })\n}\n\nfunction beforeSend(\n  { parameters, onPostCall, handlingStack }: InstrumentedMethodCall<GlobalObject, 'fetch'>,\n  observable: Observable<FetchContext>\n) {\n  const [input, init] = parameters\n  let methodFromParams = init?.method\n\n  if (methodFromParams === undefined && input instanceof Request) {\n    methodFromParams = input.method\n  }\n\n  const method = methodFromParams !== undefined ? String(methodFromParams).toUpperCase() : 'GET'\n  const url = input instanceof Request ? input.url : normalizeUrl(String(input))\n  const startClocks = clocksNow()\n\n  const context: FetchStartContext = {\n    state: 'start',\n    init,\n    input,\n    method,\n    startClocks,\n    url,\n    handlingStack,\n    isAbortedOnStart: (input instanceof Request && input.signal?.aborted) || init?.signal?.aborted || false,\n  }\n\n  observable.notify(context)\n\n  // Those properties can be changed by observable subscribers\n  parameters[0] = context.input as RequestInfo | URL\n  parameters[1] = context.init\n\n  onPostCall((responsePromise) => {\n    afterSend(observable, responsePromise, context).catch(monitorError)\n  })\n}\n\nasync function afterSend(\n  observable: Observable<FetchContext>,\n  responsePromise: Promise<Response>,\n  startContext: FetchStartContext\n) {\n  const context = startContext as unknown as FetchResolveContext\n\n  let response: Response\n\n  try {\n    response = await responsePromise\n  } catch (error) {\n    observable.notify({\n      ...context,\n      state: 'resolve',\n      status: 0,\n      isAborted:\n        context.init?.signal?.aborted || (error instanceof DOMException && error.code === DOMException.ABORT_ERR),\n      error: error as Error,\n    })\n    return\n  }\n\n  context.response = response\n  context.status = response.status\n  context.responseType = response.type\n  context.isAborted = false\n\n  const responseBodyCondition: ResponseBodyAction = responseBodyActionGetters.reduce<number>(\n    (action, getter) => Math.max(action, getter(context)),\n    ResponseBodyAction.IGNORE\n  )\n\n  if (responseBodyCondition === ResponseBodyAction.COLLECT) {\n    const clonedResponse = tryToClone(response)\n    if (clonedResponse?.body) {\n      try {\n        const bytes = await readBytesFromStream(clonedResponse.body)\n        context.responseBody = new TextDecoder().decode(bytes)\n      } catch {\n        // Ignore errors when reading the response body (e.g., stream aborted, network errors)\n        // This is not critical and should not be reported as an SDK error\n      }\n    }\n  }\n\n  observable.notify({ ...context, state: 'resolve' })\n}\n"],"mappings":";;;;;;;;;;;;;AA4CA,IAAkB,qBAAX,yBAAA,oBAAA;CACL,mBAAA,mBAAA,YAAA,KAAA;CACA,mBAAA,mBAAA,aAAA,KAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAI;AACJ,MAAM,4BAAwD,CAAC;AAE/D,SAAgB,oBAAoB,EAAE,uBAA0E,CAAC,GAAG;CAClH,IAAI,oBACF,0BAA0B,KAAK,kBAAkB;CAEnD,IAAI,CAAC,iBACH,kBAAkB,sBAAsB;CAE1C,OAAO;AACT;AAOA,SAAS,wBAAwB;CAC/B,OAAO,IAAI,YAA0B,eAAe;EAElD,IAAI,CAAC,aAAa,OAChB;EAGF,MAAM,EAAE,SAAS,iBAAiB,cAAc,UAAU,SAAS,WAAW,MAAM,UAAU,GAAG,EAC/F,sBAAsB,KACxB,CAAC;EAED,OAAO;CACT,CAAC;AACH;AAEA,SAAS,WACP,EAAE,YAAY,YAAY,iBAC1B,YACA;CACA,MAAM,CAAC,OAAO,QAAQ;CACtB,IAAI,mBAAmB,MAAM;CAE7B,IAAI,qBAAqB,KAAA,KAAa,iBAAiB,SACrD,mBAAmB,MAAM;CAG3B,MAAM,SAAS,qBAAqB,KAAA,IAAY,OAAO,gBAAgB,CAAC,CAAC,YAAY,IAAI;CACzF,MAAM,MAAM,iBAAiB,UAAU,MAAM,MAAM,aAAa,OAAO,KAAK,CAAC;CAG7E,MAAM,UAA6B;EACjC,OAAO;EACP;EACA;EACA;EACA,aAPkB,UAOR;EACV;EACA;EACA,kBAAmB,iBAAiB,WAAW,MAAM,QAAQ,WAAY,MAAM,QAAQ,WAAW;CACpG;CAEA,WAAW,OAAO,OAAO;CAGzB,WAAW,KAAK,QAAQ;CACxB,WAAW,KAAK,QAAQ;CAExB,YAAY,oBAAoB;EAC9B,UAAU,YAAY,iBAAiB,OAAO,CAAC,CAAC,MAAM,YAAY;CACpE,CAAC;AACH;AAEA,eAAe,UACb,YACA,iBACA,cACA;CACA,MAAM,UAAU;CAEhB,IAAI;CAEJ,IAAI;EACF,WAAW,MAAM;CACnB,SAAS,OAAO;EACd,WAAW,OAAO;GAChB,GAAG;GACH,OAAO;GACP,QAAQ;GACR,WACE,QAAQ,MAAM,QAAQ,WAAY,iBAAiB,gBAAgB,MAAM,SAAS,aAAa;GAC1F;EACT,CAAC;EACD;CACF;CAEA,QAAQ,WAAW;CACnB,QAAQ,SAAS,SAAS;CAC1B,QAAQ,eAAe,SAAS;CAChC,QAAQ,YAAY;CAOpB,IALkD,0BAA0B,QACzE,QAAQ,WAAW,KAAK,IAAI,QAAQ,OAAO,OAAO,CAAC,GAAA,CAI9B,MAAA,GAAkC;EACxD,MAAM,iBAAiB,WAAW,QAAQ;EAC1C,IAAI,gBAAgB,MAClB,IAAI;GACF,MAAM,QAAQ,MAAM,oBAAoB,eAAe,IAAI;GAC3D,QAAQ,eAAe,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK;EACvD,QAAQ,CAGR;CAEJ;CAEA,WAAW,OAAO;EAAE,GAAG;EAAS,OAAO;CAAU,CAAC;AACpD"}