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.

refactor(core): Refactor hasNext/stale on OperationResult to be required (#3061)

authored by

Phil Pluckthun and committed by
GitHub
2fc98429 7222ee10

+266 -56
+7
.changeset/four-boxes-impress.md
··· 1 + --- 2 + '@urql/exchange-graphcache': major 3 + '@urql/svelte': major 4 + '@urql/core': major 5 + --- 6 + 7 + Update `OperationResult.hasNext` and `OperationResult.stale` to be required fields. If you have a custom exchange creating results, you'll have to add these fields or use the `makeResult`, `mergeResultPatch`, or `makeErrorResult` helpers.
+7 -2
exchanges/auth/src/authExchange.test.ts
··· 21 21 22 22 import { vi, expect, it } from 'vitest'; 23 23 import { print } from 'graphql'; 24 - import { queryOperation } from '../../../packages/core/src/test-utils'; 24 + import { 25 + queryResponse, 26 + queryOperation, 27 + } from '../../../packages/core/src/test-utils'; 25 28 import { authExchange } from './authExchange'; 26 29 27 30 const makeExchangeArgs = () => { 28 31 const operations: Operation[] = []; 29 32 const result = vi.fn( 30 - (operation: Operation): OperationResult => ({ operation }) 33 + (operation: Operation): OperationResult => ({ ...queryResponse, operation }) 31 34 ); 32 35 33 36 return { ··· 247 250 await new Promise(resolve => setTimeout(resolve)); 248 251 249 252 result.mockReturnValueOnce({ 253 + ...queryResponse, 250 254 operation: queryOperation, 255 + data: undefined, 251 256 error: new CombinedError({ 252 257 graphQLErrors: [{ message: 'Oops' }], 253 258 }),
+3
exchanges/context/src/context.test.ts
··· 9 9 ExchangeIO, 10 10 } from '@urql/core'; 11 11 12 + import { queryResponse } from '../../../packages/core/src/test-utils'; 12 13 import { contextExchange } from './context'; 13 14 14 15 const queryOne = gql` ··· 48 49 const response = vi.fn( 49 50 (forwardOp: Operation): OperationResult => { 50 51 return { 52 + ...queryResponse, 51 53 operation: forwardOp, 52 54 data: queryOneData, 53 55 }; ··· 83 85 const response = vi.fn( 84 86 (forwardOp: Operation): OperationResult => { 85 87 return { 88 + ...queryResponse, 86 89 operation: forwardOp, 87 90 data: queryOneData, 88 91 };
+1
exchanges/execute/src/execute.test.ts
··· 272 272 operation: queryOperation, 273 273 data: mockHttpResponseData, 274 274 hasNext: false, 275 + stale: false, 275 276 }); 276 277 }); 277 278 });
+107 -27
exchanges/graphcache/src/cacheExchange.test.ts
··· 6 6 OperationResult, 7 7 CombinedError, 8 8 } from '@urql/core'; 9 + 9 10 import { vi, expect, it, describe } from 'vitest'; 10 11 11 12 import { ··· 23 24 } from 'wonka'; 24 25 25 26 import { minifyIntrospectionQuery } from '@urql/introspection'; 27 + import { queryResponse } from '../../../packages/core/src/test-utils'; 26 28 import { cacheExchange } from './cacheExchange'; 27 29 28 30 const queryOne = gql` ··· 80 82 const response = vi.fn( 81 83 (forwardOp: Operation): OperationResult => { 82 84 expect(forwardOp.key).toBe(op.key); 83 - return { operation: forwardOp, data: expected }; 85 + return { ...queryResponse, operation: forwardOp, data: expected }; 84 86 } 85 87 ); 86 88 ··· 133 135 const response = vi.fn( 134 136 (forwardOp: Operation): OperationResult => { 135 137 expect(forwardOp.key).toBe(op.key); 136 - return { operation: forwardOp, data: queryOneData }; 138 + return { ...queryResponse, operation: forwardOp, data: queryOneData }; 137 139 } 138 140 ); 139 141 ··· 205 207 const response = vi.fn( 206 208 (forwardOp: Operation): OperationResult => { 207 209 if (forwardOp.key === 1) { 208 - return { operation: opOne, data: queryOneData }; 210 + return { ...queryResponse, operation: opOne, data: queryOneData }; 209 211 } else if (forwardOp.key === 2) { 210 - return { operation: opMultiple, data: queryMultipleData }; 212 + return { 213 + ...queryResponse, 214 + operation: opMultiple, 215 + data: queryMultipleData, 216 + }; 211 217 } 212 218 213 219 return undefined as any; ··· 344 350 const response = vi.fn( 345 351 (forwardOp: Operation): OperationResult => { 346 352 if (forwardOp.key === 1) { 347 - return { operation: opOne, data: queryByIdDataA }; 353 + return { ...queryResponse, operation: opOne, data: queryByIdDataA }; 348 354 } else if (forwardOp.key === 2) { 349 - return { operation: opTwo, data: queryByIdDataB }; 355 + return { ...queryResponse, operation: opTwo, data: queryByIdDataB }; 350 356 } else if (forwardOp.key === 3) { 351 - return { operation: opMutation, data: mutationData }; 357 + return { 358 + ...queryResponse, 359 + operation: opMutation, 360 + data: mutationData, 361 + }; 352 362 } 353 363 354 364 return undefined as any; ··· 446 456 const response = vi.fn( 447 457 (forwardOp: Operation): OperationResult => { 448 458 if (forwardOp.key === 1) { 449 - return { operation: opOne, data: queryOneData }; 459 + return { ...queryResponse, operation: opOne, data: queryOneData }; 450 460 } else if (forwardOp.key === 2) { 451 - return { operation: opUnrelated, data: queryUnrelatedData }; 461 + return { 462 + ...queryResponse, 463 + operation: opUnrelated, 464 + data: queryUnrelatedData, 465 + }; 452 466 } 453 467 454 468 return undefined as any; ··· 505 519 const response = vi.fn( 506 520 (forwardOp: Operation): OperationResult => { 507 521 if (forwardOp.key === 1) { 508 - return { operation: opMutation, data: mutationData }; 522 + return { 523 + ...queryResponse, 524 + operation: opMutation, 525 + data: mutationData, 526 + }; 509 527 } 510 528 511 529 return undefined as any; ··· 565 583 const response = vi.fn( 566 584 (forwardOp: Operation): OperationResult => { 567 585 if (forwardOp.key === 1) { 568 - return { operation: opMutation, data: mutationData }; 586 + return { 587 + ...queryResponse, 588 + operation: opMutation, 589 + data: mutationData, 590 + }; 569 591 } 570 592 571 593 return undefined as any; ··· 626 648 }); 627 649 628 650 const queryResult: OperationResult = { 651 + ...queryResponse, 629 652 operation, 630 653 data: { 631 654 __typename: 'Query', ··· 729 752 const response = vi.fn( 730 753 (forwardOp: Operation): OperationResult => { 731 754 if (forwardOp.key === 1) { 732 - return { operation: opOne, data: queryOneData }; 755 + return { ...queryResponse, operation: opOne, data: queryOneData }; 733 756 } else if (forwardOp.key === 2) { 734 - return { operation: opMutation, data: mutationData }; 757 + return { 758 + ...queryResponse, 759 + operation: opMutation, 760 + data: mutationData, 761 + }; 735 762 } 736 763 737 764 return undefined as any; ··· 831 858 const response = vi.fn( 832 859 (forwardOp: Operation): OperationResult => { 833 860 if (forwardOp.key === 1) { 834 - return { operation: opOne, data: queryOneData }; 861 + return { ...queryResponse, operation: opOne, data: queryOneData }; 835 862 } else if (forwardOp.key === 2) { 836 - return { operation: opMutationOne, data: mutationData }; 863 + return { 864 + ...queryResponse, 865 + operation: opMutationOne, 866 + data: mutationData, 867 + }; 837 868 } else if (forwardOp.key === 3) { 838 - return { operation: opMutationTwo, data: mutationData }; 869 + return { 870 + ...queryResponse, 871 + operation: opMutationTwo, 872 + data: mutationData, 873 + }; 839 874 } 840 875 841 876 return undefined as any; ··· 931 966 const response = vi.fn( 932 967 (forwardOp: Operation): OperationResult => { 933 968 if (forwardOp.key === 1) { 934 - return { operation: opOne, data: queryOneData }; 969 + return { ...queryResponse, operation: opOne, data: queryOneData }; 935 970 } 936 971 937 972 return undefined as any; ··· 1045 1080 const response = vi.fn( 1046 1081 (forwardOp: Operation): OperationResult => { 1047 1082 if (forwardOp.key === 1) { 1048 - return { operation: opOne, data: authorsQueryData }; 1083 + return { ...queryResponse, operation: opOne, data: authorsQueryData }; 1049 1084 } else if (forwardOp.key === 2) { 1050 1085 return { 1086 + ...queryResponse, 1051 1087 operation: opMutation, 1052 1088 error: 'error' as any, 1053 1089 data: { __typename: 'Mutation', addAuthor: null }, ··· 1121 1157 const response = vi.fn( 1122 1158 (forwardOp: Operation): OperationResult => { 1123 1159 if (forwardOp.key === 1) { 1124 - return { operation: opOne, data: queryOneData }; 1160 + return { ...queryResponse, operation: opOne, data: queryOneData }; 1125 1161 } 1126 1162 1127 1163 return undefined as any; ··· 1203 1239 const response = vi.fn( 1204 1240 (forwardOp: Operation): OperationResult => { 1205 1241 if (forwardOp.key === 1) { 1206 - return { operation: opOne, data: queryOneData }; 1242 + return { ...queryResponse, operation: opOne, data: queryOneData }; 1207 1243 } else if (forwardOp.key === 2) { 1208 - return { operation: opMutation, data: mutationData }; 1244 + return { 1245 + ...queryResponse, 1246 + operation: opMutation, 1247 + data: mutationData, 1248 + }; 1209 1249 } 1210 1250 1211 1251 return undefined as any; ··· 1349 1389 const response = vi.fn( 1350 1390 (forwardOp: Operation): OperationResult => { 1351 1391 if (forwardOp.key === 1) { 1352 - return { operation: queryOperation, data: queryData }; 1392 + return { 1393 + ...queryResponse, 1394 + operation: queryOperation, 1395 + data: queryData, 1396 + }; 1353 1397 } else if (forwardOp.key === 2) { 1354 - return { operation: mutationOperation, data: mutationData }; 1398 + return { 1399 + ...queryResponse, 1400 + operation: mutationOperation, 1401 + data: mutationData, 1402 + }; 1355 1403 } 1356 1404 1357 1405 return undefined as any; ··· 1506 1554 const response = vi.fn( 1507 1555 (forwardOp: Operation): OperationResult => { 1508 1556 if (forwardOp.key === 1) { 1509 - return { operation: initialQueryOperation, data: queryData }; 1557 + return { 1558 + ...queryResponse, 1559 + operation: initialQueryOperation, 1560 + data: queryData, 1561 + }; 1510 1562 } else if (forwardOp.key === 2) { 1511 - return { operation: queryOperation, data: queryData }; 1563 + return { 1564 + ...queryResponse, 1565 + operation: queryOperation, 1566 + data: queryData, 1567 + }; 1512 1568 } 1513 1569 1514 1570 return undefined as any; ··· 1643 1699 const response = vi.fn( 1644 1700 (forwardOp: Operation): OperationResult => { 1645 1701 if (forwardOp.key === 1) { 1646 - return { operation: initialQueryOperation, data: queryData }; 1702 + return { 1703 + ...queryResponse, 1704 + operation: initialQueryOperation, 1705 + data: queryData, 1706 + }; 1647 1707 } else if (forwardOp.key === 2) { 1648 - return { operation: queryOperation, data: queryData }; 1708 + return { 1709 + ...queryResponse, 1710 + operation: queryOperation, 1711 + data: queryData, 1712 + }; 1649 1713 } 1650 1714 1651 1715 return undefined as any; ··· 1724 1788 const result = (operation: Operation): Source<OperationResult> => 1725 1789 pipe( 1726 1790 fromValue({ 1791 + ...queryResponse, 1727 1792 operation, 1728 1793 data: { 1729 1794 __typename: 'Query', ··· 1871 1936 nextOp(queryOpA); 1872 1937 1873 1938 nextRes({ 1939 + ...queryResponse, 1874 1940 operation: queryOpA, 1875 1941 data: { 1876 1942 __typename: 'Query', ··· 1964 2030 nextOp(queryOpB); 1965 2031 1966 2032 nextRes({ 2033 + ...queryResponse, 1967 2034 operation: queryOpA, 1968 2035 data: { 1969 2036 __typename: 'Query', ··· 1978 2045 expect(data).toHaveProperty('node.name', 'query a'); 1979 2046 1980 2047 nextRes({ 2048 + ...queryResponse, 1981 2049 operation: mutationOp, 1982 2050 data: { 1983 2051 __typename: 'Mutation', ··· 1993 2061 expect(data).toHaveProperty('node.name', 'mutation'); 1994 2062 1995 2063 nextRes({ 2064 + ...queryResponse, 1996 2065 operation: queryOpB, 1997 2066 data: { 1998 2067 __typename: 'Query', ··· 2082 2151 nextOp(mutationOp); 2083 2152 2084 2153 nextRes({ 2154 + ...queryResponse, 2085 2155 operation: queryOp, 2086 2156 data: { 2087 2157 __typename: 'Query', ··· 2096 2166 expect(data).toHaveProperty('node.name', 'optimistic'); 2097 2167 2098 2168 nextRes({ 2169 + ...queryResponse, 2099 2170 operation: mutationOp, 2100 2171 data: { 2101 2172 __typename: 'Query', ··· 2183 2254 nextOp(subscriptionOp); 2184 2255 2185 2256 nextRes({ 2257 + ...queryResponse, 2186 2258 operation: queryOpA, 2187 2259 data: { 2188 2260 __typename: 'Query', ··· 2195 2267 }); 2196 2268 2197 2269 nextRes({ 2270 + ...queryResponse, 2198 2271 operation: subscriptionOp, 2199 2272 data: { 2200 2273 node: { ··· 2296 2369 nextOp(subscriptionOp); 2297 2370 2298 2371 nextRes({ 2372 + ...queryResponse, 2299 2373 operation: queryOpA, 2300 2374 data: { 2301 2375 __typename: 'Query', ··· 2310 2384 nextOp(mutationOp); 2311 2385 2312 2386 nextRes({ 2387 + ...queryResponse, 2313 2388 operation: mutationOp, 2314 2389 data: { 2315 2390 node: { ··· 2321 2396 }); 2322 2397 2323 2398 nextRes({ 2399 + ...queryResponse, 2324 2400 operation: subscriptionOp, 2325 2401 data: { 2326 2402 node: { ··· 2332 2408 }); 2333 2409 2334 2410 nextRes({ 2411 + ...queryResponse, 2335 2412 operation: subscriptionOp, 2336 2413 data: { 2337 2414 node: { ··· 2440 2517 nextOp(normalOp); 2441 2518 2442 2519 nextRes({ 2520 + ...queryResponse, 2443 2521 operation: deferredOp, 2444 2522 data: { 2445 2523 __typename: 'Query', ··· 2450 2528 expect(deferredData).not.toHaveProperty('deferred'); 2451 2529 2452 2530 nextRes({ 2531 + ...queryResponse, 2453 2532 operation: normalOp, 2454 2533 data: { 2455 2534 __typename: 'Query', ··· 2466 2545 expect(combinedData).toHaveProperty('node.id', 2); 2467 2546 2468 2547 nextRes({ 2548 + ...queryResponse, 2469 2549 operation: deferredOp, 2470 2550 data: { 2471 2551 __typename: 'Query',
+3 -2
exchanges/graphcache/src/cacheExchange.ts
··· 26 26 import { Store, noopDataState, hydrateData, reserveLayer } from './store'; 27 27 import { Data, Dependencies, CacheExchangeOpts } from './types'; 28 28 29 - type OperationResultWithMeta = OperationResult & { 29 + interface OperationResultWithMeta extends Partial<OperationResult> { 30 + operation: Operation; 30 31 outcome: CacheOutcome; 31 32 dependencies: Dependencies; 32 - }; 33 + } 33 34 34 35 type Operations = Set<number>; 35 36 type OperationMap = Map<number, Operation>;
+8 -2
exchanges/graphcache/src/offlineExchange.test.ts
··· 9 9 import { vi, expect, it, describe } from 'vitest'; 10 10 11 11 import { pipe, map, makeSubject, tap, publish } from 'wonka'; 12 + import { queryResponse } from '../../../packages/core/src/test-utils'; 12 13 import { offlineExchange } from './offlineExchange'; 13 14 14 15 const mutationOne = gql` ··· 79 80 const response = vi.fn( 80 81 (forwardOp: Operation): OperationResult => { 81 82 expect(forwardOp.key).toBe(op.key); 82 - return { operation: forwardOp, data: mutationOneData }; 83 + return { 84 + ...queryResponse, 85 + operation: forwardOp, 86 + data: mutationOneData, 87 + }; 83 88 } 84 89 ); 85 90 ··· 125 130 (forwardOp: Operation): OperationResult => { 126 131 if (forwardOp.key === queryOp.key) { 127 132 onlineSpy.mockReturnValueOnce(true); 128 - return { operation: forwardOp, data: queryOneData }; 133 + return { ...queryResponse, operation: forwardOp, data: queryOneData }; 129 134 } else { 130 135 onlineSpy.mockReturnValueOnce(false); 131 136 return { 137 + ...queryResponse, 132 138 operation: forwardOp, 133 139 // @ts-ignore 134 140 error: { networkError: new Error('failed to fetch') },
+7
exchanges/multipart-fetch/src/__snapshots__/multipartFetchExchange.test.ts.snap
··· 5 5 "data": undefined, 6 6 "error": [CombinedError: [Network] No Content], 7 7 "extensions": undefined, 8 + "hasNext": false, 8 9 "operation": { 9 10 "context": { 10 11 "fetchOptions": { ··· 141 142 "name": "Clara", 142 143 }, 143 144 }, 145 + "stale": false, 144 146 } 145 147 `; 146 148 ··· 149 151 "data": undefined, 150 152 "error": [CombinedError: [Network] No Content], 151 153 "extensions": undefined, 154 + "hasNext": false, 152 155 "operation": { 153 156 "context": { 154 157 "fetchOptions": [MockFunction spy] { ··· 295 298 "name": "Clara", 296 299 }, 297 300 }, 301 + "stale": false, 298 302 } 299 303 `; 300 304 ··· 452 456 "name": "Clara", 453 457 }, 454 458 }, 459 + "stale": false, 455 460 } 456 461 `; 457 462 ··· 587 592 "picture": File {}, 588 593 }, 589 594 }, 595 + "stale": false, 590 596 } 591 597 `; 592 598 ··· 728 734 ], 729 735 }, 730 736 }, 737 + "stale": false, 731 738 } 732 739 `; 733 740
+2
exchanges/refocus/src/refocusExchange.test.ts
··· 9 9 ExchangeIO, 10 10 } from '@urql/core'; 11 11 12 + import { queryResponse } from '../../../packages/core/src/test-utils'; 12 13 import { refocusExchange } from './refocusExchange'; 13 14 14 15 const dispatchDebug = vi.fn(); ··· 49 50 const response = vi.fn( 50 51 (forwardOp: Operation): OperationResult => { 51 52 return { 53 + ...queryResponse, 52 54 operation: forwardOp, 53 55 data: queryOneData, 54 56 };
+3
exchanges/request-policy/src/requestPolicyExchange.test.ts
··· 9 9 ExchangeIO, 10 10 } from '@urql/core'; 11 11 12 + import { queryResponse } from '../../../packages/core/src/test-utils'; 12 13 import { requestPolicyExchange } from './requestPolicyExchange'; 13 14 14 15 const dispatchDebug = vi.fn(); ··· 53 54 const response = vi.fn( 54 55 (forwardOp: Operation): OperationResult => { 55 56 return { 57 + ...queryResponse, 56 58 operation: forwardOp, 57 59 data: queryOneData, 58 60 }; ··· 99 101 const response = vi.fn( 100 102 (forwardOp: Operation): OperationResult => { 101 103 return { 104 + ...queryResponse, 102 105 operation: forwardOp, 103 106 data: queryOneData, 104 107 };
+48 -5
packages/core/src/client.test.ts
··· 375 375 } 376 376 }), 377 377 map(op => ({ 378 + stale: false, 379 + hasNext: false, 378 380 data: op.key, 379 381 operation: op, 380 382 })) ··· 430 432 ops$, 431 433 filter(op => op.kind !== 'teardown'), 432 434 map(op => ({ 435 + hasNext: false, 436 + stale: false, 433 437 data: ++countRes, 434 438 operation: op, 435 439 })), ··· 482 486 483 487 expect(output.length).toBe(3); 484 488 expect(output[2]).toHaveProperty('data', 2); 485 - expect(output[2]).not.toHaveProperty('stale'); 489 + expect(output[2]).toHaveProperty('stale', false); 486 490 expect(output[2]).toHaveProperty('operation.key', queryOperation.key); 487 491 expect(output[2]).toHaveProperty( 488 492 'operation.context.requestPolicy', ··· 502 506 data: 1, 503 507 operation: op, 504 508 stale: true, 509 + hasNext: false, 505 510 })), 506 511 delay(1) 507 512 ); ··· 565 570 return pipe( 566 571 ops$, 567 572 map(op => ({ 573 + hasNext: false, 574 + stale: false, 568 575 data: ++i, 569 576 operation: op, 570 577 })), ··· 590 597 expect(resultOne).toHaveBeenCalledWith({ 591 598 data: 1, 592 599 operation: queryOperation, 600 + stale: false, 601 + hasNext: false, 593 602 }); 594 603 595 604 pipe(client.executeRequestOperation(queryOperation), subscribe(resultTwo)); ··· 597 606 expect(resultTwo).toHaveBeenCalledWith({ 598 607 data: 1, 599 608 operation: queryOperation, 609 + stale: false, 610 + hasNext: false, 600 611 }); 601 612 602 613 vi.advanceTimersByTime(1); ··· 611 622 return pipe( 612 623 ops$, 613 624 map(op => ({ 625 + hasNext: false, 626 + stale: false, 614 627 data: ++i, 615 628 operation: op, 616 629 })), ··· 644 657 expect(resultOne).toHaveBeenCalledWith({ 645 658 data: 1, 646 659 operation: operationOne, 660 + hasNext: false, 661 + stale: false, 647 662 }); 648 663 649 664 pipe(client.executeRequestOperation(operationTwo), subscribe(resultTwo)); ··· 652 667 data: 1, 653 668 operation: operationOne, 654 669 stale: true, 670 + hasNext: false, 655 671 }); 656 672 657 673 vi.advanceTimersByTime(1); ··· 659 675 expect(resultTwo).toHaveBeenCalledWith({ 660 676 data: 2, 661 677 operation: operationTwo, 678 + stale: false, 679 + hasNext: false, 662 680 }); 663 681 }); 664 682 ··· 668 686 return pipe( 669 687 ops$, 670 688 map(op => ({ 689 + hasNext: false, 690 + stale: false, 671 691 data: ++i, 672 692 operation: op, 673 693 })), ··· 698 718 expect(resultOne).toHaveBeenCalledWith({ 699 719 data: 1, 700 720 operation, 721 + stale: false, 722 + hasNext: false, 701 723 }); 702 724 703 725 pipe(client.executeRequestOperation(operation), subscribe(resultTwo)); ··· 706 728 data: 1, 707 729 operation, 708 730 stale: true, 731 + hasNext: false, 709 732 }); 710 733 711 734 vi.advanceTimersByTime(1); ··· 716 739 expect(resultTwo).toHaveBeenCalledWith({ 717 740 data: 2, 718 741 operation, 742 + stale: false, 743 + hasNext: false, 719 744 }); 720 745 }); 721 746 ··· 726 751 ops$, 727 752 filter(op => op.kind !== 'teardown'), 728 753 map(op => ({ 754 + hasNext: false, 755 + stale: false, 729 756 data: ++i, 730 757 operation: op, 731 758 })), ··· 751 778 expect(resultOne).toHaveBeenCalledWith({ 752 779 data: 1, 753 780 operation: queryOperation, 781 + hasNext: false, 782 + stale: false, 754 783 }); 755 784 756 785 subscription.unsubscribe(); ··· 763 792 expect(resultTwo).toHaveBeenCalledWith({ 764 793 data: 2, 765 794 operation: queryOperation, 795 + stale: false, 796 + hasNext: false, 766 797 }); 767 798 }); 768 799 ··· 774 805 map(op => ({ 775 806 data: ++i, 776 807 operation: op, 808 + hasNext: false, 809 + stale: false, 777 810 })), 778 811 take(1) 779 812 ); ··· 800 833 data: 1, 801 834 operation, 802 835 stale: true, 836 + hasNext: false, 803 837 }); 804 838 }); 805 839 ··· 807 841 const exchange: Exchange = () => ops$ => { 808 842 return pipe( 809 843 ops$, 810 - map(op => ({ data: 1, operation: op })), 844 + map(op => ({ hasNext: false, stale: false, data: 1, operation: op })), 811 845 filter(() => false) 812 846 ); 813 847 }; ··· 833 867 let i = 0; 834 868 return pipe( 835 869 ops$, 836 - map(op => ({ data: ++i, operation: op })) 870 + map(op => ({ hasNext: false, stale: false, data: ++i, operation: op })) 837 871 ); 838 872 }; 839 873 ··· 855 889 expect(resultOne).toHaveBeenCalledWith({ 856 890 data: 1, 857 891 operation, 892 + hasNext: false, 893 + stale: false, 858 894 }); 859 895 860 896 pipe(client.executeRequestOperation(operation), subscribe(resultTwo)); ··· 862 898 expect(resultTwo).toHaveBeenCalledWith({ 863 899 data: 2, 864 900 operation, 901 + hasNext: false, 902 + stale: false, 865 903 }); 866 904 867 905 expect(resultOne).toHaveBeenCalledWith({ 868 906 data: 2, 869 907 operation, 908 + hasNext: false, 909 + stale: false, 870 910 }); 871 911 }); 872 912 ··· 874 914 const exchange: Exchange = () => ops$ => { 875 915 return pipe( 876 916 ops$, 877 - map(op => ({ stale: true, data: 1, operation: op })), 917 + map(op => ({ hasNext: false, stale: true, data: 1, operation: op })), 878 918 take(1) 879 919 ); 880 920 }; ··· 893 933 data: 1, 894 934 operation: queryOperation, 895 935 stale: true, 936 + hasNext: false, 896 937 }); 897 938 898 939 pipe(client.executeRequestOperation(queryOperation), subscribe(resultTwo)); ··· 901 942 data: 1, 902 943 operation: queryOperation, 903 944 stale: true, 945 + hasNext: false, 904 946 }); 905 947 }); 906 948 ··· 941 983 const exchange: Exchange = () => ops$ => { 942 984 return pipe( 943 985 ops$, 944 - map(op => ({ stale: true, data: 1, operation: op })) 986 + map(op => ({ hasNext: false, stale: true, data: 1, operation: op })) 945 987 ); 946 988 }; 947 989 ··· 960 1002 data: 1, 961 1003 operation: queryOperation, 962 1004 stale: true, 1005 + hasNext: false, 963 1006 }); 964 1007 }); 965 1008 });
+5
packages/core/src/exchanges/__snapshots__/fetch.test.ts.snap
··· 5 5 "data": undefined, 6 6 "error": [CombinedError: [Network] No Content], 7 7 "extensions": undefined, 8 + "hasNext": false, 8 9 "operation": { 9 10 "context": { 10 11 "fetchOptions": { ··· 141 142 "name": "Clara", 142 143 }, 143 144 }, 145 + "stale": false, 144 146 } 145 147 `; 146 148 ··· 149 151 "data": undefined, 150 152 "error": [CombinedError: [Network] No Content], 151 153 "extensions": undefined, 154 + "hasNext": false, 152 155 "operation": { 153 156 "context": { 154 157 "fetchOptions": [MockFunction spy] { ··· 295 298 "name": "Clara", 296 299 }, 297 300 }, 301 + "stale": false, 298 302 } 299 303 `; 300 304 ··· 452 456 "name": "Clara", 453 457 }, 454 458 }, 459 + "stale": false, 455 460 } 456 461 `; 457 462
+1
packages/core/src/exchanges/__snapshots__/subscription.test.ts.snap
··· 118 118 "user": "colin", 119 119 }, 120 120 }, 121 + "stale": false, 121 122 } 122 123 `;
+9 -6
packages/core/src/exchanges/cache.ts
··· 76 76 }), 77 77 }); 78 78 79 - const result: OperationResult = { 80 - ...cachedResult, 81 - operation: addMetadata(operation, { 82 - cacheOutcome: cachedResult ? 'hit' : 'miss', 83 - }), 84 - }; 79 + let result: OperationResult = cachedResult!; 80 + if (process.env.NODE_ENV !== 'production') { 81 + result = { 82 + ...result, 83 + operation: addMetadata(operation, { 84 + cacheOutcome: cachedResult ? 'hit' : 'miss', 85 + }), 86 + }; 87 + } 85 88 86 89 if (operation.context.requestPolicy === 'cache-and-network') { 87 90 result.stale = true;
+2 -2
packages/core/src/exchanges/map.test.ts
··· 2 2 import { vi, expect, describe, it } from 'vitest'; 3 3 4 4 import { Client } from '../client'; 5 - import { queryOperation } from '../test-utils'; 5 + import { queryResponse, queryOperation } from '../test-utils'; 6 6 import { Operation } from '../types'; 7 7 import { mapExchange } from './map'; 8 8 ··· 210 210 forward: op$ => 211 211 pipe( 212 212 op$, 213 - map((operation: Operation) => ({ operation })) 213 + map((operation: Operation) => ({ ...queryResponse, operation })) 214 214 ), 215 215 client: {} as Client, 216 216 dispatchDebug: () => null,
+11 -6
packages/core/src/exchanges/ssr.test.ts
··· 47 47 [queryOperation.key]: { 48 48 data: serializedQueryResponse.data, 49 49 error: undefined, 50 + hasNext: false, 50 51 }, 51 52 }); 52 53 }); 53 54 54 55 it('serializes query results quickly', () => { 55 - const queryResponse: OperationResult = { 56 + const result: OperationResult = { 57 + ...queryResponse, 56 58 operation: queryOperation, 57 59 data: { 58 60 user: { ··· 62 64 }; 63 65 64 66 const serializedQueryResponse = { 65 - ...queryResponse, 66 - data: JSON.stringify(queryResponse.data), 67 + ...result, 68 + data: JSON.stringify(result.data), 67 69 }; 68 70 69 - output.mockReturnValueOnce(queryResponse); 71 + output.mockReturnValueOnce(result); 70 72 71 73 const ssr = ssrExchange(); 72 74 const { source: ops$, next } = input; ··· 74 76 75 77 publish(exchange); 76 78 next(queryOperation); 77 - queryResponse.data.user.name = 'Not Clive'; 79 + result.data.user.name = 'Not Clive'; 78 80 79 81 const data = ssr.extractData(); 80 82 expect(Object.keys(data)).toEqual(['' + queryOperation.key]); ··· 83 85 [queryOperation.key]: { 84 86 data: serializedQueryResponse.data, 85 87 error: undefined, 88 + hasNext: false, 86 89 }, 87 90 }); 88 91 }); ··· 119 122 ], 120 123 networkError: undefined, 121 124 }, 125 + hasNext: false, 122 126 }, 123 127 }); 124 128 }); ··· 147 151 [queryOperation.key]: { 148 152 data: '{"user":{"name":"Clive"}}', 149 153 extensions: '{"foo":"bar"}', 154 + hasNext: false, 150 155 }, 151 156 }); 152 157 }); ··· 219 224 isClient: true, 220 225 initialState: { 221 226 [queryOperation.key]: { 222 - hasNext: true, 223 227 ...(serializedQueryResponse as any), 228 + hasNext: true, 224 229 }, 225 230 }, 226 231 });
+8
packages/core/src/internal/__snapshots__/fetchSource.test.ts.snap
··· 5 5 "data": undefined, 6 6 "error": [CombinedError: [Network] Forbidden], 7 7 "extensions": undefined, 8 + "hasNext": false, 8 9 "operation": { 9 10 "context": { 10 11 "fetchOptions": { ··· 141 142 "name": "Clara", 142 143 }, 143 144 }, 145 + "stale": false, 144 146 } 145 147 `; 146 148 ··· 149 151 "data": undefined, 150 152 "error": [CombinedError: [Network] Forbidden], 151 153 "extensions": undefined, 154 + "hasNext": false, 152 155 "operation": { 153 156 "context": { 154 157 "fetchOptions": { ··· 285 288 "name": "Clara", 286 289 }, 287 290 }, 291 + "stale": false, 288 292 } 289 293 `; 290 294 ··· 293 297 "data": undefined, 294 298 "error": [CombinedError: [Network] Forbidden], 295 299 "extensions": undefined, 300 + "hasNext": false, 296 301 "operation": { 297 302 "context": { 298 303 "fetchOptions": { ··· 429 434 "name": "Clara", 430 435 }, 431 436 }, 437 + "stale": false, 432 438 } 433 439 `; 434 440 ··· 578 584 "name": "Clara", 579 585 }, 580 586 }, 587 + "stale": false, 581 588 } 582 589 `; 583 590 ··· 759 766 "name": "Clara", 760 767 }, 761 768 }, 769 + "stale": false, 762 770 } 763 771 `;
+6
packages/core/src/test-utils/samples.ts
··· 103 103 104 104 export const undefinedQueryResponse: OperationResult = { 105 105 operation: queryOperation, 106 + stale: false, 107 + hasNext: false, 106 108 }; 107 109 108 110 export const queryResponse: OperationResult = { ··· 112 114 name: 'Clive', 113 115 }, 114 116 }, 117 + stale: false, 118 + hasNext: false, 115 119 }; 116 120 117 121 export const mutationResponse: OperationResult = { 118 122 operation: mutationOperation, 119 123 data: {}, 124 + stale: false, 125 + hasNext: false, 120 126 }; 121 127 122 128 export const subscriptionResult: ExecutionResult = {
+2 -2
packages/core/src/types.ts
··· 565 565 * Most commonly, this flag is set for a cached result when the operation is executed using the 566 566 * `cache-and-network` {@link RequestPolicy}. 567 567 */ 568 - stale?: boolean; 568 + stale: boolean; 569 569 /** Indicates that the GraphQL response is streamed and updated results will follow. 570 570 * 571 571 * @remarks ··· 575 575 * 576 576 * For GraphQL subscriptions, this flag will always be set to `true`. 577 577 */ 578 - hasNext?: boolean; 578 + hasNext: boolean; 579 579 } 580 580 581 581 /** The input parameters a `Client` passes to an `Exchange` when it's created.
+16
packages/core/src/utils/result.test.ts
··· 38 38 }, 39 39 ], 40 40 }, 41 + stale: false, 42 + hasNext: true, 41 43 }; 42 44 43 45 const merged = mergeResultPatch(prevResult, { ··· 77 79 }, 78 80 ], 79 81 }, 82 + stale: false, 83 + hasNext: true, 80 84 }; 81 85 82 86 const patch = { __typename: 'Child' }; ··· 111 115 __typename: 'Query', 112 116 item: undefined, 113 117 }, 118 + stale: false, 119 + hasNext: true, 114 120 }; 115 121 116 122 const merged = mergeResultPatch(prevResult, { ··· 133 139 __typename: 'Query', 134 140 items: [{ __typename: 'Item' }], 135 141 }, 142 + stale: false, 143 + hasNext: true, 136 144 }; 137 145 138 146 const patch = { __typename: 'Item' }; ··· 162 170 __typename: 'Query', 163 171 items: [{ __typename: 'Item' }], 164 172 }, 173 + stale: false, 174 + hasNext: true, 165 175 }; 166 176 167 177 const merged = mergeResultPatch(prevResult, { ··· 190 200 extensions: { 191 201 base: true, 192 202 }, 203 + stale: false, 204 + hasNext: true, 193 205 }; 194 206 195 207 const merged = mergeResultPatch(prevResult, { ··· 240 252 extensions: { 241 253 base: true, 242 254 }, 255 + stale: false, 256 + hasNext: true, 243 257 }; 244 258 245 259 const merged = mergeResultPatch(prevResult, { ··· 264 278 }, 265 279 ], 266 280 }, 281 + stale: false, 282 + hasNext: true, 267 283 }; 268 284 269 285 const patch = { __typename: 'Child' };
+4
packages/core/src/utils/result.ts
··· 44 44 : undefined, 45 45 extensions: result.extensions ? { ...result.extensions } : undefined, 46 46 hasNext: result.hasNext == null ? defaultHasNext : result.hasNext, 47 + stale: false, 47 48 }; 48 49 }; 49 50 ··· 126 127 : undefined, 127 128 extensions: hasExtensions ? extensions : undefined, 128 129 hasNext: !!nextResult.hasNext, 130 + stale: false, 129 131 }; 130 132 }; 131 133 ··· 154 156 response, 155 157 }), 156 158 extensions: undefined, 159 + hasNext: false, 160 + stale: false, 157 161 });
+2
packages/react-urql/src/test-utils/ssr.test.tsx
··· 72 72 name: 'Clive', 73 73 }, 74 74 }, 75 + stale: false, 76 + hasNext: false, 75 77 }; 76 78 77 79 const url = 'https://hostname.com';
+4 -2
packages/svelte-urql/src/common.ts
··· 19 19 make(observer => store$.subscribe(observer.next)); 20 20 21 21 export const initialResult = { 22 + operation: undefined, 22 23 fetching: false, 23 - stale: false, 24 - error: undefined, 25 24 data: undefined, 25 + error: undefined, 26 26 extensions: undefined, 27 + hasNext: false, 28 + stale: false, 27 29 }; 28 30 29 31 export interface Pausable {