@khanacademy/wonder-blocks-data 4.0.0 → 5.0.0
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.
- package/CHANGELOG.md +6 -0
- package/dist/es/index.js +64 -45
- package/dist/index.js +109 -74
- package/package.json +1 -1
- package/src/__tests__/generated-snapshot.test.js +7 -7
- package/src/components/__tests__/data.test.js +11 -26
- package/src/components/__tests__/intercept-requests.test.js +58 -0
- package/src/components/data.js +4 -18
- package/src/components/intercept-context.js +4 -5
- package/src/components/intercept-requests.js +69 -0
- package/src/components/{intercept-data.md → intercept-requests.md} +18 -15
- package/src/hooks/__tests__/use-request-interception.test.js +255 -0
- package/src/hooks/use-request-interception.js +54 -0
- package/src/hooks/use-server-effect.js +3 -3
- package/src/index.js +2 -1
- package/src/components/__tests__/intercept-data.test.js +0 -63
- package/src/components/intercept-data.js +0 -66
package/CHANGELOG.md
CHANGED
package/dist/es/index.js
CHANGED
|
@@ -472,13 +472,6 @@ class TrackData extends React.Component {
|
|
|
472
472
|
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
-
/**
|
|
476
|
-
* InterceptContext defines a map from request ID to interception methods.
|
|
477
|
-
*
|
|
478
|
-
* INTERNAL USE ONLY
|
|
479
|
-
*/
|
|
480
|
-
const InterceptContext = /*#__PURE__*/React.createContext({});
|
|
481
|
-
|
|
482
475
|
/**
|
|
483
476
|
* Hook to perform an asynchronous action during server-side rendering.
|
|
484
477
|
*
|
|
@@ -494,25 +487,71 @@ const InterceptContext = /*#__PURE__*/React.createContext({});
|
|
|
494
487
|
*
|
|
495
488
|
* The asynchronous action is never invoked on the client-side.
|
|
496
489
|
*/
|
|
497
|
-
const useServerEffect = (
|
|
490
|
+
const useServerEffect = (requestId, handler, hydrate = true) => {
|
|
498
491
|
// If we're server-side or hydrating, we'll have a cached entry to use.
|
|
499
492
|
// So we get that and use it to initialize our state.
|
|
500
493
|
// This works in both hydration and SSR because the very first call to
|
|
501
494
|
// this will have cached data in those cases as it will be present on the
|
|
502
495
|
// initial render - and subsequent renders on the client it will be null.
|
|
503
|
-
const cachedResult = SsrCache.Default.getEntry(
|
|
496
|
+
const cachedResult = SsrCache.Default.getEntry(requestId); // We only track data requests when we are server-side and we don't
|
|
504
497
|
// already have a result, as given by the cachedData (which is also the
|
|
505
498
|
// initial value for the result state).
|
|
506
499
|
|
|
507
500
|
const maybeTrack = useContext(TrackerContext);
|
|
508
501
|
|
|
509
502
|
if (cachedResult == null && Server.isServerSide()) {
|
|
510
|
-
maybeTrack == null ? void 0 : maybeTrack(
|
|
503
|
+
maybeTrack == null ? void 0 : maybeTrack(requestId, handler, hydrate);
|
|
511
504
|
}
|
|
512
505
|
|
|
513
506
|
return cachedResult;
|
|
514
507
|
};
|
|
515
508
|
|
|
509
|
+
/**
|
|
510
|
+
* InterceptContext defines a map from request ID to interception methods.
|
|
511
|
+
*
|
|
512
|
+
* INTERNAL USE ONLY
|
|
513
|
+
*/
|
|
514
|
+
const InterceptContext = /*#__PURE__*/React.createContext([]);
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Allow request handling to be intercepted.
|
|
518
|
+
*
|
|
519
|
+
* Hook to take a uniquely identified request handler and return a
|
|
520
|
+
* method that will support request interception from the InterceptRequest
|
|
521
|
+
* component.
|
|
522
|
+
*
|
|
523
|
+
* If you want request interception to be supported with `useServerEffect` or
|
|
524
|
+
* any client-side effect that uses the handler, call this first to generate
|
|
525
|
+
* an intercepted handler, and then invoke `useServerEffect` (or other things)
|
|
526
|
+
* with that intercepted handler.
|
|
527
|
+
*/
|
|
528
|
+
const useRequestInterception = (requestId, handler) => {
|
|
529
|
+
// Get the interceptors that have been registered.
|
|
530
|
+
const interceptors = React.useContext(InterceptContext); // Now, we need to create a new handler that will check if the
|
|
531
|
+
// request is intercepted before ultimately calling the original handler
|
|
532
|
+
// if nothing intercepted it.
|
|
533
|
+
// We memoize this so that it only changes if something related to it
|
|
534
|
+
// changes.
|
|
535
|
+
|
|
536
|
+
const interceptedHandler = React.useMemo(() => () => {
|
|
537
|
+
// Call the interceptors from closest to furthest.
|
|
538
|
+
// If one returns a non-null result, then we keep that.
|
|
539
|
+
const interceptResponse = interceptors.reduceRight((prev, interceptor) => {
|
|
540
|
+
if (prev != null) {
|
|
541
|
+
return prev;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
return interceptor(requestId);
|
|
545
|
+
}, null); // If nothing intercepted this request, invoke the original handler.
|
|
546
|
+
// NOTE: We can't guarantee all interceptors return the same type
|
|
547
|
+
// as our handler, so how can flow know? Let's just suppress that.
|
|
548
|
+
// $FlowFixMe[incompatible-return]
|
|
549
|
+
|
|
550
|
+
return interceptResponse != null ? interceptResponse : handler();
|
|
551
|
+
}, [handler, interceptors, requestId]);
|
|
552
|
+
return interceptedHandler;
|
|
553
|
+
};
|
|
554
|
+
|
|
516
555
|
/**
|
|
517
556
|
* Turns a cache entry into a stateful result.
|
|
518
557
|
*/
|
|
@@ -561,27 +600,8 @@ const Data = ({
|
|
|
561
600
|
showOldDataWhileLoading,
|
|
562
601
|
alwaysRequestOnHydration
|
|
563
602
|
}) => {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
// uses the interceptor.
|
|
567
|
-
const interceptorMap = React.useContext(InterceptContext); // If we have an interceptor, we need to replace the handler with one
|
|
568
|
-
// that uses the interceptor. This helper function generates a new
|
|
569
|
-
// handler.
|
|
570
|
-
|
|
571
|
-
const maybeInterceptedHandler = React.useMemo(() => {
|
|
572
|
-
const interceptor = interceptorMap[requestId];
|
|
573
|
-
|
|
574
|
-
if (interceptor == null) {
|
|
575
|
-
return handler;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
return () => {
|
|
579
|
-
var _interceptor;
|
|
580
|
-
|
|
581
|
-
return (_interceptor = interceptor()) != null ? _interceptor : handler();
|
|
582
|
-
};
|
|
583
|
-
}, [handler, interceptorMap, requestId]);
|
|
584
|
-
const hydrateResult = useServerEffect(requestId, maybeInterceptedHandler, hydrate);
|
|
603
|
+
const interceptedHandler = useRequestInterception(requestId, handler);
|
|
604
|
+
const hydrateResult = useServerEffect(requestId, interceptedHandler, hydrate);
|
|
585
605
|
const [currentResult, setResult] = React.useState(hydrateResult); // Here we make sure the request still occurs client-side as needed.
|
|
586
606
|
// This is for legacy usage that expects this. Eventually we will want
|
|
587
607
|
// to deprecate.
|
|
@@ -617,7 +637,7 @@ const Data = ({
|
|
|
617
637
|
|
|
618
638
|
let cancel = false;
|
|
619
639
|
RequestFulfillment.Default.fulfill(requestId, {
|
|
620
|
-
handler:
|
|
640
|
+
handler: interceptedHandler
|
|
621
641
|
}).then(result => {
|
|
622
642
|
if (cancel) {
|
|
623
643
|
return;
|
|
@@ -669,22 +689,21 @@ const Data = ({
|
|
|
669
689
|
* be picked up by `Data` component requests from outside the children of this
|
|
670
690
|
* component.
|
|
671
691
|
*
|
|
672
|
-
*
|
|
673
|
-
*
|
|
674
|
-
*
|
|
675
|
-
* will be replaced.
|
|
692
|
+
* Interceptions within the same component tree are chained such that the
|
|
693
|
+
* interceptor closest to the intercepted request is called first, and the
|
|
694
|
+
* furthest interceptor is called last.
|
|
676
695
|
*/
|
|
677
|
-
const
|
|
678
|
-
|
|
679
|
-
handler,
|
|
696
|
+
const InterceptRequests = ({
|
|
697
|
+
interceptor,
|
|
680
698
|
children
|
|
681
699
|
}) => {
|
|
682
|
-
const
|
|
683
|
-
const
|
|
684
|
-
|
|
685
|
-
|
|
700
|
+
const interceptors = React.useContext(InterceptContext);
|
|
701
|
+
const updatedInterceptors = React.useMemo( // We could build this in reverse order so that our hook that does
|
|
702
|
+
// the interception didn't have to use reduceRight, but I think it
|
|
703
|
+
// is easier to think about if we do this in component tree order.
|
|
704
|
+
() => [].concat(interceptors, [interceptor]), [interceptors, interceptor]);
|
|
686
705
|
return /*#__PURE__*/React.createElement(InterceptContext.Provider, {
|
|
687
|
-
value:
|
|
706
|
+
value: updatedInterceptors
|
|
688
707
|
}, children);
|
|
689
708
|
};
|
|
690
709
|
|
|
@@ -964,4 +983,4 @@ const hasUnfulfilledRequests = () => {
|
|
|
964
983
|
const removeFromCache = id => SsrCache.Default.remove(id);
|
|
965
984
|
const removeAllFromCache = predicate => SsrCache.Default.removeAll(predicate);
|
|
966
985
|
|
|
967
|
-
export { Data, GqlError, GqlErrors, GqlRouter,
|
|
986
|
+
export { Data, GqlError, GqlErrors, GqlRouter, InterceptRequests, ScopedInMemoryCache, TrackData, clearSharedCache, fulfillAllDataRequests, hasUnfulfilledRequests, initializeCache, removeAllFromCache, removeFromCache, useGql, useRequestInterception, useServerEffect, useSharedCache };
|
package/dist/index.js
CHANGED
|
@@ -82,7 +82,7 @@ module.exports =
|
|
|
82
82
|
/******/
|
|
83
83
|
/******/
|
|
84
84
|
/******/ // Load entry module and return exports
|
|
85
|
-
/******/ return __webpack_require__(__webpack_require__.s =
|
|
85
|
+
/******/ return __webpack_require__(__webpack_require__.s = 20);
|
|
86
86
|
/******/ })
|
|
87
87
|
/************************************************************************/
|
|
88
88
|
/******/ ([
|
|
@@ -419,7 +419,7 @@ class ScopedInMemoryCache {
|
|
|
419
419
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
420
420
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
421
421
|
/* harmony import */ var _ssr_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
|
|
422
|
-
/* harmony import */ var _request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(
|
|
422
|
+
/* harmony import */ var _request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10);
|
|
423
423
|
|
|
424
424
|
|
|
425
425
|
|
|
@@ -558,7 +558,7 @@ class RequestTracker {
|
|
|
558
558
|
*
|
|
559
559
|
* INTERNAL USE ONLY
|
|
560
560
|
*/
|
|
561
|
-
const InterceptContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createContext"](
|
|
561
|
+
const InterceptContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createContext"]([]);
|
|
562
562
|
/* harmony default export */ __webpack_exports__["a"] = (InterceptContext);
|
|
563
563
|
|
|
564
564
|
/***/ }),
|
|
@@ -593,20 +593,20 @@ const InterceptContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["create
|
|
|
593
593
|
*
|
|
594
594
|
* The asynchronous action is never invoked on the client-side.
|
|
595
595
|
*/
|
|
596
|
-
const useServerEffect = (
|
|
596
|
+
const useServerEffect = (requestId, handler, hydrate = true) => {
|
|
597
597
|
// If we're server-side or hydrating, we'll have a cached entry to use.
|
|
598
598
|
// So we get that and use it to initialize our state.
|
|
599
599
|
// This works in both hydration and SSR because the very first call to
|
|
600
600
|
// this will have cached data in those cases as it will be present on the
|
|
601
601
|
// initial render - and subsequent renders on the client it will be null.
|
|
602
|
-
const cachedResult = _util_ssr_cache_js__WEBPACK_IMPORTED_MODULE_3__[/* SsrCache */ "a"].Default.getEntry(
|
|
602
|
+
const cachedResult = _util_ssr_cache_js__WEBPACK_IMPORTED_MODULE_3__[/* SsrCache */ "a"].Default.getEntry(requestId); // We only track data requests when we are server-side and we don't
|
|
603
603
|
// already have a result, as given by the cachedData (which is also the
|
|
604
604
|
// initial value for the result state).
|
|
605
605
|
|
|
606
606
|
const maybeTrack = Object(react__WEBPACK_IMPORTED_MODULE_1__["useContext"])(_util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__[/* TrackerContext */ "b"]);
|
|
607
607
|
|
|
608
608
|
if (cachedResult == null && _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide()) {
|
|
609
|
-
maybeTrack == null ? void 0 : maybeTrack(
|
|
609
|
+
maybeTrack == null ? void 0 : maybeTrack(requestId, handler, hydrate);
|
|
610
610
|
}
|
|
611
611
|
|
|
612
612
|
return cachedResult;
|
|
@@ -616,6 +616,57 @@ const useServerEffect = (id, handler, hydrate = true) => {
|
|
|
616
616
|
/* 9 */
|
|
617
617
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
618
618
|
|
|
619
|
+
"use strict";
|
|
620
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return useRequestInterception; });
|
|
621
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
622
|
+
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
623
|
+
/* harmony import */ var _components_intercept_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Allow request handling to be intercepted.
|
|
629
|
+
*
|
|
630
|
+
* Hook to take a uniquely identified request handler and return a
|
|
631
|
+
* method that will support request interception from the InterceptRequest
|
|
632
|
+
* component.
|
|
633
|
+
*
|
|
634
|
+
* If you want request interception to be supported with `useServerEffect` or
|
|
635
|
+
* any client-side effect that uses the handler, call this first to generate
|
|
636
|
+
* an intercepted handler, and then invoke `useServerEffect` (or other things)
|
|
637
|
+
* with that intercepted handler.
|
|
638
|
+
*/
|
|
639
|
+
const useRequestInterception = (requestId, handler) => {
|
|
640
|
+
// Get the interceptors that have been registered.
|
|
641
|
+
const interceptors = react__WEBPACK_IMPORTED_MODULE_0__["useContext"](_components_intercept_context_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"]); // Now, we need to create a new handler that will check if the
|
|
642
|
+
// request is intercepted before ultimately calling the original handler
|
|
643
|
+
// if nothing intercepted it.
|
|
644
|
+
// We memoize this so that it only changes if something related to it
|
|
645
|
+
// changes.
|
|
646
|
+
|
|
647
|
+
const interceptedHandler = react__WEBPACK_IMPORTED_MODULE_0__["useMemo"](() => () => {
|
|
648
|
+
// Call the interceptors from closest to furthest.
|
|
649
|
+
// If one returns a non-null result, then we keep that.
|
|
650
|
+
const interceptResponse = interceptors.reduceRight((prev, interceptor) => {
|
|
651
|
+
if (prev != null) {
|
|
652
|
+
return prev;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
return interceptor(requestId);
|
|
656
|
+
}, null); // If nothing intercepted this request, invoke the original handler.
|
|
657
|
+
// NOTE: We can't guarantee all interceptors return the same type
|
|
658
|
+
// as our handler, so how can flow know? Let's just suppress that.
|
|
659
|
+
// $FlowFixMe[incompatible-return]
|
|
660
|
+
|
|
661
|
+
return interceptResponse != null ? interceptResponse : handler();
|
|
662
|
+
}, [handler, interceptors, requestId]);
|
|
663
|
+
return interceptedHandler;
|
|
664
|
+
};
|
|
665
|
+
|
|
666
|
+
/***/ }),
|
|
667
|
+
/* 10 */
|
|
668
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
669
|
+
|
|
619
670
|
"use strict";
|
|
620
671
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return RequestFulfillment; });
|
|
621
672
|
/* harmony import */ var _ssr_cache_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);
|
|
@@ -707,7 +758,7 @@ class RequestFulfillment {
|
|
|
707
758
|
}
|
|
708
759
|
|
|
709
760
|
/***/ }),
|
|
710
|
-
/*
|
|
761
|
+
/* 11 */
|
|
711
762
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
712
763
|
|
|
713
764
|
"use strict";
|
|
@@ -718,7 +769,7 @@ class RequestFulfillment {
|
|
|
718
769
|
const GqlRouterContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createContext"](null);
|
|
719
770
|
|
|
720
771
|
/***/ }),
|
|
721
|
-
/*
|
|
772
|
+
/* 12 */
|
|
722
773
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
723
774
|
|
|
724
775
|
"use strict";
|
|
@@ -809,7 +860,7 @@ const useSharedCache = (id, scope, initialValue) => {
|
|
|
809
860
|
};
|
|
810
861
|
|
|
811
862
|
/***/ }),
|
|
812
|
-
/*
|
|
863
|
+
/* 13 */
|
|
813
864
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
814
865
|
|
|
815
866
|
"use strict";
|
|
@@ -840,7 +891,7 @@ class TrackData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
|
840
891
|
}
|
|
841
892
|
|
|
842
893
|
/***/ }),
|
|
843
|
-
/*
|
|
894
|
+
/* 14 */
|
|
844
895
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
845
896
|
|
|
846
897
|
"use strict";
|
|
@@ -848,10 +899,10 @@ class TrackData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
|
|
|
848
899
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
849
900
|
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
|
|
850
901
|
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__);
|
|
851
|
-
/* harmony import */ var _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(
|
|
852
|
-
/* harmony import */ var
|
|
853
|
-
/* harmony import */ var
|
|
854
|
-
/* harmony import */ var _util_result_from_cache_response_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(
|
|
902
|
+
/* harmony import */ var _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10);
|
|
903
|
+
/* harmony import */ var _hooks_use_server_effect_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8);
|
|
904
|
+
/* harmony import */ var _hooks_use_request_interception_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9);
|
|
905
|
+
/* harmony import */ var _util_result_from_cache_response_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(18);
|
|
855
906
|
|
|
856
907
|
|
|
857
908
|
|
|
@@ -872,27 +923,8 @@ const Data = ({
|
|
|
872
923
|
showOldDataWhileLoading,
|
|
873
924
|
alwaysRequestOnHydration
|
|
874
925
|
}) => {
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
// uses the interceptor.
|
|
878
|
-
const interceptorMap = react__WEBPACK_IMPORTED_MODULE_0__["useContext"](_intercept_context_js__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"]); // If we have an interceptor, we need to replace the handler with one
|
|
879
|
-
// that uses the interceptor. This helper function generates a new
|
|
880
|
-
// handler.
|
|
881
|
-
|
|
882
|
-
const maybeInterceptedHandler = react__WEBPACK_IMPORTED_MODULE_0__["useMemo"](() => {
|
|
883
|
-
const interceptor = interceptorMap[requestId];
|
|
884
|
-
|
|
885
|
-
if (interceptor == null) {
|
|
886
|
-
return handler;
|
|
887
|
-
}
|
|
888
|
-
|
|
889
|
-
return () => {
|
|
890
|
-
var _interceptor;
|
|
891
|
-
|
|
892
|
-
return (_interceptor = interceptor()) != null ? _interceptor : handler();
|
|
893
|
-
};
|
|
894
|
-
}, [handler, interceptorMap, requestId]);
|
|
895
|
-
const hydrateResult = Object(_hooks_use_server_effect_js__WEBPACK_IMPORTED_MODULE_4__[/* useServerEffect */ "a"])(requestId, maybeInterceptedHandler, hydrate);
|
|
926
|
+
const interceptedHandler = Object(_hooks_use_request_interception_js__WEBPACK_IMPORTED_MODULE_4__[/* useRequestInterception */ "a"])(requestId, handler);
|
|
927
|
+
const hydrateResult = Object(_hooks_use_server_effect_js__WEBPACK_IMPORTED_MODULE_3__[/* useServerEffect */ "a"])(requestId, interceptedHandler, hydrate);
|
|
896
928
|
const [currentResult, setResult] = react__WEBPACK_IMPORTED_MODULE_0__["useState"](hydrateResult); // Here we make sure the request still occurs client-side as needed.
|
|
897
929
|
// This is for legacy usage that expects this. Eventually we will want
|
|
898
930
|
// to deprecate.
|
|
@@ -928,7 +960,7 @@ const Data = ({
|
|
|
928
960
|
|
|
929
961
|
let cancel = false;
|
|
930
962
|
_util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__[/* RequestFulfillment */ "a"].Default.fulfill(requestId, {
|
|
931
|
-
handler:
|
|
963
|
+
handler: interceptedHandler
|
|
932
964
|
}).then(result => {
|
|
933
965
|
if (cancel) {
|
|
934
966
|
return;
|
|
@@ -973,7 +1005,7 @@ const Data = ({
|
|
|
973
1005
|
/* harmony default export */ __webpack_exports__["a"] = (Data);
|
|
974
1006
|
|
|
975
1007
|
/***/ }),
|
|
976
|
-
/*
|
|
1008
|
+
/* 15 */
|
|
977
1009
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
978
1010
|
|
|
979
1011
|
"use strict";
|
|
@@ -993,36 +1025,35 @@ const Data = ({
|
|
|
993
1025
|
* be picked up by `Data` component requests from outside the children of this
|
|
994
1026
|
* component.
|
|
995
1027
|
*
|
|
996
|
-
*
|
|
997
|
-
*
|
|
998
|
-
*
|
|
999
|
-
* will be replaced.
|
|
1028
|
+
* Interceptions within the same component tree are chained such that the
|
|
1029
|
+
* interceptor closest to the intercepted request is called first, and the
|
|
1030
|
+
* furthest interceptor is called last.
|
|
1000
1031
|
*/
|
|
1001
|
-
const
|
|
1002
|
-
|
|
1003
|
-
handler,
|
|
1032
|
+
const InterceptRequests = ({
|
|
1033
|
+
interceptor,
|
|
1004
1034
|
children
|
|
1005
1035
|
}) => {
|
|
1006
|
-
const
|
|
1007
|
-
const
|
|
1008
|
-
|
|
1009
|
-
|
|
1036
|
+
const interceptors = react__WEBPACK_IMPORTED_MODULE_0__["useContext"](_intercept_context_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"]);
|
|
1037
|
+
const updatedInterceptors = react__WEBPACK_IMPORTED_MODULE_0__["useMemo"]( // We could build this in reverse order so that our hook that does
|
|
1038
|
+
// the interception didn't have to use reduceRight, but I think it
|
|
1039
|
+
// is easier to think about if we do this in component tree order.
|
|
1040
|
+
() => [].concat(interceptors, [interceptor]), [interceptors, interceptor]);
|
|
1010
1041
|
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_intercept_context_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].Provider, {
|
|
1011
|
-
value:
|
|
1042
|
+
value: updatedInterceptors
|
|
1012
1043
|
}, children);
|
|
1013
1044
|
};
|
|
1014
1045
|
|
|
1015
|
-
/* harmony default export */ __webpack_exports__["a"] = (
|
|
1046
|
+
/* harmony default export */ __webpack_exports__["a"] = (InterceptRequests);
|
|
1016
1047
|
|
|
1017
1048
|
/***/ }),
|
|
1018
|
-
/*
|
|
1049
|
+
/* 16 */
|
|
1019
1050
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1020
1051
|
|
|
1021
1052
|
"use strict";
|
|
1022
1053
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return GqlRouter; });
|
|
1023
1054
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
1024
1055
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
1025
|
-
/* harmony import */ var _util_gql_router_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(
|
|
1056
|
+
/* harmony import */ var _util_gql_router_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11);
|
|
1026
1057
|
|
|
1027
1058
|
|
|
1028
1059
|
|
|
@@ -1059,15 +1090,15 @@ const GqlRouter = ({
|
|
|
1059
1090
|
};
|
|
1060
1091
|
|
|
1061
1092
|
/***/ }),
|
|
1062
|
-
/*
|
|
1093
|
+
/* 17 */
|
|
1063
1094
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1064
1095
|
|
|
1065
1096
|
"use strict";
|
|
1066
1097
|
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return useGql; });
|
|
1067
1098
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
|
|
1068
1099
|
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
|
|
1069
|
-
/* harmony import */ var _util_gql_router_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(
|
|
1070
|
-
/* harmony import */ var _util_get_gql_data_from_response_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(
|
|
1100
|
+
/* harmony import */ var _util_gql_router_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11);
|
|
1101
|
+
/* harmony import */ var _util_get_gql_data_from_response_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(19);
|
|
1071
1102
|
/* harmony import */ var _util_gql_error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2);
|
|
1072
1103
|
|
|
1073
1104
|
|
|
@@ -1138,7 +1169,7 @@ const useGql = () => {
|
|
|
1138
1169
|
};
|
|
1139
1170
|
|
|
1140
1171
|
/***/ }),
|
|
1141
|
-
/*
|
|
1172
|
+
/* 18 */
|
|
1142
1173
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1143
1174
|
|
|
1144
1175
|
"use strict";
|
|
@@ -1179,7 +1210,7 @@ const resultFromCachedResponse = cacheEntry => {
|
|
|
1179
1210
|
};
|
|
1180
1211
|
|
|
1181
1212
|
/***/ }),
|
|
1182
|
-
/*
|
|
1213
|
+
/* 19 */
|
|
1183
1214
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1184
1215
|
|
|
1185
1216
|
"use strict";
|
|
@@ -1247,7 +1278,7 @@ const getGqlDataFromResponse = async response => {
|
|
|
1247
1278
|
};
|
|
1248
1279
|
|
|
1249
1280
|
/***/ }),
|
|
1250
|
-
/*
|
|
1281
|
+
/* 20 */
|
|
1251
1282
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
1252
1283
|
|
|
1253
1284
|
"use strict";
|
|
@@ -1261,36 +1292,39 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
1261
1292
|
/* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__);
|
|
1262
1293
|
/* harmony import */ var _util_ssr_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
|
|
1263
1294
|
/* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6);
|
|
1264
|
-
/* harmony import */ var _components_track_data_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(
|
|
1295
|
+
/* harmony import */ var _components_track_data_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(13);
|
|
1265
1296
|
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "TrackData", function() { return _components_track_data_js__WEBPACK_IMPORTED_MODULE_3__["a"]; });
|
|
1266
1297
|
|
|
1267
|
-
/* harmony import */ var _components_data_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(
|
|
1298
|
+
/* harmony import */ var _components_data_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(14);
|
|
1268
1299
|
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Data", function() { return _components_data_js__WEBPACK_IMPORTED_MODULE_4__["a"]; });
|
|
1269
1300
|
|
|
1270
|
-
/* harmony import */ var
|
|
1271
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "
|
|
1301
|
+
/* harmony import */ var _components_intercept_requests_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(15);
|
|
1302
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "InterceptRequests", function() { return _components_intercept_requests_js__WEBPACK_IMPORTED_MODULE_5__["a"]; });
|
|
1272
1303
|
|
|
1273
1304
|
/* harmony import */ var _hooks_use_server_effect_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(8);
|
|
1274
1305
|
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useServerEffect", function() { return _hooks_use_server_effect_js__WEBPACK_IMPORTED_MODULE_6__["a"]; });
|
|
1275
1306
|
|
|
1276
|
-
/* harmony import */ var
|
|
1277
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "
|
|
1307
|
+
/* harmony import */ var _hooks_use_request_interception_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(9);
|
|
1308
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useRequestInterception", function() { return _hooks_use_request_interception_js__WEBPACK_IMPORTED_MODULE_7__["a"]; });
|
|
1309
|
+
|
|
1310
|
+
/* harmony import */ var _hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(12);
|
|
1311
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useSharedCache", function() { return _hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_8__["b"]; });
|
|
1278
1312
|
|
|
1279
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "clearSharedCache", function() { return
|
|
1313
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "clearSharedCache", function() { return _hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_8__["a"]; });
|
|
1280
1314
|
|
|
1281
|
-
/* harmony import */ var
|
|
1282
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ScopedInMemoryCache", function() { return
|
|
1315
|
+
/* harmony import */ var _util_scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(5);
|
|
1316
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ScopedInMemoryCache", function() { return _util_scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_9__["a"]; });
|
|
1283
1317
|
|
|
1284
|
-
/* harmony import */ var
|
|
1285
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlRouter", function() { return
|
|
1318
|
+
/* harmony import */ var _components_gql_router_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(16);
|
|
1319
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlRouter", function() { return _components_gql_router_js__WEBPACK_IMPORTED_MODULE_10__["a"]; });
|
|
1286
1320
|
|
|
1287
|
-
/* harmony import */ var
|
|
1288
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useGql", function() { return
|
|
1321
|
+
/* harmony import */ var _hooks_use_gql_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(17);
|
|
1322
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useGql", function() { return _hooks_use_gql_js__WEBPACK_IMPORTED_MODULE_11__["a"]; });
|
|
1289
1323
|
|
|
1290
|
-
/* harmony import */ var
|
|
1291
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlErrors", function() { return
|
|
1324
|
+
/* harmony import */ var _util_gql_error_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(2);
|
|
1325
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlErrors", function() { return _util_gql_error_js__WEBPACK_IMPORTED_MODULE_12__["b"]; });
|
|
1292
1326
|
|
|
1293
|
-
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlError", function() { return
|
|
1327
|
+
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlError", function() { return _util_gql_error_js__WEBPACK_IMPORTED_MODULE_12__["a"]; });
|
|
1294
1328
|
|
|
1295
1329
|
|
|
1296
1330
|
|
|
@@ -1317,6 +1351,7 @@ const removeAllFromCache = predicate => _util_ssr_cache_js__WEBPACK_IMPORTED_MOD
|
|
|
1317
1351
|
|
|
1318
1352
|
|
|
1319
1353
|
|
|
1354
|
+
|
|
1320
1355
|
// GraphQL
|
|
1321
1356
|
|
|
1322
1357
|
|
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@ import {View, Server} from "@khanacademy/wonder-blocks-core";
|
|
|
13
13
|
import {
|
|
14
14
|
Data,
|
|
15
15
|
initializeCache,
|
|
16
|
-
|
|
16
|
+
InterceptRequests,
|
|
17
17
|
TrackData,
|
|
18
18
|
fulfillAllDataRequests,
|
|
19
19
|
} from "@khanacademy/wonder-blocks-data";
|
|
@@ -135,13 +135,13 @@ describe("wonder-blocks-data", () => {
|
|
|
135
135
|
const myHandler = () =>
|
|
136
136
|
Promise.reject(new Error("You should not see this!"));
|
|
137
137
|
|
|
138
|
-
const
|
|
138
|
+
const interceptor = (requestId) =>
|
|
139
|
+
requestId === "INTERCEPT_EXAMPLE"
|
|
140
|
+
? Promise.resolve("INTERCEPTED DATA!")
|
|
141
|
+
: null;
|
|
139
142
|
|
|
140
143
|
const example = (
|
|
141
|
-
<
|
|
142
|
-
handler={interceptHandler}
|
|
143
|
-
requestId="INTERCEPT_EXAMPLE"
|
|
144
|
-
>
|
|
144
|
+
<InterceptRequests interceptor={interceptor}>
|
|
145
145
|
<View>
|
|
146
146
|
<Body>This received intercepted data!</Body>
|
|
147
147
|
<Data handler={myHandler} requestId="INTERCEPT_EXAMPLE">
|
|
@@ -154,7 +154,7 @@ describe("wonder-blocks-data", () => {
|
|
|
154
154
|
}}
|
|
155
155
|
</Data>
|
|
156
156
|
</View>
|
|
157
|
-
</
|
|
157
|
+
</InterceptRequests>
|
|
158
158
|
);
|
|
159
159
|
const tree = renderer.create(example).toJSON();
|
|
160
160
|
expect(tree).toMatchSnapshot();
|