@@ -8,8 +8,9 @@ import type {
8
8
GraphQLFormattedError ,
9
9
} from '../error/GraphQLError.js' ;
10
10
11
+ import type { DeferUsage } from '../type/definition.js' ;
12
+
11
13
import type {
12
- DeferUsage ,
13
14
DeferUsageSet ,
14
15
GroupedFieldSet ,
15
16
GroupedFieldSetDetails ,
@@ -303,12 +304,26 @@ export class IncrementalPublisher {
303
304
newGroupedFieldSetDeferUsages ,
304
305
newDeferMap ,
305
306
) ;
306
- const deferredGroupedFieldSetRecord = new DeferredGroupedFieldSetRecord ( {
307
- path,
308
- deferredFragmentRecords,
309
- groupedFieldSet,
310
- shouldInitiateDefer,
311
- } ) ;
307
+ const deferredGroupedFieldSetRecord =
308
+ incrementalDataRecord === undefined
309
+ ? new DeferredGroupedFieldSetRecord ( {
310
+ path,
311
+ deferredFragmentRecords,
312
+ groupedFieldSet,
313
+ deferPriority : 1 ,
314
+ streamPriority : 0 ,
315
+ shouldInitiateDefer,
316
+ } )
317
+ : new DeferredGroupedFieldSetRecord ( {
318
+ path,
319
+ deferredFragmentRecords,
320
+ groupedFieldSet,
321
+ deferPriority : shouldInitiateDefer
322
+ ? incrementalDataRecord . deferPriority + 1
323
+ : incrementalDataRecord . deferPriority ,
324
+ streamPriority : incrementalDataRecord . streamPriority ,
325
+ shouldInitiateDefer,
326
+ } ) ;
312
327
for ( const deferredFragmentRecord of deferredFragmentRecords ) {
313
328
deferredFragmentRecord . _pending . add ( deferredGroupedFieldSetRecord ) ;
314
329
deferredFragmentRecord . deferredGroupedFieldSetRecords . add (
@@ -342,11 +357,22 @@ export class IncrementalPublisher {
342
357
incrementalDataRecord : IncrementalDataRecord | undefined ,
343
358
) : StreamItemsRecord {
344
359
const parents = getSubsequentResultRecords ( incrementalDataRecord ) ;
345
- const streamItemsRecord = new StreamItemsRecord ( {
346
- streamRecord,
347
- path,
348
- parents,
349
- } ) ;
360
+ const streamItemsRecord =
361
+ incrementalDataRecord === undefined
362
+ ? new StreamItemsRecord ( {
363
+ streamRecord,
364
+ path,
365
+ deferPriority : 0 ,
366
+ streamPriority : 1 ,
367
+ parents,
368
+ } )
369
+ : new StreamItemsRecord ( {
370
+ streamRecord,
371
+ path,
372
+ deferPriority : incrementalDataRecord . deferPriority ,
373
+ streamPriority : incrementalDataRecord . streamPriority + 1 ,
374
+ parents,
375
+ } ) ;
350
376
351
377
if ( parents === undefined ) {
352
378
this . _initialResult . children . add ( streamItemsRecord ) ;
@@ -672,13 +698,17 @@ export class IncrementalPublisher {
672
698
673
699
if ( isStreamItemsRecord ( subsequentResultRecord ) ) {
674
700
this . _introduce ( subsequentResultRecord ) ;
701
+ subsequentResultRecord . publish ( ) ;
675
702
return ;
676
703
}
677
704
678
705
if ( subsequentResultRecord . _pending . size === 0 ) {
679
706
subsequentResultRecord . isCompleted = true ;
680
707
this . _push ( subsequentResultRecord ) ;
681
708
} else {
709
+ for ( const deferredGroupedFieldSetRecord of subsequentResultRecord . deferredGroupedFieldSetRecords ) {
710
+ deferredGroupedFieldSetRecord . publish ( ) ;
711
+ }
682
712
this . _introduce ( subsequentResultRecord ) ;
683
713
}
684
714
}
@@ -748,24 +778,41 @@ export class IncrementalPublisher {
748
778
/** @internal */
749
779
export class DeferredGroupedFieldSetRecord {
750
780
path : ReadonlyArray < string | number > ;
781
+ deferPriority : number ;
782
+ streamPriority : number ;
751
783
deferredFragmentRecords : ReadonlyArray < DeferredFragmentRecord > ;
752
784
groupedFieldSet : GroupedFieldSet ;
753
785
shouldInitiateDefer : boolean ;
754
786
errors : Array < GraphQLError > ;
755
787
data : ObjMap < unknown > | undefined ;
788
+ published : true | Promise < void > ;
789
+ publish : ( ) => void ;
756
790
sent : boolean ;
757
791
758
792
constructor ( opts : {
759
793
path : Path | undefined ;
794
+ deferPriority : number ;
795
+ streamPriority : number ;
760
796
deferredFragmentRecords : ReadonlyArray < DeferredFragmentRecord > ;
761
797
groupedFieldSet : GroupedFieldSet ;
762
798
shouldInitiateDefer : boolean ;
763
799
} ) {
764
800
this . path = pathToArray ( opts . path ) ;
801
+ this . deferPriority = opts . deferPriority ;
802
+ this . streamPriority = opts . streamPriority ;
765
803
this . deferredFragmentRecords = opts . deferredFragmentRecords ;
766
804
this . groupedFieldSet = opts . groupedFieldSet ;
767
805
this . shouldInitiateDefer = opts . shouldInitiateDefer ;
768
806
this . errors = [ ] ;
807
+ // promiseWithResolvers uses void only as a generic type parameter
808
+ // see: https://typescript-eslint.io/rules/no-invalid-void-type/
809
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
810
+ const { promise : published , resolve } = promiseWithResolvers < void > ( ) ;
811
+ this . published = published ;
812
+ this . publish = ( ) => {
813
+ resolve ( ) ;
814
+ this . published = true ;
815
+ } ;
769
816
this . sent = false ;
770
817
}
771
818
}
@@ -822,26 +869,43 @@ export class StreamItemsRecord {
822
869
errors : Array < GraphQLError > ;
823
870
streamRecord : StreamRecord ;
824
871
path : ReadonlyArray < string | number > ;
872
+ deferPriority : number ;
873
+ streamPriority : number ;
825
874
items : Array < unknown > ;
826
875
parents : ReadonlyArray < SubsequentResultRecord > | undefined ;
827
876
children : Set < SubsequentResultRecord > ;
828
877
isFinalRecord ?: boolean ;
829
878
isCompletedAsyncIterator ?: boolean ;
830
879
isCompleted : boolean ;
880
+ published : true | Promise < void > ;
881
+ publish : ( ) => void ;
831
882
sent : boolean ;
832
883
833
884
constructor ( opts : {
834
885
streamRecord : StreamRecord ;
835
886
path : Path | undefined ;
887
+ deferPriority : number ;
888
+ streamPriority : number ;
836
889
parents : ReadonlyArray < SubsequentResultRecord > | undefined ;
837
890
} ) {
838
891
this . streamRecord = opts . streamRecord ;
839
892
this . path = pathToArray ( opts . path ) ;
893
+ this . deferPriority = opts . deferPriority ;
894
+ this . streamPriority = opts . streamPriority ;
840
895
this . parents = opts . parents ;
841
896
this . children = new Set ( ) ;
842
897
this . errors = [ ] ;
843
898
this . isCompleted = false ;
844
899
this . items = [ ] ;
900
+ // promiseWithResolvers uses void only as a generic type parameter
901
+ // see: https://typescript-eslint.io/rules/no-invalid-void-type/
902
+ // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
903
+ const { promise : published , resolve } = promiseWithResolvers < void > ( ) ;
904
+ this . published = published ;
905
+ this . publish = ( ) => {
906
+ resolve ( ) ;
907
+ this . published = true ;
908
+ } ;
845
909
this . sent = false ;
846
910
}
847
911
}
0 commit comments