@@ -15,6 +15,7 @@ import {
1515import { getFragmentDependenciesForAST } from 'graphql-language-service' ;
1616import { ReactNode , useCallback , useMemo , useRef , useState } from 'react' ;
1717import setValue from 'set-value' ;
18+ import getValue from 'get-value' ;
1819
1920import { useAutoCompleteLeafs , useEditorContext } from './editor' ;
2021import { UseAutoCompleteLeafsArgs } from './editor/hooks' ;
@@ -343,31 +344,85 @@ type IncrementalResult = {
343344 incremental ?: ReadonlyArray < IncrementalResult > ;
344345 label ?: string ;
345346 items ?: ReadonlyArray < Record < string , unknown > > | null ;
347+ pending ?: ReadonlyArray < { id : string ; path : ReadonlyArray < string | number > } > ;
348+ completed ?: ReadonlyArray < {
349+ id : string ;
350+ errors ?: ReadonlyArray < GraphQLError > ;
351+ } > ;
352+ id ?: string ;
353+ subPath ?: ReadonlyArray < string | number > ;
346354} ;
347355
356+ const pathsMap = new WeakMap <
357+ ExecutionResult ,
358+ Map < string , ReadonlyArray < string | number > >
359+ > ( ) ;
360+
348361/**
349362 * @param executionResult The complete execution result object which will be
350363 * mutated by merging the contents of the incremental result.
351364 * @param incrementalResult The incremental result that will be merged into the
352365 * complete execution result.
353366 */
354- function mergeIncrementalResult (
355- executionResult : ExecutionResult ,
367+ export function mergeIncrementalResult (
368+ executionResult : IncrementalResult ,
356369 incrementalResult : IncrementalResult ,
357370) : void {
358- const path = [ 'data' , ...( incrementalResult . path ?? [ ] ) ] ;
359-
360- if ( incrementalResult . items ) {
361- for ( const item of incrementalResult . items ) {
362- setValue ( executionResult , path . join ( '.' ) , item ) ;
363- // Increment the last path segment (the array index) to merge the next item at the next index
364- // eslint-disable-next-line unicorn/prefer-at -- cannot mutate the array using Array.at()
365- ( path [ path . length - 1 ] as number ) ++ ;
371+ let path : ReadonlyArray < string | number > | undefined = [
372+ 'data' ,
373+ ...( incrementalResult . path ?? [ ] ) ,
374+ ] ;
375+
376+ for ( const result of [ executionResult , incrementalResult ] ) {
377+ if ( result . pending ) {
378+ let paths = pathsMap . get ( executionResult ) ;
379+ if ( paths === undefined ) {
380+ paths = new Map ( ) ;
381+ pathsMap . set ( executionResult , paths ) ;
382+ }
383+
384+ for ( const { id, path : pendingPath } of result . pending ) {
385+ paths . set ( id , [ 'data' , ...pendingPath ] ) ;
386+ }
366387 }
367388 }
368389
369- if ( incrementalResult . data ) {
370- setValue ( executionResult , path . join ( '.' ) , incrementalResult . data , {
390+ const { items } = incrementalResult ;
391+ if ( items ) {
392+ const { id } = incrementalResult ;
393+ if ( id ) {
394+ path = pathsMap . get ( executionResult ) ?. get ( id ) ;
395+ if ( path === undefined ) {
396+ throw new Error ( 'Invalid incremental delivery format.' ) ;
397+ }
398+
399+ const list = getValue ( executionResult , path . join ( '.' ) ) ;
400+ list . push ( ...items ) ;
401+ } else {
402+ path = [ 'data' , ...( incrementalResult . path ?? [ ] ) ] ;
403+ for ( const item of items ) {
404+ setValue ( executionResult , path . join ( '.' ) , item ) ;
405+ // Increment the last path segment (the array index) to merge the next item at the next index
406+ // eslint-disable-next-line unicorn/prefer-at -- cannot mutate the array using Array.at()
407+ ( path [ path . length - 1 ] as number ) ++ ;
408+ }
409+ }
410+ }
411+
412+ const { data } = incrementalResult ;
413+ if ( data ) {
414+ const { id } = incrementalResult ;
415+ if ( id ) {
416+ path = pathsMap . get ( executionResult ) ?. get ( id ) ;
417+ if ( path === undefined ) {
418+ throw new Error ( 'Invalid incremental delivery format.' ) ;
419+ }
420+ const { subPath } = incrementalResult ;
421+ if ( subPath !== undefined ) {
422+ path = [ ...path , ...subPath ] ;
423+ }
424+ }
425+ setValue ( executionResult , path . join ( '.' ) , data , {
371426 merge : true ,
372427 } ) ;
373428 }
@@ -390,4 +445,16 @@ function mergeIncrementalResult(
390445 mergeIncrementalResult ( executionResult , incrementalSubResult ) ;
391446 }
392447 }
448+
449+ if ( incrementalResult . completed ) {
450+ // Remove tracking and add additional errors
451+ for ( const { id, errors } of incrementalResult . completed ) {
452+ pathsMap . get ( executionResult ) ?. delete ( id ) ;
453+
454+ if ( errors ) {
455+ executionResult . errors ||= [ ] ;
456+ ( executionResult . errors as GraphQLError [ ] ) . push ( ...errors ) ;
457+ }
458+ }
459+ }
393460}
0 commit comments