{"version":3,"file":"serverSentEvents.gen.cjs","names":[],"sources":["../../../../src/generated/mapi/core/serverSentEvents.gen.ts"],"sourcesContent":["// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Config } from './types.gen';\n\nexport type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, 'method'> &\n  Pick<Config, 'method' | 'responseTransformer' | 'responseValidator'> & {\n    /**\n     * Fetch API implementation. You can use this option to provide a custom\n     * fetch instance.\n     *\n     * @default globalThis.fetch\n     */\n    fetch?: typeof fetch;\n    /**\n     * Implementing clients can call request interceptors inside this hook.\n     */\n    onRequest?: (url: string, init: RequestInit) => Promise<Request>;\n    /**\n     * Callback invoked when a network or parsing error occurs during streaming.\n     *\n     * This option applies only if the endpoint returns a stream of events.\n     *\n     * @param error The error that occurred.\n     */\n    onSseError?: (error: unknown) => void;\n    /**\n     * Callback invoked when an event is streamed from the server.\n     *\n     * This option applies only if the endpoint returns a stream of events.\n     *\n     * @param event Event streamed from the server.\n     * @returns Nothing (void).\n     */\n    onSseEvent?: (event: StreamEvent<TData>) => void;\n    serializedBody?: RequestInit['body'];\n    /**\n     * Default retry delay in milliseconds.\n     *\n     * This option applies only if the endpoint returns a stream of events.\n     *\n     * @default 3000\n     */\n    sseDefaultRetryDelay?: number;\n    /**\n     * Maximum number of retry attempts before giving up.\n     */\n    sseMaxRetryAttempts?: number;\n    /**\n     * Maximum retry delay in milliseconds.\n     *\n     * Applies only when exponential backoff is used.\n     *\n     * This option applies only if the endpoint returns a stream of events.\n     *\n     * @default 30000\n     */\n    sseMaxRetryDelay?: number;\n    /**\n     * Optional sleep function for retry backoff.\n     *\n     * Defaults to using `setTimeout`.\n     */\n    sseSleepFn?: (ms: number) => Promise<void>;\n    url: string;\n  };\n\nexport interface StreamEvent<TData = unknown> {\n  data: TData;\n  event?: string;\n  id?: string;\n  retry?: number;\n}\n\nexport type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {\n  stream: AsyncGenerator<\n    TData extends Record<string, unknown> ? TData[keyof TData] : TData,\n    TReturn,\n    TNext\n  >;\n};\n\nexport const createSseClient = <TData = unknown>({\n  onRequest,\n  onSseError,\n  onSseEvent,\n  responseTransformer,\n  responseValidator,\n  sseDefaultRetryDelay,\n  sseMaxRetryAttempts,\n  sseMaxRetryDelay,\n  sseSleepFn,\n  url,\n  ...options\n}: ServerSentEventsOptions): ServerSentEventsResult<TData> => {\n  let lastEventId: string | undefined;\n\n  const sleep = sseSleepFn ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));\n\n  const createStream = async function* () {\n    let retryDelay: number = sseDefaultRetryDelay ?? 3000;\n    let attempt = 0;\n    const signal = options.signal ?? new AbortController().signal;\n\n    while (true) {\n      if (signal.aborted) break;\n\n      attempt++;\n\n      const headers =\n        options.headers instanceof Headers\n          ? options.headers\n          : new Headers(options.headers as Record<string, string> | undefined);\n\n      if (lastEventId !== undefined) {\n        headers.set('Last-Event-ID', lastEventId);\n      }\n\n      try {\n        const requestInit: RequestInit = {\n          redirect: 'follow',\n          ...options,\n          body: options.serializedBody,\n          headers,\n          signal,\n        };\n        let request = new Request(url, requestInit);\n        if (onRequest) {\n          request = await onRequest(url, requestInit);\n        }\n        // fetch must be assigned here, otherwise it would throw the error:\n        // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation\n        const _fetch = options.fetch ?? globalThis.fetch;\n        const response = await _fetch(request);\n\n        if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);\n\n        if (!response.body) throw new Error('No body in SSE response');\n\n        const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();\n\n        let buffer = '';\n\n        const abortHandler = () => {\n          try {\n            reader.cancel();\n          } catch {\n            // noop\n          }\n        };\n\n        signal.addEventListener('abort', abortHandler);\n\n        try {\n          while (true) {\n            const { done, value } = await reader.read();\n            if (done) break;\n            buffer += value;\n            // Normalize line endings: CRLF -> LF, then CR -> LF\n            buffer = buffer.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\n\n            const chunks = buffer.split('\\n\\n');\n            buffer = chunks.pop() ?? '';\n\n            for (const chunk of chunks) {\n              const lines = chunk.split('\\n');\n              const dataLines: Array<string> = [];\n              let eventName: string | undefined;\n\n              for (const line of lines) {\n                if (line.startsWith('data:')) {\n                  dataLines.push(line.replace(/^data:\\s*/, ''));\n                } else if (line.startsWith('event:')) {\n                  eventName = line.replace(/^event:\\s*/, '');\n                } else if (line.startsWith('id:')) {\n                  lastEventId = line.replace(/^id:\\s*/, '');\n                } else if (line.startsWith('retry:')) {\n                  const parsed = Number.parseInt(line.replace(/^retry:\\s*/, ''), 10);\n                  if (!Number.isNaN(parsed)) {\n                    retryDelay = parsed;\n                  }\n                }\n              }\n\n              let data: unknown;\n              let parsedJson = false;\n\n              if (dataLines.length) {\n                const rawData = dataLines.join('\\n');\n                try {\n                  data = JSON.parse(rawData);\n                  parsedJson = true;\n                } catch {\n                  data = rawData;\n                }\n              }\n\n              if (parsedJson) {\n                if (responseValidator) {\n                  await responseValidator(data);\n                }\n\n                if (responseTransformer) {\n                  data = await responseTransformer(data);\n                }\n              }\n\n              onSseEvent?.({\n                data,\n                event: eventName,\n                id: lastEventId,\n                retry: retryDelay,\n              });\n\n              if (dataLines.length) {\n                yield data as any;\n              }\n            }\n          }\n        } finally {\n          signal.removeEventListener('abort', abortHandler);\n          reader.releaseLock();\n        }\n\n        break; // exit loop on normal completion\n      } catch (error) {\n        // connection failed or aborted; retry after delay\n        onSseError?.(error);\n\n        if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {\n          break; // stop after firing error\n        }\n\n        // exponential backoff: double retry each attempt, cap at 30s\n        const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);\n        await sleep(backoff);\n      }\n    }\n  };\n\n  const stream = createStream();\n\n  return { stream };\n};\n"],"mappings":"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"}