@khanacademy/wonder-blocks-data 2.3.4 → 3.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/es/index.js +212 -446
  3. package/dist/index.js +230 -478
  4. package/docs.md +19 -13
  5. package/package.json +2 -3
  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 -117
  12. package/src/components/data.md +38 -60
  13. package/src/components/intercept-data.js +2 -34
  14. package/src/components/intercept-data.md +7 -105
  15. package/src/hooks/__tests__/use-data.test.js +790 -0
  16. package/src/hooks/use-data.js +138 -0
  17. package/src/index.js +1 -3
  18. package/src/util/__tests__/memory-cache.test.js +134 -35
  19. package/src/util/__tests__/request-fulfillment.test.js +21 -36
  20. package/src/util/__tests__/request-handler.test.js +30 -30
  21. package/src/util/__tests__/request-tracking.test.js +29 -30
  22. package/src/util/__tests__/response-cache.test.js +521 -561
  23. package/src/util/__tests__/result-from-cache-entry.test.js +68 -0
  24. package/src/util/memory-cache.js +18 -14
  25. package/src/util/request-fulfillment.js +4 -0
  26. package/src/util/request-handler.js +2 -27
  27. package/src/util/request-handler.md +0 -32
  28. package/src/util/response-cache.js +50 -110
  29. package/src/util/result-from-cache-entry.js +38 -0
  30. package/src/util/types.js +14 -35
  31. package/LICENSE +0 -21
  32. package/src/components/__tests__/intercept-cache.test.js +0 -124
  33. package/src/components/__tests__/internal-data.test.js +0 -1030
  34. package/src/components/intercept-cache.js +0 -79
  35. package/src/components/intercept-cache.md +0 -103
  36. package/src/components/internal-data.js +0 -219
  37. package/src/util/__tests__/no-cache.test.js +0 -112
  38. package/src/util/no-cache.js +0 -67
  39. 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,133 @@ 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); // We only track data requests when we are server-side and we don't
428
+ // already have a result, as given by the cachedData (which is also the
429
+ // initial value for the result state).
430
+
431
+ const maybeTrack = Object(react__WEBPACK_IMPORTED_MODULE_1__["useContext"])(_util_request_tracking_js__WEBPACK_IMPORTED_MODULE_4__[/* TrackerContext */ "b"]);
432
+
433
+ if (result == null && _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide()) {
434
+ maybeTrack == null ? void 0 : maybeTrack(handler, options);
435
+ } // Lookup to see if there's an interceptor for the handler.
436
+ // If we have one, we need to replace the handler with one that
437
+ // uses the interceptor.
438
+
439
+
440
+ const interceptorMap = Object(react__WEBPACK_IMPORTED_MODULE_1__["useContext"])(_components_intercept_context_js__WEBPACK_IMPORTED_MODULE_3__[/* default */ "a"]);
441
+ const interceptor = interceptorMap[handler.type]; // We need to update our request when the handler changes or the key
442
+ // to the options change, so we keep track of those.
443
+ // However, even if we are hydrating from cache, we still need to make the
444
+ // request at least once, so we do not initialize these references.
445
+
446
+ const handlerRef = Object(react__WEBPACK_IMPORTED_MODULE_1__["useRef"])();
447
+ const keyRef = Object(react__WEBPACK_IMPORTED_MODULE_1__["useRef"])();
448
+ const interceptorRef = Object(react__WEBPACK_IMPORTED_MODULE_1__["useRef"])(); // This effect will ensure that we fulfill the request as desired.
449
+
450
+ Object(react__WEBPACK_IMPORTED_MODULE_1__["useEffect"])(() => {
451
+ // If we are server-side, then just skip the effect. We track requests
452
+ // during SSR and fulfill them outside of the React render cycle.
453
+ // NOTE: This shouldn't happen since effects would not run on the server
454
+ // but let's be defensive - I think it makes the code clearer.
455
+
456
+ /* istanbul ignore next */
457
+ if (_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide()) {
458
+ return;
459
+ } // Update our refs to the current handler and key.
460
+
461
+
462
+ handlerRef.current = handler;
463
+ keyRef.current = handler.getKey(options);
464
+ interceptorRef.current = interceptor; // If we're not hydrating a result, we want to make sure we set our
465
+ // result to null so that we're in the loading state.
466
+
467
+ if (cachedResult == null) {
468
+ // Mark ourselves as loading.
469
+ setResult(null);
483
470
  }
484
471
 
485
- return defaultInstance;
486
- }
472
+ const getMaybeInterceptedHandler = () => {
473
+ if (interceptor == null) {
474
+ return handler;
475
+ }
487
476
 
488
- }
477
+ const fulfillRequestFn = options => {
478
+ var _interceptor$fulfillR;
479
+
480
+ return (_interceptor$fulfillR = interceptor.fulfillRequest(options)) != null ? _interceptor$fulfillR : handler.fulfillRequest(options);
481
+ };
482
+
483
+ return {
484
+ fulfillRequest: fulfillRequestFn,
485
+ getKey: options => handler.getKey(options),
486
+ type: handler.type,
487
+ hydrate: handler.hydrate
488
+ };
489
+ }; // We aren't server-side, so let's make the request.
490
+ // The request handler is in control of whether that request actually
491
+ // happens or not.
492
+
493
+
494
+ let cancel = false;
495
+ _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__[/* RequestFulfillment */ "a"].Default.fulfill(getMaybeInterceptedHandler(), options).then(updateEntry => {
496
+ if (cancel) {
497
+ return;
498
+ }
499
+
500
+ setResult(updateEntry);
501
+ return;
502
+ }).catch(e => {
503
+ if (cancel) {
504
+ return;
505
+ }
506
+ /**
507
+ * We should never get here as errors in fulfillment are part
508
+ * of the `then`, but if we do.
509
+ */
510
+ // eslint-disable-next-line no-console
511
+
512
+
513
+ console.error(`Unexpected error occurred during data fulfillment: ${e}`);
514
+ setResult({
515
+ data: null,
516
+ error: typeof e === "string" ? e : e.message
517
+ });
518
+ return;
519
+ });
520
+ return () => {
521
+ cancel = true;
522
+ }; // - handler.getKey is a proxy for options
523
+ // - We don't want to trigger on cachedResult changing, we're
524
+ // just using that as a flag for render state if the other things
525
+ // trigger this effect.
526
+ // eslint-disable-next-line react-hooks/exhaustive-deps
527
+ }, [handler, handler.getKey(options), interceptor]);
528
+ return Object(_util_result_from_cache_entry_js__WEBPACK_IMPORTED_MODULE_5__[/* resultFromCacheEntry */ "a"])(result);
529
+ };
489
530
 
490
531
  /***/ }),
491
532
  /* 6 */
@@ -493,7 +534,7 @@ class NoCache {
493
534
 
494
535
  "use strict";
495
536
  /* 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);
537
+ /* harmony import */ var _response_cache_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
497
538
 
498
539
 
499
540
  let _default;
@@ -546,6 +587,8 @@ class RequestFulfillment {
546
587
  delete handlerRequests[key];
547
588
  /**
548
589
  * Let's cache the data!
590
+ *
591
+ * NOTE: This only caches when we're server side.
549
592
  */
550
593
 
551
594
  return cacheData(handler, options, data);
@@ -553,6 +596,8 @@ class RequestFulfillment {
553
596
  delete handlerRequests[key];
554
597
  /**
555
598
  * Let's cache the error!
599
+ *
600
+ * NOTE: This only caches when we're server side.
556
601
  */
557
602
 
558
603
  return cacheError(handler, options, error);
@@ -596,9 +641,7 @@ function deepClone(source) {
596
641
  *
597
642
  * Special case cache implementation for the memory cache.
598
643
  *
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).
644
+ * This is only used within our framework for SSR (see ./response-cache.js).
602
645
  */
603
646
 
604
647
 
@@ -606,7 +649,7 @@ class MemoryCache {
606
649
  constructor(source = null) {
607
650
  this.store = (handler, options, entry) => {
608
651
  const requestType = handler.type;
609
- const frozenEntry = Object.isFrozen(entry) ? entry : Object.freeze(entry); // Ensure we have a cache location for this handler type.
652
+ const frozenEntry = Object.freeze(entry); // Ensure we have a cache location for this handler type.
610
653
 
611
654
  this._cache[requestType] = this._cache[requestType] || {}; // Cache the data.
612
655
 
@@ -666,16 +709,22 @@ class MemoryCache {
666
709
 
667
710
  if (!handlerCache) {
668
711
  return 0;
669
- } // Apply the predicate to what we have cached.
670
-
712
+ }
671
713
 
672
714
  let removedCount = 0;
673
715
 
674
- for (const [key, entry] of Object.entries(handlerCache)) {
675
- if (typeof predicate !== "function" || predicate(key, entry)) {
676
- removedCount++;
677
- delete handlerCache[key];
716
+ if (typeof predicate === "function") {
717
+ // Apply the predicate to what we have cached.
718
+ for (const [key, entry] of Object.entries(handlerCache)) {
719
+ if (predicate(key, entry)) {
720
+ removedCount++;
721
+ delete handlerCache[key];
722
+ }
678
723
  }
724
+ } else {
725
+ // We're removing everything so delete the entire subcache.
726
+ removedCount = Object.keys(handlerCache).length;
727
+ delete this._cache[requestType];
679
728
  }
680
729
 
681
730
  return removedCount;
@@ -705,6 +754,12 @@ class MemoryCache {
705
754
  }
706
755
  }
707
756
  }
757
+ /**
758
+ * Indicate if this cache is being used or now.
759
+ *
760
+ * When the cache has entries, returns `true`; otherwise, returns `false`.
761
+ */
762
+
708
763
 
709
764
  get inUse() {
710
765
  return Object.keys(this._cache).length > 0;
@@ -725,9 +780,8 @@ class MemoryCache {
725
780
  * use with the Wonder Blocks Data framework.
726
781
  */
727
782
  class RequestHandler {
728
- constructor(type, cache, hydrate = true) {
783
+ constructor(type, hydrate = true) {
729
784
  this._type = type;
730
- this._cache = cache || null;
731
785
  this._hydrate = !!hydrate;
732
786
  }
733
787
 
@@ -735,26 +789,10 @@ class RequestHandler {
735
789
  return this._type;
736
790
  }
737
791
 
738
- get cache() {
739
- return this._cache;
740
- }
741
-
742
792
  get hydrate() {
743
793
  return this._hydrate;
744
794
  }
745
795
 
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
796
  getKey(options) {
759
797
  try {
760
798
  return options === undefined ? "undefined" : JSON.stringify(options);
@@ -777,7 +815,7 @@ class RequestHandler {
777
815
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return TrackData; });
778
816
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
779
817
  /* 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);
818
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
781
819
  /* 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
820
  /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
783
821
 
@@ -805,14 +843,9 @@ class TrackData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
805
843
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
806
844
 
807
845
  "use strict";
808
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Data; });
809
846
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
810
847
  /* 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
-
848
+ /* harmony import */ var _hooks_use_data_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
816
849
 
817
850
 
818
851
 
@@ -821,83 +854,12 @@ class TrackData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
821
854
  * requirements can be placed in a React application in a manner that will
822
855
  * support server-side rendering and efficient caching.
823
856
  */
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
- }
857
+ const Data = props => {
858
+ const data = Object(_hooks_use_data_js__WEBPACK_IMPORTED_MODULE_1__[/* useData */ "a"])(props.handler, props.options);
859
+ return props.children(data);
860
+ };
899
861
 
900
- }
862
+ /* harmony default export */ __webpack_exports__["a"] = (Data);
901
863
 
902
864
  /***/ }),
903
865
  /* 11 */
@@ -916,9 +878,6 @@ class Data extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
916
878
  * type of a given handler and provide alternative results. This is mostly
917
879
  * useful for testing.
918
880
  *
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
881
  * This component is not recommended for use in production code as it
923
882
  * can prevent predictable functioning of the Wonder Blocks Data framework.
924
883
  * One possible side-effect is that inflight requests from the interceptor could
@@ -935,8 +894,7 @@ class InterceptData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
935
894
  return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_intercept_context_js__WEBPACK_IMPORTED_MODULE_1__[/* default */ "a"].Consumer, null, value => {
936
895
  const handlerType = this.props.handler.type;
937
896
  const interceptor = { ...value[handlerType],
938
- fulfillRequest: this.props.fulfillRequest || null,
939
- shouldRefreshCache: this.props.shouldRefreshCache || null
897
+ fulfillRequest: this.props.fulfillRequest
940
898
  };
941
899
  const newValue = { ...value,
942
900
  [handlerType]: interceptor
@@ -954,248 +912,46 @@ class InterceptData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
954
912
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
955
913
 
956
914
  "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
-
915
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return resultFromCacheEntry; });
1014
916
  /**
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
917
+ * Turns a cache entry into a stateful result.
1019
918
  */
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
-
919
+ const resultFromCacheEntry = cacheEntry => {
920
+ // No cache entry means we didn't load one yet.
921
+ if (cacheEntry == null) {
1124
922
  return {
1125
- loading: cachedData == null,
1126
- data: cachedData && cachedData.data,
1127
- error: cachedData && cachedData.error
923
+ status: "loading"
1128
924
  };
1129
925
  }
1130
926
 
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
- }
927
+ const {
928
+ data,
929
+ error
930
+ } = cacheEntry;
1155
931
 
932
+ if (data != null) {
1156
933
  return {
1157
- loading: false,
1158
- error
934
+ status: "success",
935
+ data
1159
936
  };
1160
937
  }
1161
938
 
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);
939
+ if (error == null) {
940
+ // We should never get here ever.
941
+ return {
942
+ status: "error",
943
+ error: "Loaded result has invalid state where data and error are missing"
944
+ };
1193
945
  }
1194
946
 
1195
- }
947
+ return {
948
+ status: "error",
949
+ error
950
+ };
951
+ };
1196
952
 
1197
953
  /***/ }),
1198
- /* 14 */
954
+ /* 13 */
1199
955
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1200
956
 
1201
957
  "use strict";
@@ -1205,9 +961,9 @@ __webpack_require__.r(__webpack_exports__);
1205
961
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hasUnfulfilledRequests", function() { return hasUnfulfilledRequests; });
1206
962
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeFromCache", function() { return removeFromCache; });
1207
963
  /* 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);
964
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1209
965
  /* 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);
966
+ /* harmony import */ var _util_response_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
1211
967
  /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
1212
968
  /* harmony import */ var _util_request_handler_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8);
1213
969
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "RequestHandler", function() { return _util_request_handler_js__WEBPACK_IMPORTED_MODULE_3__["a"]; });
@@ -1221,11 +977,8 @@ __webpack_require__.r(__webpack_exports__);
1221
977
  /* harmony import */ var _components_intercept_data_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(11);
1222
978
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "InterceptData", function() { return _components_intercept_data_js__WEBPACK_IMPORTED_MODULE_6__["a"]; });
1223
979
 
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"]; });
980
+ /* harmony import */ var _hooks_use_data_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(5);
981
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useData", function() { return _hooks_use_data_js__WEBPACK_IMPORTED_MODULE_7__["a"]; });
1229
982
 
1230
983
 
1231
984
 
@@ -1259,6 +1012,5 @@ const removeAllFromCache = (handler, predicate) => _util_response_cache_js__WEBP
1259
1012
 
1260
1013
 
1261
1014
 
1262
-
1263
1015
  /***/ })
1264
1016
  /******/ ]);