{"version":3,"file":"sse.cjs","names":[],"sources":["../../src/utils/sse.ts"],"sourcesContent":["const CR = \"\\r\".charCodeAt(0);\nconst LF = \"\\n\".charCodeAt(0);\nconst NULL = \"\\0\".charCodeAt(0);\nconst COLON = \":\".charCodeAt(0);\nconst SPACE = \" \".charCodeAt(0);\n\nconst TRAILING_NEWLINE = [CR, LF];\n\nexport function BytesLineDecoder() {\n  let buffer: Uint8Array[] = [];\n  let trailingCr = false;\n\n  return new TransformStream<Uint8Array, Uint8Array>({\n    start() {\n      buffer = [];\n      trailingCr = false;\n    },\n\n    transform(chunk, controller) {\n      // See https://docs.python.org/3/glossary.html#term-universal-newlines\n      let text = chunk;\n\n      // Handle trailing CR from previous chunk\n      if (trailingCr) {\n        text = joinArrays([[CR], text]);\n        trailingCr = false;\n      }\n\n      // Check for trailing CR in current chunk\n      if (text.length > 0 && text.at(-1) === CR) {\n        trailingCr = true;\n        text = text.subarray(0, -1);\n      }\n\n      if (!text.length) return;\n      const trailingNewline = TRAILING_NEWLINE.includes(text.at(-1)!);\n\n      const lastIdx = text.length - 1;\n      const { lines } = text.reduce<{ lines: Uint8Array[]; from: number }>(\n        (acc, cur, idx) => {\n          if (acc.from > idx) return acc;\n\n          if (cur === CR || cur === LF) {\n            acc.lines.push(text.subarray(acc.from, idx));\n            if (cur === CR && text[idx + 1] === LF) {\n              acc.from = idx + 2;\n            } else {\n              acc.from = idx + 1;\n            }\n          }\n\n          if (idx === lastIdx && acc.from <= lastIdx) {\n            acc.lines.push(text.subarray(acc.from));\n          }\n\n          return acc;\n        },\n        { lines: [], from: 0 }\n      );\n\n      if (lines.length === 1 && !trailingNewline) {\n        buffer.push(lines[0]);\n        return;\n      }\n\n      if (buffer.length) {\n        // Include existing buffer in first line\n        buffer.push(lines[0]);\n        lines[0] = joinArrays(buffer);\n        buffer = [];\n      }\n\n      if (!trailingNewline) {\n        // If the last segment is not newline terminated,\n        // buffer it for the next chunk\n        if (lines.length) buffer = [lines.pop()!];\n      }\n\n      // Enqueue complete lines\n      for (const line of lines) {\n        controller.enqueue(line);\n      }\n    },\n\n    flush(controller) {\n      if (buffer.length) {\n        controller.enqueue(joinArrays(buffer));\n      }\n    },\n  });\n}\n\ninterface StreamPart {\n  id: string | undefined;\n  event: string;\n  data: unknown;\n}\n\nexport function SSEDecoder() {\n  let event = \"\";\n  let data: Uint8Array[] = [];\n  let lastEventId = \"\";\n  let retry: number | null = null;\n\n  const decoder = new TextDecoder();\n\n  return new TransformStream<Uint8Array, StreamPart>({\n    transform(chunk, controller) {\n      // Handle empty line case\n      if (!chunk.length) {\n        if (!event && !data.length && !lastEventId && retry == null) return;\n\n        const sse = {\n          id: lastEventId || undefined,\n          event,\n          data: data.length ? decodeArraysToJson(decoder, data) : null,\n        };\n\n        // NOTE: as per the SSE spec, do not reset lastEventId\n        event = \"\";\n        data = [];\n        retry = null;\n\n        controller.enqueue(sse);\n        return;\n      }\n\n      // Ignore comments\n      if (chunk[0] === COLON) return;\n\n      const sepIdx = chunk.indexOf(COLON);\n      if (sepIdx === -1) return;\n\n      const fieldName = decoder.decode(chunk.subarray(0, sepIdx));\n      let value = chunk.subarray(sepIdx + 1);\n      if (value[0] === SPACE) value = value.subarray(1);\n\n      if (fieldName === \"event\") {\n        event = decoder.decode(value);\n      } else if (fieldName === \"data\") {\n        data.push(value);\n      } else if (fieldName === \"id\") {\n        if (value.indexOf(NULL) === -1) lastEventId = decoder.decode(value);\n      } else if (fieldName === \"retry\") {\n        const retryNum = Number.parseInt(decoder.decode(value), 10);\n        if (!Number.isNaN(retryNum)) retry = retryNum;\n      }\n    },\n\n    flush(controller) {\n      if (event) {\n        controller.enqueue({\n          id: lastEventId || undefined,\n          event,\n          data: data.length ? decodeArraysToJson(decoder, data) : null,\n        });\n      }\n    },\n  });\n}\n\nfunction joinArrays(data: ArrayLike<number>[]) {\n  const totalLength = data.reduce((acc, curr) => acc + curr.length, 0);\n  const merged = new Uint8Array(totalLength);\n  let offset = 0;\n  for (const c of data) {\n    merged.set(c, offset);\n    offset += c.length;\n  }\n  return merged;\n}\n\nfunction decodeArraysToJson(decoder: TextDecoder, data: ArrayLike<number>[]) {\n  return JSON.parse(decoder.decode(joinArrays(data)));\n}\n"],"mappings":"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"}