@@ -10,6 +10,41 @@ export async function* parseSSE(response: Response): AsyncGenerator<ServerSentEv
1010
1111 const decoder = new TextDecoder ( ) ;
1212 let buffer = '' ;
13+ let event : Partial < ServerSentEvent > = { } ;
14+
15+ const processLine = ( rawLine : string ) : ServerSentEvent | undefined => {
16+ const line = rawLine . endsWith ( '\r' ) ? rawLine . slice ( 0 , - 1 ) : rawLine ;
17+
18+ if ( line === '' ) {
19+ const completed = event . data !== undefined
20+ ? { data : event . data , event : event . event , id : event . id }
21+ : undefined ;
22+ event = { } ;
23+ return completed ;
24+ }
25+
26+ if ( line . startsWith ( ':' ) ) return undefined ;
27+
28+ const colonIndex = line . indexOf ( ':' ) ;
29+ if ( colonIndex === - 1 ) return undefined ;
30+
31+ const field = line . slice ( 0 , colonIndex ) ;
32+ const value = line . slice ( colonIndex + 1 ) . trimStart ( ) ;
33+
34+ switch ( field ) {
35+ case 'data' :
36+ event . data = event . data !== undefined ? `${ event . data } \n${ value } ` : value ;
37+ break ;
38+ case 'event' :
39+ event . event = value ;
40+ break ;
41+ case 'id' :
42+ event . id = value ;
43+ break ;
44+ }
45+
46+ return undefined ;
47+ } ;
1348
1449 try {
1550 while ( true ) {
@@ -21,45 +56,25 @@ export async function* parseSSE(response: Response): AsyncGenerator<ServerSentEv
2156 const lines = buffer . split ( '\n' ) ;
2257 buffer = lines . pop ( ) || '' ;
2358
24- let event : Partial < ServerSentEvent > = { } ;
25-
2659 for ( const line of lines ) {
27- if ( line === '' ) {
28- if ( event . data !== undefined ) {
29- yield { data : event . data , event : event . event , id : event . id } ;
30- }
31- event = { } ;
32- continue ;
60+ const completed = processLine ( line ) ;
61+ if ( completed ) {
62+ yield completed ;
3363 }
64+ }
65+ }
3466
35- if ( line . startsWith ( ':' ) ) continue ; // comment
36-
37- const colonIndex = line . indexOf ( ':' ) ;
38- if ( colonIndex === - 1 ) continue ;
39-
40- const field = line . slice ( 0 , colonIndex ) ;
41- const value = line . slice ( colonIndex + 1 ) . trimStart ( ) ;
67+ buffer += decoder . decode ( ) ;
4268
43- switch ( field ) {
44- case 'data' :
45- event . data = event . data !== undefined ? `${ event . data } \n${ value } ` : value ;
46- break ;
47- case 'event' :
48- event . event = value ;
49- break ;
50- case 'id' :
51- event . id = value ;
52- break ;
53- }
69+ if ( buffer . length > 0 ) {
70+ const completed = processLine ( buffer ) ;
71+ if ( completed ) {
72+ yield completed ;
5473 }
5574 }
5675
57- // Flush remaining
58- if ( buffer . trim ( ) && buffer . includes ( 'data:' ) ) {
59- const colonIndex = buffer . indexOf ( ':' ) ;
60- if ( colonIndex !== - 1 ) {
61- yield { data : buffer . slice ( colonIndex + 1 ) . trimStart ( ) } ;
62- }
76+ if ( event . data !== undefined ) {
77+ yield { data : event . data , event : event . event , id : event . id } ;
6378 }
6479 } finally {
6580 reader . releaseLock ( ) ;
0 commit comments