@@ -100,7 +100,8 @@ export interface IncrementalDeferResult<
100
100
> {
101
101
errors ?: ReadonlyArray < GraphQLError > ;
102
102
data : TData ;
103
- path : ReadonlyArray < string | number > ;
103
+ id : string ;
104
+ subPath ?: ReadonlyArray < string | number > ;
104
105
extensions ?: TExtensions ;
105
106
}
106
107
@@ -110,7 +111,8 @@ export interface FormattedIncrementalDeferResult<
110
111
> {
111
112
errors ?: ReadonlyArray < GraphQLFormattedError > ;
112
113
data : TData ;
113
- path : ReadonlyArray < string | number > ;
114
+ id : string ;
115
+ subPath ?: ReadonlyArray < string | number > ;
114
116
extensions ?: TExtensions ;
115
117
}
116
118
@@ -120,7 +122,8 @@ export interface IncrementalStreamResult<
120
122
> {
121
123
errors ?: ReadonlyArray < GraphQLError > ;
122
124
items : TData ;
123
- path : ReadonlyArray < string | number > ;
125
+ id : string ;
126
+ subPath ?: ReadonlyArray < string | number > ;
124
127
extensions ?: TExtensions ;
125
128
}
126
129
@@ -130,7 +133,8 @@ export interface FormattedIncrementalStreamResult<
130
133
> {
131
134
errors ?: ReadonlyArray < GraphQLFormattedError > ;
132
135
items : TData ;
133
- path : ReadonlyArray < string | number > ;
136
+ id : string ;
137
+ subPath ?: ReadonlyArray < string | number > ;
134
138
extensions ?: TExtensions ;
135
139
}
136
140
@@ -146,13 +150,13 @@ export type FormattedIncrementalResult<
146
150
| FormattedIncrementalStreamResult < TData , TExtensions > ;
147
151
148
152
export interface PendingResult {
153
+ id : string ;
149
154
path : ReadonlyArray < string | number > ;
150
155
label ?: string ;
151
156
}
152
157
153
158
export interface CompletedResult {
154
- path : ReadonlyArray < string | number > ;
155
- label ?: string ;
159
+ id : string ;
156
160
errors ?: ReadonlyArray < GraphQLError > ;
157
161
}
158
162
@@ -178,6 +182,7 @@ export interface FormattedCompletedResult {
178
182
* @internal
179
183
*/
180
184
export class IncrementalPublisher {
185
+ private _nextId = 0 ;
181
186
private _released : Set < SubsequentResultRecord > ;
182
187
private _pending : Set < SubsequentResultRecord > ;
183
188
@@ -372,7 +377,10 @@ export class IncrementalPublisher {
372
377
const pendingResults : Array < PendingResult > = [ ] ;
373
378
for ( const pendingSource of pendingSources ) {
374
379
pendingSource . pendingSent = true ;
380
+ const id = this . _getNextId ( ) ;
381
+ pendingSource . id = id ;
375
382
const pendingResult : PendingResult = {
383
+ id,
376
384
path : pendingSource . path ,
377
385
} ;
378
386
if ( pendingSource . label !== undefined ) {
@@ -383,6 +391,10 @@ export class IncrementalPublisher {
383
391
return pendingResults ;
384
392
}
385
393
394
+ private _getNextId ( ) : string {
395
+ return String ( this . _nextId ++ ) ;
396
+ }
397
+
386
398
private _subscribe ( ) : AsyncGenerator <
387
399
SubsequentIncrementalExecutionResult ,
388
400
void ,
@@ -554,7 +566,9 @@ export class IncrementalPublisher {
554
566
}
555
567
const incrementalResult : IncrementalStreamResult = {
556
568
items : subsequentResultRecord . items ,
557
- path : subsequentResultRecord . streamRecord . path ,
569
+ // safe because `id` is defined once the stream has been released as pending
570
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
571
+ id : subsequentResultRecord . streamRecord . id ! ,
558
572
} ;
559
573
if ( subsequentResultRecord . errors . length > 0 ) {
560
574
incrementalResult . errors = subsequentResultRecord . errors ;
@@ -571,11 +585,8 @@ export class IncrementalPublisher {
571
585
for ( const deferredGroupedFieldSetRecord of subsequentResultRecord . deferredGroupedFieldSetRecords ) {
572
586
if ( ! deferredGroupedFieldSetRecord . sent ) {
573
587
deferredGroupedFieldSetRecord . sent = true ;
574
- const incrementalResult : IncrementalDeferResult = {
575
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
576
- data : deferredGroupedFieldSetRecord . data ! ,
577
- path : deferredGroupedFieldSetRecord . path ,
578
- } ;
588
+ const incrementalResult : IncrementalDeferResult =
589
+ this . _getIncrementalDeferResult ( deferredGroupedFieldSetRecord ) ;
579
590
if ( deferredGroupedFieldSetRecord . errors . length > 0 ) {
580
591
incrementalResult . errors = deferredGroupedFieldSetRecord . errors ;
581
592
}
@@ -592,15 +603,49 @@ export class IncrementalPublisher {
592
603
} ;
593
604
}
594
605
606
+ private _getIncrementalDeferResult (
607
+ deferredGroupedFieldSetRecord : DeferredGroupedFieldSetRecord ,
608
+ ) : IncrementalDeferResult {
609
+ const { data, deferredFragmentRecords } = deferredGroupedFieldSetRecord ;
610
+ let maxLength = deferredFragmentRecords [ 0 ] . path . length ;
611
+ let maxIndex = 0 ;
612
+ for ( let i = 1 ; i < deferredFragmentRecords . length ; i ++ ) {
613
+ const deferredFragmentRecord = deferredFragmentRecords [ i ] ;
614
+ const length = deferredFragmentRecord . path . length ;
615
+ if ( length > maxLength ) {
616
+ maxLength = length ;
617
+ maxIndex = i ;
618
+ }
619
+ }
620
+ const recordWithLongestPath = deferredFragmentRecords [ maxIndex ] ;
621
+ const longestPath = recordWithLongestPath . path ;
622
+ const subPath = deferredGroupedFieldSetRecord . path . slice (
623
+ longestPath . length ,
624
+ ) ;
625
+ const id = recordWithLongestPath . id ;
626
+ const incrementalDeferResult : IncrementalDeferResult = {
627
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
628
+ data : data ! ,
629
+ // safe because `id` is defined once the fragment has been released as pending
630
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
631
+ id : id ! ,
632
+ } ;
633
+
634
+ if ( subPath . length > 0 ) {
635
+ incrementalDeferResult . subPath = subPath ;
636
+ }
637
+
638
+ return incrementalDeferResult ;
639
+ }
640
+
595
641
private _completedRecordToResult (
596
642
completedRecord : DeferredFragmentRecord | StreamRecord ,
597
643
) : CompletedResult {
598
644
const result : CompletedResult = {
599
- path : completedRecord . path ,
645
+ // safe because `id` is defined once the stream has been released as pending
646
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
647
+ id : completedRecord . id ! ,
600
648
} ;
601
- if ( completedRecord . label !== undefined ) {
602
- result . label = completedRecord . label ;
603
- }
604
649
if ( completedRecord . errors . length > 0 ) {
605
650
result . errors = completedRecord . errors ;
606
651
}
@@ -736,6 +781,7 @@ export class DeferredGroupedFieldSetRecord {
736
781
export class DeferredFragmentRecord {
737
782
path : ReadonlyArray < string | number > ;
738
783
label : string | undefined ;
784
+ id : string | undefined ;
739
785
children : Set < SubsequentResultRecord > ;
740
786
deferredGroupedFieldSetRecords : Set < DeferredGroupedFieldSetRecord > ;
741
787
errors : Array < GraphQLError > ;
@@ -758,6 +804,7 @@ export class DeferredFragmentRecord {
758
804
export class StreamRecord {
759
805
label : string | undefined ;
760
806
path : ReadonlyArray < string | number > ;
807
+ id : string | undefined ;
761
808
errors : Array < GraphQLError > ;
762
809
earlyReturn ?: ( ( ) => Promise < unknown > ) | undefined ;
763
810
pendingSent ?: boolean ;
0 commit comments