{"version":3,"sources":["../src/index.ts","../src/sse.ts","../src/utils.ts","../src/fetch.ts"],"sourcesContent":["export * from './fetch';\nexport * from './interface';","import { Bytes, ServerSentEvent, LinesResult } from './interface';\n\nexport const NewLineChars = {\n  NewLine: 10,\n  CarriageReturn: 13,\n  Space: 32,\n  Colon: 58\n};\n\nexport async function parseServerSentEvent(stream: ReadableStream<Uint8Array>, onMessage: (event: ServerSentEvent) => void) {\n  const lineDecoder = new LineDecoder();\n\n  await getBytes(stream, (chunk: Uint8Array) => {\n    const decoder = new MessageDecoder();\n    // get string lines, newline-separated should be \\n,\\r,\\r\\n\n    const list = lineDecoder.getLines(chunk);\n    for (const data of list) {\n      const source = decoder.decode(data.line, data.fieldLength);\n      if (source) onMessage(source);\n    }\n  });\n}\n\n/**\n * Converts a ReadableStream into a callback pattern.\n */\nasync function getBytes(stream: ReadableStream<Uint8Array>, onChunk: (arr: Uint8Array) => void) {\n  const reader = stream.getReader();\n  while (true) {\n    const { done, value } = await reader.read();\n    if (done) break;\n    onChunk(value);\n  }\n}\n\n/**\n * decode string lines to ServerSentEvent\n */\nexport class MessageDecoder {\n  private data: string[];\n  private event: string | null;\n  private chunks: string[];\n\n  constructor() {\n    this.event = null;\n    this.data = [];\n    this.chunks = [];\n  }\n\n\n  public decode(line: Uint8Array, filedLength: number) {\n    if (line.length === 0) {\n      // empty line denotes end of message. return event data and start a new message:\n      const sse: ServerSentEvent = {\n        event: this.event,\n        data: this.data.join('\\n'),\n        raw: this.chunks,\n      };\n\n      // new message\n      this.event = null;\n      this.data = [];\n      this.chunks = [];\n\n      return sse;\n    } else if (filedLength > 0) {\n      // line is of format \"<field>:<value>\" or \"<field>: <value>\"\n      const field = this.decodeText(line.subarray(0, filedLength));\n      const valueOffset = filedLength + (line[filedLength + 1] === NewLineChars.Space ? 2 : 1);\n      const value = this.decodeText(line.subarray(valueOffset));\n\n      this.chunks.push(value);\n      switch (field) {\n      case 'event':\n        this.event = value;\n        break;\n      case 'data':\n        this.data.push(value);\n        break;\n      }\n    }\n  }\n\n  private decodeText(bytes: Bytes): string {\n    // Node:\n    if (typeof Buffer !== 'undefined') {\n      if (bytes instanceof Buffer) {\n        return bytes.toString('utf-8');\n      }\n      if (bytes instanceof Uint8Array) {\n        return Buffer.from(bytes).toString('utf-8');\n      }\n\n      throw new Error(\n        `Unexpected: received non-Uint8Array (${bytes.constructor.name}) stream chunk in an environment with a global \"Buffer\" defined, which this library assumes to be Node. Please report this error.`,\n      );\n    }\n\n    // Browser\n    if (typeof TextDecoder !== 'undefined') {\n      if (bytes instanceof Uint8Array || bytes instanceof ArrayBuffer) {\n        const decoder = new TextDecoder('utf8');\n        return decoder.decode(bytes);\n      }\n\n      throw new Error(\n        `Unexpected: received non-Uint8Array/ArrayBuffer (${\n          (bytes as any).constructor.name\n        }) in a web platform. Please report this error.`,\n      );\n    }\n\n    throw new Error(\n      'Unexpected: neither Buffer nor TextDecoder are available as globals. Please report this error.',\n    );\n  }\n}\n\n/**\n * Parses any byte chunks into EventSource line buffers.\n */\nexport class LineDecoder {\n  private buffer: Uint8Array | undefined;\n  private position: number;\n  private fieldLength: number;\n  private trailingNewLine: boolean;\n\n  constructor() {\n    this.position = 0;\n    this.fieldLength = -1;\n    this.buffer = undefined;\n    this.trailingNewLine = false;\n  }\n\n  getLines(chunk: Uint8Array): LinesResult[] {\n    if (this.buffer === undefined) {\n      this.buffer = chunk;\n      this.position = 0;\n      this.fieldLength = -1;\n    } else {\n      const buffer = new Uint8Array(this.buffer.length + chunk.length);\n      buffer.set(this.buffer);\n      buffer.set(chunk, this.buffer.length);\n      this.buffer = buffer;\n    }\n\n    const { buffer } = this;\n\n    const bufLength = this.buffer.length;\n    let lineStart = 0;\n    let resultBuf: Uint8Array = new Uint8Array();\n    let resultFieldLength = -1;\n    const list: LinesResult[] = [];\n    while (this.position < bufLength) {\n      // check new line char, if checked, skip to next char\n      if (this.trailingNewLine) {\n        if (buffer[this.position] === NewLineChars.NewLine) {\n          lineStart = ++this.position;\n        }\n\n        this.trailingNewLine = false;\n      }\n\n      let lineEnd = -1;\n      for (; this.position < bufLength && lineEnd === -1; ++this.position) {\n        switch (buffer[this.position]) {\n        case NewLineChars.Colon:\n          if (this.fieldLength === -1) this.fieldLength = this.position - lineStart;\n          break;\n        // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n        // @ts-ignore - this case ('\\r') should fallthrough to NewLine '\\n'\n        case NewLineChars.CarriageReturn:\n          this.trailingNewLine = true;\n        // eslint-disable-next-line no-fallthrough\n        case NewLineChars.NewLine:\n          lineEnd = this.position;\n          break;\n        }\n      }\n\n      if (lineEnd === -1) {\n        // the line has not ended, so we need to the next line and continue parsing.\n        break;\n      }\n\n      // got the data\n      resultBuf = this.buffer.subarray(lineStart, lineEnd);\n      resultFieldLength = this.fieldLength;\n      list.push({ fieldLength: resultFieldLength, line: resultBuf });\n      lineStart = this.position;\n      this.fieldLength = -1;\n    }\n\n    if (lineStart === bufLength) {\n      this.buffer = undefined;\n    } else if (lineStart !== 0) {\n      this.buffer = this.buffer.subarray(lineStart);\n      this.position -= lineStart;\n    }\n\n    \n    return list;\n  }\n}\n","export const checkOk = async (response: Response): Promise<void> => {\n  if (!response.ok) {\n    const defaultMessage = `Error ${response.status}: ${response.statusText}`;\n    let message = '';\n    if (response.headers.get('content-type')?.includes('application/json')) {\n      try {\n        const errorData = await response.json();\n        message = typeof errorData.message === 'string' ? errorData.message : \n          typeof errorData.error === 'string' ? errorData.error : \n            JSON.stringify(errorData.message || errorData.error) || defaultMessage;\n      } catch(error) {\n        throw new Error('Failed to parse error response as JSON');\n      }\n    } else {\n      try {\n        const textData = await response.text();\n        message = textData || defaultMessage;\n      } catch(error) {\n        throw new Error('Failed to parse error response as text');\n      }\n    }\n\n    throw new Error(message);\n  }\n};\n","import { IFetchOptions } from './interface';\nimport { parseServerSentEvent } from './sse';\nimport { checkOk } from './utils';\n\nexport async function fetchEventData(url: string, options: IFetchOptions = {}): Promise<void> {\n  const { method, data = null, headers = {}, signal, onMessage, onError, onOpen, onClose } = options;\n  const defaultHeaders = {\n    Accept: 'text/event-stream',\n    'Content-Type': 'application/json'\n  };\n  const mergedHeaders = {\n    ...defaultHeaders,\n    ...headers\n  };\n  let body: BodyInit | null;\n  if (isPlainObject(data)) {\n    body = JSON.stringify(data as Record<string, any>);\n  } else {\n    body = data as (BodyInit | null);\n  }\n  try {\n    const res = await fetch(url, {\n      method,\n      headers: mergedHeaders,\n      body,\n      signal: signal\n    });\n    await checkOk(res);\n    onOpen?.(res);\n    // consumes data\n    if (typeof onMessage === 'function' && res.body) {\n      await parseServerSentEvent(res.body, (event) => {\n        onMessage(event);\n      });\n      onClose?.();\n    }\n  } catch (err: any) {\n    onError?.(err);\n  }\n}\n\nfunction isPlainObject(obj: any): boolean {\n  if (obj === null || typeof obj !== 'object') {\n    return false;\n  }\n  const proto = Object.getPrototypeOf(obj);\n  return proto === Object.prototype || proto === null;\n}\n"],"mappings":"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","names":["buffer"]}