Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(graphcache): Cascade `@defer`, `@_optional`, and `@_required` state only per nested fragment spread (#3517)

authored by

Phil Pluckthun and committed by
GitHub
e9b476b6 ceeb73bb

+43 -18
+5
.changeset/sixty-needles-exercise.md
··· 1 + --- 2 + '@urql/exchange-graphcache': patch 3 + --- 4 + 5 + Prevent `@defer` from being applied in child field selections. Previously, a child field (i.e. a nested field) under a `@defer`-ed fragment would also become optional, which was based on a prior version of the DeferStream spec which didn't require deferred fields to be delivered as a group.
+4 -2
exchanges/graphcache/src/cacheExchange.test.ts
··· 909 909 todos { 910 910 id 911 911 text 912 - ... on Todo @_optional { 913 - completed 912 + ... @_optional { 913 + ... on Todo { 914 + completed 915 + } 914 916 } 915 917 } 916 918 }
+2 -2
exchanges/graphcache/src/operations/query.ts
··· 145 145 const iterate = makeSelectionIterator( 146 146 entityKey, 147 147 entityKey, 148 - deferRef, 148 + false, 149 149 undefined, 150 150 select, 151 151 ctx ··· 390 390 const iterate = makeSelectionIterator( 391 391 typename, 392 392 entityKey, 393 - deferRef, 393 + false, 394 394 undefined, 395 395 select, 396 396 ctx
+31 -13
exchanges/graphcache/src/operations/shared.ts
··· 71 71 entityKey: string, 72 72 error: CombinedError | undefined 73 73 ): Context => { 74 - deferRef = false; 75 - 76 74 const ctx: Context = { 77 75 store, 78 76 variables, ··· 163 161 (): FormattedNode<FieldNode> | undefined; 164 162 } 165 163 166 - export const makeSelectionIterator = ( 167 - typename: void | string, 164 + // NOTE: Outside of this file, we expect `_defer` to always be reset to `false` 165 + export function makeSelectionIterator( 166 + typename: undefined | string, 167 + entityKey: string, 168 + _defer: false, 169 + _optional: undefined, 170 + selectionSet: FormattedNode<SelectionSet>, 171 + ctx: Context 172 + ): SelectionIterator; 173 + // NOTE: Inside this file we expect the state to be recursively passed on 174 + export function makeSelectionIterator( 175 + typename: undefined | string, 168 176 entityKey: string, 169 - defer: boolean, 170 - optional: boolean | undefined, 177 + _defer: boolean, 178 + _optional: undefined | boolean, 171 179 selectionSet: FormattedNode<SelectionSet>, 172 180 ctx: Context 173 - ): SelectionIterator => { 181 + ): SelectionIterator; 182 + 183 + export function makeSelectionIterator( 184 + typename: undefined | string, 185 + entityKey: string, 186 + _defer: boolean, 187 + _optional: boolean | undefined, 188 + selectionSet: FormattedNode<SelectionSet>, 189 + ctx: Context 190 + ): SelectionIterator { 174 191 let child: SelectionIterator | void; 175 192 let index = 0; 176 193 ··· 178 195 let node: FormattedNode<FieldNode> | undefined; 179 196 while (child || index < selectionSet.length) { 180 197 node = undefined; 181 - deferRef = defer; 182 - optionalRef = optional; 198 + deferRef = _defer; 199 + optionalRef = _optional; 183 200 if (child) { 184 201 if ((node = child())) { 185 202 return node; ··· 212 229 if (isMatching) { 213 230 if (process.env.NODE_ENV !== 'production') 214 231 pushDebugNode(typename, fragment); 215 - 216 232 const isFragmentOptional = isOptional(select); 217 233 child = makeSelectionIterator( 218 234 typename, 219 235 entityKey, 220 - defer || isDeferred(select, ctx.variables), 221 - isFragmentOptional, 236 + _defer || isDeferred(select, ctx.variables), 237 + isFragmentOptional !== undefined 238 + ? isFragmentOptional 239 + : _optional, 222 240 getSelectionSet(fragment), 223 241 ctx 224 242 ); ··· 230 248 } 231 249 } 232 250 }; 233 - }; 251 + } 234 252 235 253 export const ensureData = (x: DataField): Data | NullArray<Data> | null => 236 254 x == null ? null : (x as Data | NullArray<Data>);
+1 -1
exchanges/graphcache/src/operations/write.ts
··· 239 239 const iterate = makeSelectionIterator( 240 240 typename, 241 241 entityKey || typename, 242 - deferRef, 242 + false, 243 243 undefined, 244 244 select, 245 245 ctx