@@ -8,13 +8,7 @@ import type {
88 GraphQLFormattedError ,
99} from '../error/GraphQLError.js' ;
1010
11- import type {
12- DeferUsage ,
13- DeferUsageSet ,
14- GroupedFieldSet ,
15- GroupedFieldSetDetails ,
16- } from './collectFields.js' ;
17- import type { StreamUsage } from './execute.js' ;
11+ import type { GroupedFieldSet } from './collectFields.js' ;
1812
1913interface IncrementalUpdate < TData = unknown , TExtensions = ObjMap < unknown > > {
2014 incremental : ReadonlyArray < IncrementalResult < TData , TExtensions > > ;
@@ -188,112 +182,38 @@ export class IncrementalPublisher {
188182 this . _reset ( ) ;
189183 }
190184
191- prepareInitialResultRecord ( ) : InitialResultRecord {
192- return new InitialResultRecord ( ) ;
185+ reportNewDeferFragmentRecord (
186+ deferredFragmentRecord : DeferredFragmentRecord ,
187+ parentIncrementalResultRecord :
188+ | InitialResultRecord
189+ | DeferredFragmentRecord
190+ | StreamItemsRecord ,
191+ ) : void {
192+ parentIncrementalResultRecord . children . add ( deferredFragmentRecord ) ;
193193 }
194194
195- prepareNewDeferRecords (
196- newGroupedFieldSetDetails : Map < DeferUsageSet , GroupedFieldSetDetails > ,
197- newDeferUsages : ReadonlyArray < DeferUsage > ,
198- incrementalDataRecord : IncrementalDataRecord ,
199- deferMap ?: ReadonlyMap < DeferUsage , DeferredFragmentRecord > ,
200- path ?: Path | undefined ,
201- ) : {
202- newDeferMap : ReadonlyMap < DeferUsage , DeferredFragmentRecord > ;
203- newDeferredGroupedFieldSetRecords : ReadonlyArray < DeferredGroupedFieldSetRecord > ;
204- } {
205- let newDeferMap ;
206- if ( newDeferUsages . length === 0 ) {
207- newDeferMap = deferMap ?? new Map < DeferUsage , DeferredFragmentRecord > ( ) ;
208- } else {
209- newDeferMap =
210- deferMap === undefined
211- ? new Map < DeferUsage , DeferredFragmentRecord > ( )
212- : new Map < DeferUsage , DeferredFragmentRecord > ( deferMap ) ;
213- for ( const deferUsage of newDeferUsages ) {
214- const deferredFragmentRecord = new DeferredFragmentRecord ( {
215- path,
216- label : deferUsage . label ,
217- } ) ;
218-
219- const parentDeferUsage = deferUsage . ancestors [ 0 ] ;
220-
221- const parent =
222- parentDeferUsage === undefined
223- ? ( incrementalDataRecord as InitialResultRecord | StreamItemsRecord )
224- : this . _deferredFragmentRecordFromDeferUsage (
225- parentDeferUsage ,
226- newDeferMap ,
227- ) ;
228- parent . children . add ( deferredFragmentRecord ) ;
229-
230- newDeferMap . set ( deferUsage , deferredFragmentRecord ) ;
231- }
232- }
233-
234- const newDeferredGroupedFieldSetRecords : Array < DeferredGroupedFieldSetRecord > =
235- [ ] ;
236-
237- for ( const [
238- newGroupedFieldSetDeferUsages ,
239- { groupedFieldSet, shouldInitiateDefer } ,
240- ] of newGroupedFieldSetDetails ) {
241- const deferredFragmentRecords = this . _getDeferredFragmentRecords (
242- newGroupedFieldSetDeferUsages ,
243- newDeferMap ,
195+ reportNewDeferredGroupedFieldSetRecord (
196+ deferredGroupedFieldSetRecord : DeferredGroupedFieldSetRecord ,
197+ ) : void {
198+ for ( const deferredFragmentRecord of deferredGroupedFieldSetRecord . deferredFragmentRecords ) {
199+ deferredFragmentRecord . _pending . add ( deferredGroupedFieldSetRecord ) ;
200+ deferredFragmentRecord . deferredGroupedFieldSetRecords . add (
201+ deferredGroupedFieldSetRecord ,
244202 ) ;
245- const deferredGroupedFieldSetRecord = new DeferredGroupedFieldSetRecord ( {
246- path,
247- deferredFragmentRecords,
248- groupedFieldSet,
249- shouldInitiateDefer,
250- } ) ;
251- for ( const deferredFragmentRecord of deferredFragmentRecords ) {
252- deferredFragmentRecord . _pending . add ( deferredGroupedFieldSetRecord ) ;
253- deferredFragmentRecord . deferredGroupedFieldSetRecords . add (
254- deferredGroupedFieldSetRecord ,
255- ) ;
256- }
257- newDeferredGroupedFieldSetRecords . push ( deferredGroupedFieldSetRecord ) ;
258203 }
259-
260- return {
261- newDeferMap,
262- newDeferredGroupedFieldSetRecords,
263- } ;
264204 }
265205
266- prepareNewStreamRecord (
267- streamUsage : StreamUsage ,
268- path : Path ,
269- asyncIterator ?: AsyncIterator < unknown > | undefined ,
270- ) : StreamRecord {
271- return new StreamRecord ( {
272- label : streamUsage . label ,
273- path,
274- asyncIterator,
275- } ) ;
276- }
277-
278- prepareNewStreamItemsRecord (
279- streamRecord : StreamRecord ,
280- path : Path | undefined ,
281- incrementalDataRecord : IncrementalDataRecord ,
282- ) : StreamItemsRecord {
283- const streamItemsRecord = new StreamItemsRecord ( {
284- streamRecord,
285- path,
286- } ) ;
287-
288- if ( isDeferredGroupedFieldSetRecord ( incrementalDataRecord ) ) {
289- for ( const parent of incrementalDataRecord . deferredFragmentRecords ) {
206+ reportNewStreamItemsRecord (
207+ streamItemsRecord : StreamItemsRecord ,
208+ parentIncrementalDataRecord : IncrementalDataRecord ,
209+ ) : void {
210+ if ( isDeferredGroupedFieldSetRecord ( parentIncrementalDataRecord ) ) {
211+ for ( const parent of parentIncrementalDataRecord . deferredFragmentRecords ) {
290212 parent . children . add ( streamItemsRecord ) ;
291213 }
292214 } else {
293- incrementalDataRecord . children . add ( streamItemsRecord ) ;
215+ parentIncrementalDataRecord . children . add ( streamItemsRecord ) ;
294216 }
295-
296- return streamItemsRecord ;
297217 }
298218
299219 completeDeferredGroupedFieldSet (
@@ -341,6 +261,9 @@ export class IncrementalPublisher {
341261 streamItemsRecord . streamRecord . errors . push ( error ) ;
342262 this . setIsFinalRecord ( streamItemsRecord ) ;
343263 streamItemsRecord . isCompleted = true ;
264+ streamItemsRecord . streamRecord . earlyReturn ?.( ) . catch ( ( ) => {
265+ // ignore error
266+ } ) ;
344267 this . _release ( streamItemsRecord ) ;
345268 }
346269
@@ -418,7 +341,7 @@ export class IncrementalPublisher {
418341 }
419342
420343 streams . forEach ( ( stream ) => {
421- stream . asyncIterator ?. return ?.( ) . catch ( ( ) => {
344+ stream . earlyReturn ?.( ) . catch ( ( ) => {
422345 // ignore error
423346 } ) ;
424347 } ) ;
@@ -469,10 +392,10 @@ export class IncrementalPublisher {
469392 streams . add ( subsequentResultRecord . streamRecord ) ;
470393 }
471394 }
472- const promises : Array < Promise < IteratorResult < unknown > > > = [ ] ;
395+ const promises : Array < Promise < unknown > > = [ ] ;
473396 streams . forEach ( ( streamRecord ) => {
474- if ( streamRecord . asyncIterator ?. return ) {
475- promises . push ( streamRecord . asyncIterator . return ( ) ) ;
397+ if ( streamRecord . earlyReturn ) {
398+ promises . push ( streamRecord . earlyReturn ( ) ) ;
476399 }
477400 } ) ;
478401 await Promise . all ( promises ) ;
@@ -569,31 +492,26 @@ export class IncrementalPublisher {
569492 this . _publish ( child ) ;
570493 }
571494 if ( isStreamItemsRecord ( subsequentResultRecord ) ) {
572- if ( ! subsequentResultRecord . sent ) {
573- subsequentResultRecord . sent = true ;
574- if ( subsequentResultRecord . isFinalRecord ) {
575- completedResults . push (
576- this . _completedRecordToResult (
577- subsequentResultRecord . streamRecord ,
578- ) ,
579- ) ;
580- }
581- if ( subsequentResultRecord . isCompletedAsyncIterator ) {
582- // async iterable resolver just finished but there may be pending payloads
583- continue ;
584- }
585- if ( subsequentResultRecord . streamRecord . errors . length > 0 ) {
586- continue ;
587- }
588- const incrementalResult : IncrementalStreamResult = {
589- items : subsequentResultRecord . items ,
590- path : subsequentResultRecord . streamRecord . path ,
591- } ;
592- if ( subsequentResultRecord . errors . length > 0 ) {
593- incrementalResult . errors = subsequentResultRecord . errors ;
594- }
595- incrementalResults . push ( incrementalResult ) ;
495+ if ( subsequentResultRecord . isFinalRecord ) {
496+ completedResults . push (
497+ this . _completedRecordToResult ( subsequentResultRecord . streamRecord ) ,
498+ ) ;
499+ }
500+ if ( subsequentResultRecord . isCompletedAsyncIterator ) {
501+ // async iterable resolver just finished but there may be pending payloads
502+ continue ;
596503 }
504+ if ( subsequentResultRecord . streamRecord . errors . length > 0 ) {
505+ continue ;
506+ }
507+ const incrementalResult : IncrementalStreamResult = {
508+ items : subsequentResultRecord . items ,
509+ path : subsequentResultRecord . streamRecord . path ,
510+ } ;
511+ if ( subsequentResultRecord . errors . length > 0 ) {
512+ incrementalResult . errors = subsequentResultRecord . errors ;
513+ }
514+ incrementalResults . push ( incrementalResult ) ;
597515 } else {
598516 completedResults . push (
599517 this . _completedRecordToResult ( subsequentResultRecord ) ,
@@ -639,23 +557,6 @@ export class IncrementalPublisher {
639557 return result ;
640558 }
641559
642- private _getDeferredFragmentRecords (
643- deferUsages : DeferUsageSet ,
644- deferMap : ReadonlyMap < DeferUsage , DeferredFragmentRecord > ,
645- ) : ReadonlyArray < DeferredFragmentRecord > {
646- return Array . from ( deferUsages ) . map ( ( deferUsage ) =>
647- this . _deferredFragmentRecordFromDeferUsage ( deferUsage , deferMap ) ,
648- ) ;
649- }
650-
651- private _deferredFragmentRecordFromDeferUsage (
652- deferUsage : DeferUsage ,
653- deferMap : ReadonlyMap < DeferUsage , DeferredFragmentRecord > ,
654- ) : DeferredFragmentRecord {
655- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
656- return deferMap . get ( deferUsage ) ! ;
657- }
658-
659560 private _publish ( subsequentResultRecord : SubsequentResultRecord ) : void {
660561 if ( isStreamItemsRecord ( subsequentResultRecord ) ) {
661562 if ( subsequentResultRecord . isCompleted ) {
@@ -734,6 +635,18 @@ export class IncrementalPublisher {
734635 }
735636}
736637
638+ function isDeferredGroupedFieldSetRecord (
639+ incrementalDataRecord : unknown ,
640+ ) : incrementalDataRecord is DeferredGroupedFieldSetRecord {
641+ return incrementalDataRecord instanceof DeferredGroupedFieldSetRecord ;
642+ }
643+
644+ function isStreamItemsRecord (
645+ subsequentResultRecord : unknown ,
646+ ) : subsequentResultRecord is StreamItemsRecord {
647+ return subsequentResultRecord instanceof StreamItemsRecord ;
648+ }
649+
737650/** @internal */
738651export class InitialResultRecord {
739652 errors : Array < GraphQLError > ;
@@ -795,16 +708,16 @@ export class StreamRecord {
795708 label : string | undefined ;
796709 path : ReadonlyArray < string | number > ;
797710 errors : Array < GraphQLError > ;
798- asyncIterator ?: AsyncIterator < unknown > | undefined ;
711+ earlyReturn ?: ( ( ) => Promise < unknown > ) | undefined ;
799712 constructor ( opts : {
800713 label : string | undefined ;
801714 path : Path ;
802- asyncIterator ?: AsyncIterator < unknown > | undefined ;
715+ earlyReturn ?: ( ( ) => Promise < unknown > ) | undefined ;
803716 } ) {
804717 this . label = opts . label ;
805718 this . path = pathToArray ( opts . path ) ;
806719 this . errors = [ ] ;
807- this . asyncIterator = opts . asyncIterator ;
720+ this . earlyReturn = opts . earlyReturn ;
808721 }
809722}
810723
@@ -819,7 +732,6 @@ export class StreamItemsRecord {
819732 isCompletedAsyncIterator ?: boolean ;
820733 isCompleted : boolean ;
821734 filtered : boolean ;
822- sent : boolean ;
823735
824736 constructor ( opts : { streamRecord : StreamRecord ; path : Path | undefined } ) {
825737 this . streamRecord = opts . streamRecord ;
@@ -829,7 +741,6 @@ export class StreamItemsRecord {
829741 this . isCompleted = false ;
830742 this . filtered = false ;
831743 this . items = [ ] ;
832- this . sent = false ;
833744 }
834745}
835746
@@ -839,15 +750,3 @@ export type IncrementalDataRecord =
839750 | StreamItemsRecord ;
840751
841752type SubsequentResultRecord = DeferredFragmentRecord | StreamItemsRecord ;
842-
843- function isDeferredGroupedFieldSetRecord (
844- incrementalDataRecord : unknown ,
845- ) : incrementalDataRecord is DeferredGroupedFieldSetRecord {
846- return incrementalDataRecord instanceof DeferredGroupedFieldSetRecord ;
847- }
848-
849- function isStreamItemsRecord (
850- subsequentResultRecord : unknown ,
851- ) : subsequentResultRecord is StreamItemsRecord {
852- return subsequentResultRecord instanceof StreamItemsRecord ;
853- }
0 commit comments