@khanacademy/wonder-blocks-data 7.0.1 → 8.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/es/index.js +286 -107
  3. package/dist/index.js +1089 -713
  4. package/package.json +1 -1
  5. package/src/__docs__/_overview_ssr_.stories.mdx +13 -13
  6. package/src/__docs__/exports.abort-inflight-requests.stories.mdx +20 -0
  7. package/src/__docs__/exports.data.stories.mdx +3 -3
  8. package/src/__docs__/{exports.fulfill-all-data-requests.stories.mdx → exports.fetch-tracked-requests.stories.mdx} +5 -5
  9. package/src/__docs__/exports.get-gql-request-id.stories.mdx +24 -0
  10. package/src/__docs__/{exports.has-unfulfilled-requests.stories.mdx → exports.has-tracked-requests-to-be-fetched.stories.mdx} +4 -4
  11. package/src/__docs__/exports.intialize-hydration-cache.stories.mdx +29 -0
  12. package/src/__docs__/exports.purge-caches.stories.mdx +23 -0
  13. package/src/__docs__/{exports.remove-all-from-cache.stories.mdx → exports.purge-hydration-cache.stories.mdx} +4 -4
  14. package/src/__docs__/{exports.clear-shared-cache.stories.mdx → exports.purge-shared-cache.stories.mdx} +4 -4
  15. package/src/__docs__/exports.track-data.stories.mdx +4 -4
  16. package/src/__docs__/exports.use-cached-effect.stories.mdx +7 -4
  17. package/src/__docs__/exports.use-gql.stories.mdx +1 -33
  18. package/src/__docs__/exports.use-server-effect.stories.mdx +1 -1
  19. package/src/__docs__/exports.use-shared-cache.stories.mdx +2 -2
  20. package/src/__docs__/types.fetch-policy.stories.mdx +44 -0
  21. package/src/__docs__/types.response-cache.stories.mdx +1 -1
  22. package/src/__tests__/generated-snapshot.test.js +5 -5
  23. package/src/components/__tests__/data.test.js +2 -6
  24. package/src/hooks/__tests__/use-cached-effect.test.js +341 -100
  25. package/src/hooks/__tests__/use-hydratable-effect.test.js +15 -9
  26. package/src/hooks/__tests__/use-shared-cache.test.js +6 -6
  27. package/src/hooks/use-cached-effect.js +169 -93
  28. package/src/hooks/use-hydratable-effect.js +8 -1
  29. package/src/hooks/use-shared-cache.js +2 -2
  30. package/src/index.js +14 -78
  31. package/src/util/__tests__/get-gql-request-id.test.js +74 -0
  32. package/src/util/__tests__/graphql-document-node-parser.test.js +542 -0
  33. package/src/util/__tests__/hydration-cache-api.test.js +35 -0
  34. package/src/util/__tests__/purge-caches.test.js +29 -0
  35. package/src/util/__tests__/request-api.test.js +188 -0
  36. package/src/util/__tests__/request-fulfillment.test.js +42 -0
  37. package/src/util/__tests__/ssr-cache.test.js +58 -60
  38. package/src/util/__tests__/to-gql-operation.test.js +42 -0
  39. package/src/util/data-error.js +6 -0
  40. package/src/util/get-gql-request-id.js +50 -0
  41. package/src/util/graphql-document-node-parser.js +133 -0
  42. package/src/util/graphql-types.js +30 -0
  43. package/src/util/hydration-cache-api.js +28 -0
  44. package/src/util/purge-caches.js +15 -0
  45. package/src/util/request-api.js +66 -0
  46. package/src/util/request-fulfillment.js +32 -12
  47. package/src/util/request-tracking.js +1 -1
  48. package/src/util/ssr-cache.js +13 -31
  49. package/src/util/to-gql-operation.js +44 -0
  50. package/src/util/types.js +31 -0
  51. package/src/__docs__/exports.intialize-cache.stories.mdx +0 -29
  52. package/src/__docs__/exports.remove-from-cache.stories.mdx +0 -25
  53. package/src/__docs__/exports.request-fulfillment.stories.mdx +0 -36
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # @khanacademy/wonder-blocks-data
2
2
 
3
+ ## 8.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 580141ed: Always initialize SSR-only cache
8
+
9
+ ## 8.0.1
10
+
11
+ ### Patch Changes
12
+
13
+ - e5fa4d9e: Make sure ssr-only cache is initialized when purging caches in test environment
14
+
15
+ ## 8.0.0
16
+
17
+ ### Major Changes
18
+
19
+ - 0720470e: Renamed `initializeCache` to `initializeHydrationCache`, deleted `removeFromCache`, renamed `removeAllFromCache` to `purgeHydrationCache`
20
+ - cf9ed87f: Add `fetchPolicy` to `useCachedEffect` options, add `refetch` to `useCachedEffect` return value (return value is now a tuple of [result, refetch]), add abort API to request fulfillment (not truly aborting though)
21
+ - b882b082: Stop exporting `RequestFulfillment`, update `useCachedEffect` to consider scope with sharing inflight requests
22
+ - 0720470e: Rename `fulfillAllDataRequests` to `fetchTrackedRequests`, rename `hasUnfulfilledRequests` to `hasTrackedRequestsToBeFetched`
23
+ - 0720470e: Renamed `clearSharedCache` to `purgeSharedCache`
24
+
25
+ ### Minor Changes
26
+
27
+ - 0720470e: Add `purgeCaches` export for purging all caches with one call
28
+ - 75c10036: Add `abortInflightRequests` to exports
29
+ - a85f2f3a: Provide `getGqlRequestId` function
30
+
31
+ ### Patch Changes
32
+
33
+ - 1385f468: Removed unnecessary `new` on tracking context creation
34
+
3
35
  ## 7.0.1
4
36
 
5
37
  ### Patch Changes
package/dist/es/index.js CHANGED
@@ -4,11 +4,14 @@ import _extends from '@babel/runtime/helpers/extends';
4
4
  import * as React from 'react';
5
5
  import { useContext, useRef, useMemo, useCallback } from 'react';
6
6
 
7
+ const FetchPolicy = require("flow-enums-runtime").Mirrored(["CacheBeforeNetwork", "CacheAndNetwork", "CacheOnly", "NetworkOnly"]);
8
+
7
9
  const DataErrors = Object.freeze({
8
10
  Unknown: "Unknown",
9
11
  Internal: "Internal",
10
12
  InvalidInput: "InvalidInput",
11
13
  Network: "Network",
14
+ NotAllowed: "NotAllowed",
12
15
  Parse: "Parse",
13
16
  Hydrated: "Hydrated"
14
17
  });
@@ -169,31 +172,22 @@ class SsrCache {
169
172
  };
170
173
 
171
174
  this.getEntry = id => {
172
- var _this$_ssrOnlyCache$g, _this$_ssrOnlyCache;
173
-
174
- const internalEntry = (_this$_ssrOnlyCache$g = (_this$_ssrOnlyCache = this._ssrOnlyCache) == null ? void 0 : _this$_ssrOnlyCache.get(DefaultScope$2, id)) != null ? _this$_ssrOnlyCache$g : this._hydrationCache.get(DefaultScope$2, id);
175
+ const ssrEntry = Server.isServerSide() ? this._ssrOnlyCache.get(DefaultScope$2, id) : null;
176
+ const internalEntry = ssrEntry != null ? ssrEntry : this._hydrationCache.get(DefaultScope$2, id);
175
177
 
176
- if (this._ssrOnlyCache == null && internalEntry != null) {
178
+ if (!Server.isServerSide() && internalEntry != null) {
177
179
  this._hydrationCache.purge(DefaultScope$2, id);
178
180
  }
179
181
 
180
182
  return internalEntry;
181
183
  };
182
184
 
183
- this.remove = id => {
184
- var _this$_ssrOnlyCache$p, _this$_ssrOnlyCache2;
185
-
186
- return this._hydrationCache.purge(DefaultScope$2, id) || ((_this$_ssrOnlyCache$p = (_this$_ssrOnlyCache2 = this._ssrOnlyCache) == null ? void 0 : _this$_ssrOnlyCache2.purge(DefaultScope$2, id)) != null ? _this$_ssrOnlyCache$p : false);
187
- };
188
-
189
- this.removeAll = predicate => {
190
- var _this$_ssrOnlyCache3;
191
-
185
+ this.purgeData = predicate => {
192
186
  const realPredicate = predicate ? (_, key, cachedEntry) => predicate(key, cachedEntry) : undefined;
193
187
 
194
188
  this._hydrationCache.purgeAll(realPredicate);
195
189
 
196
- (_this$_ssrOnlyCache3 = this._ssrOnlyCache) == null ? void 0 : _this$_ssrOnlyCache3.purgeAll(realPredicate);
190
+ this._ssrOnlyCache.purgeAll(realPredicate);
197
191
  };
198
192
 
199
193
  this.cloneHydratableData = () => {
@@ -204,7 +198,7 @@ class SsrCache {
204
198
  return (_cache$DefaultScope = cache[DefaultScope$2]) != null ? _cache$DefaultScope : {};
205
199
  };
206
200
 
207
- this._ssrOnlyCache = Server.isServerSide() ? ssrOnlyCache || new SerializableInMemoryCache() : undefined;
201
+ this._ssrOnlyCache = ssrOnlyCache || new SerializableInMemoryCache();
208
202
  this._hydrationCache = hydrationCache || new SerializableInMemoryCache();
209
203
  }
210
204
 
@@ -215,9 +209,7 @@ class SsrCache {
215
209
  if (hydrate) {
216
210
  this._hydrationCache.set(DefaultScope$2, id, frozenEntry);
217
211
  } else {
218
- var _this$_ssrOnlyCache4;
219
-
220
- (_this$_ssrOnlyCache4 = this._ssrOnlyCache) == null ? void 0 : _this$_ssrOnlyCache4.set(DefaultScope$2, id, frozenEntry);
212
+ this._ssrOnlyCache.set(DefaultScope$2, id, frozenEntry);
221
213
  }
222
214
  }
223
215
 
@@ -226,6 +218,9 @@ class SsrCache {
226
218
 
227
219
  }
228
220
 
221
+ const initializeHydrationCache = source => SsrCache.Default.initialize(source);
222
+ const purgeHydrationCache = predicate => SsrCache.Default.purgeData(predicate);
223
+
229
224
  let _default$1;
230
225
 
231
226
  class RequestFulfillment {
@@ -268,6 +263,14 @@ class RequestFulfillment {
268
263
  this._requests[id] = request;
269
264
  return request;
270
265
  };
266
+
267
+ this.abort = id => {
268
+ delete this._requests[id];
269
+ };
270
+
271
+ this.abortAll = () => {
272
+ Object.keys(this._requests).forEach(id => this.abort(id));
273
+ };
271
274
  }
272
275
 
273
276
  static get Default() {
@@ -280,7 +283,7 @@ class RequestFulfillment {
280
283
 
281
284
  }
282
285
 
283
- const TrackerContext = new React.createContext(null);
286
+ const TrackerContext = React.createContext(null);
284
287
 
285
288
  let _default;
286
289
 
@@ -352,6 +355,77 @@ class RequestTracker {
352
355
 
353
356
  }
354
357
 
358
+ const SSRCheck = () => {
359
+ if (Server.isServerSide()) {
360
+ return null;
361
+ }
362
+
363
+ if (process.env.NODE_ENV === "production") {
364
+ return new DataError("No CSR tracking", DataErrors.NotAllowed);
365
+ } else {
366
+ return new DataError("Data requests are not tracked for fulfillment when when client-side", DataErrors.NotAllowed);
367
+ }
368
+ };
369
+
370
+ const fetchTrackedRequests = () => {
371
+ const ssrCheck = SSRCheck();
372
+
373
+ if (ssrCheck != null) {
374
+ return Promise.reject(ssrCheck);
375
+ }
376
+
377
+ return RequestTracker.Default.fulfillTrackedRequests();
378
+ };
379
+ const hasTrackedRequestsToBeFetched = () => {
380
+ const ssrCheck = SSRCheck();
381
+
382
+ if (ssrCheck != null) {
383
+ throw ssrCheck;
384
+ }
385
+
386
+ return RequestTracker.Default.hasUnfulfilledRequests;
387
+ };
388
+ const abortInflightRequests = () => {
389
+ RequestFulfillment.Default.abortAll();
390
+ };
391
+
392
+ const cache$1 = new ScopedInMemoryCache();
393
+ const purgeSharedCache = (scope = "") => {
394
+ if (scope && typeof scope === "string") {
395
+ cache$1.purgeScope(scope);
396
+ } else {
397
+ cache$1.purgeAll();
398
+ }
399
+ };
400
+ const useSharedCache = (id, scope, initialValue) => {
401
+ if (!id || typeof id !== "string") {
402
+ throw new DataError("id must be a non-empty string", DataErrors.InvalidInput);
403
+ }
404
+
405
+ if (!scope || typeof scope !== "string") {
406
+ throw new DataError("scope must be a non-empty string", DataErrors.InvalidInput);
407
+ }
408
+
409
+ const cacheValue = React.useCallback(value => value == null ? cache$1.purge(scope, id) : cache$1.set(scope, id, value), [id, scope]);
410
+ let currentValue = cache$1.get(scope, id);
411
+
412
+ if (currentValue == null && initialValue !== undefined) {
413
+ const value = typeof initialValue === "function" ? initialValue() : initialValue;
414
+
415
+ if (value != null) {
416
+ cacheValue(value);
417
+ currentValue = value;
418
+ }
419
+ }
420
+
421
+ return [currentValue, cacheValue];
422
+ };
423
+
424
+ const purgeCaches = () => {
425
+ purgeSharedCache();
426
+ purgeHydrationCache();
427
+ };
428
+
355
429
  class TrackData extends React.Component {
356
430
  render() {
357
431
  if (!Server.isServerSide()) {
@@ -438,41 +512,12 @@ const useServerEffect = (requestId, handler, options = {}) => {
438
512
  return cachedResult == null ? null : resultFromCachedResponse(cachedResult);
439
513
  };
440
514
 
441
- const cache = new ScopedInMemoryCache();
442
- const clearSharedCache = (scope = "") => {
443
- if (scope && typeof scope === "string") {
444
- cache.purgeScope(scope);
445
- } else {
446
- cache.purgeAll();
447
- }
448
- };
449
- const useSharedCache = (id, scope, initialValue) => {
450
- if (!id || typeof id !== "string") {
451
- throw new DataError("id must be a non-empty string", DataErrors.InvalidInput);
452
- }
453
-
454
- if (!scope || typeof scope !== "string") {
455
- throw new DataError("scope must be a non-empty string", DataErrors.InvalidInput);
456
- }
457
-
458
- const cacheValue = React.useCallback(value => value == null ? cache.purge(scope, id) : cache.set(scope, id, value), [id, scope]);
459
- let currentValue = cache.get(scope, id);
460
-
461
- if (currentValue == null && initialValue !== undefined) {
462
- const value = typeof initialValue === "function" ? initialValue() : initialValue;
463
-
464
- if (value != null) {
465
- cacheValue(value);
466
- currentValue = value;
467
- }
468
- }
469
-
470
- return [currentValue, cacheValue];
471
- };
472
-
473
515
  const DefaultScope$1 = "useCachedEffect";
474
516
  const useCachedEffect = (requestId, handler, options = {}) => {
517
+ var _ref;
518
+
475
519
  const {
520
+ fetchPolicy = FetchPolicy.CacheBeforeNetwork,
476
521
  skip: hardSkip = false,
477
522
  retainResultOnChange = false,
478
523
  onResultChanged,
@@ -481,55 +526,102 @@ const useCachedEffect = (requestId, handler, options = {}) => {
481
526
  const interceptedHandler = useRequestInterception(requestId, handler);
482
527
  const [mostRecentResult, setMostRecentResult] = useSharedCache(requestId, scope);
483
528
  const forceUpdate = useForceUpdate();
484
- const setCacheAndNotify = React.useCallback(value => {
485
- setMostRecentResult(value);
529
+ const networkResultRef = React.useRef();
530
+ const currentRequestRef = React.useRef();
531
+ const fetchRequest = React.useMemo(() => {
532
+ var _currentRequestRef$cu;
486
533
 
487
- if (onResultChanged != null) {
488
- onResultChanged(value);
489
- } else {
490
- forceUpdate();
491
- }
492
- }, [setMostRecentResult, onResultChanged, forceUpdate]);
493
- const requestIdRef = React.useRef();
494
- const previousRequestId = requestIdRef.current;
495
- const softSkip = React.useMemo(() => {
496
- if (requestId === previousRequestId) {
497
- return true;
498
- }
534
+ (_currentRequestRef$cu = currentRequestRef.current) == null ? void 0 : _currentRequestRef$cu.cancel();
535
+ currentRequestRef.current = null;
536
+ networkResultRef.current = null;
499
537
 
500
- if (mostRecentResult != null) {
501
- return true;
502
- }
538
+ const fetchFn = () => {
539
+ var _currentRequestRef$cu2, _currentRequestRef$cu3;
503
540
 
504
- return false;
505
- }, [requestId, previousRequestId, mostRecentResult]);
506
- React.useEffect(() => {
507
- let cancel = false;
541
+ if (fetchPolicy === FetchPolicy.CacheOnly) {
542
+ throw new DataError("Cannot fetch with CacheOnly policy", DataErrors.NotAllowed);
543
+ }
508
544
 
509
- if (hardSkip || softSkip) {
510
- return;
511
- }
545
+ const request = RequestFulfillment.Default.fulfill(`${requestId}|${scope}`, {
546
+ handler: interceptedHandler
547
+ });
512
548
 
513
- requestIdRef.current = requestId;
514
- RequestFulfillment.Default.fulfill(requestId, {
515
- handler: interceptedHandler
516
- }).then(result => {
517
- if (cancel) {
549
+ if (request === ((_currentRequestRef$cu2 = currentRequestRef.current) == null ? void 0 : _currentRequestRef$cu2.request)) {
518
550
  return;
519
551
  }
520
552
 
521
- setCacheAndNotify(result);
553
+ networkResultRef.current = null;
554
+ (_currentRequestRef$cu3 = currentRequestRef.current) == null ? void 0 : _currentRequestRef$cu3.cancel();
555
+ let cancel = false;
556
+ request.then(result => {
557
+ currentRequestRef.current = null;
558
+
559
+ if (cancel) {
560
+ return;
561
+ }
562
+
563
+ setMostRecentResult(result);
564
+ networkResultRef.current = result;
565
+
566
+ if (onResultChanged != null) {
567
+ onResultChanged(result);
568
+ } else {
569
+ forceUpdate();
570
+ }
571
+
572
+ return;
573
+ });
574
+ currentRequestRef.current = {
575
+ requestId,
576
+ request,
577
+
578
+ cancel() {
579
+ cancel = true;
580
+ RequestFulfillment.Default.abort(requestId);
581
+ }
582
+
583
+ };
584
+ };
585
+
586
+ return fetchFn;
587
+ }, [requestId, onResultChanged, forceUpdate, setMostRecentResult, fetchPolicy]);
588
+ const requestIdRef = React.useRef(requestId);
589
+ const shouldFetch = React.useMemo(() => {
590
+ if (hardSkip) {
591
+ return false;
592
+ }
593
+
594
+ switch (fetchPolicy) {
595
+ case FetchPolicy.CacheOnly:
596
+ return false;
597
+
598
+ case FetchPolicy.CacheBeforeNetwork:
599
+ return mostRecentResult == null || requestId !== requestIdRef.current;
600
+
601
+ case FetchPolicy.CacheAndNetwork:
602
+ case FetchPolicy.NetworkOnly:
603
+ return networkResultRef.current == null;
604
+ }
605
+ }, [requestId, mostRecentResult, fetchPolicy, hardSkip]);
606
+ requestIdRef.current = requestId;
607
+ React.useEffect(() => {
608
+ if (!shouldFetch) {
522
609
  return;
523
- });
610
+ }
611
+
612
+ fetchRequest();
524
613
  return () => {
525
- cancel = true;
614
+ var _currentRequestRef$cu4;
615
+
616
+ (_currentRequestRef$cu4 = currentRequestRef.current) == null ? void 0 : _currentRequestRef$cu4.cancel();
617
+ currentRequestRef.current = null;
526
618
  };
527
- }, [hardSkip, requestId]);
619
+ }, [shouldFetch, fetchRequest]);
528
620
  const lastResultAgnosticOfIdRef = React.useRef(Status.loading());
529
621
  const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : Status.loading();
530
- const result = React.useMemo(() => mostRecentResult != null ? mostRecentResult : loadingResult, [mostRecentResult, loadingResult]);
622
+ const result = (_ref = fetchPolicy === FetchPolicy.NetworkOnly ? networkResultRef.current : mostRecentResult) != null ? _ref : loadingResult;
531
623
  lastResultAgnosticOfIdRef.current = result;
532
- return result;
624
+ return [result, fetchRequest];
533
625
  };
534
626
 
535
627
  const WhenClientSide = require("flow-enums-runtime").Mirrored(["DoNotHydrate", "ExecuteWhenNoResult", "ExecuteWhenNoSuccessResult", "AlwaysExecute"]);
@@ -564,11 +656,12 @@ const useHydratableEffect = (requestId, handler, options = {}) => {
564
656
  }
565
657
  }, [serverResult]);
566
658
  useSharedCache(requestId, scope, getDefaultCacheValue);
567
- const clientResult = useCachedEffect(requestId, handler, {
659
+ const [clientResult] = useCachedEffect(requestId, handler, {
568
660
  skip,
569
661
  onResultChanged,
570
662
  retainResultOnChange,
571
- scope
663
+ scope,
664
+ fetchPolicy: FetchPolicy.CacheBeforeNetwork
572
665
  });
573
666
  return serverResult != null ? serverResult : clientResult;
574
667
  };
@@ -598,6 +691,110 @@ const InterceptRequests = ({
598
691
  }, children);
599
692
  };
600
693
 
694
+ const toString = valid => {
695
+ var _JSON$stringify;
696
+
697
+ if (typeof valid === "string") {
698
+ return valid;
699
+ }
700
+
701
+ return (_JSON$stringify = JSON.stringify(valid)) != null ? _JSON$stringify : "";
702
+ };
703
+
704
+ const getGqlRequestId = (operation, variables, context) => {
705
+ const parts = [];
706
+ const sortableContext = new URLSearchParams(context);
707
+ sortableContext.sort();
708
+ parts.push(sortableContext.toString());
709
+ parts.push(operation.id);
710
+
711
+ if (variables != null) {
712
+ const stringifiedVariables = Object.keys(variables).reduce((acc, key) => {
713
+ acc[key] = toString(variables[key]);
714
+ return acc;
715
+ }, {});
716
+ const sortableVariables = new URLSearchParams(stringifiedVariables);
717
+ sortableVariables.sort();
718
+ parts.push(sortableVariables.toString());
719
+ }
720
+
721
+ return parts.join("|");
722
+ };
723
+
724
+ const DocumentTypes = Object.freeze({
725
+ query: "query",
726
+ mutation: "mutation"
727
+ });
728
+ const cache = new Map();
729
+ function graphQLDocumentNodeParser(document) {
730
+ var _definition$name;
731
+
732
+ const cached = cache.get(document);
733
+
734
+ if (cached) {
735
+ return cached;
736
+ }
737
+
738
+ if (!(document != null && document.kind)) {
739
+ if (process.env.NODE_ENV === "production") {
740
+ throw new DataError("Bad DocumentNode", DataErrors.InvalidInput);
741
+ } else {
742
+ throw new DataError(`Argument of ${JSON.stringify(document)} passed to parser was not a valid GraphQL ` + `DocumentNode. You may need to use 'graphql-tag' or another method ` + `to convert your operation into a document`, DataErrors.InvalidInput);
743
+ }
744
+ }
745
+
746
+ const fragments = document.definitions.filter(x => x.kind === "FragmentDefinition");
747
+ const queries = document.definitions.filter(x => x.kind === "OperationDefinition" && x.operation === "query");
748
+ const mutations = document.definitions.filter(x => x.kind === "OperationDefinition" && x.operation === "mutation");
749
+ const subscriptions = document.definitions.filter(x => x.kind === "OperationDefinition" && x.operation === "subscription");
750
+
751
+ if (fragments.length && !queries.length && !mutations.length) {
752
+ if (process.env.NODE_ENV === "production") {
753
+ throw new DataError("Fragment only", DataErrors.InvalidInput);
754
+ } else {
755
+ throw new DataError(`Passing only a fragment to 'graphql' is not supported. ` + `You must include a query or mutation as well`, DataErrors.InvalidInput);
756
+ }
757
+ }
758
+
759
+ if (subscriptions.length) {
760
+ if (process.env.NODE_ENV === "production") {
761
+ throw new DataError("No subscriptions", DataErrors.InvalidInput);
762
+ } else {
763
+ throw new DataError(`We do not support subscriptions. ` + `${JSON.stringify(document)} had ${subscriptions.length} subscriptions`, DataErrors.InvalidInput);
764
+ }
765
+ }
766
+
767
+ if (queries.length + mutations.length > 1) {
768
+ if (process.env.NODE_ENV === "production") {
769
+ throw new DataError("Too many ops", DataErrors.InvalidInput);
770
+ } else {
771
+ throw new DataError(`We only support one query or mutation per component. ` + `${JSON.stringify(document)} had ${queries.length} queries and ` + `${mutations.length} mutations. `, DataErrors.InvalidInput);
772
+ }
773
+ }
774
+
775
+ const type = queries.length ? DocumentTypes.query : DocumentTypes.mutation;
776
+ const definitions = queries.length ? queries : mutations;
777
+ const definition = definitions[0];
778
+ const variables = definition.variableDefinitions || [];
779
+ const name = ((_definition$name = definition.name) == null ? void 0 : _definition$name.kind) === "Name" ? definition.name.value : "data";
780
+ const payload = {
781
+ name,
782
+ type,
783
+ variables
784
+ };
785
+ cache.set(document, payload);
786
+ return payload;
787
+ }
788
+
789
+ const toGqlOperation = documentNode => {
790
+ const definition = graphQLDocumentNodeParser(documentNode);
791
+ const wbDataOperation = {
792
+ id: definition.name,
793
+ type: definition.type
794
+ };
795
+ return wbDataOperation;
796
+ };
797
+
601
798
  const GqlRouterContext = React.createContext(null);
602
799
 
603
800
  const GqlRouter = ({
@@ -739,22 +936,4 @@ const useGql = (context = {}) => {
739
936
  return gqlFetch;
740
937
  };
741
938
 
742
- const initializeCache = source => SsrCache.Default.initialize(source);
743
- const fulfillAllDataRequests = () => {
744
- if (!Server.isServerSide()) {
745
- return Promise.reject(new Error("Data requests are not tracked when client-side"));
746
- }
747
-
748
- return RequestTracker.Default.fulfillTrackedRequests();
749
- };
750
- const hasUnfulfilledRequests = () => {
751
- if (!Server.isServerSide()) {
752
- throw new Error("Data requests are not tracked when client-side");
753
- }
754
-
755
- return RequestTracker.Default.hasUnfulfilledRequests;
756
- };
757
- const removeFromCache = id => SsrCache.Default.remove(id);
758
- const removeAllFromCache = predicate => SsrCache.Default.removeAll(predicate);
759
-
760
- export { Data, DataError, DataErrors, GqlError, GqlErrors, GqlRouter, InterceptRequests, RequestFulfillment, ScopedInMemoryCache, SerializableInMemoryCache, Status, TrackData, WhenClientSide, clearSharedCache, fulfillAllDataRequests, hasUnfulfilledRequests, initializeCache, removeAllFromCache, removeFromCache, useCachedEffect, useGql, useHydratableEffect, useServerEffect, useSharedCache };
939
+ export { Data, DataError, DataErrors, FetchPolicy, GqlError, GqlErrors, GqlRouter, InterceptRequests, ScopedInMemoryCache, SerializableInMemoryCache, Status, TrackData, WhenClientSide, abortInflightRequests, fetchTrackedRequests, getGqlRequestId, graphQLDocumentNodeParser, hasTrackedRequestsToBeFetched, initializeHydrationCache, purgeCaches, purgeHydrationCache, purgeSharedCache, toGqlOperation, useCachedEffect, useGql, useHydratableEffect, useServerEffect, useSharedCache };