@@ -269,23 +269,21 @@ export abstract class AbstractRemote {
269
269
*/
270
270
async socketStream ( options : SocketSyncStreamOptions ) : Promise < DataStream < StreamingSyncLine > > {
271
271
const bson = await this . getBSON ( ) ;
272
- return await this . socketStreamInternal ( options , bson ) ;
273
- }
274
-
275
- /**
276
- * Connects to the sync/stream websocket endpoint without decoding BSON in JavaScript.
277
- */
278
- async socketStreamRaw ( options : SocketSyncStreamOptions ) : Promise < DataStream < Buffer < ArrayBuffer > > > {
279
- return this . socketStreamInternal ( options ) ;
272
+ return await this . socketStreamRaw ( options , ( data ) => bson . deserialize ( data ) , bson ) ;
280
273
}
281
274
282
275
/**
283
276
* Returns a data stream of sync line data.
284
277
*
285
- * @param bson A BSON encoder and decoder. When set, the data stream will emit parsed instances of
286
- * {@link StreamingSyncLine}. Otherwise, unparsed buffers will be emitted instead.
278
+ * @param map Maps received payload frames to the typed event value.
279
+ * @param bson A BSON encoder and decoder. When set, the data stream will be requested with a BSON payload
280
+ * (required for compatibility with older sync services).
287
281
*/
288
- private async socketStreamInternal ( options : SocketSyncStreamOptions , bson ?: typeof BSON ) : Promise < DataStream > {
282
+ async socketStreamRaw < T > (
283
+ options : SocketSyncStreamOptions ,
284
+ map : ( buffer : Buffer ) => T ,
285
+ bson ?: typeof BSON
286
+ ) : Promise < DataStream > {
289
287
const { path, fetchStrategy = FetchStrategy . Buffered } = options ;
290
288
const mimeType = bson == null ? 'application/json' : 'application/bson' ;
291
289
@@ -415,7 +413,7 @@ export abstract class AbstractRemote {
415
413
return ;
416
414
}
417
415
418
- stream . enqueueData ( bson != null ? bson . deserialize ( data ) : data ) ;
416
+ stream . enqueueData ( map ( data ) ) ;
419
417
} ,
420
418
onComplete : ( ) => {
421
419
stream . close ( ) ;
@@ -455,43 +453,18 @@ export abstract class AbstractRemote {
455
453
}
456
454
457
455
/**
458
- * Connects to the sync/stream http endpoint
456
+ * Connects to the sync/stream http endpoint, parsing lines as JSON.
459
457
*/
460
458
async postStream ( options : SyncStreamOptions ) : Promise < DataStream < StreamingSyncLine > > {
461
- const jsonS = await this . postStreamRaw ( options ) ;
462
-
463
- const stream = new DataStream ( {
464
- logger : this . logger
465
- } ) ;
466
-
467
- const r = jsonS . getReader ( ) ;
468
-
469
- const l = stream . registerListener ( {
470
- lowWater : async ( ) => {
471
- try {
472
- const { done, value } = await r . read ( ) ;
473
- // Exit if we're done
474
- if ( done ) {
475
- stream . close ( ) ;
476
- l ?.( ) ;
477
- return ;
478
- }
479
- stream . enqueueData ( JSON . parse ( value ) ) ;
480
- } catch ( ex ) {
481
- stream . close ( ) ;
482
- throw ex ;
483
- }
484
- } ,
485
- closed : ( ) => {
486
- r . cancel ( ) ;
487
- l ?.( ) ;
488
- }
459
+ return await this . postStreamRaw ( options , ( line ) => {
460
+ return JSON . parse ( line ) as StreamingSyncLine ;
489
461
} ) ;
490
-
491
- return stream ;
492
462
}
493
463
494
- async postStreamRaw ( options : SyncStreamOptions ) : Promise < ReadableStream < string > > {
464
+ /**
465
+ * Connects to the sync/stream http endpoint, mapping and emitting each received string line.
466
+ */
467
+ async postStreamRaw < T > ( options : SyncStreamOptions , mapLine : ( line : string ) => T ) : Promise < DataStream < T > > {
495
468
const { data, path, headers, abortSignal } = options ;
496
469
497
470
const request = await this . buildRequest ( path ) ;
@@ -566,40 +539,52 @@ export abstract class AbstractRemote {
566
539
const decoder = new TextDecoder ( ) ;
567
540
let buffer = '' ;
568
541
569
- const outputStream = new ReadableStream < string > ( {
570
- pull : async ( controller ) => {
571
- let didCompleteLine = false ;
542
+ const stream = new DataStream < T > ( {
543
+ logger : this . logger
544
+ } ) ;
572
545
573
- while ( ! didCompleteLine ) {
574
- const { done, value } = await reader . read ( ) ;
575
- if ( done ) {
576
- const remaining = buffer . trim ( ) ;
577
- if ( remaining . length != 0 ) {
578
- controller . enqueue ( remaining ) ;
579
- }
546
+ const l = stream . registerListener ( {
547
+ lowWater : async ( ) => {
548
+ try {
549
+ let didCompleteLine = false ;
550
+ while ( ! didCompleteLine ) {
551
+ const { done, value } = await reader . read ( ) ;
552
+ if ( done ) {
553
+ const remaining = buffer . trim ( ) ;
554
+ if ( remaining . length != 0 ) {
555
+ stream . enqueueData ( mapLine ( remaining ) ) ;
556
+ }
580
557
581
- controller . close ( ) ;
582
- await closeReader ( ) ;
583
- return ;
584
- }
558
+ stream . close ( ) ;
559
+ await closeReader ( ) ;
560
+ return ;
561
+ }
585
562
586
- const data = decoder . decode ( value , { stream : true } ) ;
587
- buffer += data ;
563
+ const data = decoder . decode ( value , { stream : true } ) ;
564
+ buffer += data ;
588
565
589
- const lines = buffer . split ( '\n' ) ;
590
- for ( var i = 0 ; i < lines . length - 1 ; i ++ ) {
591
- var l = lines [ i ] . trim ( ) ;
592
- if ( l . length > 0 ) {
593
- controller . enqueue ( l ) ;
594
- didCompleteLine = true ;
566
+ const lines = buffer . split ( '\n' ) ;
567
+ for ( var i = 0 ; i < lines . length - 1 ; i ++ ) {
568
+ var l = lines [ i ] . trim ( ) ;
569
+ if ( l . length > 0 ) {
570
+ stream . enqueueData ( mapLine ( l ) ) ;
571
+ didCompleteLine = true ;
572
+ }
595
573
}
596
- }
597
574
598
- buffer = lines [ lines . length - 1 ] ;
575
+ buffer = lines [ lines . length - 1 ] ;
576
+ }
577
+ } catch ( ex ) {
578
+ stream . close ( ) ;
579
+ throw ex ;
599
580
}
581
+ } ,
582
+ closed : ( ) => {
583
+ closeReader ( ) ;
584
+ l ?.( ) ;
600
585
}
601
586
} ) ;
602
587
603
- return outputStream ;
588
+ return stream ;
604
589
}
605
590
}
0 commit comments