@khanacademy/wonder-blocks-data 2.3.2 → 3.0.1

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 (41) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/es/index.js +210 -439
  3. package/dist/index.js +235 -478
  4. package/docs.md +19 -13
  5. package/package.json +6 -7
  6. package/src/__tests__/__snapshots__/generated-snapshot.test.js.snap +40 -160
  7. package/src/__tests__/generated-snapshot.test.js +15 -195
  8. package/src/components/__tests__/data.test.js +159 -965
  9. package/src/components/__tests__/intercept-data.test.js +9 -66
  10. package/src/components/__tests__/track-data.test.js +6 -5
  11. package/src/components/data.js +9 -119
  12. package/src/components/data.md +38 -60
  13. package/src/components/intercept-context.js +2 -3
  14. package/src/components/intercept-data.js +2 -34
  15. package/src/components/intercept-data.md +7 -105
  16. package/src/hooks/__tests__/use-data.test.js +826 -0
  17. package/src/hooks/use-data.js +143 -0
  18. package/src/index.js +1 -3
  19. package/src/util/__tests__/memory-cache.test.js +134 -35
  20. package/src/util/__tests__/request-fulfillment.test.js +21 -36
  21. package/src/util/__tests__/request-handler.test.js +30 -30
  22. package/src/util/__tests__/request-tracking.test.js +29 -30
  23. package/src/util/__tests__/response-cache.test.js +521 -561
  24. package/src/util/__tests__/result-from-cache-entry.test.js +68 -0
  25. package/src/util/memory-cache.js +20 -15
  26. package/src/util/request-fulfillment.js +4 -0
  27. package/src/util/request-handler.js +4 -28
  28. package/src/util/request-handler.md +0 -32
  29. package/src/util/request-tracking.js +2 -3
  30. package/src/util/response-cache.js +50 -110
  31. package/src/util/result-from-cache-entry.js +38 -0
  32. package/src/util/types.js +14 -35
  33. package/LICENSE +0 -21
  34. package/src/components/__tests__/intercept-cache.test.js +0 -124
  35. package/src/components/__tests__/internal-data.test.js +0 -1030
  36. package/src/components/intercept-cache.js +0 -79
  37. package/src/components/intercept-cache.md +0 -103
  38. package/src/components/internal-data.js +0 -219
  39. package/src/util/__tests__/no-cache.test.js +0 -112
  40. package/src/util/no-cache.js +0 -66
  41. package/src/util/no-cache.md +0 -66
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 = 14);
85
+ /******/ return __webpack_require__(__webpack_require__.s = 13);
86
86
  /******/ })
87
87
  /************************************************************************/
88
88
  /******/ ([
@@ -93,15 +93,19 @@ module.exports = require("react");
93
93
 
94
94
  /***/ }),
95
95
  /* 1 */
96
+ /***/ (function(module, exports) {
97
+
98
+ module.exports = require("@khanacademy/wonder-blocks-core");
99
+
100
+ /***/ }),
101
+ /* 2 */
96
102
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
97
103
 
98
104
  "use strict";
99
105
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ResponseCache; });
100
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
106
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
101
107
  /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__);
102
108
  /* harmony import */ var _memory_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
103
- /* harmony import */ var _no_cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
104
-
105
109
 
106
110
 
107
111
 
@@ -126,24 +130,22 @@ class ResponseCache {
126
130
  return _default;
127
131
  }
128
132
 
129
- constructor(memoryCache = null, ssrOnlyCache = null) {
133
+ constructor(hydrationCache = null, ssrOnlyCache = null) {
130
134
  this.initialize = source => {
131
- if (this._hydrationAndDefaultCache.inUse) {
135
+ if (this._hydrationCache.inUse) {
132
136
  throw new Error("Cannot initialize data response cache more than once");
133
137
  }
134
138
 
135
139
  try {
136
- this._hydrationAndDefaultCache = new _memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"](source);
140
+ this._hydrationCache = new _memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"](source);
137
141
  } catch (e) {
138
142
  throw new Error(`An error occurred trying to initialize the data response cache: ${e}`);
139
143
  }
140
144
  };
141
145
 
142
- this.cacheData = (handler, options, data) => {
143
- return this._setCacheEntry(handler, options, {
144
- data
145
- });
146
- };
146
+ this.cacheData = (handler, options, data) => this._setCacheEntry(handler, options, {
147
+ data
148
+ });
147
149
 
148
150
  this.cacheError = (handler, options, error) => {
149
151
  const errorMessage = typeof error === "string" ? error : error.message;
@@ -153,110 +155,64 @@ class ResponseCache {
153
155
  };
154
156
 
155
157
  this.getEntry = (handler, options) => {
156
- // If we're not server-side, and the handler has a custom cache
157
- // let's try to use it.
158
- if (this._ssrOnlyCache == null && handler.cache != null) {
159
- const entry = handler.cache.retrieve(handler, options);
160
-
161
- if (entry != null) {
162
- // Custom cache has an entry, so use it.
163
- return entry;
164
- }
165
- } // Get the internal entry for the handler.
166
- // This allows us to use our hydrated cache during hydration.
167
- // If we just returned null when the custom cache didn't have it,
168
- // we would never hydrate properly.
169
-
170
-
171
- const internalEntry = this._defaultCache(handler).retrieve(handler, options); // If we are not server-side and we hydrated something that the custom
172
- // cache didn't have, we need to make sure the custom cache contains
173
- // that value.
174
-
175
-
176
- if (this._ssrOnlyCache == null && handler.cache != null && internalEntry != null) {
177
- // Yes, if this throws, we will have a problem. We want that.
178
- // Bad cache implementations should be overt.
179
- handler.cache.store(handler, options, internalEntry); // We now delete this from our in-memory cache as we don't need it.
158
+ // Get the cached entry for this value.
159
+ // If the handler wants WB Data to hydrate (i.e. handler.hydrate is
160
+ // true), we use our hydration cache. Otherwise, if we're server-side
161
+ // we use our SSR-only cache. Otherwise, there's no entry to return.
162
+ const cache = handler.hydrate ? this._hydrationCache : _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide() ? this._ssrOnlyCache : undefined;
163
+ const internalEntry = cache == null ? void 0 : cache.retrieve(handler, options); // If we are not server-side and we hydrated something, let's clear
164
+ // that from the hydration cache to save memory.
165
+
166
+ if (this._ssrOnlyCache == null && internalEntry != null) {
167
+ // We now delete this from our hydration cache as we don't need it.
180
168
  // This does mean that if another handler of the same type but
181
- // without a custom cache won't get the value, but that's not an
182
- // expected valid usage of this framework - two handlers with
183
- // different caching options shouldn't be using the same type name.
184
-
185
- this._hydrationAndDefaultCache.remove(handler, options);
169
+ // without some sort of linked cache won't get the value, but
170
+ // that's not an expected use-case. If two different places use the
171
+ // same handler and options (i.e. the same request), then the
172
+ // handler should cater to that to ensure they share the result.
173
+ this._hydrationCache.remove(handler, options);
186
174
  }
187
175
 
188
176
  return internalEntry;
189
177
  };
190
178
 
191
179
  this.remove = (handler, options) => {
180
+ var _this$_ssrOnlyCache$r, _this$_ssrOnlyCache;
181
+
192
182
  // NOTE(somewhatabstract): We could invoke removeAll with a predicate
193
183
  // to match the key of the entry we're removing, but that's an
194
184
  // inefficient way to remove a single item, so let's not do that.
195
- // If we're not server-side, and the handler has a custom cache
196
- // let's try to use it.
197
- const customCache = this._ssrOnlyCache == null ? handler.cache : null;
198
- const removedCustom = !!(customCache != null && customCache.remove(handler, options)); // Delete the entry from our internal cache.
199
- // Even if we have a custom cache, we want to make sure we still
200
- // removed the same value from internal cache since this could be
201
- // getting called before hydration for some complex advanced usage
202
- // reason.
203
-
204
- return this._defaultCache(handler).remove(handler, options) || removedCustom;
185
+ // Delete the entry from the appropriate cache.
186
+ return handler.hydrate ? this._hydrationCache.remove(handler, options) : (_this$_ssrOnlyCache$r = (_this$_ssrOnlyCache = this._ssrOnlyCache) == null ? void 0 : _this$_ssrOnlyCache.remove(handler, options)) != null ? _this$_ssrOnlyCache$r : false;
205
187
  };
206
188
 
207
189
  this.removeAll = (handler, predicate) => {
208
- // If we're not server-side, and the handler has a custom cache
209
- // let's try to use it.
210
- const customCache = this._ssrOnlyCache == null ? handler.cache : null;
211
- const removedCountCustom = (customCache == null ? void 0 : customCache.removeAll(handler, predicate)) || 0; // Apply the predicate to what we have in our internal cached.
212
- // Even if we have a custom cache, we want to make sure we still
213
- // removed the same value from internal cache since this could be
214
- // getting called before hydration for some complex advanced usage
215
- // reason.
216
-
217
- const removedCount = this._defaultCache(handler).removeAll(handler, predicate); // We have no idea which keys were removed from which caches,
218
- // so we can't dedupe the remove counts based on keys.
219
- // That's why we return the total records deleted rather than the
220
- // total keys deleted.
221
-
222
-
223
- return removedCount + removedCountCustom;
190
+ var _this$_ssrOnlyCache$r2, _this$_ssrOnlyCache2;
191
+
192
+ // Apply the predicate to what we have in the appropriate cache.
193
+ return handler.hydrate ? this._hydrationCache.removeAll(handler, predicate) : (_this$_ssrOnlyCache$r2 = (_this$_ssrOnlyCache2 = this._ssrOnlyCache) == null ? void 0 : _this$_ssrOnlyCache2.removeAll(handler, predicate)) != null ? _this$_ssrOnlyCache$r2 : 0;
224
194
  };
225
195
 
226
196
  this.cloneHydratableData = () => {
227
197
  // We return our hydration cache only.
228
- return this._hydrationAndDefaultCache.cloneData();
198
+ return this._hydrationCache.cloneData();
229
199
  };
230
200
 
231
201
  this._ssrOnlyCache = _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide() ? ssrOnlyCache || new _memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"]() : undefined;
232
- this._hydrationAndDefaultCache = memoryCache || new _memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"]();
233
- }
234
- /**
235
- * Returns the default cache to use for the given handler.
236
- */
237
-
238
-
239
- _defaultCache(handler) {
240
- if (handler.hydrate) {
241
- return this._hydrationAndDefaultCache;
242
- } // If the handler doesn't want to hydrate, we return the SSR-only cache.
243
- // If we are client-side, we return our non-caching implementation.
244
-
245
-
246
- return this._ssrOnlyCache || _no_cache_js__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"].Default;
202
+ this._hydrationCache = hydrationCache || new _memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"]();
247
203
  }
248
204
 
249
205
  _setCacheEntry(handler, options, entry) {
250
206
  const frozenEntry = Object.freeze(entry);
251
207
 
252
- if (this._ssrOnlyCache == null && handler.cache != null) {
253
- // We are not server-side, and our handler has its own cache,
254
- // so we use that to store values.
255
- handler.cache.store(handler, options, frozenEntry);
256
- } else {
257
- // We are either server-side, or our handler doesn't provide
258
- // a caching override.
259
- this._defaultCache(handler).store(handler, options, frozenEntry);
208
+ if (this._ssrOnlyCache != null) {
209
+ // We are server-side.
210
+ // We need to store this value.
211
+ if (handler.hydrate) {
212
+ this._hydrationCache.store(handler, options, frozenEntry);
213
+ } else {
214
+ this._ssrOnlyCache.store(handler, options, frozenEntry);
215
+ }
260
216
  }
261
217
 
262
218
  return frozenEntry;
@@ -270,12 +226,6 @@ class ResponseCache {
270
226
 
271
227
  }
272
228
 
273
- /***/ }),
274
- /* 2 */
275
- /***/ (function(module, exports) {
276
-
277
- module.exports = require("@khanacademy/wonder-blocks-core");
278
-
279
229
  /***/ }),
280
230
  /* 3 */
281
231
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
@@ -285,7 +235,7 @@ module.exports = require("@khanacademy/wonder-blocks-core");
285
235
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return RequestTracker; });
286
236
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
287
237
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
288
- /* harmony import */ var _response_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
238
+ /* harmony import */ var _response_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
289
239
  /* harmony import */ var _request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6);
290
240
 
291
241
 
@@ -450,42 +400,138 @@ const InterceptContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["create
450
400
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
451
401
 
452
402
  "use strict";
453
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return NoCache; });
454
- let defaultInstance = null;
455
- /**
456
- * This is a cache implementation to use when no caching is wanted.
457
- *
458
- * Use this with your request handler if you want to support server-side
459
- * rendering of your data requests, but want to ensure data is never cached
460
- * on the client-side.
461
- *
462
- * This is better than having `shouldRefreshCache` always return `true` in the
463
- * handler as this ensures that cache space and memory are never used for the
464
- * requested data after hydration has finished.
465
- */
403
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return useData; });
404
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
405
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__);
406
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
407
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
408
+ /* harmony import */ var _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6);
409
+ /* harmony import */ var _components_intercept_context_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4);
410
+ /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(3);
411
+ /* harmony import */ var _util_result_from_cache_entry_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(12);
412
+ /* harmony import */ var _util_response_cache_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(2);
466
413
 
467
- class NoCache {
468
- constructor() {
469
- this.store = (handler, options, entry) => {
470
- /* empty */
471
- };
472
414
 
473
- this.retrieve = (handler, options) => null;
474
415
 
475
- this.remove = (handler, options) => false;
476
416
 
477
- this.removeAll = (handler, predicate) => 0;
478
- }
479
417
 
480
- static get Default() {
481
- if (defaultInstance == null) {
482
- defaultInstance = new NoCache();
418
+
419
+
420
+ const useData = (handler, options) => {
421
+ // If we're server-side or hydrating, we'll have a cached entry to use.
422
+ // So we get that and use it to initialize our state.
423
+ // This works in both hydration and SSR because the very first call to
424
+ // this will have cached data in those cases as it will be present on the
425
+ // initial render - and subsequent renders on the client it will be null.
426
+ const cachedResult = _util_response_cache_js__WEBPACK_IMPORTED_MODULE_6__[/* ResponseCache */ "a"].Default.getEntry(handler, options);
427
+ const [result, setResult] = Object(react__WEBPACK_IMPORTED_MODULE_1__["useState"])(cachedResult); // Lookup to see if there's an interceptor for the handler.
428
+ // If we have one, we need to replace the handler with one that
429
+ // uses the interceptor.
430
+
431
+ const interceptorMap = Object(react__WEBPACK_IMPORTED_MODULE_1__["useContext"])(_components_intercept_context_js__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"]);
432
+ const interceptor = interceptorMap[handler.type]; // If we have an interceptor, we need to replace the handler with one that
433
+ // uses the interceptor. This helper function generates a new handler.
434
+ // We need this before we track the request as we want the interceptor
435
+ // to also work for tracked requests to simplify testing the server-side
436
+ // request fulfillment.
437
+
438
+ const getMaybeInterceptedHandler = () => {
439
+ if (interceptor == null) {
440
+ return handler;
483
441
  }
484
442
 
485
- return defaultInstance;
486
- }
443
+ const fulfillRequestFn = options => {
444
+ var _interceptor$fulfillR;
487
445
 
488
- }
446
+ return (_interceptor$fulfillR = interceptor.fulfillRequest(options)) != null ? _interceptor$fulfillR : handler.fulfillRequest(options);
447
+ };
448
+
449
+ return {
450
+ fulfillRequest: fulfillRequestFn,
451
+ getKey: options => handler.getKey(options),
452
+ type: handler.type,
453
+ hydrate: handler.hydrate
454
+ };
455
+ }; // We only track data requests when we are server-side and we don't
456
+ // already have a result, as given by the cachedData (which is also the
457
+ // initial value for the result state).
458
+
459
+
460
+ const maybeTrack = Object(react__WEBPACK_IMPORTED_MODULE_1__["useContext"])(_util_request_tracking_js__WEBPACK_IMPORTED_MODULE_4__[/* TrackerContext */ "b"]);
461
+
462
+ if (result == null && _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide()) {
463
+ maybeTrack == null ? void 0 : maybeTrack(getMaybeInterceptedHandler(), options);
464
+ } // We need to update our request when the handler changes or the key
465
+ // to the options change, so we keep track of those.
466
+ // However, even if we are hydrating from cache, we still need to make the
467
+ // request at least once, so we do not initialize these references.
468
+
469
+
470
+ const handlerRef = Object(react__WEBPACK_IMPORTED_MODULE_1__["useRef"])();
471
+ const keyRef = Object(react__WEBPACK_IMPORTED_MODULE_1__["useRef"])();
472
+ const interceptorRef = Object(react__WEBPACK_IMPORTED_MODULE_1__["useRef"])(); // This effect will ensure that we fulfill the request as desired.
473
+
474
+ Object(react__WEBPACK_IMPORTED_MODULE_1__["useEffect"])(() => {
475
+ // If we are server-side, then just skip the effect. We track requests
476
+ // during SSR and fulfill them outside of the React render cycle.
477
+ // NOTE: This shouldn't happen since effects would not run on the server
478
+ // but let's be defensive - I think it makes the code clearer.
479
+
480
+ /* istanbul ignore next */
481
+ if (_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide()) {
482
+ return;
483
+ } // Update our refs to the current handler and key.
484
+
485
+
486
+ handlerRef.current = handler;
487
+ keyRef.current = handler.getKey(options);
488
+ interceptorRef.current = interceptor; // If we're not hydrating a result, we want to make sure we set our
489
+ // result to null so that we're in the loading state.
490
+
491
+ if (cachedResult == null) {
492
+ // Mark ourselves as loading.
493
+ setResult(null);
494
+ } // We aren't server-side, so let's make the request.
495
+ // The request handler is in control of whether that request actually
496
+ // happens or not.
497
+
498
+
499
+ let cancel = false;
500
+ _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__[/* RequestFulfillment */ "a"].Default.fulfill(getMaybeInterceptedHandler(), options).then(updateEntry => {
501
+ if (cancel) {
502
+ return;
503
+ }
504
+
505
+ setResult(updateEntry);
506
+ return;
507
+ }).catch(e => {
508
+ if (cancel) {
509
+ return;
510
+ }
511
+ /**
512
+ * We should never get here as errors in fulfillment are part
513
+ * of the `then`, but if we do.
514
+ */
515
+ // eslint-disable-next-line no-console
516
+
517
+
518
+ console.error(`Unexpected error occurred during data fulfillment: ${e}`);
519
+ setResult({
520
+ data: null,
521
+ error: typeof e === "string" ? e : e.message
522
+ });
523
+ return;
524
+ });
525
+ return () => {
526
+ cancel = true;
527
+ }; // - handler.getKey is a proxy for options
528
+ // - We don't want to trigger on cachedResult changing, we're
529
+ // just using that as a flag for render state if the other things
530
+ // trigger this effect.
531
+ // eslint-disable-next-line react-hooks/exhaustive-deps
532
+ }, [handler, handler.getKey(options), interceptor]);
533
+ return Object(_util_result_from_cache_entry_js__WEBPACK_IMPORTED_MODULE_5__[/* resultFromCacheEntry */ "a"])(result);
534
+ };
489
535
 
490
536
  /***/ }),
491
537
  /* 6 */
@@ -493,7 +539,7 @@ class NoCache {
493
539
 
494
540
  "use strict";
495
541
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return RequestFulfillment; });
496
- /* harmony import */ var _response_cache_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
542
+ /* harmony import */ var _response_cache_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
497
543
 
498
544
 
499
545
  let _default;
@@ -546,6 +592,8 @@ class RequestFulfillment {
546
592
  delete handlerRequests[key];
547
593
  /**
548
594
  * Let's cache the data!
595
+ *
596
+ * NOTE: This only caches when we're server side.
549
597
  */
550
598
 
551
599
  return cacheData(handler, options, data);
@@ -553,6 +601,8 @@ class RequestFulfillment {
553
601
  delete handlerRequests[key];
554
602
  /**
555
603
  * Let's cache the error!
604
+ *
605
+ * NOTE: This only caches when we're server side.
556
606
  */
557
607
 
558
608
  return cacheError(handler, options, error);
@@ -596,9 +646,7 @@ function deepClone(source) {
596
646
  *
597
647
  * Special case cache implementation for the memory cache.
598
648
  *
599
- * This is only used within our framework. Handlers don't need to
600
- * provide this as a custom cache as the framework will default to this in the
601
- * absence of a custom cache. We use this for SSR too (see ./response-cache.js).
649
+ * This is only used within our framework for SSR (see ./response-cache.js).
602
650
  */
603
651
 
604
652
 
@@ -606,7 +654,7 @@ class MemoryCache {
606
654
  constructor(source = null) {
607
655
  this.store = (handler, options, entry) => {
608
656
  const requestType = handler.type;
609
- const frozenEntry = Object.isFrozen(entry) ? entry : Object.freeze(entry); // Ensure we have a cache location for this handler type.
657
+ const frozenEntry = Object.freeze(entry); // Ensure we have a cache location for this handler type.
610
658
 
611
659
  this._cache[requestType] = this._cache[requestType] || {}; // Cache the data.
612
660
 
@@ -666,16 +714,22 @@ class MemoryCache {
666
714
 
667
715
  if (!handlerCache) {
668
716
  return 0;
669
- } // Apply the predicate to what we have cached.
670
-
717
+ }
671
718
 
672
719
  let removedCount = 0;
673
720
 
674
- for (const [key, entry] of Object.entries(handlerCache)) {
675
- if (typeof predicate !== "function" || predicate(key, entry)) {
676
- removedCount++;
677
- delete handlerCache[key];
721
+ if (typeof predicate === "function") {
722
+ // Apply the predicate to what we have cached.
723
+ for (const [key, entry] of Object.entries(handlerCache)) {
724
+ if (predicate(key, entry)) {
725
+ removedCount++;
726
+ delete handlerCache[key];
727
+ }
678
728
  }
729
+ } else {
730
+ // We're removing everything so delete the entire subcache.
731
+ removedCount = Object.keys(handlerCache).length;
732
+ delete this._cache[requestType];
679
733
  }
680
734
 
681
735
  return removedCount;
@@ -705,6 +759,12 @@ class MemoryCache {
705
759
  }
706
760
  }
707
761
  }
762
+ /**
763
+ * Indicate if this cache is being used or now.
764
+ *
765
+ * When the cache has entries, returns `true`; otherwise, returns `false`.
766
+ */
767
+
708
768
 
709
769
  get inUse() {
710
770
  return Object.keys(this._cache).length > 0;
@@ -725,9 +785,8 @@ class MemoryCache {
725
785
  * use with the Wonder Blocks Data framework.
726
786
  */
727
787
  class RequestHandler {
728
- constructor(type, cache, hydrate = true) {
788
+ constructor(type, hydrate = true) {
729
789
  this._type = type;
730
- this._cache = cache || null;
731
790
  this._hydrate = !!hydrate;
732
791
  }
733
792
 
@@ -735,26 +794,10 @@ class RequestHandler {
735
794
  return this._type;
736
795
  }
737
796
 
738
- get cache() {
739
- return this._cache;
740
- }
741
-
742
797
  get hydrate() {
743
798
  return this._hydrate;
744
799
  }
745
800
 
746
- shouldRefreshCache(options, cachedEntry) {
747
- /**
748
- * By default, the cache needs a refresh if the current entry is an
749
- * error.
750
- *
751
- * This means that an error will cause a re-request on render.
752
- * Useful if the server rendered an error, as it means the client
753
- * will update after rehydration.
754
- */
755
- return cachedEntry == null || cachedEntry.error != null;
756
- }
757
-
758
801
  getKey(options) {
759
802
  try {
760
803
  return options === undefined ? "undefined" : JSON.stringify(options);
@@ -777,7 +820,7 @@ class RequestHandler {
777
820
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return TrackData; });
778
821
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
779
822
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
780
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
823
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
781
824
  /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__);
782
825
  /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
783
826
 
@@ -805,14 +848,9 @@ class TrackData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
805
848
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
806
849
 
807
850
  "use strict";
808
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Data; });
809
851
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
810
852
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
811
- /* harmony import */ var _util_response_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
812
- /* harmony import */ var _internal_data_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(13);
813
- /* harmony import */ var _intercept_context_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4);
814
-
815
-
853
+ /* harmony import */ var _hooks_use_data_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
816
854
 
817
855
 
818
856
 
@@ -821,83 +859,12 @@ class TrackData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
821
859
  * requirements can be placed in a React application in a manner that will
822
860
  * support server-side rendering and efficient caching.
823
861
  */
824
- class Data extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
825
- _getHandlerFromInterceptor(interceptor) {
826
- const {
827
- handler
828
- } = this.props;
829
-
830
- if (!interceptor) {
831
- return handler;
832
- }
833
-
834
- const {
835
- fulfillRequest,
836
- shouldRefreshCache
837
- } = interceptor;
838
- const fulfillRequestFn = fulfillRequest ? options => {
839
- const interceptedResult = fulfillRequest(options);
840
- return interceptedResult != null ? interceptedResult : handler.fulfillRequest(options);
841
- } : options => handler.fulfillRequest(options);
842
- const shouldRefreshCacheFn = shouldRefreshCache ? (options, cacheEntry) => {
843
- const interceptedResult = shouldRefreshCache(options, cacheEntry);
844
- return interceptedResult != null ? interceptedResult : handler.shouldRefreshCache(options, cacheEntry);
845
- } : (options, cacheEntry) => handler.shouldRefreshCache(options, cacheEntry);
846
- return {
847
- fulfillRequest: fulfillRequestFn,
848
- shouldRefreshCache: shouldRefreshCacheFn,
849
- getKey: options => handler.getKey(options),
850
- type: handler.type,
851
- cache: handler.cache,
852
- hydrate: handler.hydrate
853
- };
854
- }
855
-
856
- _getCacheLookupFnFromInterceptor(interceptor) {
857
- const getEntry = interceptor && interceptor.getEntry;
858
-
859
- if (!getEntry) {
860
- return _util_response_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* ResponseCache */ "a"].Default.getEntry;
861
- }
862
-
863
- return (handler, options) => {
864
- // 1. Lookup the current cache value.
865
- const cacheEntry = _util_response_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* ResponseCache */ "a"].Default.getEntry(handler, options); // 2. See if our interceptor wants to override it.
866
-
867
- const interceptedData = getEntry(options, cacheEntry); // 3. Return the appropriate response.
868
-
869
- return interceptedData != null ? interceptedData : cacheEntry;
870
- };
871
- }
872
-
873
- render() {
874
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_intercept_context_js__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"].Consumer, null, value => {
875
- const handlerType = this.props.handler.type;
876
- const interceptor = value[handlerType];
877
-
878
- const handler = this._getHandlerFromInterceptor(interceptor);
879
-
880
- const getEntry = this._getCacheLookupFnFromInterceptor(interceptor);
881
- /**
882
- * Need to share our types with InternalData so Flow
883
- * doesn't need to infer them and find mismatches.
884
- * However, just deriving a new component creates issues
885
- * where InternalData starts rerendering too often.
886
- * Couldn't track down why, so suppressing the error
887
- * instead.
888
- */
889
-
890
-
891
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_internal_data_js__WEBPACK_IMPORTED_MODULE_2__[/* default */ "a"] // $FlowIgnore[incompatible-type-arg]
892
- , {
893
- handler: handler,
894
- options: this.props.options,
895
- getEntry: getEntry
896
- }, result => this.props.children(result));
897
- });
898
- }
862
+ const Data = props => {
863
+ const data = Object(_hooks_use_data_js__WEBPACK_IMPORTED_MODULE_1__[/* useData */ "a"])(props.handler, props.options);
864
+ return props.children(data);
865
+ };
899
866
 
900
- }
867
+ /* harmony default export */ __webpack_exports__["a"] = (Data);
901
868
 
902
869
  /***/ }),
903
870
  /* 11 */
@@ -916,9 +883,6 @@ class Data extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
916
883
  * type of a given handler and provide alternative results. This is mostly
917
884
  * useful for testing.
918
885
  *
919
- * Results from this interceptor will end up in the cache. If you
920
- * wish to only override the cache, use `InterceptCache` instead.
921
- *
922
886
  * This component is not recommended for use in production code as it
923
887
  * can prevent predictable functioning of the Wonder Blocks Data framework.
924
888
  * One possible side-effect is that inflight requests from the interceptor could
@@ -935,8 +899,7 @@ class InterceptData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
935
899
  return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_intercept_context_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].Consumer, null, value => {
936
900
  const handlerType = this.props.handler.type;
937
901
  const interceptor = { ...value[handlerType],
938
- fulfillRequest: this.props.fulfillRequest || null,
939
- shouldRefreshCache: this.props.shouldRefreshCache || null
902
+ fulfillRequest: this.props.fulfillRequest
940
903
  };
941
904
  const newValue = { ...value,
942
905
  [handlerType]: interceptor
@@ -954,248 +917,46 @@ class InterceptData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
954
917
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
955
918
 
956
919
  "use strict";
957
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return InterceptCache; });
958
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
959
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
960
- /* harmony import */ var _intercept_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
961
-
962
-
963
-
964
- /**
965
- * This component provides a mechanism to intercept cache lookups for the
966
- * type of a given handler and provide alternative values. This is mostly
967
- * useful for testing.
968
- *
969
- * This does not modify the cache in any way. If you want to intercept
970
- * requests and cache based on the intercept, then use `InterceptData`.
971
- *
972
- * This component is generally not suitable for use in production code as it
973
- * can prevent predictable functioning of the Wonder Blocks Data framework.
974
- *
975
- * These components do not chain. If a different `InterceptCache` instance is
976
- * rendered within this one that intercepts the same handler type, then that
977
- * new instance will replace this interceptor for its children.
978
- */
979
- class InterceptCache extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
980
- render() {
981
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_intercept_context_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].Consumer, null, value => {
982
- const handlerType = this.props.handler.type;
983
- const interceptor = { ...value[handlerType],
984
- getEntry: this.props.getEntry
985
- };
986
- const newValue = { ...value,
987
- [handlerType]: interceptor
988
- };
989
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_intercept_context_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].Provider, {
990
- value: newValue
991
- }, this.props.children);
992
- });
993
- }
994
-
995
- }
996
-
997
- /***/ }),
998
- /* 13 */
999
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
1000
-
1001
- "use strict";
1002
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return InternalData; });
1003
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
1004
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1005
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
1006
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__);
1007
- /* harmony import */ var _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6);
1008
- /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3);
1009
-
1010
-
1011
-
1012
-
1013
-
920
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return resultFromCacheEntry; });
1014
921
  /**
1015
- * This component is responsible for actually handling the data request.
1016
- * It is wrapped by Data in order to support intercepts and be exported for use.
1017
- *
1018
- * INTERNAL USE ONLY
922
+ * Turns a cache entry into a stateful result.
1019
923
  */
1020
- class InternalData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
1021
- constructor(props) {
1022
- super(props);
1023
- this.state = this._buildStateAndfulfillNeeds(props);
1024
- }
1025
-
1026
- componentDidMount() {
1027
- this._mounted = true;
1028
- }
1029
-
1030
- shouldComponentUpdate(nextProps, nextState) {
1031
- /**
1032
- * We only bother updating if our state changed.
1033
- *
1034
- * And we only update the state if props changed
1035
- * or we got new data/error.
1036
- */
1037
- if (!this._propsMatch(nextProps)) {
1038
- const newState = this._buildStateAndfulfillNeeds(nextProps);
1039
-
1040
- this.setState(newState);
1041
- }
1042
-
1043
- return this.state.loading !== nextState.loading || this.state.data !== nextState.data || this.state.error !== nextState.error;
1044
- }
1045
-
1046
- componentWillUnmount() {
1047
- this._mounted = false;
1048
- }
1049
-
1050
- _propsMatch(otherProps) {
1051
- const {
1052
- handler,
1053
- options
1054
- } = this.props;
1055
- const {
1056
- handler: prevHandler,
1057
- options: prevOptions
1058
- } = otherProps;
1059
- return handler === prevHandler && handler.getKey(options) === prevHandler.getKey(prevOptions);
1060
- }
1061
-
1062
- _buildStateAndfulfillNeeds(propsAtFulfillment) {
1063
- const {
1064
- getEntry,
1065
- handler,
1066
- options
1067
- } = propsAtFulfillment;
1068
- const cachedData = getEntry(handler, options);
1069
-
1070
- if (!_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__["Server"].isServerSide() && (cachedData == null || handler.shouldRefreshCache(options, cachedData))) {
1071
- /**
1072
- * We're not on the server, the cache missed, or our handler says
1073
- * we should refresh the cache.
1074
- *
1075
- * Therefore, we need to request data.
1076
- *
1077
- * We have to do this here from the constructor so that this
1078
- * data request is tracked when performing server-side rendering.
1079
- */
1080
- _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__[/* RequestFulfillment */ "a"].Default.fulfill(handler, options).then(cacheEntry => {
1081
- /**
1082
- * We get here, we should have updated the cache.
1083
- * However, we need to update the component, but we
1084
- * should only do that if the props are the same as they
1085
- * were when this was called.
1086
- */
1087
- if (this._mounted && this._propsMatch(propsAtFulfillment)) {
1088
- this.setState({
1089
- loading: false,
1090
- data: cacheEntry.data,
1091
- error: cacheEntry.error
1092
- });
1093
- }
1094
-
1095
- return null;
1096
- }).catch(e => {
1097
- /**
1098
- * We should never get here, but if we do.
1099
- */
1100
- // eslint-disable-next-line no-console
1101
- console.error(`Unexpected error occurred during data fulfillment: ${e}`);
1102
-
1103
- if (this._mounted && this._propsMatch(propsAtFulfillment)) {
1104
- this.setState({
1105
- loading: false,
1106
- data: null,
1107
- error: typeof e === "string" ? e : e.message
1108
- });
1109
- }
1110
-
1111
- return null;
1112
- });
1113
- }
1114
- /**
1115
- * This is the default response for the server and for the initial
1116
- * client-side render if we have cachedData.
1117
- *
1118
- * This ensures we don't make promises we don't want when doing
1119
- * server-side rendering. Instead, we either have data from the cache
1120
- * or we don't.
1121
- */
1122
-
1123
-
924
+ const resultFromCacheEntry = cacheEntry => {
925
+ // No cache entry means we didn't load one yet.
926
+ if (cacheEntry == null) {
1124
927
  return {
1125
- loading: cachedData == null,
1126
- data: cachedData && cachedData.data,
1127
- error: cachedData && cachedData.error
928
+ status: "loading"
1128
929
  };
1129
930
  }
1130
931
 
1131
- _resultFromState() {
1132
- const {
1133
- loading,
1134
- data,
1135
- error
1136
- } = this.state;
1137
-
1138
- if (loading) {
1139
- return {
1140
- loading: true
1141
- };
1142
- }
1143
-
1144
- if (data != null) {
1145
- return {
1146
- loading: false,
1147
- data
1148
- };
1149
- }
1150
-
1151
- if (error == null) {
1152
- // We should never get here ever.
1153
- throw new Error("Loaded result has invalid state where data and error are missing");
1154
- }
932
+ const {
933
+ data,
934
+ error
935
+ } = cacheEntry;
1155
936
 
937
+ if (data != null) {
1156
938
  return {
1157
- loading: false,
1158
- error
939
+ status: "success",
940
+ data
1159
941
  };
1160
942
  }
1161
943
 
1162
- _renderContent(result) {
1163
- const {
1164
- children
1165
- } = this.props;
1166
- return children(result);
1167
- }
1168
-
1169
- _renderWithTrackingContext(result) {
1170
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_util_request_tracking_js__WEBPACK_IMPORTED_MODULE_3__[/* TrackerContext */ "b"].Consumer, null, track => {
1171
- /**
1172
- * If data tracking wasn't enabled, don't do it.
1173
- */
1174
- if (track != null) {
1175
- track(this.props.handler, this.props.options);
1176
- }
1177
-
1178
- return this._renderContent(result);
1179
- });
1180
- }
1181
-
1182
- render() {
1183
- const result = this._resultFromState(); // We only track data requests when we are server-side and we don't
1184
- // already have a result. The existence of a result is indicated by the
1185
- // loading flag being false.
1186
-
1187
-
1188
- if (result.loading && _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__["Server"].isServerSide()) {
1189
- return this._renderWithTrackingContext(result);
1190
- }
1191
-
1192
- return this._renderContent(result);
944
+ if (error == null) {
945
+ // We should never get here ever.
946
+ return {
947
+ status: "error",
948
+ error: "Loaded result has invalid state where data and error are missing"
949
+ };
1193
950
  }
1194
951
 
1195
- }
952
+ return {
953
+ status: "error",
954
+ error
955
+ };
956
+ };
1196
957
 
1197
958
  /***/ }),
1198
- /* 14 */
959
+ /* 13 */
1199
960
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1200
961
 
1201
962
  "use strict";
@@ -1205,9 +966,9 @@ __webpack_require__.r(__webpack_exports__);
1205
966
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hasUnfulfilledRequests", function() { return hasUnfulfilledRequests; });
1206
967
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeFromCache", function() { return removeFromCache; });
1207
968
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeAllFromCache", function() { return removeAllFromCache; });
1208
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
969
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1209
970
  /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__);
1210
- /* harmony import */ var _util_response_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
971
+ /* harmony import */ var _util_response_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
1211
972
  /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
1212
973
  /* harmony import */ var _util_request_handler_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8);
1213
974
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "RequestHandler", function() { return _util_request_handler_js__WEBPACK_IMPORTED_MODULE_3__["a"]; });
@@ -1221,11 +982,8 @@ __webpack_require__.r(__webpack_exports__);
1221
982
  /* harmony import */ var _components_intercept_data_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(11);
1222
983
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "InterceptData", function() { return _components_intercept_data_js__WEBPACK_IMPORTED_MODULE_6__["a"]; });
1223
984
 
1224
- /* harmony import */ var _components_intercept_cache_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(12);
1225
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "InterceptCache", function() { return _components_intercept_cache_js__WEBPACK_IMPORTED_MODULE_7__["a"]; });
1226
-
1227
- /* harmony import */ var _util_no_cache_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(5);
1228
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "NoCache", function() { return _util_no_cache_js__WEBPACK_IMPORTED_MODULE_8__["a"]; });
985
+ /* harmony import */ var _hooks_use_data_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(5);
986
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useData", function() { return _hooks_use_data_js__WEBPACK_IMPORTED_MODULE_7__["a"]; });
1229
987
 
1230
988
 
1231
989
 
@@ -1259,6 +1017,5 @@ const removeAllFromCache = (handler, predicate) => _util_response_cache_js__WEBP
1259
1017
 
1260
1018
 
1261
1019
 
1262
-
1263
1020
  /***/ })
1264
1021
  /******/ ]);