avancement planning
This commit is contained in:
+104
-44
@@ -5,6 +5,7 @@ class ParseError extends Error {
|
||||
super(message), this.name = "ParseError", this.type = options.type, this.field = options.field, this.value = options.value, this.line = options.line;
|
||||
}
|
||||
}
|
||||
const LF = 10, CR = 13, SPACE = 32;
|
||||
function noop(_arg) {
|
||||
}
|
||||
function createParser(callbacks) {
|
||||
@@ -12,39 +13,109 @@ function createParser(callbacks) {
|
||||
throw new TypeError(
|
||||
"`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?"
|
||||
);
|
||||
const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks;
|
||||
let incompleteLine = "", isFirstChunk = !0, id, data = "", eventType = "";
|
||||
function feed(newChunk) {
|
||||
const chunk = isFirstChunk ? newChunk.replace(/^\xEF\xBB\xBF/, "") : newChunk, [complete, incomplete] = splitLines(`${incompleteLine}${chunk}`);
|
||||
for (const line of complete)
|
||||
parseLine(line);
|
||||
incompleteLine = incomplete, isFirstChunk = !1;
|
||||
const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks, pendingFragments = [];
|
||||
let isFirstChunk = !0, id, data = "", dataLines = 0, eventType;
|
||||
function feed(chunk) {
|
||||
if (isFirstChunk && (isFirstChunk = !1, chunk.charCodeAt(0) === 239 && chunk.charCodeAt(1) === 187 && chunk.charCodeAt(2) === 191 && (chunk = chunk.slice(3))), pendingFragments.length === 0) {
|
||||
const trailing2 = processLines(chunk);
|
||||
trailing2 !== "" && pendingFragments.push(trailing2);
|
||||
return;
|
||||
}
|
||||
if (chunk.indexOf(`
|
||||
`) === -1 && chunk.indexOf("\r") === -1) {
|
||||
pendingFragments.push(chunk);
|
||||
return;
|
||||
}
|
||||
pendingFragments.push(chunk);
|
||||
const input = pendingFragments.join("");
|
||||
pendingFragments.length = 0;
|
||||
const trailing = processLines(input);
|
||||
trailing !== "" && pendingFragments.push(trailing);
|
||||
}
|
||||
function parseLine(line) {
|
||||
if (line === "") {
|
||||
function processLines(chunk) {
|
||||
let searchIndex = 0;
|
||||
if (chunk.indexOf("\r") === -1) {
|
||||
let lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
for (; lfIndex !== -1; ) {
|
||||
if (searchIndex === lfIndex) {
|
||||
dataLines > 0 && onEvent({ id, event: eventType, data }), id = void 0, data = "", dataLines = 0, eventType = void 0, searchIndex = lfIndex + 1, lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
continue;
|
||||
}
|
||||
const firstCharCode = chunk.charCodeAt(searchIndex);
|
||||
if (isDataPrefix(chunk, searchIndex, firstCharCode)) {
|
||||
const valueStart = chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5, value = chunk.slice(valueStart, lfIndex);
|
||||
if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {
|
||||
onEvent({ id, event: eventType, data: value }), id = void 0, data = "", eventType = void 0, searchIndex = lfIndex + 2, lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
continue;
|
||||
}
|
||||
data = dataLines === 0 ? value : `${data}
|
||||
${value}`, dataLines++;
|
||||
} else isEventPrefix(chunk, searchIndex, firstCharCode) ? eventType = chunk.slice(
|
||||
chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,
|
||||
lfIndex
|
||||
) || void 0 : parseLine(chunk, searchIndex, lfIndex);
|
||||
searchIndex = lfIndex + 1, lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
}
|
||||
return chunk.slice(searchIndex);
|
||||
}
|
||||
for (; searchIndex < chunk.length; ) {
|
||||
const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
let lineEnd = -1;
|
||||
if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = crIndex < lfIndex ? crIndex : lfIndex : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1)
|
||||
break;
|
||||
parseLine(chunk, searchIndex, lineEnd), searchIndex = lineEnd + 1, chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF && searchIndex++;
|
||||
}
|
||||
return chunk.slice(searchIndex);
|
||||
}
|
||||
function parseLine(chunk, start, end) {
|
||||
if (start === end) {
|
||||
dispatchEvent();
|
||||
return;
|
||||
}
|
||||
if (line.startsWith(":")) {
|
||||
onComment && onComment(line.slice(line.startsWith(": ") ? 2 : 1));
|
||||
const firstCharCode = chunk.charCodeAt(start);
|
||||
if (isDataPrefix(chunk, start, firstCharCode)) {
|
||||
const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5, value2 = chunk.slice(valueStart, end);
|
||||
data = dataLines === 0 ? value2 : `${data}
|
||||
${value2}`, dataLines++;
|
||||
return;
|
||||
}
|
||||
const fieldSeparatorIndex = line.indexOf(":");
|
||||
if (fieldSeparatorIndex !== -1) {
|
||||
const field = line.slice(0, fieldSeparatorIndex), offset = line[fieldSeparatorIndex + 1] === " " ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
|
||||
processField(field, value, line);
|
||||
if (isEventPrefix(chunk, start, firstCharCode)) {
|
||||
eventType = chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || void 0;
|
||||
return;
|
||||
}
|
||||
processField(line, "", line);
|
||||
if (firstCharCode === 105 && chunk.charCodeAt(start + 1) === 100 && chunk.charCodeAt(start + 2) === 58) {
|
||||
const value2 = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end);
|
||||
id = value2.includes("\0") ? void 0 : value2;
|
||||
return;
|
||||
}
|
||||
if (firstCharCode === 58) {
|
||||
if (onComment) {
|
||||
const line2 = chunk.slice(start, end);
|
||||
onComment(line2.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1));
|
||||
}
|
||||
return;
|
||||
}
|
||||
const line = chunk.slice(start, end), fieldSeparatorIndex = line.indexOf(":");
|
||||
if (fieldSeparatorIndex === -1) {
|
||||
processField(line, "", line);
|
||||
return;
|
||||
}
|
||||
const field = line.slice(0, fieldSeparatorIndex), offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
|
||||
processField(field, value, line);
|
||||
}
|
||||
function processField(field, value, line) {
|
||||
switch (field) {
|
||||
case "event":
|
||||
eventType = value;
|
||||
eventType = value || void 0;
|
||||
break;
|
||||
case "data":
|
||||
data = `${data}${value}
|
||||
`;
|
||||
data = dataLines === 0 ? value : `${data}
|
||||
${value}`, dataLines++;
|
||||
break;
|
||||
case "id":
|
||||
id = value.includes("\0") ? void 0 : value;
|
||||
@@ -69,37 +140,26 @@ function createParser(callbacks) {
|
||||
}
|
||||
}
|
||||
function dispatchEvent() {
|
||||
data.length > 0 && onEvent({
|
||||
dataLines > 0 && onEvent({
|
||||
id,
|
||||
event: eventType || void 0,
|
||||
// If the data buffer's last character is a U+000A LINE FEED (LF) character,
|
||||
// then remove the last character from the data buffer.
|
||||
data: data.endsWith(`
|
||||
`) ? data.slice(0, -1) : data
|
||||
}), id = void 0, data = "", eventType = "";
|
||||
event: eventType,
|
||||
data
|
||||
}), id = void 0, data = "", dataLines = 0, eventType = void 0;
|
||||
}
|
||||
function reset(options = {}) {
|
||||
incompleteLine && options.consume && parseLine(incompleteLine), isFirstChunk = !0, id = void 0, data = "", eventType = "", incompleteLine = "";
|
||||
if (options.consume && pendingFragments.length > 0) {
|
||||
const incompleteLine = pendingFragments.join("");
|
||||
parseLine(incompleteLine, 0, incompleteLine.length);
|
||||
}
|
||||
isFirstChunk = !0, id = void 0, data = "", dataLines = 0, eventType = void 0, pendingFragments.length = 0;
|
||||
}
|
||||
return { feed, reset };
|
||||
}
|
||||
function splitLines(chunk) {
|
||||
const lines = [];
|
||||
let incompleteLine = "", searchIndex = 0;
|
||||
for (; searchIndex < chunk.length; ) {
|
||||
const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
let lineEnd = -1;
|
||||
if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) {
|
||||
incompleteLine = chunk.slice(searchIndex);
|
||||
break;
|
||||
} else {
|
||||
const line = chunk.slice(searchIndex, lineEnd);
|
||||
lines.push(line), searchIndex = lineEnd + 1, chunk[searchIndex - 1] === "\r" && chunk[searchIndex] === `
|
||||
` && searchIndex++;
|
||||
}
|
||||
}
|
||||
return [lines, incompleteLine];
|
||||
function isDataPrefix(chunk, i, firstCharCode) {
|
||||
return firstCharCode === 100 && chunk.charCodeAt(i + 1) === 97 && chunk.charCodeAt(i + 2) === 116 && chunk.charCodeAt(i + 3) === 97 && chunk.charCodeAt(i + 4) === 58;
|
||||
}
|
||||
function isEventPrefix(chunk, i, firstCharCode) {
|
||||
return firstCharCode === 101 && chunk.charCodeAt(i + 1) === 118 && chunk.charCodeAt(i + 2) === 101 && chunk.charCodeAt(i + 3) === 110 && chunk.charCodeAt(i + 4) === 116 && chunk.charCodeAt(i + 5) === 58;
|
||||
}
|
||||
exports.ParseError = ParseError;
|
||||
exports.createParser = createParser;
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+23
-21
@@ -10,13 +10,15 @@
|
||||
* @returns A new EventSource parser, with `parse` and `reset` methods.
|
||||
* @public
|
||||
*/
|
||||
export declare function createParser(callbacks: ParserCallbacks): EventSourceParser
|
||||
export declare function createParser(
|
||||
callbacks: ParserCallbacks,
|
||||
): EventSourceParser;
|
||||
|
||||
/**
|
||||
* The type of error that occurred.
|
||||
* @public
|
||||
*/
|
||||
export declare type ErrorType = 'invalid-retry' | 'unknown-field'
|
||||
export declare type ErrorType = "invalid-retry" | "unknown-field";
|
||||
|
||||
/**
|
||||
* A parsed EventSource message event
|
||||
@@ -29,16 +31,16 @@ export declare interface EventSourceMessage {
|
||||
* implementation in that browsers will default this to `message`, whereas this parser will
|
||||
* leave this as `undefined` if not explicitly declared.
|
||||
*/
|
||||
event?: string | undefined
|
||||
event?: string | undefined;
|
||||
/**
|
||||
* ID of the message, if any was provided by the server. Can be used by clients to keep the
|
||||
* last received message ID in sync when reconnecting.
|
||||
*/
|
||||
id?: string | undefined
|
||||
id?: string | undefined;
|
||||
/**
|
||||
* The data received for this message
|
||||
*/
|
||||
data: string
|
||||
data: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +59,7 @@ export declare interface EventSourceParser {
|
||||
* @param chunk - The chunk to parse. Can be a partial, eg in the case of streaming messages.
|
||||
* @public
|
||||
*/
|
||||
feed(chunk: string): void
|
||||
feed(chunk: string): void;
|
||||
/**
|
||||
* Resets the parser state. This is required when you have a new stream of messages -
|
||||
* for instance in the case of a client being disconnected and reconnecting.
|
||||
@@ -69,7 +71,7 @@ export declare interface EventSourceParser {
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
reset(options?: {consume?: boolean}): void
|
||||
reset(options?: { consume?: boolean }): void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,28 +83,28 @@ export declare class ParseError extends Error {
|
||||
/**
|
||||
* The type of error that occurred.
|
||||
*/
|
||||
type: ErrorType
|
||||
type: ErrorType;
|
||||
/**
|
||||
* In the case of an unknown field encountered in the stream, this will be the field name.
|
||||
*/
|
||||
field?: string | undefined
|
||||
field?: string | undefined;
|
||||
/**
|
||||
* In the case of an unknown field encountered in the stream, this will be the value of the field.
|
||||
*/
|
||||
value?: string | undefined
|
||||
value?: string | undefined;
|
||||
/**
|
||||
* The line that caused the error, if available.
|
||||
*/
|
||||
line?: string | undefined
|
||||
line?: string | undefined;
|
||||
constructor(
|
||||
message: string,
|
||||
options: {
|
||||
type: ErrorType
|
||||
field?: string
|
||||
value?: string
|
||||
line?: string
|
||||
type: ErrorType;
|
||||
field?: string;
|
||||
value?: string;
|
||||
line?: string;
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,19 +120,19 @@ export declare interface ParserCallbacks {
|
||||
*
|
||||
* @param event - The parsed event/message
|
||||
*/
|
||||
onEvent?: ((event: EventSourceMessage) => void) | undefined
|
||||
onEvent?: ((event: EventSourceMessage) => void) | undefined;
|
||||
/**
|
||||
* Callback for when the server sends a new reconnection interval through the `retry` field.
|
||||
*
|
||||
* @param retry - The number of milliseconds to wait before reconnecting.
|
||||
*/
|
||||
onRetry?: ((retry: number) => void) | undefined
|
||||
onRetry?: ((retry: number) => void) | undefined;
|
||||
/**
|
||||
* Callback for when a comment is encountered in the stream.
|
||||
*
|
||||
* @param comment - The comment encountered in the stream.
|
||||
*/
|
||||
onComment?: ((comment: string) => void) | undefined
|
||||
onComment?: ((comment: string) => void) | undefined;
|
||||
/**
|
||||
* Callback for when an error occurs during parsing. This is a catch-all for any errors
|
||||
* that occur during parsing, and can be used to handle them in a custom way. Most clients
|
||||
@@ -138,7 +140,7 @@ export declare interface ParserCallbacks {
|
||||
*
|
||||
* @param error - The error that occurred during parsing
|
||||
*/
|
||||
onError?: ((error: ParseError) => void) | undefined
|
||||
onError?: ((error: ParseError) => void) | undefined;
|
||||
}
|
||||
|
||||
export {}
|
||||
export {};
|
||||
|
||||
+23
-21
@@ -10,13 +10,15 @@
|
||||
* @returns A new EventSource parser, with `parse` and `reset` methods.
|
||||
* @public
|
||||
*/
|
||||
export declare function createParser(callbacks: ParserCallbacks): EventSourceParser
|
||||
export declare function createParser(
|
||||
callbacks: ParserCallbacks,
|
||||
): EventSourceParser;
|
||||
|
||||
/**
|
||||
* The type of error that occurred.
|
||||
* @public
|
||||
*/
|
||||
export declare type ErrorType = 'invalid-retry' | 'unknown-field'
|
||||
export declare type ErrorType = "invalid-retry" | "unknown-field";
|
||||
|
||||
/**
|
||||
* A parsed EventSource message event
|
||||
@@ -29,16 +31,16 @@ export declare interface EventSourceMessage {
|
||||
* implementation in that browsers will default this to `message`, whereas this parser will
|
||||
* leave this as `undefined` if not explicitly declared.
|
||||
*/
|
||||
event?: string | undefined
|
||||
event?: string | undefined;
|
||||
/**
|
||||
* ID of the message, if any was provided by the server. Can be used by clients to keep the
|
||||
* last received message ID in sync when reconnecting.
|
||||
*/
|
||||
id?: string | undefined
|
||||
id?: string | undefined;
|
||||
/**
|
||||
* The data received for this message
|
||||
*/
|
||||
data: string
|
||||
data: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +59,7 @@ export declare interface EventSourceParser {
|
||||
* @param chunk - The chunk to parse. Can be a partial, eg in the case of streaming messages.
|
||||
* @public
|
||||
*/
|
||||
feed(chunk: string): void
|
||||
feed(chunk: string): void;
|
||||
/**
|
||||
* Resets the parser state. This is required when you have a new stream of messages -
|
||||
* for instance in the case of a client being disconnected and reconnecting.
|
||||
@@ -69,7 +71,7 @@ export declare interface EventSourceParser {
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
reset(options?: {consume?: boolean}): void
|
||||
reset(options?: { consume?: boolean }): void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,28 +83,28 @@ export declare class ParseError extends Error {
|
||||
/**
|
||||
* The type of error that occurred.
|
||||
*/
|
||||
type: ErrorType
|
||||
type: ErrorType;
|
||||
/**
|
||||
* In the case of an unknown field encountered in the stream, this will be the field name.
|
||||
*/
|
||||
field?: string | undefined
|
||||
field?: string | undefined;
|
||||
/**
|
||||
* In the case of an unknown field encountered in the stream, this will be the value of the field.
|
||||
*/
|
||||
value?: string | undefined
|
||||
value?: string | undefined;
|
||||
/**
|
||||
* The line that caused the error, if available.
|
||||
*/
|
||||
line?: string | undefined
|
||||
line?: string | undefined;
|
||||
constructor(
|
||||
message: string,
|
||||
options: {
|
||||
type: ErrorType
|
||||
field?: string
|
||||
value?: string
|
||||
line?: string
|
||||
type: ErrorType;
|
||||
field?: string;
|
||||
value?: string;
|
||||
line?: string;
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,19 +120,19 @@ export declare interface ParserCallbacks {
|
||||
*
|
||||
* @param event - The parsed event/message
|
||||
*/
|
||||
onEvent?: ((event: EventSourceMessage) => void) | undefined
|
||||
onEvent?: ((event: EventSourceMessage) => void) | undefined;
|
||||
/**
|
||||
* Callback for when the server sends a new reconnection interval through the `retry` field.
|
||||
*
|
||||
* @param retry - The number of milliseconds to wait before reconnecting.
|
||||
*/
|
||||
onRetry?: ((retry: number) => void) | undefined
|
||||
onRetry?: ((retry: number) => void) | undefined;
|
||||
/**
|
||||
* Callback for when a comment is encountered in the stream.
|
||||
*
|
||||
* @param comment - The comment encountered in the stream.
|
||||
*/
|
||||
onComment?: ((comment: string) => void) | undefined
|
||||
onComment?: ((comment: string) => void) | undefined;
|
||||
/**
|
||||
* Callback for when an error occurs during parsing. This is a catch-all for any errors
|
||||
* that occur during parsing, and can be used to handle them in a custom way. Most clients
|
||||
@@ -138,7 +140,7 @@ export declare interface ParserCallbacks {
|
||||
*
|
||||
* @param error - The error that occurred during parsing
|
||||
*/
|
||||
onError?: ((error: ParseError) => void) | undefined
|
||||
onError?: ((error: ParseError) => void) | undefined;
|
||||
}
|
||||
|
||||
export {}
|
||||
export {};
|
||||
|
||||
+104
-44
@@ -3,6 +3,7 @@ class ParseError extends Error {
|
||||
super(message), this.name = "ParseError", this.type = options.type, this.field = options.field, this.value = options.value, this.line = options.line;
|
||||
}
|
||||
}
|
||||
const LF = 10, CR = 13, SPACE = 32;
|
||||
function noop(_arg) {
|
||||
}
|
||||
function createParser(callbacks) {
|
||||
@@ -10,39 +11,109 @@ function createParser(callbacks) {
|
||||
throw new TypeError(
|
||||
"`callbacks` must be an object, got a function instead. Did you mean `{onEvent: fn}`?"
|
||||
);
|
||||
const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks;
|
||||
let incompleteLine = "", isFirstChunk = !0, id, data = "", eventType = "";
|
||||
function feed(newChunk) {
|
||||
const chunk = isFirstChunk ? newChunk.replace(/^\xEF\xBB\xBF/, "") : newChunk, [complete, incomplete] = splitLines(`${incompleteLine}${chunk}`);
|
||||
for (const line of complete)
|
||||
parseLine(line);
|
||||
incompleteLine = incomplete, isFirstChunk = !1;
|
||||
const { onEvent = noop, onError = noop, onRetry = noop, onComment } = callbacks, pendingFragments = [];
|
||||
let isFirstChunk = !0, id, data = "", dataLines = 0, eventType;
|
||||
function feed(chunk) {
|
||||
if (isFirstChunk && (isFirstChunk = !1, chunk.charCodeAt(0) === 239 && chunk.charCodeAt(1) === 187 && chunk.charCodeAt(2) === 191 && (chunk = chunk.slice(3))), pendingFragments.length === 0) {
|
||||
const trailing2 = processLines(chunk);
|
||||
trailing2 !== "" && pendingFragments.push(trailing2);
|
||||
return;
|
||||
}
|
||||
if (chunk.indexOf(`
|
||||
`) === -1 && chunk.indexOf("\r") === -1) {
|
||||
pendingFragments.push(chunk);
|
||||
return;
|
||||
}
|
||||
pendingFragments.push(chunk);
|
||||
const input = pendingFragments.join("");
|
||||
pendingFragments.length = 0;
|
||||
const trailing = processLines(input);
|
||||
trailing !== "" && pendingFragments.push(trailing);
|
||||
}
|
||||
function parseLine(line) {
|
||||
if (line === "") {
|
||||
function processLines(chunk) {
|
||||
let searchIndex = 0;
|
||||
if (chunk.indexOf("\r") === -1) {
|
||||
let lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
for (; lfIndex !== -1; ) {
|
||||
if (searchIndex === lfIndex) {
|
||||
dataLines > 0 && onEvent({ id, event: eventType, data }), id = void 0, data = "", dataLines = 0, eventType = void 0, searchIndex = lfIndex + 1, lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
continue;
|
||||
}
|
||||
const firstCharCode = chunk.charCodeAt(searchIndex);
|
||||
if (isDataPrefix(chunk, searchIndex, firstCharCode)) {
|
||||
const valueStart = chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5, value = chunk.slice(valueStart, lfIndex);
|
||||
if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {
|
||||
onEvent({ id, event: eventType, data: value }), id = void 0, data = "", eventType = void 0, searchIndex = lfIndex + 2, lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
continue;
|
||||
}
|
||||
data = dataLines === 0 ? value : `${data}
|
||||
${value}`, dataLines++;
|
||||
} else isEventPrefix(chunk, searchIndex, firstCharCode) ? eventType = chunk.slice(
|
||||
chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,
|
||||
lfIndex
|
||||
) || void 0 : parseLine(chunk, searchIndex, lfIndex);
|
||||
searchIndex = lfIndex + 1, lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
}
|
||||
return chunk.slice(searchIndex);
|
||||
}
|
||||
for (; searchIndex < chunk.length; ) {
|
||||
const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
let lineEnd = -1;
|
||||
if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = crIndex < lfIndex ? crIndex : lfIndex : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1)
|
||||
break;
|
||||
parseLine(chunk, searchIndex, lineEnd), searchIndex = lineEnd + 1, chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF && searchIndex++;
|
||||
}
|
||||
return chunk.slice(searchIndex);
|
||||
}
|
||||
function parseLine(chunk, start, end) {
|
||||
if (start === end) {
|
||||
dispatchEvent();
|
||||
return;
|
||||
}
|
||||
if (line.startsWith(":")) {
|
||||
onComment && onComment(line.slice(line.startsWith(": ") ? 2 : 1));
|
||||
const firstCharCode = chunk.charCodeAt(start);
|
||||
if (isDataPrefix(chunk, start, firstCharCode)) {
|
||||
const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5, value2 = chunk.slice(valueStart, end);
|
||||
data = dataLines === 0 ? value2 : `${data}
|
||||
${value2}`, dataLines++;
|
||||
return;
|
||||
}
|
||||
const fieldSeparatorIndex = line.indexOf(":");
|
||||
if (fieldSeparatorIndex !== -1) {
|
||||
const field = line.slice(0, fieldSeparatorIndex), offset = line[fieldSeparatorIndex + 1] === " " ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
|
||||
processField(field, value, line);
|
||||
if (isEventPrefix(chunk, start, firstCharCode)) {
|
||||
eventType = chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || void 0;
|
||||
return;
|
||||
}
|
||||
processField(line, "", line);
|
||||
if (firstCharCode === 105 && chunk.charCodeAt(start + 1) === 100 && chunk.charCodeAt(start + 2) === 58) {
|
||||
const value2 = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end);
|
||||
id = value2.includes("\0") ? void 0 : value2;
|
||||
return;
|
||||
}
|
||||
if (firstCharCode === 58) {
|
||||
if (onComment) {
|
||||
const line2 = chunk.slice(start, end);
|
||||
onComment(line2.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1));
|
||||
}
|
||||
return;
|
||||
}
|
||||
const line = chunk.slice(start, end), fieldSeparatorIndex = line.indexOf(":");
|
||||
if (fieldSeparatorIndex === -1) {
|
||||
processField(line, "", line);
|
||||
return;
|
||||
}
|
||||
const field = line.slice(0, fieldSeparatorIndex), offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1, value = line.slice(fieldSeparatorIndex + offset);
|
||||
processField(field, value, line);
|
||||
}
|
||||
function processField(field, value, line) {
|
||||
switch (field) {
|
||||
case "event":
|
||||
eventType = value;
|
||||
eventType = value || void 0;
|
||||
break;
|
||||
case "data":
|
||||
data = `${data}${value}
|
||||
`;
|
||||
data = dataLines === 0 ? value : `${data}
|
||||
${value}`, dataLines++;
|
||||
break;
|
||||
case "id":
|
||||
id = value.includes("\0") ? void 0 : value;
|
||||
@@ -67,37 +138,26 @@ function createParser(callbacks) {
|
||||
}
|
||||
}
|
||||
function dispatchEvent() {
|
||||
data.length > 0 && onEvent({
|
||||
dataLines > 0 && onEvent({
|
||||
id,
|
||||
event: eventType || void 0,
|
||||
// If the data buffer's last character is a U+000A LINE FEED (LF) character,
|
||||
// then remove the last character from the data buffer.
|
||||
data: data.endsWith(`
|
||||
`) ? data.slice(0, -1) : data
|
||||
}), id = void 0, data = "", eventType = "";
|
||||
event: eventType,
|
||||
data
|
||||
}), id = void 0, data = "", dataLines = 0, eventType = void 0;
|
||||
}
|
||||
function reset(options = {}) {
|
||||
incompleteLine && options.consume && parseLine(incompleteLine), isFirstChunk = !0, id = void 0, data = "", eventType = "", incompleteLine = "";
|
||||
if (options.consume && pendingFragments.length > 0) {
|
||||
const incompleteLine = pendingFragments.join("");
|
||||
parseLine(incompleteLine, 0, incompleteLine.length);
|
||||
}
|
||||
isFirstChunk = !0, id = void 0, data = "", dataLines = 0, eventType = void 0, pendingFragments.length = 0;
|
||||
}
|
||||
return { feed, reset };
|
||||
}
|
||||
function splitLines(chunk) {
|
||||
const lines = [];
|
||||
let incompleteLine = "", searchIndex = 0;
|
||||
for (; searchIndex < chunk.length; ) {
|
||||
const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
|
||||
`, searchIndex);
|
||||
let lineEnd = -1;
|
||||
if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) {
|
||||
incompleteLine = chunk.slice(searchIndex);
|
||||
break;
|
||||
} else {
|
||||
const line = chunk.slice(searchIndex, lineEnd);
|
||||
lines.push(line), searchIndex = lineEnd + 1, chunk[searchIndex - 1] === "\r" && chunk[searchIndex] === `
|
||||
` && searchIndex++;
|
||||
}
|
||||
}
|
||||
return [lines, incompleteLine];
|
||||
function isDataPrefix(chunk, i, firstCharCode) {
|
||||
return firstCharCode === 100 && chunk.charCodeAt(i + 1) === 97 && chunk.charCodeAt(i + 2) === 116 && chunk.charCodeAt(i + 3) === 97 && chunk.charCodeAt(i + 4) === 58;
|
||||
}
|
||||
function isEventPrefix(chunk, i, firstCharCode) {
|
||||
return firstCharCode === 101 && chunk.charCodeAt(i + 1) === 118 && chunk.charCodeAt(i + 2) === 101 && chunk.charCodeAt(i + 3) === 110 && chunk.charCodeAt(i + 4) === 116 && chunk.charCodeAt(i + 5) === 58;
|
||||
}
|
||||
export {
|
||||
ParseError,
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+22
-19
@@ -2,7 +2,7 @@
|
||||
* The type of error that occurred.
|
||||
* @public
|
||||
*/
|
||||
export declare type ErrorType = 'invalid-retry' | 'unknown-field'
|
||||
export declare type ErrorType = "invalid-retry" | "unknown-field";
|
||||
|
||||
/**
|
||||
* A parsed EventSource message event
|
||||
@@ -15,16 +15,16 @@ export declare interface EventSourceMessage {
|
||||
* implementation in that browsers will default this to `message`, whereas this parser will
|
||||
* leave this as `undefined` if not explicitly declared.
|
||||
*/
|
||||
event?: string | undefined
|
||||
event?: string | undefined;
|
||||
/**
|
||||
* ID of the message, if any was provided by the server. Can be used by clients to keep the
|
||||
* last received message ID in sync when reconnecting.
|
||||
*/
|
||||
id?: string | undefined
|
||||
id?: string | undefined;
|
||||
/**
|
||||
* The data received for this message
|
||||
*/
|
||||
data: string
|
||||
data: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,8 +48,11 @@ export declare interface EventSourceMessage {
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export declare class EventSourceParserStream extends TransformStream<string, EventSourceMessage> {
|
||||
constructor({onError, onRetry, onComment}?: StreamOptions)
|
||||
export declare class EventSourceParserStream extends TransformStream<
|
||||
string,
|
||||
EventSourceMessage
|
||||
> {
|
||||
constructor({ onError, onRetry, onComment }?: StreamOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,28 +64,28 @@ export declare class ParseError extends Error {
|
||||
/**
|
||||
* The type of error that occurred.
|
||||
*/
|
||||
type: ErrorType
|
||||
type: ErrorType;
|
||||
/**
|
||||
* In the case of an unknown field encountered in the stream, this will be the field name.
|
||||
*/
|
||||
field?: string | undefined
|
||||
field?: string | undefined;
|
||||
/**
|
||||
* In the case of an unknown field encountered in the stream, this will be the value of the field.
|
||||
*/
|
||||
value?: string | undefined
|
||||
value?: string | undefined;
|
||||
/**
|
||||
* The line that caused the error, if available.
|
||||
*/
|
||||
line?: string | undefined
|
||||
line?: string | undefined;
|
||||
constructor(
|
||||
message: string,
|
||||
options: {
|
||||
type: ErrorType
|
||||
field?: string
|
||||
value?: string
|
||||
line?: string
|
||||
type: ErrorType;
|
||||
field?: string;
|
||||
value?: string;
|
||||
line?: string;
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,19 +103,19 @@ export declare interface StreamOptions {
|
||||
*
|
||||
* @defaultValue `undefined`
|
||||
*/
|
||||
onError?: ('terminate' | ((error: Error) => void)) | undefined
|
||||
onError?: ("terminate" | ((error: Error) => void)) | undefined;
|
||||
/**
|
||||
* Callback for when a reconnection interval is sent from the server.
|
||||
*
|
||||
* @param retry - The number of milliseconds to wait before reconnecting.
|
||||
*/
|
||||
onRetry?: ((retry: number) => void) | undefined
|
||||
onRetry?: ((retry: number) => void) | undefined;
|
||||
/**
|
||||
* Callback for when a comment is encountered in the stream.
|
||||
*
|
||||
* @param comment - The comment encountered in the stream.
|
||||
*/
|
||||
onComment?: ((comment: string) => void) | undefined
|
||||
onComment?: ((comment: string) => void) | undefined;
|
||||
}
|
||||
|
||||
export {}
|
||||
export {};
|
||||
|
||||
+22
-19
@@ -2,7 +2,7 @@
|
||||
* The type of error that occurred.
|
||||
* @public
|
||||
*/
|
||||
export declare type ErrorType = 'invalid-retry' | 'unknown-field'
|
||||
export declare type ErrorType = "invalid-retry" | "unknown-field";
|
||||
|
||||
/**
|
||||
* A parsed EventSource message event
|
||||
@@ -15,16 +15,16 @@ export declare interface EventSourceMessage {
|
||||
* implementation in that browsers will default this to `message`, whereas this parser will
|
||||
* leave this as `undefined` if not explicitly declared.
|
||||
*/
|
||||
event?: string | undefined
|
||||
event?: string | undefined;
|
||||
/**
|
||||
* ID of the message, if any was provided by the server. Can be used by clients to keep the
|
||||
* last received message ID in sync when reconnecting.
|
||||
*/
|
||||
id?: string | undefined
|
||||
id?: string | undefined;
|
||||
/**
|
||||
* The data received for this message
|
||||
*/
|
||||
data: string
|
||||
data: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,8 +48,11 @@ export declare interface EventSourceMessage {
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export declare class EventSourceParserStream extends TransformStream<string, EventSourceMessage> {
|
||||
constructor({onError, onRetry, onComment}?: StreamOptions)
|
||||
export declare class EventSourceParserStream extends TransformStream<
|
||||
string,
|
||||
EventSourceMessage
|
||||
> {
|
||||
constructor({ onError, onRetry, onComment }?: StreamOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,28 +64,28 @@ export declare class ParseError extends Error {
|
||||
/**
|
||||
* The type of error that occurred.
|
||||
*/
|
||||
type: ErrorType
|
||||
type: ErrorType;
|
||||
/**
|
||||
* In the case of an unknown field encountered in the stream, this will be the field name.
|
||||
*/
|
||||
field?: string | undefined
|
||||
field?: string | undefined;
|
||||
/**
|
||||
* In the case of an unknown field encountered in the stream, this will be the value of the field.
|
||||
*/
|
||||
value?: string | undefined
|
||||
value?: string | undefined;
|
||||
/**
|
||||
* The line that caused the error, if available.
|
||||
*/
|
||||
line?: string | undefined
|
||||
line?: string | undefined;
|
||||
constructor(
|
||||
message: string,
|
||||
options: {
|
||||
type: ErrorType
|
||||
field?: string
|
||||
value?: string
|
||||
line?: string
|
||||
type: ErrorType;
|
||||
field?: string;
|
||||
value?: string;
|
||||
line?: string;
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,19 +103,19 @@ export declare interface StreamOptions {
|
||||
*
|
||||
* @defaultValue `undefined`
|
||||
*/
|
||||
onError?: ('terminate' | ((error: Error) => void)) | undefined
|
||||
onError?: ("terminate" | ((error: Error) => void)) | undefined;
|
||||
/**
|
||||
* Callback for when a reconnection interval is sent from the server.
|
||||
*
|
||||
* @param retry - The number of milliseconds to wait before reconnecting.
|
||||
*/
|
||||
onRetry?: ((retry: number) => void) | undefined
|
||||
onRetry?: ((retry: number) => void) | undefined;
|
||||
/**
|
||||
* Callback for when a comment is encountered in the stream.
|
||||
*
|
||||
* @param comment - The comment encountered in the stream.
|
||||
*/
|
||||
onComment?: ((comment: string) => void) | undefined
|
||||
onComment?: ((comment: string) => void) | undefined;
|
||||
}
|
||||
|
||||
export {}
|
||||
export {};
|
||||
|
||||
Reference in New Issue
Block a user