mirror of
https://github.com/wassname/chatGPTBox.git
synced 2026-06-29 06:31:10 +08:00
131 lines
3.5 KiB
JavaScript
131 lines
3.5 KiB
JavaScript
// https://www.npmjs.com/package/eventsource-parser/v/1.1.1
|
|
|
|
function createParser(onParse) {
|
|
let isFirstChunk
|
|
let bytes
|
|
let buffer
|
|
let startingPosition
|
|
let startingFieldLength
|
|
let eventId
|
|
let eventName
|
|
let data
|
|
reset()
|
|
return {
|
|
feed,
|
|
reset,
|
|
}
|
|
function reset() {
|
|
isFirstChunk = true
|
|
bytes = []
|
|
buffer = ''
|
|
startingPosition = 0
|
|
startingFieldLength = -1
|
|
eventId = void 0
|
|
eventName = void 0
|
|
data = ''
|
|
}
|
|
|
|
function feed(chunk) {
|
|
bytes = bytes.concat(Array.from(chunk))
|
|
buffer = new TextDecoder().decode(new Uint8Array(bytes))
|
|
if (isFirstChunk && hasBom(buffer)) {
|
|
buffer = buffer.slice(BOM.length)
|
|
}
|
|
isFirstChunk = false
|
|
const length = buffer.length
|
|
let position = 0
|
|
let discardTrailingNewline = false
|
|
while (position < length) {
|
|
if (discardTrailingNewline) {
|
|
if (buffer[position] === '\n') {
|
|
++position
|
|
}
|
|
discardTrailingNewline = false
|
|
}
|
|
let lineLength = -1
|
|
let fieldLength = startingFieldLength
|
|
let character
|
|
for (let index = startingPosition; lineLength < 0 && index < length; ++index) {
|
|
character = buffer[index]
|
|
if (character === ':' && fieldLength < 0) {
|
|
fieldLength = index - position
|
|
} else if (character === '\r') {
|
|
discardTrailingNewline = true
|
|
lineLength = index - position
|
|
} else if (character === '\n') {
|
|
lineLength = index - position
|
|
}
|
|
}
|
|
if (lineLength < 0) {
|
|
startingPosition = length - position
|
|
startingFieldLength = fieldLength
|
|
break
|
|
} else {
|
|
startingPosition = 0
|
|
startingFieldLength = -1
|
|
}
|
|
parseEventStreamLine(buffer, position, fieldLength, lineLength)
|
|
position += lineLength + 1
|
|
}
|
|
if (position === length) {
|
|
bytes = []
|
|
buffer = ''
|
|
} else if (position > 0) {
|
|
bytes = bytes.slice(new TextEncoder().encode(buffer.slice(0, position)).length)
|
|
buffer = buffer.slice(position)
|
|
}
|
|
}
|
|
|
|
function parseEventStreamLine(lineBuffer, index, fieldLength, lineLength) {
|
|
if (lineLength === 0) {
|
|
if (data.length > 0) {
|
|
onParse({
|
|
type: 'event',
|
|
id: eventId,
|
|
event: eventName || void 0,
|
|
data: data.slice(0, -1),
|
|
// remove trailing newline
|
|
})
|
|
|
|
data = ''
|
|
eventId = void 0
|
|
}
|
|
eventName = void 0
|
|
return
|
|
}
|
|
const noValue = fieldLength < 0
|
|
const field = lineBuffer.slice(index, index + (noValue ? lineLength : fieldLength))
|
|
let step = 0
|
|
if (noValue) {
|
|
step = lineLength
|
|
} else if (lineBuffer[index + fieldLength + 1] === ' ') {
|
|
step = fieldLength + 2
|
|
} else {
|
|
step = fieldLength + 1
|
|
}
|
|
const position = index + step
|
|
const valueLength = lineLength - step
|
|
const value = lineBuffer.slice(position, position + valueLength).toString()
|
|
if (field === 'data') {
|
|
data += value ? ''.concat(value, '\n') : '\n'
|
|
} else if (field === 'event') {
|
|
eventName = value
|
|
} else if (field === 'id' && !value.includes('\0')) {
|
|
eventId = value
|
|
} else if (field === 'retry') {
|
|
const retry = parseInt(value, 10)
|
|
if (!Number.isNaN(retry)) {
|
|
onParse({
|
|
type: 'reconnect-interval',
|
|
value: retry,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const BOM = [239, 187, 191]
|
|
function hasBom(buffer) {
|
|
return BOM.every((charCode, index) => buffer.charCodeAt(index) === charCode)
|
|
}
|
|
export { createParser }
|