{"version":3,"sources":["../../src/internals/fetcher.ts"],"names":["RestfulClientError","FrameworkError","createURLParams","data","urlTokenParams","URLSearchParams","key","value","Object","entries","undefined","Array","isArray","forEach","v","append","String","isPlainObject","set","toString","RestfulClient","Serializable","emitter","constructor","input","Emitter","root","child","namespace","creator","stream","path","init","paths","baseUrl","headers","groupId","url","URL","options","method","then","raw","assign","fromEntries","emit","emitterToGenerator","fetchEventSource","onopen","response","ok","get","EventStreamContentType","context","err","text","isRetryable","status","onmessage","msg","event","onclose","onerror","catch","error","doNothing","finally","fetch","getHeaders","target","searchParams","includes","json","createSnapshot","shallowCopy","loadSnapshot","snapshot"],"mappings":"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","file":"fetcher.cjs","sourcesContent":["/**\n * Copyright 2025 IBM Corp.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FrameworkError } from \"@/errors.js\";\nimport { Serializable } from \"@/internals/serializable.js\";\nimport {\n  EventSourceMessage,\n  EventStreamContentType,\n  fetchEventSource,\n} from \"@ai-zen/node-fetch-event-source\";\nimport { FetchEventSourceInit } from \"@ai-zen/node-fetch-event-source/lib/cjs/fetch.js\";\nimport { emitterToGenerator } from \"@/internals/helpers/promise.js\";\nimport { doNothing, isPlainObject } from \"remeda\";\nimport { Callback, Emitter } from \"@/emitter/emitter.js\";\nimport { shallowCopy } from \"@/serializer/utils.js\";\n\nexport class RestfulClientError extends FrameworkError {}\n\ntype URLParamType = string | number | boolean | null | undefined;\nexport function createURLParams(\n  data: Record<string, URLParamType | URLParamType[] | Record<string, any>>,\n) {\n  const urlTokenParams = new URLSearchParams();\n  for (const [key, value] of Object.entries(data)) {\n    if (value === undefined) {\n      continue;\n    }\n\n    if (Array.isArray(value)) {\n      value.forEach((v) => {\n        if (v !== undefined) {\n          urlTokenParams.append(key, String(v));\n        }\n      });\n    } else if (isPlainObject(value)) {\n      urlTokenParams.set(key, createURLParams(value).toString());\n    } else {\n      urlTokenParams.set(key, String(value));\n    }\n  }\n  return urlTokenParams;\n}\n\ninterface FetchInput {\n  url: string;\n  options: RequestInit;\n}\n\nexport interface StreamInput {\n  url: string;\n  options: FetchEventSourceInit;\n}\n\nexport interface RestfulClientEvents {\n  fetchStart: Callback<{ input: FetchInput }>;\n  fetchError: Callback<{ error: Error; input: FetchInput }>;\n  fetchSuccess: Callback<{ response: Response; data: any; input: FetchInput }>;\n  fetchDone: Callback<{ input: FetchInput }>;\n\n  streamStart: Callback<{ input: StreamInput }>;\n  streamOpen: Callback<{ input: StreamInput }>;\n  streamSuccess: Callback<{ input: StreamInput }>;\n  streamMessage: Callback<{ data: EventSourceMessage; input: StreamInput }>;\n  streamError: Callback<{ error: Error; input: StreamInput }>;\n  streamDone: Callback<{ input: StreamInput }>;\n}\n\nexport class RestfulClient<K extends Record<string, string>> extends Serializable {\n  public readonly emitter = Emitter.root.child<RestfulClientEvents>({\n    namespace: [\"internals\", \"restfulClient\"],\n    creator: this,\n  });\n\n  constructor(\n    protected input: {\n      baseUrl: string;\n      headers: () => Promise<Headers>;\n      paths: K;\n    },\n  ) {\n    super();\n  }\n\n  async *stream(\n    path: keyof K,\n    init: FetchEventSourceInit,\n  ): AsyncGenerator<EventSourceMessage, void, void> {\n    const { paths, baseUrl, headers } = this.input;\n    const emitter = this.emitter.child({\n      groupId: \"stream\",\n    });\n\n    const input: StreamInput = {\n      url: new URL(paths[path] ?? path, baseUrl).toString(),\n      options: {\n        ...init,\n        method: \"POST\",\n        headers: await headers().then((raw) =>\n          Object.assign(Object.fromEntries(raw.entries()), init?.headers),\n        ),\n      },\n    };\n    await emitter.emit(\"streamStart\", { input });\n\n    return yield* emitterToGenerator(async ({ emit }) =>\n      fetchEventSource(input.url, {\n        ...input.options,\n        async onopen(response) {\n          if (response.ok && response.headers.get(\"content-type\") === EventStreamContentType) {\n            await emitter.emit(\"streamOpen\", { input });\n            return;\n          }\n          throw new RestfulClientError(\"Failed to stream!\", [], {\n            context: {\n              url: response.url,\n              err: await response.text(),\n              response,\n            },\n            isRetryable: response.status >= 400 && response.status < 500 && response.status !== 429,\n          });\n        },\n        async onmessage(msg) {\n          if (msg?.event === \"error\") {\n            throw new RestfulClientError(`Error during streaming has occurred.`, [], {\n              context: msg,\n            });\n          }\n          await emitter.emit(\"streamMessage\", { input, data: msg });\n          emit(msg);\n        },\n        onclose() {},\n        onerror(err) {\n          throw new RestfulClientError(`Error during streaming has occurred.`, [err]);\n        },\n      })\n        .then(() => emitter.emit(\"streamSuccess\", { input }))\n        .catch(async (error) => {\n          await emitter.emit(\"streamError\", { input, error }).catch(doNothing());\n          throw error;\n        })\n        .finally(() => emitter.emit(\"streamDone\", { input })),\n    );\n  }\n\n  async fetch(path: keyof K, init?: RequestInit & { searchParams?: URLSearchParams }) {\n    const emitter = this.emitter.child({\n      groupId: \"fetch\",\n    });\n\n    const { paths, baseUrl, headers: getHeaders } = this.input;\n\n    const target = new URL(paths[path] ?? path, baseUrl);\n    if (init?.searchParams) {\n      for (const [key, value] of init.searchParams) {\n        target.searchParams.set(key, value);\n      }\n    }\n\n    const input: FetchInput = {\n      url: target.toString(),\n      options: {\n        ...init,\n        headers: await getHeaders().then((raw) =>\n          Object.assign(Object.fromEntries(raw.entries()), init?.headers),\n        ),\n      },\n    };\n\n    await emitter.emit(\"fetchStart\", { input });\n    try {\n      const response = await fetch(input.url, input.options);\n\n      if (!response.ok) {\n        throw new RestfulClientError(\"Fetch has failed\", [], {\n          context: {\n            url: response.url,\n            error: await response.text(),\n            response,\n          },\n          isRetryable: [408, 503].includes(response.status ?? 500),\n        });\n      }\n\n      const data = await response.json();\n      await emitter.emit(\"fetchSuccess\", { response, data, input });\n      return data;\n    } catch (error) {\n      await emitter.emit(\"fetchError\", { error, input: input });\n      throw error;\n    } finally {\n      await emitter.emit(\"fetchDone\", { input: input });\n    }\n  }\n\n  createSnapshot() {\n    return {\n      input: shallowCopy(this.input),\n      emitter: this.emitter,\n    };\n  }\n\n  loadSnapshot(snapshot: ReturnType<typeof this.createSnapshot>): void {\n    Object.assign(this, snapshot);\n  }\n}\n"]}