@@ -8,8 +8,9 @@ import type {
88 GraphQLFormattedError ,
99} from '../error/GraphQLError.js' ;
1010
11+ import type { DeferUsage } from '../type/definition.js' ;
12+
1113import type {
12- DeferUsage ,
1314 DeferUsageSet ,
1415 GroupedFieldSet ,
1516 GroupedFieldSetDetails ,
@@ -303,12 +304,26 @@ export class IncrementalPublisher {
303304 newGroupedFieldSetDeferUsages ,
304305 newDeferMap ,
305306 ) ;
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+ } ) ;
312327 for ( const deferredFragmentRecord of deferredFragmentRecords ) {
313328 deferredFragmentRecord . _pending . add ( deferredGroupedFieldSetRecord ) ;
314329 deferredFragmentRecord . deferredGroupedFieldSetRecords . add (
@@ -342,11 +357,22 @@ export class IncrementalPublisher {
342357 incrementalDataRecord : IncrementalDataRecord | undefined ,
343358 ) : StreamItemsRecord {
344359 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+ } ) ;
350376
351377 if ( parents === undefined ) {
352378 this . _initialResult . children . add ( streamItemsRecord ) ;
@@ -672,13 +698,17 @@ export class IncrementalPublisher {
672698
673699 if ( isStreamItemsRecord ( subsequentResultRecord ) ) {
674700 this . _introduce ( subsequentResultRecord ) ;
701+ subsequentResultRecord . publish ( ) ;
675702 return ;
676703 }
677704
678705 if ( subsequentResultRecord . _pending . size === 0 ) {
679706 subsequentResultRecord . isCompleted = true ;
680707 this . _push ( subsequentResultRecord ) ;
681708 } else {
709+ for ( const deferredGroupedFieldSetRecord of subsequentResultRecord . deferredGroupedFieldSetRecords ) {
710+ deferredGroupedFieldSetRecord . publish ( ) ;
711+ }
682712 this . _introduce ( subsequentResultRecord ) ;
683713 }
684714 }
@@ -748,24 +778,41 @@ export class IncrementalPublisher {
748778/** @internal */
749779export class DeferredGroupedFieldSetRecord {
750780 path : ReadonlyArray < string | number > ;
781+ deferPriority : number ;
782+ streamPriority : number ;
751783 deferredFragmentRecords : ReadonlyArray < DeferredFragmentRecord > ;
752784 groupedFieldSet : GroupedFieldSet ;
753785 shouldInitiateDefer : boolean ;
754786 errors : Array < GraphQLError > ;
755787 data : ObjMap < unknown > | undefined ;
788+ published : true | Promise < void > ;
789+ publish : ( ) => void ;
756790 sent : boolean ;
757791
758792 constructor ( opts : {
759793 path : Path | undefined ;
794+ deferPriority : number ;
795+ streamPriority : number ;
760796 deferredFragmentRecords : ReadonlyArray < DeferredFragmentRecord > ;
761797 groupedFieldSet : GroupedFieldSet ;
762798 shouldInitiateDefer : boolean ;
763799 } ) {
764800 this . path = pathToArray ( opts . path ) ;
801+ this . deferPriority = opts . deferPriority ;
802+ this . streamPriority = opts . streamPriority ;
765803 this . deferredFragmentRecords = opts . deferredFragmentRecords ;
766804 this . groupedFieldSet = opts . groupedFieldSet ;
767805 this . shouldInitiateDefer = opts . shouldInitiateDefer ;
768806 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+ } ;
769816 this . sent = false ;
770817 }
771818}
@@ -822,26 +869,43 @@ export class StreamItemsRecord {
822869 errors : Array < GraphQLError > ;
823870 streamRecord : StreamRecord ;
824871 path : ReadonlyArray < string | number > ;
872+ deferPriority : number ;
873+ streamPriority : number ;
825874 items : Array < unknown > ;
826875 parents : ReadonlyArray < SubsequentResultRecord > | undefined ;
827876 children : Set < SubsequentResultRecord > ;
828877 isFinalRecord ?: boolean ;
829878 isCompletedAsyncIterator ?: boolean ;
830879 isCompleted : boolean ;
880+ published : true | Promise < void > ;
881+ publish : ( ) => void ;
831882 sent : boolean ;
832883
833884 constructor ( opts : {
834885 streamRecord : StreamRecord ;
835886 path : Path | undefined ;
887+ deferPriority : number ;
888+ streamPriority : number ;
836889 parents : ReadonlyArray < SubsequentResultRecord > | undefined ;
837890 } ) {
838891 this . streamRecord = opts . streamRecord ;
839892 this . path = pathToArray ( opts . path ) ;
893+ this . deferPriority = opts . deferPriority ;
894+ this . streamPriority = opts . streamPriority ;
840895 this . parents = opts . parents ;
841896 this . children = new Set ( ) ;
842897 this . errors = [ ] ;
843898 this . isCompleted = false ;
844899 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+ } ;
845909 this . sent = false ;
846910 }
847911}
0 commit comments