@khanacademy/wonder-blocks-data 7.0.1 → 8.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/es/index.js +286 -107
  3. package/dist/index.js +1089 -713
  4. package/package.json +1 -1
  5. package/src/__docs__/_overview_ssr_.stories.mdx +13 -13
  6. package/src/__docs__/exports.abort-inflight-requests.stories.mdx +20 -0
  7. package/src/__docs__/exports.data.stories.mdx +3 -3
  8. package/src/__docs__/{exports.fulfill-all-data-requests.stories.mdx → exports.fetch-tracked-requests.stories.mdx} +5 -5
  9. package/src/__docs__/exports.get-gql-request-id.stories.mdx +24 -0
  10. package/src/__docs__/{exports.has-unfulfilled-requests.stories.mdx → exports.has-tracked-requests-to-be-fetched.stories.mdx} +4 -4
  11. package/src/__docs__/exports.intialize-hydration-cache.stories.mdx +29 -0
  12. package/src/__docs__/exports.purge-caches.stories.mdx +23 -0
  13. package/src/__docs__/{exports.remove-all-from-cache.stories.mdx → exports.purge-hydration-cache.stories.mdx} +4 -4
  14. package/src/__docs__/{exports.clear-shared-cache.stories.mdx → exports.purge-shared-cache.stories.mdx} +4 -4
  15. package/src/__docs__/exports.track-data.stories.mdx +4 -4
  16. package/src/__docs__/exports.use-cached-effect.stories.mdx +7 -4
  17. package/src/__docs__/exports.use-gql.stories.mdx +1 -33
  18. package/src/__docs__/exports.use-server-effect.stories.mdx +1 -1
  19. package/src/__docs__/exports.use-shared-cache.stories.mdx +2 -2
  20. package/src/__docs__/types.fetch-policy.stories.mdx +44 -0
  21. package/src/__docs__/types.response-cache.stories.mdx +1 -1
  22. package/src/__tests__/generated-snapshot.test.js +5 -5
  23. package/src/components/__tests__/data.test.js +2 -6
  24. package/src/hooks/__tests__/use-cached-effect.test.js +341 -100
  25. package/src/hooks/__tests__/use-hydratable-effect.test.js +15 -9
  26. package/src/hooks/__tests__/use-shared-cache.test.js +6 -6
  27. package/src/hooks/use-cached-effect.js +169 -93
  28. package/src/hooks/use-hydratable-effect.js +8 -1
  29. package/src/hooks/use-shared-cache.js +2 -2
  30. package/src/index.js +14 -78
  31. package/src/util/__tests__/get-gql-request-id.test.js +74 -0
  32. package/src/util/__tests__/graphql-document-node-parser.test.js +542 -0
  33. package/src/util/__tests__/hydration-cache-api.test.js +35 -0
  34. package/src/util/__tests__/purge-caches.test.js +29 -0
  35. package/src/util/__tests__/request-api.test.js +188 -0
  36. package/src/util/__tests__/request-fulfillment.test.js +42 -0
  37. package/src/util/__tests__/ssr-cache.test.js +58 -60
  38. package/src/util/__tests__/to-gql-operation.test.js +42 -0
  39. package/src/util/data-error.js +6 -0
  40. package/src/util/get-gql-request-id.js +50 -0
  41. package/src/util/graphql-document-node-parser.js +133 -0
  42. package/src/util/graphql-types.js +30 -0
  43. package/src/util/hydration-cache-api.js +28 -0
  44. package/src/util/purge-caches.js +15 -0
  45. package/src/util/request-api.js +66 -0
  46. package/src/util/request-fulfillment.js +32 -12
  47. package/src/util/request-tracking.js +1 -1
  48. package/src/util/ssr-cache.js +13 -31
  49. package/src/util/to-gql-operation.js +44 -0
  50. package/src/util/types.js +31 -0
  51. package/src/__docs__/exports.intialize-cache.stories.mdx +0 -29
  52. package/src/__docs__/exports.remove-from-cache.stories.mdx +0 -25
  53. package/src/__docs__/exports.request-fulfillment.stories.mdx +0 -36
package/dist/index.js CHANGED
@@ -82,23 +82,17 @@ module.exports =
82
82
  /******/
83
83
  /******/
84
84
  /******/ // Load entry module and return exports
85
- /******/ return __webpack_require__(__webpack_require__.s = 27);
85
+ /******/ return __webpack_require__(__webpack_require__.s = 35);
86
86
  /******/ })
87
87
  /************************************************************************/
88
88
  /******/ ([
89
89
  /* 0 */
90
- /***/ (function(module, exports) {
91
-
92
- module.exports = require("react");
93
-
94
- /***/ }),
95
- /* 1 */
96
90
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
97
91
 
98
92
  "use strict";
99
93
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return DataErrors; });
100
94
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return DataError; });
101
- /* harmony import */ var _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
95
+ /* harmony import */ var _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
102
96
  /* harmony import */ var _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0__);
103
97
 
104
98
 
@@ -126,6 +120,12 @@ const DataErrors = Object.freeze({
126
120
  */
127
121
  Network: "Network",
128
122
 
123
+ /**
124
+ * There was a problem due to the state of the system not matching the
125
+ * requested operation or input.
126
+ */
127
+ NotAllowed: "NotAllowed",
128
+
129
129
  /**
130
130
  * Response could not be parsed.
131
131
  */
@@ -157,6 +157,12 @@ class DataError extends _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_
157
157
 
158
158
  }
159
159
 
160
+ /***/ }),
161
+ /* 1 */
162
+ /***/ (function(module, exports) {
163
+
164
+ module.exports = require("react");
165
+
160
166
  /***/ }),
161
167
  /* 2 */
162
168
  /***/ (function(module, exports) {
@@ -167,10 +173,34 @@ module.exports = require("@khanacademy/wonder-blocks-core");
167
173
  /* 3 */
168
174
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
169
175
 
176
+ "use strict";
177
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return FetchPolicy; });
178
+ // TODO(somewhatabstract, FEI-4172): Update eslint-plugin-flowtype when
179
+ // they've fixed https://github.com/gajus/eslint-plugin-flowtype/issues/502
180
+
181
+ /* eslint-disable no-undef */
182
+
183
+ /**
184
+ * Defines the various fetch policies that can be applied to requests.
185
+ */
186
+ const FetchPolicy = __webpack_require__(22).Mirrored(["CacheBeforeNetwork", "CacheAndNetwork", "CacheOnly", "NetworkOnly"]);
187
+ /* eslint-enable no-undef */
188
+
189
+ /**
190
+ * Define what can be cached.
191
+ *
192
+ * We disallow functions and undefined as undefined represents a cache miss
193
+ * and functions are not allowed.
194
+ */
195
+
196
+ /***/ }),
197
+ /* 4 */
198
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
199
+
170
200
  "use strict";
171
201
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return GqlErrors; });
172
202
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return GqlError; });
173
- /* harmony import */ var _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
203
+ /* harmony import */ var _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
174
204
  /* harmony import */ var _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0__);
175
205
 
176
206
 
@@ -215,201 +245,143 @@ class GqlError extends _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0
215
245
  }
216
246
 
217
247
  /***/ }),
218
- /* 4 */
248
+ /* 5 */
219
249
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
220
250
 
221
251
  "use strict";
222
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Status; });
223
- const loadingStatus = Object.freeze({
224
- status: "loading"
225
- });
226
- const abortedStatus = Object.freeze({
227
- status: "aborted"
228
- });
229
- /**
230
- * Create Result<TData> instances with specific statuses.
231
- */
232
-
233
- const Status = Object.freeze({
234
- loading: () => loadingStatus,
235
- aborted: () => abortedStatus,
236
- success: data => ({
237
- status: "success",
238
- data
239
- }),
240
- error: error => ({
241
- status: "error",
242
- error
243
- })
244
- });
252
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return purgeSharedCache; });
253
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return useSharedCache; });
254
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
255
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
256
+ /* harmony import */ var _util_data_error_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
257
+ /* harmony import */ var _util_scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11);
245
258
 
246
- /***/ }),
247
- /* 5 */
248
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
249
259
 
250
- "use strict";
251
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SsrCache; });
252
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
253
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__);
254
- /* harmony import */ var _serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12);
255
260
 
256
261
 
257
- const DefaultScope = "default";
258
262
  /**
259
- * The default instance is stored here.
260
- * It's created below in the Default() static property.
263
+ * This is the cache.
264
+ * It's incredibly complex.
265
+ * Very in-memory. So cache. Such complex. Wow.
266
+ */
267
+ const cache = new _util_scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_2__[/* ScopedInMemoryCache */ "a"]();
268
+ /**
269
+ * Purge the in-memory cache or a single scope within it.
261
270
  */
262
271
 
263
- let _default;
272
+ const purgeSharedCache = (scope = "") => {
273
+ // If we have a valid scope (empty string is falsy), then clear that scope.
274
+ if (scope && typeof scope === "string") {
275
+ cache.purgeScope(scope);
276
+ } else {
277
+ // Just reset the object. This should be sufficient.
278
+ cache.purgeAll();
279
+ }
280
+ };
264
281
  /**
265
- * Implements the response cache.
282
+ * Hook to retrieve data from and store data in an in-memory cache.
266
283
  *
267
- * INTERNAL USE ONLY
284
+ * @returns {[?ReadOnlyCacheValue, CacheValueFn]}
285
+ * Returns an array containing the current cache entry (or undefined), a
286
+ * function to set the cache entry (passing null or undefined to this function
287
+ * will delete the entry).
288
+ *
289
+ * To clear a single scope within the cache or the entire cache,
290
+ * the `clearScopedCache` export is available.
291
+ *
292
+ * NOTE: Unlike useState or useReducer, we don't automatically update folks
293
+ * if the value they reference changes. We might add it later (if we need to),
294
+ * but the likelihood here is that things won't be changing in this cache in a
295
+ * way where we would need that. If we do (and likely only in specific
296
+ * circumstances), we should consider adding a simple boolean useState that can
297
+ * be toggled to cause a rerender whenever the referenced cached data changes
298
+ * so that callers can re-render on cache changes. However, we should make
299
+ * sure this toggling is optional - or we could use a callback argument, to
300
+ * achieve this on an as-needed basis.
268
301
  */
269
302
 
270
-
271
- class SsrCache {
272
- static get Default() {
273
- if (!_default) {
274
- _default = new SsrCache();
275
- }
276
-
277
- return _default;
303
+ const useSharedCache = (id, scope, initialValue) => {
304
+ // Verify arguments.
305
+ if (!id || typeof id !== "string") {
306
+ throw new _util_data_error_js__WEBPACK_IMPORTED_MODULE_1__[/* DataError */ "a"]("id must be a non-empty string", _util_data_error_js__WEBPACK_IMPORTED_MODULE_1__[/* DataErrors */ "b"].InvalidInput);
278
307
  }
279
308
 
280
- constructor(hydrationCache = null, ssrOnlyCache = null) {
281
- this.initialize = source => {
282
- if (this._hydrationCache.inUse) {
283
- throw new Error("Cannot initialize data response cache more than once");
284
- }
285
-
286
- this._hydrationCache = new _serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* SerializableInMemoryCache */ "a"]({
287
- // $FlowIgnore[incompatible-call]
288
- [DefaultScope]: source
289
- });
290
- };
291
-
292
- this.cacheData = (id, data, hydrate) => this._setCachedResponse(id, {
293
- data
294
- }, hydrate);
295
-
296
- this.cacheError = (id, error, hydrate) => {
297
- const errorMessage = typeof error === "string" ? error : error.message;
298
- return this._setCachedResponse(id, {
299
- error: errorMessage
300
- }, hydrate);
301
- };
302
-
303
- this.getEntry = id => {
304
- var _this$_ssrOnlyCache$g, _this$_ssrOnlyCache;
305
-
306
- // Get the cached entry for this value.
307
- // We first look in the ssr cache and then the hydration cache.
308
- const internalEntry = (_this$_ssrOnlyCache$g = (_this$_ssrOnlyCache = this._ssrOnlyCache) == null ? void 0 : _this$_ssrOnlyCache.get(DefaultScope, id)) != null ? _this$_ssrOnlyCache$g : this._hydrationCache.get(DefaultScope, id); // If we are not server-side and we hydrated something, let's clear
309
- // that from the hydration cache to save memory.
310
-
311
- if (this._ssrOnlyCache == null && internalEntry != null) {
312
- // We now delete this from our hydration cache as we don't need it.
313
- // This does mean that if another handler of the same type but
314
- // without some sort of linked cache won't get the value, but
315
- // that's not an expected use-case. If two different places use the
316
- // same handler and options (i.e. the same request), then the
317
- // handler should cater to that to ensure they share the result.
318
- this._hydrationCache.purge(DefaultScope, id);
319
- } // Getting the typing right between the in-memory cache and this
320
- // is hard. Just telling flow it's OK.
321
- // $FlowIgnore[incompatible-return]
322
-
323
-
324
- return internalEntry;
325
- };
326
-
327
- this.remove = id => {
328
- var _this$_ssrOnlyCache$p, _this$_ssrOnlyCache2;
329
-
330
- // NOTE(somewhatabstract): We could invoke removeAll with a predicate
331
- // to match the key of the entry we're removing, but that's an
332
- // inefficient way to remove a single item, so let's not do that.
333
- // Delete the entry from the appropriate cache.
334
- return this._hydrationCache.purge(DefaultScope, id) || ((_this$_ssrOnlyCache$p = (_this$_ssrOnlyCache2 = this._ssrOnlyCache) == null ? void 0 : _this$_ssrOnlyCache2.purge(DefaultScope, id)) != null ? _this$_ssrOnlyCache$p : false);
335
- };
336
-
337
- this.removeAll = predicate => {
338
- var _this$_ssrOnlyCache3;
339
-
340
- const realPredicate = predicate ? // We know what we're putting into the cache so let's assume it
341
- // conforms.
342
- // $FlowIgnore[incompatible-call]
343
- (_, key, cachedEntry) => predicate(key, cachedEntry) : undefined; // Apply the predicate to what we have in our caches.
344
-
345
- this._hydrationCache.purgeAll(realPredicate);
346
-
347
- (_this$_ssrOnlyCache3 = this._ssrOnlyCache) == null ? void 0 : _this$_ssrOnlyCache3.purgeAll(realPredicate);
348
- };
309
+ if (!scope || typeof scope !== "string") {
310
+ throw new _util_data_error_js__WEBPACK_IMPORTED_MODULE_1__[/* DataError */ "a"]("scope must be a non-empty string", _util_data_error_js__WEBPACK_IMPORTED_MODULE_1__[/* DataErrors */ "b"].InvalidInput);
311
+ } // Memoize our APIs.
312
+ // This one allows callers to set or replace the cached value.
349
313
 
350
- this.cloneHydratableData = () => {
351
- var _cache$DefaultScope;
352
314
 
353
- // We return our hydration cache only.
354
- const cache = this._hydrationCache.clone(); // If we're empty, we still want to return an object, so we default
355
- // to an empty object.
356
- // We only need the default scope out of our scoped in-memory cache.
357
- // We know that it conforms to our expectations.
358
- // $FlowIgnore[incompatible-return]
315
+ const cacheValue = react__WEBPACK_IMPORTED_MODULE_0__["useCallback"](value => value == null ? cache.purge(scope, id) : cache.set(scope, id, value), [id, scope]); // We don't memo-ize the current value, just in case the cache was updated
316
+ // since our last run through. Also, our cache does not know what type it
317
+ // stores, so we have to cast it to the type we're exporting. This is a
318
+ // dev time courtesy, rather than a runtime thing.
319
+ // $FlowIgnore[incompatible-type]
359
320
 
321
+ let currentValue = cache.get(scope, id); // If we have an initial value, we need to add it to the cache
322
+ // and use it as our current value.
360
323
 
361
- return (_cache$DefaultScope = cache[DefaultScope]) != null ? _cache$DefaultScope : {};
362
- };
324
+ if (currentValue == null && initialValue !== undefined) {
325
+ // Get the initial value.
326
+ const value = typeof initialValue === "function" ? initialValue() : initialValue;
363
327
 
364
- this._ssrOnlyCache = _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide() ? ssrOnlyCache || new _serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* SerializableInMemoryCache */ "a"]() : undefined;
365
- this._hydrationCache = hydrationCache || new _serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* SerializableInMemoryCache */ "a"]();
366
- }
328
+ if (value != null) {
329
+ // Update the cache.
330
+ cacheValue(value); // Make sure we return this value as our current value.
367
331
 
368
- _setCachedResponse(id, entry, hydrate) {
369
- const frozenEntry = Object.freeze(entry);
332
+ currentValue = value;
333
+ }
334
+ } // Now we have everything, let's return it.
370
335
 
371
- if (_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide()) {
372
- // We are server-side.
373
- // We need to store this value.
374
- if (hydrate) {
375
- this._hydrationCache.set(DefaultScope, id, frozenEntry);
376
- } else {
377
- var _this$_ssrOnlyCache4;
378
336
 
379
- // Usually, when server-side, this cache will always be present.
380
- // We do fake server-side in our doc example though, when it
381
- // won't be.
382
- (_this$_ssrOnlyCache4 = this._ssrOnlyCache) == null ? void 0 : _this$_ssrOnlyCache4.set(DefaultScope, id, frozenEntry);
383
- }
384
- }
337
+ return [currentValue, cacheValue];
338
+ };
385
339
 
386
- return frozenEntry;
387
- }
388
- /**
389
- * Initialize the cache from a given cache state.
390
- *
391
- * This can only be called if the cache is not already in use.
392
- */
340
+ /***/ }),
341
+ /* 6 */
342
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
393
343
 
344
+ "use strict";
345
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return Status; });
346
+ const loadingStatus = Object.freeze({
347
+ status: "loading"
348
+ });
349
+ const abortedStatus = Object.freeze({
350
+ status: "aborted"
351
+ });
352
+ /**
353
+ * Create Result<TData> instances with specific statuses.
354
+ */
394
355
 
395
- }
356
+ const Status = Object.freeze({
357
+ loading: () => loadingStatus,
358
+ aborted: () => abortedStatus,
359
+ success: data => ({
360
+ status: "success",
361
+ data
362
+ }),
363
+ error: error => ({
364
+ status: "error",
365
+ error
366
+ })
367
+ });
396
368
 
397
369
  /***/ }),
398
- /* 6 */
370
+ /* 7 */
399
371
  /***/ (function(module, exports) {
400
372
 
401
373
  module.exports = require("@khanacademy/wonder-stuff-core");
402
374
 
403
375
  /***/ }),
404
- /* 7 */
376
+ /* 8 */
405
377
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
406
378
 
407
379
  "use strict";
408
380
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return TrackerContext; });
409
381
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return RequestTracker; });
410
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
382
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
411
383
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
412
- /* harmony import */ var _ssr_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
384
+ /* harmony import */ var _ssr_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9);
413
385
  /* harmony import */ var _request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10);
414
386
 
415
387
 
@@ -420,7 +392,7 @@ module.exports = require("@khanacademy/wonder-stuff-core");
420
392
  *
421
393
  * INTERNAL USE ONLY
422
394
  */
423
- const TrackerContext = new react__WEBPACK_IMPORTED_MODULE_0__["createContext"](null);
395
+ const TrackerContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createContext"](null);
424
396
  /**
425
397
  * The default instance is stored here.
426
398
  * It's created below in the Default() static property.
@@ -579,105 +551,243 @@ class RequestTracker {
579
551
  }
580
552
 
581
553
  /***/ }),
582
- /* 8 */
554
+ /* 9 */
583
555
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
584
556
 
585
557
  "use strict";
586
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return clearSharedCache; });
587
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return useSharedCache; });
588
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
589
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
590
- /* harmony import */ var _util_data_error_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
591
- /* harmony import */ var _util_scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9);
592
-
593
-
558
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SsrCache; });
559
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
560
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__);
561
+ /* harmony import */ var _serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(13);
594
562
 
595
563
 
564
+ const DefaultScope = "default";
596
565
  /**
597
- * This is the cache.
598
- * It's incredibly complex.
599
- * Very in-memory. So cache. Such complex. Wow.
566
+ * The default instance is stored here.
567
+ * It's created below in the Default() static property.
600
568
  */
601
- const cache = new _util_scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_2__[/* ScopedInMemoryCache */ "a"]();
569
+
570
+ let _default;
602
571
  /**
603
- * Clear the in-memory cache or a single scope within it.
572
+ * Implements the response cache.
573
+ *
574
+ * INTERNAL USE ONLY
604
575
  */
605
576
 
606
- const clearSharedCache = (scope = "") => {
607
- // If we have a valid scope (empty string is falsy), then clear that scope.
608
- if (scope && typeof scope === "string") {
609
- cache.purgeScope(scope);
610
- } else {
611
- // Just reset the object. This should be sufficient.
612
- cache.purgeAll();
577
+
578
+ class SsrCache {
579
+ static get Default() {
580
+ if (!_default) {
581
+ _default = new SsrCache();
582
+ }
583
+
584
+ return _default;
613
585
  }
614
- };
586
+
587
+ constructor(hydrationCache = null, ssrOnlyCache = null) {
588
+ this.initialize = source => {
589
+ if (this._hydrationCache.inUse) {
590
+ throw new Error("Cannot initialize data response cache more than once");
591
+ }
592
+
593
+ this._hydrationCache = new _serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* SerializableInMemoryCache */ "a"]({
594
+ // $FlowIgnore[incompatible-call]
595
+ [DefaultScope]: source
596
+ });
597
+ };
598
+
599
+ this.cacheData = (id, data, hydrate) => this._setCachedResponse(id, {
600
+ data
601
+ }, hydrate);
602
+
603
+ this.cacheError = (id, error, hydrate) => {
604
+ const errorMessage = typeof error === "string" ? error : error.message;
605
+ return this._setCachedResponse(id, {
606
+ error: errorMessage
607
+ }, hydrate);
608
+ };
609
+
610
+ this.getEntry = id => {
611
+ // Get the cached entry for this value.
612
+ // We first look in the ssr cache, if we need to.
613
+ const ssrEntry = _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide() ? this._ssrOnlyCache.get(DefaultScope, id) : null; // Now we defer to the SSR value, and fallback to the hydration cache.
614
+
615
+ const internalEntry = ssrEntry != null ? ssrEntry : this._hydrationCache.get(DefaultScope, id); // If we are not server-side and we hydrated something, let's clear
616
+ // that from the hydration cache to save memory.
617
+
618
+ if (!_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide() && internalEntry != null) {
619
+ // We now delete this from our hydration cache as we don't need it.
620
+ // This does mean that if another handler of the same type but
621
+ // without some sort of linked cache won't get the value, but
622
+ // that's not an expected use-case. If two different places use the
623
+ // same handler and options (i.e. the same request), then the
624
+ // handler should cater to that to ensure they share the result.
625
+ this._hydrationCache.purge(DefaultScope, id);
626
+ } // Getting the typing right between the in-memory cache and this
627
+ // is hard. Just telling flow it's OK.
628
+ // $FlowIgnore[incompatible-return]
629
+
630
+
631
+ return internalEntry;
632
+ };
633
+
634
+ this.purgeData = predicate => {
635
+ const realPredicate = predicate ? // We know what we're putting into the cache so let's assume it
636
+ // conforms.
637
+ // $FlowIgnore[incompatible-call]
638
+ (_, key, cachedEntry) => predicate(key, cachedEntry) : undefined; // Apply the predicate to what we have in our caches.
639
+
640
+ this._hydrationCache.purgeAll(realPredicate);
641
+
642
+ this._ssrOnlyCache.purgeAll(realPredicate);
643
+ };
644
+
645
+ this.cloneHydratableData = () => {
646
+ var _cache$DefaultScope;
647
+
648
+ // We return our hydration cache only.
649
+ const cache = this._hydrationCache.clone(); // If we're empty, we still want to return an object, so we default
650
+ // to an empty object.
651
+ // We only need the default scope out of our scoped in-memory cache.
652
+ // We know that it conforms to our expectations.
653
+ // $FlowIgnore[incompatible-return]
654
+
655
+
656
+ return (_cache$DefaultScope = cache[DefaultScope]) != null ? _cache$DefaultScope : {};
657
+ };
658
+
659
+ this._ssrOnlyCache = ssrOnlyCache || new _serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* SerializableInMemoryCache */ "a"]();
660
+ this._hydrationCache = hydrationCache || new _serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* SerializableInMemoryCache */ "a"]();
661
+ }
662
+
663
+ _setCachedResponse(id, entry, hydrate) {
664
+ const frozenEntry = Object.freeze(entry);
665
+
666
+ if (_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide()) {
667
+ // We are server-side.
668
+ // We need to store this value.
669
+ if (hydrate) {
670
+ this._hydrationCache.set(DefaultScope, id, frozenEntry);
671
+ } else {
672
+ // Usually, when server-side, this cache will always be present.
673
+ // We do fake server-side in our doc example though, when it
674
+ // won't be.
675
+ this._ssrOnlyCache.set(DefaultScope, id, frozenEntry);
676
+ }
677
+ }
678
+
679
+ return frozenEntry;
680
+ }
681
+ /**
682
+ * Initialize the cache from a given cache state.
683
+ *
684
+ * This can only be called if the cache is not already in use.
685
+ */
686
+
687
+
688
+ }
689
+
690
+ /***/ }),
691
+ /* 10 */
692
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
693
+
694
+ "use strict";
695
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return RequestFulfillment; });
696
+ /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
697
+
698
+
699
+ let _default;
615
700
  /**
616
- * Hook to retrieve data from and store data in an in-memory cache.
617
- *
618
- * @returns {[?ReadOnlyCacheValue, CacheValueFn]}
619
- * Returns an array containing the current cache entry (or undefined), a
620
- * function to set the cache entry (passing null or undefined to this function
621
- * will delete the entry).
622
- *
623
- * To clear a single scope within the cache or the entire cache,
624
- * the `clearScopedCache` export is available.
625
- *
626
- * NOTE: Unlike useState or useReducer, we don't automatically update folks
627
- * if the value they reference changes. We might add it later (if we need to),
628
- * but the likelihood here is that things won't be changing in this cache in a
629
- * way where we would need that. If we do (and likely only in specific
630
- * circumstances), we should consider adding a simple boolean useState that can
631
- * be toggled to cause a rerender whenever the referenced cached data changes
632
- * so that callers can re-render on cache changes. However, we should make
633
- * sure this toggling is optional - or we could use a callback argument, to
634
- * achieve this on an as-needed basis.
701
+ * This fulfills a request, making sure that in-flight requests are shared.
635
702
  */
636
703
 
637
- const useSharedCache = (id, scope, initialValue) => {
638
- // Verify arguments.
639
- if (!id || typeof id !== "string") {
640
- throw new _util_data_error_js__WEBPACK_IMPORTED_MODULE_1__[/* DataError */ "a"]("id must be a non-empty string", _util_data_error_js__WEBPACK_IMPORTED_MODULE_1__[/* DataErrors */ "b"].InvalidInput);
641
- }
642
704
 
643
- if (!scope || typeof scope !== "string") {
644
- throw new _util_data_error_js__WEBPACK_IMPORTED_MODULE_1__[/* DataError */ "a"]("scope must be a non-empty string", _util_data_error_js__WEBPACK_IMPORTED_MODULE_1__[/* DataErrors */ "b"].InvalidInput);
645
- } // Memoize our APIs.
646
- // This one allows callers to set or replace the cached value.
705
+ class RequestFulfillment {
706
+ constructor() {
707
+ this._requests = {};
647
708
 
709
+ this.fulfill = (id, {
710
+ handler,
711
+ hydrate = true
712
+ }) => {
713
+ /**
714
+ * If we have an inflight request, we'll provide that.
715
+ */
716
+ const inflight = this._requests[id];
648
717
 
649
- const cacheValue = react__WEBPACK_IMPORTED_MODULE_0__["useCallback"](value => value == null ? cache.purge(scope, id) : cache.set(scope, id, value), [id, scope]); // We don't memo-ize the current value, just in case the cache was updated
650
- // since our last run through. Also, our cache does not know what type it
651
- // stores, so we have to cast it to the type we're exporting. This is a
652
- // dev time courtesy, rather than a runtime thing.
653
- // $FlowIgnore[incompatible-type]
718
+ if (inflight) {
719
+ return inflight;
720
+ }
721
+ /**
722
+ * We don't have an inflight request, so let's set one up.
723
+ */
654
724
 
655
- let currentValue = cache.get(scope, id); // If we have an initial value, we need to add it to the cache
656
- // and use it as our current value.
657
725
 
658
- if (currentValue == null && initialValue !== undefined) {
659
- // Get the initial value.
660
- const value = typeof initialValue === "function" ? initialValue() : initialValue;
726
+ const request = handler().then(data => ({
727
+ status: "success",
728
+ data
729
+ })).catch(error => {
730
+ const actualError = typeof error === "string" ? new _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataError */ "a"]("Request failed", _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataErrors */ "b"].Unknown, {
731
+ metadata: {
732
+ unexpectedError: error
733
+ }
734
+ }) : error; // Return aborted result if the request was aborted.
735
+ // The only way to detect this reliably, it seems, is to
736
+ // check the error name and see if it's "AbortError" (this
737
+ // is also what Apollo does).
738
+ // Even then, it's reliant on the handler supporting aborts.
739
+ // TODO(somewhatabstract, FEI-4276): Add first class abort
740
+ // support to the handler API.
661
741
 
662
- if (value != null) {
663
- // Update the cache.
664
- cacheValue(value); // Make sure we return this value as our current value.
742
+ if (actualError.name === "AbortError") {
743
+ return {
744
+ status: "aborted"
745
+ };
746
+ }
665
747
 
666
- currentValue = value;
748
+ return {
749
+ status: "error",
750
+ error: actualError
751
+ };
752
+ }).finally(() => {
753
+ delete this._requests[id];
754
+ }); // Store the request in our cache.
755
+
756
+ this._requests[id] = request;
757
+ return request;
758
+ };
759
+
760
+ this.abort = id => {
761
+ // TODO(somewhatabstract, FEI-4276): Add first class abort
762
+ // support to the handler API.
763
+ // For now, we will just clear the request out of the list.
764
+ // When abort is implemented, the `finally` in the `fulfill` method
765
+ // would handle the deletion.
766
+ delete this._requests[id];
767
+ };
768
+
769
+ this.abortAll = () => {
770
+ Object.keys(this._requests).forEach(id => this.abort(id));
771
+ };
772
+ }
773
+
774
+ static get Default() {
775
+ if (!_default) {
776
+ _default = new RequestFulfillment();
667
777
  }
668
- } // Now we have everything, let's return it.
669
778
 
779
+ return _default;
780
+ }
670
781
 
671
- return [currentValue, cacheValue];
672
- };
782
+ }
673
783
 
674
784
  /***/ }),
675
- /* 9 */
785
+ /* 11 */
676
786
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
677
787
 
678
788
  "use strict";
679
789
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return ScopedInMemoryCache; });
680
- /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
790
+ /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
681
791
 
682
792
 
683
793
  /**
@@ -796,107 +906,32 @@ class ScopedInMemoryCache {
796
906
  }
797
907
 
798
908
  /***/ }),
799
- /* 10 */
909
+ /* 12 */
800
910
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
801
911
 
802
912
  "use strict";
803
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return RequestFulfillment; });
804
- /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
913
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return WhenClientSide; });
914
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return useHydratableEffect; });
915
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
916
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
917
+ /* harmony import */ var _use_server_effect_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(16);
918
+ /* harmony import */ var _use_shared_cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
919
+ /* harmony import */ var _use_cached_effect_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(17);
920
+ /* harmony import */ var _util_types_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(3);
805
921
 
806
922
 
807
- let _default;
808
- /**
809
- * This fulfills a request, making sure that in-flight requests are shared.
810
- */
811
-
812
-
813
- class RequestFulfillment {
814
- constructor() {
815
- this._requests = {};
816
-
817
- this.fulfill = (id, {
818
- handler,
819
- hydrate = true
820
- }) => {
821
- /**
822
- * If we have an inflight request, we'll provide that.
823
- */
824
- const inflight = this._requests[id];
825
-
826
- if (inflight) {
827
- return inflight;
828
- }
829
- /**
830
- * We don't have an inflight request, so let's set one up.
831
- */
832
-
833
-
834
- const request = handler().then(data => ({
835
- status: "success",
836
- data
837
- })).catch(error => {
838
- const actualError = typeof error === "string" ? new _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataError */ "a"]("Request failed", _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataErrors */ "b"].Unknown, {
839
- metadata: {
840
- unexpectedError: error
841
- }
842
- }) : error; // Return aborted result if the request was aborted.
843
- // The only way to detect this reliably, it seems, is to
844
- // check the error name and see if it's "AbortError" (this
845
- // is also what Apollo does).
846
- // Even then, it's reliant on the handler supporting aborts.
847
- // TODO(somewhatabstract, FEI-4276): Add first class abort
848
- // support to the handler API.
849
-
850
- if (actualError.name === "AbortError") {
851
- return {
852
- status: "aborted"
853
- };
854
- }
855
-
856
- return {
857
- status: "error",
858
- error: actualError
859
- };
860
- }).finally(() => {
861
- delete this._requests[id];
862
- }); // Store the request in our cache.
863
-
864
- this._requests[id] = request;
865
- return request;
866
- };
867
- }
868
-
869
- static get Default() {
870
- if (!_default) {
871
- _default = new RequestFulfillment();
872
- }
873
-
874
- return _default;
875
- }
876
-
877
- }
878
-
879
- /***/ }),
880
- /* 11 */
881
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
882
-
883
- "use strict";
884
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return WhenClientSide; });
885
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return useHydratableEffect; });
886
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
887
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
888
- /* harmony import */ var _use_server_effect_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14);
889
- /* harmony import */ var _use_shared_cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8);
890
- /* harmony import */ var _use_cached_effect_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(15);
891
-
892
923
 
924
+ // TODO(somewhatabstract, FEI-4174): Update eslint-plugin-import when they
925
+ // have fixed:
926
+ // https://github.com/import-js/eslint-plugin-import/issues/2073
927
+ // eslint-disable-next-line import/named
893
928
 
894
929
 
895
930
 
896
931
  /**
897
932
  * Policies to define how a hydratable effect should behave client-side.
898
933
  */
899
- const WhenClientSide = __webpack_require__(28).Mirrored(["DoNotHydrate", "ExecuteWhenNoResult", "ExecuteWhenNoSuccessResult", "AlwaysExecute"]);
934
+ const WhenClientSide = __webpack_require__(22).Mirrored(["DoNotHydrate", "ExecuteWhenNoResult", "ExecuteWhenNoSuccessResult", "AlwaysExecute"]);
900
935
  const DefaultScope = "useHydratableEffect";
901
936
  /**
902
937
  * Hook to execute an async operation on server and client.
@@ -968,11 +1003,13 @@ const useHydratableEffect = (requestId, handler, options = {}) => {
968
1003
  scope, // The scope of the cached items
969
1004
  getDefaultCacheValue); // When we're client-side, we ultimately want the result from this call.
970
1005
 
971
- const clientResult = Object(_use_cached_effect_js__WEBPACK_IMPORTED_MODULE_3__[/* useCachedEffect */ "a"])(requestId, handler, {
1006
+ const [clientResult] = Object(_use_cached_effect_js__WEBPACK_IMPORTED_MODULE_3__[/* useCachedEffect */ "a"])(requestId, handler, {
972
1007
  skip,
973
1008
  onResultChanged,
974
1009
  retainResultOnChange,
975
- scope
1010
+ scope,
1011
+ // Be explicit about our fetch policy for clarity.
1012
+ fetchPolicy: _util_types_js__WEBPACK_IMPORTED_MODULE_4__[/* FetchPolicy */ "a"].CacheBeforeNetwork
976
1013
  }); // OK, now which result do we return.
977
1014
  // Well, we return the serverResult on our very first call and then
978
1015
  // the clientResult thereafter. The great thing is that after the very
@@ -982,15 +1019,15 @@ const useHydratableEffect = (requestId, handler, options = {}) => {
982
1019
  };
983
1020
 
984
1021
  /***/ }),
985
- /* 12 */
1022
+ /* 13 */
986
1023
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
987
1024
 
988
1025
  "use strict";
989
1026
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SerializableInMemoryCache; });
990
- /* harmony import */ var _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
1027
+ /* harmony import */ var _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
991
1028
  /* harmony import */ var _khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_stuff_core__WEBPACK_IMPORTED_MODULE_0__);
992
- /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
993
- /* harmony import */ var _scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9);
1029
+ /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
1030
+ /* harmony import */ var _scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11);
994
1031
 
995
1032
 
996
1033
 
@@ -1032,11 +1069,11 @@ class SerializableInMemoryCache extends _scoped_in_memory_cache_js__WEBPACK_IMPO
1032
1069
  }
1033
1070
 
1034
1071
  /***/ }),
1035
- /* 13 */
1072
+ /* 14 */
1036
1073
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1037
1074
 
1038
1075
  "use strict";
1039
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
1076
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1040
1077
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1041
1078
 
1042
1079
 
@@ -1049,19 +1086,47 @@ const InterceptContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["create
1049
1086
  /* harmony default export */ __webpack_exports__["a"] = (InterceptContext);
1050
1087
 
1051
1088
  /***/ }),
1052
- /* 14 */
1089
+ /* 15 */
1090
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
1091
+
1092
+ "use strict";
1093
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return initializeHydrationCache; });
1094
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return purgeHydrationCache; });
1095
+ /* harmony import */ var _ssr_cache_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9);
1096
+
1097
+
1098
+ /**
1099
+ * Initialize the hydration cache.
1100
+ *
1101
+ * @param {ResponseCache} source The cache content to use for initializing the
1102
+ * cache.
1103
+ * @throws {Error} If the cache is already initialized.
1104
+ */
1105
+ const initializeHydrationCache = source => _ssr_cache_js__WEBPACK_IMPORTED_MODULE_0__[/* SsrCache */ "a"].Default.initialize(source);
1106
+ /**
1107
+ * Purge cached hydration responses that match the given predicate.
1108
+ *
1109
+ * @param {(id: string) => boolean} [predicate] The predicate to match against
1110
+ * the cached hydration responses. If no predicate is provided, all cached
1111
+ * hydration responses will be purged.
1112
+ */
1113
+
1114
+ const purgeHydrationCache = predicate => _ssr_cache_js__WEBPACK_IMPORTED_MODULE_0__[/* SsrCache */ "a"].Default.purgeData(predicate);
1115
+
1116
+ /***/ }),
1117
+ /* 16 */
1053
1118
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1054
1119
 
1055
1120
  "use strict";
1056
1121
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return useServerEffect; });
1057
1122
  /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
1058
1123
  /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__);
1059
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
1124
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
1060
1125
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
1061
- /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
1062
- /* harmony import */ var _util_ssr_cache_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5);
1063
- /* harmony import */ var _util_result_from_cache_response_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(24);
1064
- /* harmony import */ var _use_request_interception_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(16);
1126
+ /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8);
1127
+ /* harmony import */ var _util_ssr_cache_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9);
1128
+ /* harmony import */ var _util_result_from_cache_response_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(32);
1129
+ /* harmony import */ var _use_request_interception_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(19);
1065
1130
 
1066
1131
 
1067
1132
 
@@ -1112,25 +1177,33 @@ const useServerEffect = (requestId, handler, options = {}) => {
1112
1177
  };
1113
1178
 
1114
1179
  /***/ }),
1115
- /* 15 */
1180
+ /* 17 */
1116
1181
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1117
1182
 
1118
1183
  "use strict";
1119
1184
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return useCachedEffect; });
1120
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
1185
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1121
1186
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1122
1187
  /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
1123
1188
  /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__);
1124
- /* harmony import */ var _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10);
1125
- /* harmony import */ var _util_status_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4);
1126
- /* harmony import */ var _use_shared_cache_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8);
1127
- /* harmony import */ var _use_request_interception_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(16);
1189
+ /* harmony import */ var _util_data_error_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(0);
1190
+ /* harmony import */ var _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10);
1191
+ /* harmony import */ var _util_status_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(6);
1192
+ /* harmony import */ var _use_shared_cache_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(5);
1193
+ /* harmony import */ var _use_request_interception_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(19);
1194
+ /* harmony import */ var _util_types_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(3);
1128
1195
 
1129
1196
 
1130
1197
 
1131
1198
 
1132
1199
 
1133
1200
 
1201
+
1202
+ // TODO(somewhatabstract, FEI-4174): Update eslint-plugin-import when they
1203
+ // have fixed:
1204
+ // https://github.com/import-js/eslint-plugin-import/issues/2073
1205
+ // eslint-disable-next-line import/named
1206
+
1134
1207
  const DefaultScope = "useCachedEffect";
1135
1208
  /**
1136
1209
  * Hook to execute and cache an async operation on the client.
@@ -1150,7 +1223,10 @@ const DefaultScope = "useCachedEffect";
1150
1223
  */
1151
1224
 
1152
1225
  const useCachedEffect = (requestId, handler, options = {}) => {
1226
+ var _ref;
1227
+
1153
1228
  const {
1229
+ fetchPolicy = _util_types_js__WEBPACK_IMPORTED_MODULE_7__[/* FetchPolicy */ "a"].CacheBeforeNetwork,
1154
1230
  skip: hardSkip = false,
1155
1231
  retainResultOnChange = false,
1156
1232
  onResultChanged,
@@ -1158,124 +1234,263 @@ const useCachedEffect = (requestId, handler, options = {}) => {
1158
1234
  } = options; // Plug in to the request interception framework for code that wants
1159
1235
  // to use that.
1160
1236
 
1161
- const interceptedHandler = Object(_use_request_interception_js__WEBPACK_IMPORTED_MODULE_5__[/* useRequestInterception */ "a"])(requestId, handler); // Instead of using state, which would be local to just this hook instance,
1237
+ const interceptedHandler = Object(_use_request_interception_js__WEBPACK_IMPORTED_MODULE_6__[/* useRequestInterception */ "a"])(requestId, handler); // Instead of using state, which would be local to just this hook instance,
1162
1238
  // we use a shared in-memory cache.
1163
1239
 
1164
- const [mostRecentResult, setMostRecentResult] = Object(_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_4__[/* useSharedCache */ "b"])(requestId, // The key of the cached item
1240
+ const [mostRecentResult, setMostRecentResult] = Object(_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_5__[/* useSharedCache */ "b"])(requestId, // The key of the cached item
1165
1241
  scope // The scope of the cached items
1166
1242
  // No default value. We don't want the loading status there; to ensure
1167
1243
  // that all calls when the request is in-flight will update once that
1168
1244
  // request is done, we want the cache to be empty until that point.
1169
- ); // Build a function that will update the cache and either invoke the
1170
- // callback provided in options, or force an update.
1171
-
1172
- const forceUpdate = Object(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__["useForceUpdate"])();
1173
- const setCacheAndNotify = react__WEBPACK_IMPORTED_MODULE_0__["useCallback"](value => {
1174
- setMostRecentResult(value); // If our caller provided a cacheUpdated callback, we use that.
1175
- // Otherwise, we toggle our little state update.
1176
-
1177
- if (onResultChanged != null) {
1178
- onResultChanged(value);
1179
- } else {
1180
- forceUpdate();
1181
- }
1182
- }, [setMostRecentResult, onResultChanged, forceUpdate]); // We need to trigger a re-render when the request ID changes as that
1183
- // indicates its a different request. We don't default the current id as
1184
- // this is a proxy for the first render, where we will make the request
1185
- // if we don't already have a cached value.
1186
-
1187
- const requestIdRef = react__WEBPACK_IMPORTED_MODULE_0__["useRef"]();
1188
- const previousRequestId = requestIdRef.current; // Calculate our soft skip state.
1189
- // Soft skip changes are things that should skip the effect if something
1190
- // else triggers the effect to run, but should not itself trigger the effect
1191
- // (which would cancel a previous invocation).
1192
-
1193
- const softSkip = react__WEBPACK_IMPORTED_MODULE_0__["useMemo"](() => {
1194
- if (requestId === previousRequestId) {
1195
- // If the requestId is unchanged, it means we already rendered at
1196
- // least once and so we already made the request at least once. So
1197
- // we can bail out right here.
1198
- return true;
1199
- } // If we already have a cached value, we're going to skip.
1200
-
1201
-
1202
- if (mostRecentResult != null) {
1203
- return true;
1245
+ );
1246
+ const forceUpdate = Object(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__["useForceUpdate"])(); // For the NetworkOnly fetch policy, we ignore the cached value.
1247
+ // So we need somewhere else to store the network value.
1248
+
1249
+ const networkResultRef = react__WEBPACK_IMPORTED_MODULE_0__["useRef"](); // Set up the function that will do the fetching.
1250
+
1251
+ const currentRequestRef = react__WEBPACK_IMPORTED_MODULE_0__["useRef"]();
1252
+ const fetchRequest = react__WEBPACK_IMPORTED_MODULE_0__["useMemo"](() => {
1253
+ var _currentRequestRef$cu;
1254
+
1255
+ // We aren't using useCallback here because we need to make sure that
1256
+ // if we are rememo-izing, we cancel any inflight request for the old
1257
+ // callback.
1258
+ (_currentRequestRef$cu = currentRequestRef.current) == null ? void 0 : _currentRequestRef$cu.cancel();
1259
+ currentRequestRef.current = null;
1260
+ networkResultRef.current = null;
1261
+
1262
+ const fetchFn = () => {
1263
+ var _currentRequestRef$cu2, _currentRequestRef$cu3;
1264
+
1265
+ if (fetchPolicy === _util_types_js__WEBPACK_IMPORTED_MODULE_7__[/* FetchPolicy */ "a"].CacheOnly) {
1266
+ throw new _util_data_error_js__WEBPACK_IMPORTED_MODULE_2__[/* DataError */ "a"]("Cannot fetch with CacheOnly policy", _util_data_error_js__WEBPACK_IMPORTED_MODULE_2__[/* DataErrors */ "b"].NotAllowed);
1267
+ } // We use our request fulfillment here so that in-flight
1268
+ // requests are shared. In order to ensure that we don't share
1269
+ // in-flight requests for different scopes, we add the scope to the
1270
+ // requestId.
1271
+ // We do this as a courtesy to simplify usage in sandboxed
1272
+ // uses like storybook where we want each story to perform their
1273
+ // own requests from scratch and not share inflight requests across
1274
+ // stories.
1275
+ // Since this only occurs here, nothing else will care about this
1276
+ // change except the request tracking.
1277
+
1278
+
1279
+ const request = _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_3__[/* RequestFulfillment */ "a"].Default.fulfill(`${requestId}|${scope}`, {
1280
+ handler: interceptedHandler
1281
+ });
1282
+
1283
+ if (request === ((_currentRequestRef$cu2 = currentRequestRef.current) == null ? void 0 : _currentRequestRef$cu2.request)) {
1284
+ // The request inflight is the same, so do nothing.
1285
+ // NOTE: Perhaps if invoked via a refetch, we will want to
1286
+ // override this behavior and force a new request?
1287
+ return;
1288
+ } // Clear the last network result.
1289
+
1290
+
1291
+ networkResultRef.current = null; // Cancel the previous request.
1292
+
1293
+ (_currentRequestRef$cu3 = currentRequestRef.current) == null ? void 0 : _currentRequestRef$cu3.cancel(); // TODO(somewhatabstract, FEI-4276):
1294
+ // Until our RequestFulfillment API supports cancelling/aborting, we
1295
+ // will have to do it.
1296
+
1297
+ let cancel = false; // NOTE: Our request fulfillment handles the error cases here.
1298
+ // Catching shouldn't serve a purpose.
1299
+ // eslint-disable-next-line promise/catch-or-return
1300
+
1301
+ request.then(result => {
1302
+ currentRequestRef.current = null;
1303
+
1304
+ if (cancel) {
1305
+ // We don't modify our result if the request was cancelled
1306
+ // as it means that this hook no longer cares about that old
1307
+ // request.
1308
+ return;
1309
+ } // Now we need to update the cache and notify or force a rerender.
1310
+
1311
+
1312
+ setMostRecentResult(result);
1313
+ networkResultRef.current = result;
1314
+
1315
+ if (onResultChanged != null) {
1316
+ // If we have a callback, call it to let our caller know we
1317
+ // got a result.
1318
+ onResultChanged(result);
1319
+ } else {
1320
+ // If there's no callback, and this is using cache in some
1321
+ // capacity, just force a rerender.
1322
+ forceUpdate();
1323
+ }
1324
+
1325
+ return; // Shut up eslint always-return rule.
1326
+ });
1327
+ currentRequestRef.current = {
1328
+ requestId,
1329
+ request,
1330
+
1331
+ cancel() {
1332
+ cancel = true;
1333
+ _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_3__[/* RequestFulfillment */ "a"].Default.abort(requestId);
1334
+ }
1335
+
1336
+ };
1337
+ }; // Now we can return the new fetch function.
1338
+
1339
+
1340
+ return fetchFn; // We deliberately ignore the handler here because we want folks to use
1341
+ // interceptor functions inline in props for simplicity. This is OK
1342
+ // since changing the handler without changing the requestId doesn't
1343
+ // really make sense - the same requestId should be handled the same as
1344
+ // each other.
1345
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1346
+ }, [requestId, onResultChanged, forceUpdate, setMostRecentResult, fetchPolicy]); // We need to trigger a re-render when the request ID changes as that
1347
+ // indicates its a different request.
1348
+
1349
+ const requestIdRef = react__WEBPACK_IMPORTED_MODULE_0__["useRef"](requestId); // Calculate if we want to fetch the result or not.
1350
+ // If this is true, we will do a new fetch, cancelling the previous fetch
1351
+ // if there is one inflight.
1352
+
1353
+ const shouldFetch = react__WEBPACK_IMPORTED_MODULE_0__["useMemo"](() => {
1354
+ if (hardSkip) {
1355
+ // We don't fetch if we've been told to hard skip.
1356
+ return false;
1204
1357
  }
1205
1358
 
1206
- return false;
1207
- }, [requestId, previousRequestId, mostRecentResult]); // So now we make sure the client-side request happens per our various
1208
- // options.
1359
+ switch (fetchPolicy) {
1360
+ case _util_types_js__WEBPACK_IMPORTED_MODULE_7__[/* FetchPolicy */ "a"].CacheOnly:
1361
+ // Don't want to do a network request if we're only
1362
+ // interested in the cache.
1363
+ return false;
1364
+
1365
+ case _util_types_js__WEBPACK_IMPORTED_MODULE_7__[/* FetchPolicy */ "a"].CacheBeforeNetwork:
1366
+ // If we don't have a cached value or this is a new requestId,
1367
+ // then we need to fetch.
1368
+ return mostRecentResult == null || requestId !== requestIdRef.current;
1209
1369
 
1370
+ case _util_types_js__WEBPACK_IMPORTED_MODULE_7__[/* FetchPolicy */ "a"].CacheAndNetwork:
1371
+ case _util_types_js__WEBPACK_IMPORTED_MODULE_7__[/* FetchPolicy */ "a"].NetworkOnly:
1372
+ // We don't care about the cache. If we don't have a network
1373
+ // result, then we need to fetch one.
1374
+ return networkResultRef.current == null;
1375
+ }
1376
+ }, [requestId, mostRecentResult, fetchPolicy, hardSkip]); // Let's make sure our ref is set to the most recent requestId.
1377
+
1378
+ requestIdRef.current = requestId;
1210
1379
  react__WEBPACK_IMPORTED_MODULE_0__["useEffect"](() => {
1211
- let cancel = false; // We don't do anything if we've been told to hard skip (a hard skip
1212
- // means we should cancel the previous request and is therefore a
1213
- // dependency on that), or we have determined we have already done
1214
- // enough and can soft skip (a soft skip doesn't trigger the request
1215
- // to re-run; we don't want to cancel the in progress effect if we're
1216
- // soft skipping.
1217
-
1218
- if (hardSkip || softSkip) {
1380
+ if (!shouldFetch) {
1219
1381
  return;
1220
- } // If we got here, we're going to perform the request.
1221
- // Let's make sure our ref is set to the most recent requestId.
1222
-
1223
-
1224
- requestIdRef.current = requestId; // OK, we've done all our checks and things. It's time to make the
1225
- // request. We use our request fulfillment here so that in-flight
1226
- // requests are shared.
1227
- // NOTE: Our request fulfillment handles the error cases here.
1228
- // Catching shouldn't serve a purpose.
1229
- // eslint-disable-next-line promise/catch-or-return
1230
-
1231
- _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__[/* RequestFulfillment */ "a"].Default.fulfill(requestId, {
1232
- handler: interceptedHandler
1233
- }).then(result => {
1234
- if (cancel) {
1235
- // We don't modify our result if an earlier effect was
1236
- // cancelled as it means that this hook no longer cares about
1237
- // that old request.
1238
- return;
1239
- }
1382
+ }
1240
1383
 
1241
- setCacheAndNotify(result);
1242
- return; // Shut up eslint always-return rule.
1243
- });
1384
+ fetchRequest();
1244
1385
  return () => {
1245
- // TODO(somewhatabstract, FEI-4276): Eventually, we will want to be
1246
- // able abort in-flight requests, but for now, we don't have that.
1247
- // (Of course, we will only want to abort them if no one is waiting
1248
- // on them)
1249
- // For now, we just block cancelled requests from changing our
1250
- // cache.
1251
- cancel = true;
1252
- }; // We only want to run this effect if the requestId, or skip values
1253
- // change. These are the only two things that should affect the
1254
- // cancellation of a pending request. We do not update if the handler
1255
- // changes, in order to simplify the API - otherwise, callers would
1256
- // not be able to use inline functions with this hook.
1257
- // eslint-disable-next-line react-hooks/exhaustive-deps
1258
- }, [hardSkip, requestId]); // We track the last result we returned in order to support the
1386
+ var _currentRequestRef$cu4;
1387
+
1388
+ (_currentRequestRef$cu4 = currentRequestRef.current) == null ? void 0 : _currentRequestRef$cu4.cancel();
1389
+ currentRequestRef.current = null;
1390
+ };
1391
+ }, [shouldFetch, fetchRequest]); // We track the last result we returned in order to support the
1259
1392
  // "retainResultOnChange" option.
1260
1393
 
1261
- const lastResultAgnosticOfIdRef = react__WEBPACK_IMPORTED_MODULE_0__["useRef"](_util_status_js__WEBPACK_IMPORTED_MODULE_3__[/* Status */ "a"].loading());
1262
- const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : _util_status_js__WEBPACK_IMPORTED_MODULE_3__[/* Status */ "a"].loading(); // Loading is a transient state, so we only use it here; it's not something
1394
+ const lastResultAgnosticOfIdRef = react__WEBPACK_IMPORTED_MODULE_0__["useRef"](_util_status_js__WEBPACK_IMPORTED_MODULE_4__[/* Status */ "a"].loading());
1395
+ const loadingResult = retainResultOnChange ? lastResultAgnosticOfIdRef.current : _util_status_js__WEBPACK_IMPORTED_MODULE_4__[/* Status */ "a"].loading(); // Loading is a transient state, so we only use it here; it's not something
1263
1396
  // we cache.
1264
1397
 
1265
- const result = react__WEBPACK_IMPORTED_MODULE_0__["useMemo"](() => mostRecentResult != null ? mostRecentResult : loadingResult, [mostRecentResult, loadingResult]);
1266
- lastResultAgnosticOfIdRef.current = result;
1267
- return result;
1398
+ const result = (_ref = fetchPolicy === _util_types_js__WEBPACK_IMPORTED_MODULE_7__[/* FetchPolicy */ "a"].NetworkOnly ? networkResultRef.current : mostRecentResult) != null ? _ref : loadingResult;
1399
+ lastResultAgnosticOfIdRef.current = result; // We return the result and a function for triggering a refetch.
1400
+
1401
+ return [result, fetchRequest];
1268
1402
  };
1269
1403
 
1270
1404
  /***/ }),
1271
- /* 16 */
1405
+ /* 18 */
1406
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
1407
+
1408
+ "use strict";
1409
+ /* unused harmony export DocumentTypes */
1410
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return graphQLDocumentNodeParser; });
1411
+ /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
1412
+
1413
+ const DocumentTypes = Object.freeze({
1414
+ query: "query",
1415
+ mutation: "mutation"
1416
+ });
1417
+ const cache = new Map();
1418
+ /**
1419
+ * Parse a GraphQL document node to determine some info about it.
1420
+ *
1421
+ * This is based on:
1422
+ * https://github.com/apollographql/react-apollo/blob/3bc993b2ea91704bd6a2667f42d1940656c071ff/src/parser.ts
1423
+ */
1424
+
1425
+ function graphQLDocumentNodeParser(document) {
1426
+ var _definition$name;
1427
+
1428
+ const cached = cache.get(document);
1429
+
1430
+ if (cached) {
1431
+ return cached;
1432
+ }
1433
+ /**
1434
+ * Saftey check for proper usage.
1435
+ */
1436
+
1437
+
1438
+ if (!(document != null && document.kind)) {
1439
+ if (true) {
1440
+ throw new _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataError */ "a"]("Bad DocumentNode", _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataErrors */ "b"].InvalidInput);
1441
+ } else {}
1442
+ }
1443
+
1444
+ const fragments = document.definitions.filter(x => x.kind === "FragmentDefinition");
1445
+ const queries = document.definitions.filter(x => // $FlowIgnore[prop-missing]
1446
+ x.kind === "OperationDefinition" && x.operation === "query");
1447
+ const mutations = document.definitions.filter(x => // $FlowIgnore[prop-missing]
1448
+ x.kind === "OperationDefinition" && x.operation === "mutation");
1449
+ const subscriptions = document.definitions.filter(x => // $FlowIgnore[prop-missing]
1450
+ x.kind === "OperationDefinition" && x.operation === "subscription");
1451
+
1452
+ if (fragments.length && !queries.length && !mutations.length) {
1453
+ if (true) {
1454
+ throw new _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataError */ "a"]("Fragment only", _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataErrors */ "b"].InvalidInput);
1455
+ } else {}
1456
+ }
1457
+
1458
+ if (subscriptions.length) {
1459
+ if (true) {
1460
+ throw new _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataError */ "a"]("No subscriptions", _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataErrors */ "b"].InvalidInput);
1461
+ } else {}
1462
+ }
1463
+
1464
+ if (queries.length + mutations.length > 1) {
1465
+ if (true) {
1466
+ throw new _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataError */ "a"]("Too many ops", _data_error_js__WEBPACK_IMPORTED_MODULE_0__[/* DataErrors */ "b"].InvalidInput);
1467
+ } else {}
1468
+ }
1469
+
1470
+ const type = queries.length ? DocumentTypes.query : DocumentTypes.mutation;
1471
+ const definitions = queries.length ? queries : mutations;
1472
+ const definition = definitions[0];
1473
+ const variables = definition.variableDefinitions || []; // fallback to using data if no name
1474
+
1475
+ const name = ((_definition$name = definition.name) == null ? void 0 : _definition$name.kind) === "Name" ? definition.name.value : "data";
1476
+ const payload = {
1477
+ name,
1478
+ type,
1479
+ variables
1480
+ };
1481
+ cache.set(document, payload);
1482
+ return payload;
1483
+ }
1484
+
1485
+ /***/ }),
1486
+ /* 19 */
1272
1487
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1273
1488
 
1274
1489
  "use strict";
1275
1490
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return useRequestInterception; });
1276
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
1491
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1277
1492
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1278
- /* harmony import */ var _components_intercept_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(13);
1493
+ /* harmony import */ var _components_intercept_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14);
1279
1494
 
1280
1495
 
1281
1496
 
@@ -1313,67 +1528,289 @@ const useRequestInterception = (requestId, handler) => {
1313
1528
  // as our handler, so how can flow know? Let's just suppress that.
1314
1529
  // $FlowFixMe[incompatible-return]
1315
1530
 
1316
- return interceptResponse != null ? interceptResponse : handler();
1317
- }, [handler, interceptors, requestId]);
1318
- return interceptedHandler;
1531
+ return interceptResponse != null ? interceptResponse : handler();
1532
+ }, [handler, interceptors, requestId]);
1533
+ return interceptedHandler;
1534
+ };
1535
+
1536
+ /***/ }),
1537
+ /* 20 */
1538
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
1539
+
1540
+ "use strict";
1541
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return GqlRouterContext; });
1542
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1543
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1544
+
1545
+ const GqlRouterContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createContext"](null);
1546
+
1547
+ /***/ }),
1548
+ /* 21 */
1549
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
1550
+
1551
+ "use strict";
1552
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return mergeGqlContext; });
1553
+ /**
1554
+ * Construct a complete GqlContext from current defaults and a partial context.
1555
+ *
1556
+ * Values in the partial context that are `undefined` will be ignored.
1557
+ * Values in the partial context that are `null` will be deleted.
1558
+ */
1559
+ const mergeGqlContext = (defaultContext, overrides) => {
1560
+ // Let's merge the partial context default context. We deliberately
1561
+ // don't spread because spreading would overwrite default context
1562
+ // values with undefined or null if the partial context includes a value
1563
+ // explicitly set to undefined or null.
1564
+ return Object.keys(overrides).reduce((acc, key) => {
1565
+ // Undefined values are ignored.
1566
+ if (overrides[key] !== undefined) {
1567
+ if (overrides[key] === null) {
1568
+ // Null indicates we delete this context value.
1569
+ delete acc[key];
1570
+ } else {
1571
+ // Otherwise, we set it.
1572
+ acc[key] = overrides[key];
1573
+ }
1574
+ }
1575
+
1576
+ return acc;
1577
+ }, { ...defaultContext
1578
+ });
1579
+ };
1580
+
1581
+ /***/ }),
1582
+ /* 22 */
1583
+ /***/ (function(module, exports, __webpack_require__) {
1584
+
1585
+ "use strict";
1586
+ /**
1587
+ * Copyright (c) Facebook, Inc. and its affiliates.
1588
+ *
1589
+ * This source code is licensed under the MIT license found in the
1590
+ * LICENSE file in the root directory of this source tree.
1591
+ */
1592
+
1593
+
1594
+
1595
+ // Below we want to use `hasOwnProperty` on an object that doesn't have
1596
+ // `Object.prototype` in its proto chain, so we must extract it here.
1597
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
1598
+
1599
+ // Map from an enum object to a reverse map of its values to names
1600
+ var reverseMapCache = typeof WeakMap === 'function' ? new WeakMap() : new Map();
1601
+
1602
+ // Computes the reverse mapping of the enum object: from value to name.
1603
+ // Flow Enum values are unique (enforced by the parser), so this is a
1604
+ // one to one mapping.
1605
+ function getReverseMap(enumObject) {
1606
+ var reverseMap = reverseMapCache.get(enumObject);
1607
+ if (reverseMap !== undefined) {
1608
+ return reverseMap;
1609
+ }
1610
+ // We aren't using `Object.values` because that gets enumerable
1611
+ // properties, and our properties aren't enumerable.
1612
+ var newReverseMap = new Map();
1613
+ Object.getOwnPropertyNames(enumObject).forEach(function (name) {
1614
+ newReverseMap.set(enumObject[name], name);
1615
+ });
1616
+ reverseMapCache.set(enumObject, newReverseMap);
1617
+ return newReverseMap;
1618
+ }
1619
+
1620
+ var EnumPrototype = Object.freeze(
1621
+ Object.defineProperties(Object.create(null), {
1622
+ isValid: {
1623
+ value: function (x) {
1624
+ return getReverseMap(this).has(x);
1625
+ },
1626
+ },
1627
+ cast: {
1628
+ value: function (x) {
1629
+ return this.isValid(x) ? x : undefined;
1630
+ },
1631
+ },
1632
+ members: {
1633
+ value: function () {
1634
+ return getReverseMap(this).keys();
1635
+ },
1636
+ },
1637
+ getName: {
1638
+ value: function (value) {
1639
+ return getReverseMap(this).get(value);
1640
+ }
1641
+ }
1642
+ })
1643
+ );
1644
+
1645
+ // `members` is an object mapping name to value.
1646
+ function Enum(members) {
1647
+ var o = Object.create(EnumPrototype);
1648
+ for (var k in members) {
1649
+ if (hasOwnProperty.call(members, k)) {
1650
+ // Create non-enumerable properties.
1651
+ Object.defineProperty(o, k, {value: members[k]});
1652
+ }
1653
+ }
1654
+ return Object.freeze(o);
1655
+ }
1656
+
1657
+ // Mirrored enum (string enum with no member initializers).
1658
+ // Optimized implementation, taking advantage of the fact that
1659
+ // keys and values are identical.
1660
+ var EnumMirroredPrototype = Object.freeze(
1661
+ Object.defineProperties(Object.create(null), {
1662
+ isValid: {
1663
+ value: function (x) {
1664
+ if (typeof x === 'string') {
1665
+ return hasOwnProperty.call(this, x);
1666
+ }
1667
+ return false;
1668
+ },
1669
+ },
1670
+ cast: {
1671
+ value: EnumPrototype.cast,
1672
+ },
1673
+ members: {
1674
+ value: function () {
1675
+ // We aren't using `Object.values` because that gets enumerable
1676
+ // properties, and our properties aren't enumerable.
1677
+ return Object.getOwnPropertyNames(this).values();
1678
+ },
1679
+ },
1680
+ getName: {
1681
+ value: function (value) {
1682
+ return value;
1683
+ }
1684
+ }
1685
+ })
1686
+ );
1687
+
1688
+ // `members` is an array of names (which, are also the values).
1689
+ Enum.Mirrored = function EnumMirrored(members) {
1690
+ var o = Object.create(EnumMirroredPrototype);
1691
+ for (var i = 0, len = members.length; i < len; ++i) {
1692
+ // Value is same as key. Also, non-enumerable.
1693
+ Object.defineProperty(o, members[i], {value: members[i]});
1694
+ }
1695
+ return Object.freeze(o);
1696
+ };
1697
+
1698
+ Object.freeze(Enum.Mirrored);
1699
+
1700
+ module.exports = Object.freeze(Enum);
1701
+
1702
+
1703
+ /***/ }),
1704
+ /* 23 */
1705
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
1706
+
1707
+ "use strict";
1708
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return fetchTrackedRequests; });
1709
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "c", function() { return hasTrackedRequestsToBeFetched; });
1710
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return abortInflightRequests; });
1711
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
1712
+ /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__);
1713
+ /* harmony import */ var _request_tracking_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8);
1714
+ /* harmony import */ var _request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10);
1715
+ /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(0);
1716
+
1717
+
1718
+
1719
+
1720
+
1721
+ const SSRCheck = () => {
1722
+ if (_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide()) {
1723
+ return null;
1724
+ }
1725
+
1726
+ if (true) {
1727
+ return new _data_error_js__WEBPACK_IMPORTED_MODULE_3__[/* DataError */ "a"]("No CSR tracking", _data_error_js__WEBPACK_IMPORTED_MODULE_3__[/* DataErrors */ "b"].NotAllowed);
1728
+ } else {}
1729
+ };
1730
+ /**
1731
+ * Fetches all tracked data requests.
1732
+ *
1733
+ * This is for use with the `TrackData` component during server-side rendering.
1734
+ *
1735
+ * @throws {Error} If executed outside of server-side rendering.
1736
+ * @returns {Promise<void>} A promise that resolves when all tracked requests
1737
+ * have been fetched.
1738
+ */
1739
+
1740
+
1741
+ const fetchTrackedRequests = () => {
1742
+ const ssrCheck = SSRCheck();
1743
+
1744
+ if (ssrCheck != null) {
1745
+ return Promise.reject(ssrCheck);
1746
+ }
1747
+
1748
+ return _request_tracking_js__WEBPACK_IMPORTED_MODULE_1__[/* RequestTracker */ "a"].Default.fulfillTrackedRequests();
1319
1749
  };
1750
+ /**
1751
+ * Indicate if there are tracked requests waiting to be fetched.
1752
+ *
1753
+ * This is used in conjunction with `TrackData`.
1754
+ *
1755
+ * @throws {Error} If executed outside of server-side rendering.
1756
+ * @returns {boolean} `true` if there are unfetched tracked requests;
1757
+ * otherwise, `false`.
1758
+ */
1320
1759
 
1321
- /***/ }),
1322
- /* 17 */
1323
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
1760
+ const hasTrackedRequestsToBeFetched = () => {
1761
+ const ssrCheck = SSRCheck();
1324
1762
 
1325
- "use strict";
1326
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return GqlRouterContext; });
1327
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
1328
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1763
+ if (ssrCheck != null) {
1764
+ throw ssrCheck;
1765
+ }
1329
1766
 
1330
- const GqlRouterContext = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createContext"](null);
1767
+ return _request_tracking_js__WEBPACK_IMPORTED_MODULE_1__[/* RequestTracker */ "a"].Default.hasUnfulfilledRequests;
1768
+ };
1769
+ /**
1770
+ * Abort all in-flight requests.
1771
+ *
1772
+ * This aborts all requests currently inflight via our default request
1773
+ * fulfillment.
1774
+ */
1775
+
1776
+ const abortInflightRequests = () => {
1777
+ _request_fulfillment_js__WEBPACK_IMPORTED_MODULE_2__[/* RequestFulfillment */ "a"].Default.abortAll();
1778
+ };
1331
1779
 
1332
1780
  /***/ }),
1333
- /* 18 */
1781
+ /* 24 */
1334
1782
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1335
1783
 
1336
1784
  "use strict";
1337
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return mergeGqlContext; });
1785
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return purgeCaches; });
1786
+ /* harmony import */ var _hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5);
1787
+ /* harmony import */ var _hydration_cache_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(15);
1788
+
1789
+
1338
1790
  /**
1339
- * Construct a complete GqlContext from current defaults and a partial context.
1791
+ * Purge all caches managed by Wonder Blocks Data.
1340
1792
  *
1341
- * Values in the partial context that are `undefined` will be ignored.
1342
- * Values in the partial context that are `null` will be deleted.
1793
+ * This is a convenience method that purges the shared cache and the hydration
1794
+ * cache. It is useful for testing purposes to avoid having to reason about
1795
+ * which caches may have been used during a given test run.
1343
1796
  */
1344
- const mergeGqlContext = (defaultContext, overrides) => {
1345
- // Let's merge the partial context default context. We deliberately
1346
- // don't spread because spreading would overwrite default context
1347
- // values with undefined or null if the partial context includes a value
1348
- // explicitly set to undefined or null.
1349
- return Object.keys(overrides).reduce((acc, key) => {
1350
- // Undefined values are ignored.
1351
- if (overrides[key] !== undefined) {
1352
- if (overrides[key] === null) {
1353
- // Null indicates we delete this context value.
1354
- delete acc[key];
1355
- } else {
1356
- // Otherwise, we set it.
1357
- acc[key] = overrides[key];
1358
- }
1359
- }
1360
1797
 
1361
- return acc;
1362
- }, { ...defaultContext
1363
- });
1798
+ const purgeCaches = () => {
1799
+ Object(_hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_0__[/* purgeSharedCache */ "a"])();
1800
+ Object(_hydration_cache_api_js__WEBPACK_IMPORTED_MODULE_1__[/* purgeHydrationCache */ "b"])();
1364
1801
  };
1365
1802
 
1366
1803
  /***/ }),
1367
- /* 19 */
1804
+ /* 25 */
1368
1805
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1369
1806
 
1370
1807
  "use strict";
1371
1808
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return TrackData; });
1372
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
1809
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1373
1810
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1374
1811
  /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
1375
1812
  /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_1__);
1376
- /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
1813
+ /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8);
1377
1814
 
1378
1815
 
1379
1816
 
@@ -1395,13 +1832,13 @@ class TrackData extends react__WEBPACK_IMPORTED_MODULE_0__["Component"] {
1395
1832
  }
1396
1833
 
1397
1834
  /***/ }),
1398
- /* 20 */
1835
+ /* 26 */
1399
1836
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1400
1837
 
1401
1838
  "use strict";
1402
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
1839
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1403
1840
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1404
- /* harmony import */ var _hooks_use_hydratable_effect_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11);
1841
+ /* harmony import */ var _hooks_use_hydratable_effect_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12);
1405
1842
 
1406
1843
 
1407
1844
 
@@ -1427,13 +1864,13 @@ const Data = ({
1427
1864
  /* harmony default export */ __webpack_exports__["a"] = (Data);
1428
1865
 
1429
1866
  /***/ }),
1430
- /* 21 */
1867
+ /* 27 */
1431
1868
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1432
1869
 
1433
1870
  "use strict";
1434
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
1871
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1435
1872
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1436
- /* harmony import */ var _intercept_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(13);
1873
+ /* harmony import */ var _intercept_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14);
1437
1874
 
1438
1875
 
1439
1876
 
@@ -1468,14 +1905,110 @@ const InterceptRequests = ({
1468
1905
  /* harmony default export */ __webpack_exports__["a"] = (InterceptRequests);
1469
1906
 
1470
1907
  /***/ }),
1471
- /* 22 */
1908
+ /* 28 */
1909
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
1910
+
1911
+ "use strict";
1912
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return getGqlRequestId; });
1913
+ const toString = valid => {
1914
+ var _JSON$stringify;
1915
+
1916
+ if (typeof valid === "string") {
1917
+ return valid;
1918
+ }
1919
+
1920
+ return (_JSON$stringify = JSON.stringify(valid)) != null ? _JSON$stringify : "";
1921
+ };
1922
+ /**
1923
+ * Get an identifier for a given request.
1924
+ */
1925
+
1926
+
1927
+ const getGqlRequestId = (operation, variables, context) => {
1928
+ // We add all the bits for this into an array and then join them with
1929
+ // a chosen separator.
1930
+ const parts = []; // First, we push the context values.
1931
+
1932
+ const sortableContext = new URLSearchParams(context); // $FlowIgnore[prop-missing] Flow has incomplete support for URLSearchParams
1933
+
1934
+ sortableContext.sort();
1935
+ parts.push(sortableContext.toString()); // Now we add the operation identifier.
1936
+
1937
+ parts.push(operation.id); // Finally, if we have variables, we add those too.
1938
+
1939
+ if (variables != null) {
1940
+ // We need to turn each variable into a string.
1941
+ const stringifiedVariables = Object.keys(variables).reduce((acc, key) => {
1942
+ acc[key] = toString(variables[key]);
1943
+ return acc;
1944
+ }, {}); // We use the same mechanism as context to sort and arrange the
1945
+ // variables.
1946
+
1947
+ const sortableVariables = new URLSearchParams(stringifiedVariables); // $FlowIgnore[prop-missing] Flow has incomplete support for URLSearchParams
1948
+
1949
+ sortableVariables.sort();
1950
+ parts.push(sortableVariables.toString());
1951
+ }
1952
+
1953
+ return parts.join("|");
1954
+ };
1955
+
1956
+ /***/ }),
1957
+ /* 29 */
1958
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
1959
+
1960
+ "use strict";
1961
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return toGqlOperation; });
1962
+ /* harmony import */ var _graphql_document_node_parser_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(18);
1963
+
1964
+
1965
+ /**
1966
+ * Convert a GraphQL DocumentNode to a base Wonder Blocks Data GqlOperation.
1967
+ *
1968
+ * If you want to include the query/mutation body, extend the result of this
1969
+ * method and use the `graphql/language/printer` like:
1970
+ *
1971
+ * ```js
1972
+ * import {print} from "graphql/language/printer";
1973
+ *
1974
+ * const gqlOpWithBody = {
1975
+ * ...toGqlOperation(documentNode),
1976
+ * query: print(documentNode),
1977
+ * };
1978
+ * ```
1979
+ *
1980
+ * If you want to enforce inclusion of __typename properties, then you can use
1981
+ * `apollo-utilities` first to modify the document:
1982
+ *
1983
+ * ```js
1984
+ * import {print} from "graphql/language/printer";
1985
+ * import {addTypenameToDocument} from "apollo-utilities";
1986
+ *
1987
+ * const documentWithTypenames = addTypenameToDocument(documentNode);
1988
+ * const gqlOpWithBody = {
1989
+ * ...toGqlOperation(documentWithTypenames),
1990
+ * query: print(documentWithTypenames),
1991
+ * };
1992
+ * ```
1993
+ */
1994
+ const toGqlOperation = documentNode => {
1995
+ const definition = Object(_graphql_document_node_parser_js__WEBPACK_IMPORTED_MODULE_0__[/* graphQLDocumentNodeParser */ "a"])(documentNode);
1996
+ const wbDataOperation = {
1997
+ id: definition.name,
1998
+ type: definition.type
1999
+ };
2000
+ return wbDataOperation;
2001
+ };
2002
+
2003
+ /***/ }),
2004
+ /* 30 */
1472
2005
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1473
2006
 
1474
2007
  "use strict";
1475
2008
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return GqlRouter; });
1476
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
2009
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1477
2010
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1478
- /* harmony import */ var _util_gql_router_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(17);
2011
+ /* harmony import */ var _util_gql_router_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(20);
1479
2012
 
1480
2013
 
1481
2014
 
@@ -1512,16 +2045,16 @@ const GqlRouter = ({
1512
2045
  };
1513
2046
 
1514
2047
  /***/ }),
1515
- /* 23 */
2048
+ /* 31 */
1516
2049
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1517
2050
 
1518
2051
  "use strict";
1519
2052
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return useGql; });
1520
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
2053
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1521
2054
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1522
- /* harmony import */ var _util_merge_gql_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18);
1523
- /* harmony import */ var _use_gql_router_context_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(25);
1524
- /* harmony import */ var _util_get_gql_data_from_response_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(26);
2055
+ /* harmony import */ var _util_merge_gql_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21);
2056
+ /* harmony import */ var _use_gql_router_context_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(33);
2057
+ /* harmony import */ var _util_get_gql_data_from_response_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(34);
1525
2058
 
1526
2059
 
1527
2060
 
@@ -1562,13 +2095,13 @@ const useGql = (context = {}) => {
1562
2095
  };
1563
2096
 
1564
2097
  /***/ }),
1565
- /* 24 */
2098
+ /* 32 */
1566
2099
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1567
2100
 
1568
2101
  "use strict";
1569
2102
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return resultFromCachedResponse; });
1570
- /* harmony import */ var _status_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);
1571
- /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1);
2103
+ /* harmony import */ var _status_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
2104
+ /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(0);
1572
2105
 
1573
2106
 
1574
2107
 
@@ -1602,16 +2135,16 @@ const resultFromCachedResponse = cacheEntry => {
1602
2135
  };
1603
2136
 
1604
2137
  /***/ }),
1605
- /* 25 */
2138
+ /* 33 */
1606
2139
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1607
2140
 
1608
2141
  "use strict";
1609
2142
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return useGqlRouterContext; });
1610
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
2143
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1611
2144
  /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
1612
- /* harmony import */ var _util_merge_gql_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(18);
1613
- /* harmony import */ var _util_gql_router_context_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(17);
1614
- /* harmony import */ var _util_gql_error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3);
2145
+ /* harmony import */ var _util_merge_gql_context_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21);
2146
+ /* harmony import */ var _util_gql_router_context_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(20);
2147
+ /* harmony import */ var _util_gql_error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4);
1615
2148
 
1616
2149
 
1617
2150
 
@@ -1654,13 +2187,13 @@ const useGqlRouterContext = (contextOverrides = {}) => {
1654
2187
  };
1655
2188
 
1656
2189
  /***/ }),
1657
- /* 26 */
2190
+ /* 34 */
1658
2191
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1659
2192
 
1660
2193
  "use strict";
1661
2194
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return getGqlDataFromResponse; });
1662
- /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
1663
- /* harmony import */ var _gql_error_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
2195
+ /* harmony import */ var _data_error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
2196
+ /* harmony import */ var _gql_error_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
1664
2197
 
1665
2198
 
1666
2199
  /**
@@ -1724,272 +2257,115 @@ const getGqlDataFromResponse = async response => {
1724
2257
  };
1725
2258
 
1726
2259
  /***/ }),
1727
- /* 27 */
2260
+ /* 35 */
1728
2261
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
1729
2262
 
1730
2263
  "use strict";
1731
2264
  __webpack_require__.r(__webpack_exports__);
1732
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "initializeCache", function() { return initializeCache; });
1733
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fulfillAllDataRequests", function() { return fulfillAllDataRequests; });
1734
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "hasUnfulfilledRequests", function() { return hasUnfulfilledRequests; });
1735
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeFromCache", function() { return removeFromCache; });
1736
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "removeAllFromCache", function() { return removeAllFromCache; });
1737
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
1738
- /* harmony import */ var _khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__);
1739
- /* harmony import */ var _util_ssr_cache_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
1740
- /* harmony import */ var _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
1741
- /* harmony import */ var _components_track_data_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(19);
1742
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "TrackData", function() { return _components_track_data_js__WEBPACK_IMPORTED_MODULE_3__["a"]; });
1743
-
1744
- /* harmony import */ var _components_data_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20);
1745
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Data", function() { return _components_data_js__WEBPACK_IMPORTED_MODULE_4__["a"]; });
1746
-
1747
- /* harmony import */ var _components_intercept_requests_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(21);
1748
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "InterceptRequests", function() { return _components_intercept_requests_js__WEBPACK_IMPORTED_MODULE_5__["a"]; });
1749
-
1750
- /* harmony import */ var _util_data_error_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1);
1751
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "DataError", function() { return _util_data_error_js__WEBPACK_IMPORTED_MODULE_6__["a"]; });
1752
-
1753
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "DataErrors", function() { return _util_data_error_js__WEBPACK_IMPORTED_MODULE_6__["b"]; });
1754
-
1755
- /* harmony import */ var _hooks_use_server_effect_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(14);
1756
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useServerEffect", function() { return _hooks_use_server_effect_js__WEBPACK_IMPORTED_MODULE_7__["a"]; });
1757
-
1758
- /* harmony import */ var _hooks_use_cached_effect_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(15);
1759
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useCachedEffect", function() { return _hooks_use_cached_effect_js__WEBPACK_IMPORTED_MODULE_8__["a"]; });
1760
-
1761
- /* harmony import */ var _hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(8);
1762
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useSharedCache", function() { return _hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_9__["b"]; });
1763
-
1764
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "clearSharedCache", function() { return _hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_9__["a"]; });
2265
+ /* harmony import */ var _util_types_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
2266
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "FetchPolicy", function() { return _util_types_js__WEBPACK_IMPORTED_MODULE_0__["a"]; });
1765
2267
 
1766
- /* harmony import */ var _hooks_use_hydratable_effect_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(11);
1767
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useHydratableEffect", function() { return _hooks_use_hydratable_effect_js__WEBPACK_IMPORTED_MODULE_10__["b"]; });
2268
+ /* harmony import */ var _util_hydration_cache_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(15);
2269
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "initializeHydrationCache", function() { return _util_hydration_cache_api_js__WEBPACK_IMPORTED_MODULE_1__["a"]; });
1768
2270
 
1769
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "WhenClientSide", function() { return _hooks_use_hydratable_effect_js__WEBPACK_IMPORTED_MODULE_10__["a"]; });
2271
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "purgeHydrationCache", function() { return _util_hydration_cache_api_js__WEBPACK_IMPORTED_MODULE_1__["b"]; });
1770
2272
 
1771
- /* harmony import */ var _util_scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(9);
1772
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ScopedInMemoryCache", function() { return _util_scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_11__["a"]; });
2273
+ /* harmony import */ var _util_request_api_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(23);
2274
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "fetchTrackedRequests", function() { return _util_request_api_js__WEBPACK_IMPORTED_MODULE_2__["b"]; });
1773
2275
 
1774
- /* harmony import */ var _util_serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(12);
1775
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "SerializableInMemoryCache", function() { return _util_serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_12__["a"]; });
2276
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "hasTrackedRequestsToBeFetched", function() { return _util_request_api_js__WEBPACK_IMPORTED_MODULE_2__["c"]; });
1776
2277
 
1777
- /* harmony import */ var _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(10);
1778
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "RequestFulfillment", function() { return _util_request_fulfillment_js__WEBPACK_IMPORTED_MODULE_13__["a"]; });
2278
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "abortInflightRequests", function() { return _util_request_api_js__WEBPACK_IMPORTED_MODULE_2__["a"]; });
1779
2279
 
1780
- /* harmony import */ var _util_status_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(4);
1781
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Status", function() { return _util_status_js__WEBPACK_IMPORTED_MODULE_14__["a"]; });
1782
-
1783
- /* harmony import */ var _components_gql_router_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(22);
1784
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlRouter", function() { return _components_gql_router_js__WEBPACK_IMPORTED_MODULE_15__["a"]; });
2280
+ /* harmony import */ var _util_purge_caches_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(24);
2281
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "purgeCaches", function() { return _util_purge_caches_js__WEBPACK_IMPORTED_MODULE_3__["a"]; });
1785
2282
 
1786
- /* harmony import */ var _hooks_use_gql_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(23);
1787
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useGql", function() { return _hooks_use_gql_js__WEBPACK_IMPORTED_MODULE_16__["a"]; });
2283
+ /* harmony import */ var _components_track_data_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(25);
2284
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "TrackData", function() { return _components_track_data_js__WEBPACK_IMPORTED_MODULE_4__["a"]; });
1788
2285
 
1789
- /* harmony import */ var _util_gql_error_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(3);
1790
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlError", function() { return _util_gql_error_js__WEBPACK_IMPORTED_MODULE_17__["a"]; });
2286
+ /* harmony import */ var _components_data_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(26);
2287
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Data", function() { return _components_data_js__WEBPACK_IMPORTED_MODULE_5__["a"]; });
1791
2288
 
1792
- /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlErrors", function() { return _util_gql_error_js__WEBPACK_IMPORTED_MODULE_17__["b"]; });
2289
+ /* harmony import */ var _components_intercept_requests_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(27);
2290
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "InterceptRequests", function() { return _components_intercept_requests_js__WEBPACK_IMPORTED_MODULE_6__["a"]; });
1793
2291
 
2292
+ /* harmony import */ var _util_data_error_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(0);
2293
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "DataError", function() { return _util_data_error_js__WEBPACK_IMPORTED_MODULE_7__["a"]; });
1794
2294
 
2295
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "DataErrors", function() { return _util_data_error_js__WEBPACK_IMPORTED_MODULE_7__["b"]; });
1795
2296
 
2297
+ /* harmony import */ var _hooks_use_server_effect_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(16);
2298
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useServerEffect", function() { return _hooks_use_server_effect_js__WEBPACK_IMPORTED_MODULE_8__["a"]; });
1796
2299
 
2300
+ /* harmony import */ var _hooks_use_cached_effect_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(17);
2301
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useCachedEffect", function() { return _hooks_use_cached_effect_js__WEBPACK_IMPORTED_MODULE_9__["a"]; });
1797
2302
 
1798
- /**
1799
- * Initialize the hydration cache.
1800
- *
1801
- * @param {ResponseCache} source The cache content to use for initializing the
1802
- * cache.
1803
- * @throws {Error} If the cache is already initialized.
1804
- */
1805
- const initializeCache = source => _util_ssr_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* SsrCache */ "a"].Default.initialize(source);
1806
- /**
1807
- * Fulfill all tracked data requests.
1808
- *
1809
- * This is for use with the `TrackData` component during server-side rendering.
1810
- *
1811
- * @throws {Error} If executed outside of server-side rendering.
1812
- * @returns {Promise<void>} A promise that resolves when all tracked requests
1813
- * have been fulfilled.
1814
- */
2303
+ /* harmony import */ var _hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(5);
2304
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useSharedCache", function() { return _hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_10__["b"]; });
1815
2305
 
1816
- const fulfillAllDataRequests = () => {
1817
- if (!_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide()) {
1818
- return Promise.reject(new Error("Data requests are not tracked when client-side"));
1819
- }
2306
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "purgeSharedCache", function() { return _hooks_use_shared_cache_js__WEBPACK_IMPORTED_MODULE_10__["a"]; });
1820
2307
 
1821
- return _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__[/* RequestTracker */ "a"].Default.fulfillTrackedRequests();
1822
- };
1823
- /**
1824
- * Indicate if there are unfulfilled tracked requests.
1825
- *
1826
- * This is used in conjunction with `TrackData`.
1827
- *
1828
- * @throws {Error} If executed outside of server-side rendering.
1829
- * @returns {boolean} `true` if there are unfulfilled tracked requests;
1830
- * otherwise, `false`.
1831
- */
2308
+ /* harmony import */ var _hooks_use_hydratable_effect_js__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(12);
2309
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useHydratableEffect", function() { return _hooks_use_hydratable_effect_js__WEBPACK_IMPORTED_MODULE_11__["b"]; });
1832
2310
 
1833
- const hasUnfulfilledRequests = () => {
1834
- if (!_khanacademy_wonder_blocks_core__WEBPACK_IMPORTED_MODULE_0__["Server"].isServerSide()) {
1835
- throw new Error("Data requests are not tracked when client-side");
1836
- }
2311
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "WhenClientSide", function() { return _hooks_use_hydratable_effect_js__WEBPACK_IMPORTED_MODULE_11__["a"]; });
1837
2312
 
1838
- return _util_request_tracking_js__WEBPACK_IMPORTED_MODULE_2__[/* RequestTracker */ "a"].Default.hasUnfulfilledRequests;
1839
- };
1840
- /**
1841
- * Remove the request identified from the cached hydration responses.
1842
- *
1843
- * @param {string} id The request ID of the response to remove from the cache.
1844
- */
2313
+ /* harmony import */ var _util_scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(11);
2314
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "ScopedInMemoryCache", function() { return _util_scoped_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_12__["a"]; });
1845
2315
 
1846
- const removeFromCache = id => _util_ssr_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* SsrCache */ "a"].Default.remove(id);
1847
- /**
1848
- * Remove all cached hydration responses that match the given predicate.
1849
- *
1850
- * @param {(id: string) => boolean} [predicate] The predicate to match against
1851
- * the cached hydration responses. If no predicate is provided, all cached
1852
- * hydration responses will be removed.
1853
- */
2316
+ /* harmony import */ var _util_serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(13);
2317
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "SerializableInMemoryCache", function() { return _util_serializable_in_memory_cache_js__WEBPACK_IMPORTED_MODULE_13__["a"]; });
1854
2318
 
1855
- const removeAllFromCache = predicate => _util_ssr_cache_js__WEBPACK_IMPORTED_MODULE_1__[/* SsrCache */ "a"].Default.removeAll(predicate);
2319
+ /* harmony import */ var _util_status_js__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(6);
2320
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "Status", function() { return _util_status_js__WEBPACK_IMPORTED_MODULE_14__["a"]; });
1856
2321
 
2322
+ /* harmony import */ var _util_get_gql_request_id_js__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(28);
2323
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "getGqlRequestId", function() { return _util_get_gql_request_id_js__WEBPACK_IMPORTED_MODULE_15__["a"]; });
1857
2324
 
2325
+ /* harmony import */ var _util_graphql_document_node_parser_js__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(18);
2326
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "graphQLDocumentNodeParser", function() { return _util_graphql_document_node_parser_js__WEBPACK_IMPORTED_MODULE_16__["a"]; });
1858
2327
 
2328
+ /* harmony import */ var _util_to_gql_operation_js__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(29);
2329
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "toGqlOperation", function() { return _util_to_gql_operation_js__WEBPACK_IMPORTED_MODULE_17__["a"]; });
1859
2330
 
2331
+ /* harmony import */ var _components_gql_router_js__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(30);
2332
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlRouter", function() { return _components_gql_router_js__WEBPACK_IMPORTED_MODULE_18__["a"]; });
1860
2333
 
2334
+ /* harmony import */ var _hooks_use_gql_js__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(31);
2335
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "useGql", function() { return _hooks_use_gql_js__WEBPACK_IMPORTED_MODULE_19__["a"]; });
1861
2336
 
2337
+ /* harmony import */ var _util_gql_error_js__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(4);
2338
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlError", function() { return _util_gql_error_js__WEBPACK_IMPORTED_MODULE_20__["a"]; });
1862
2339
 
2340
+ /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "GqlErrors", function() { return _util_gql_error_js__WEBPACK_IMPORTED_MODULE_20__["b"]; });
1863
2341
 
2342
+ // TODO(somewhatabstract, FEI-4174): Update eslint-plugin-import when they
2343
+ // have fixed:
2344
+ // https://github.com/import-js/eslint-plugin-import/issues/2073
2345
+ // eslint-disable-next-line import/named
1864
2346
 
1865
2347
 
1866
2348
 
1867
- // GraphQL
1868
2349
 
1869
2350
 
1870
2351
 
1871
2352
 
1872
2353
 
1873
- /***/ }),
1874
- /* 28 */
1875
- /***/ (function(module, exports, __webpack_require__) {
1876
2354
 
1877
- "use strict";
1878
- /**
1879
- * Copyright (c) Facebook, Inc. and its affiliates.
1880
- *
1881
- * This source code is licensed under the MIT license found in the
1882
- * LICENSE file in the root directory of this source tree.
1883
- */
1884
2355
 
1885
2356
 
1886
2357
 
1887
- // Below we want to use `hasOwnProperty` on an object that doesn't have
1888
- // `Object.prototype` in its proto chain, so we must extract it here.
1889
- var hasOwnProperty = Object.prototype.hasOwnProperty;
1890
2358
 
1891
- // Map from an enum object to a reverse map of its values to names
1892
- var reverseMapCache = typeof WeakMap === 'function' ? new WeakMap() : new Map();
1893
2359
 
1894
- // Computes the reverse mapping of the enum object: from value to name.
1895
- // Flow Enum values are unique (enforced by the parser), so this is a
1896
- // one to one mapping.
1897
- function getReverseMap(enumObject) {
1898
- var reverseMap = reverseMapCache.get(enumObject);
1899
- if (reverseMap !== undefined) {
1900
- return reverseMap;
1901
- }
1902
- // We aren't using `Object.values` because that gets enumerable
1903
- // properties, and our properties aren't enumerable.
1904
- var newReverseMap = new Map();
1905
- Object.getOwnPropertyNames(enumObject).forEach(function (name) {
1906
- newReverseMap.set(enumObject[name], name);
1907
- });
1908
- reverseMapCache.set(enumObject, newReverseMap);
1909
- return newReverseMap;
1910
- }
2360
+ ////////////////////////////////////////////////////////////////////////////////
2361
+ // GraphQL
2362
+ ////////////////////////////////////////////////////////////////////////////////
1911
2363
 
1912
- var EnumPrototype = Object.freeze(
1913
- Object.defineProperties(Object.create(null), {
1914
- isValid: {
1915
- value: function (x) {
1916
- return getReverseMap(this).has(x);
1917
- },
1918
- },
1919
- cast: {
1920
- value: function (x) {
1921
- return this.isValid(x) ? x : undefined;
1922
- },
1923
- },
1924
- members: {
1925
- value: function () {
1926
- return getReverseMap(this).keys();
1927
- },
1928
- },
1929
- getName: {
1930
- value: function (value) {
1931
- return getReverseMap(this).get(value);
1932
- }
1933
- }
1934
- })
1935
- );
1936
2364
 
1937
- // `members` is an object mapping name to value.
1938
- function Enum(members) {
1939
- var o = Object.create(EnumPrototype);
1940
- for (var k in members) {
1941
- if (hasOwnProperty.call(members, k)) {
1942
- // Create non-enumerable properties.
1943
- Object.defineProperty(o, k, {value: members[k]});
1944
- }
1945
- }
1946
- return Object.freeze(o);
1947
- }
1948
2365
 
1949
- // Mirrored enum (string enum with no member initializers).
1950
- // Optimized implementation, taking advantage of the fact that
1951
- // keys and values are identical.
1952
- var EnumMirroredPrototype = Object.freeze(
1953
- Object.defineProperties(Object.create(null), {
1954
- isValid: {
1955
- value: function (x) {
1956
- if (typeof x === 'string') {
1957
- return hasOwnProperty.call(this, x);
1958
- }
1959
- return false;
1960
- },
1961
- },
1962
- cast: {
1963
- value: EnumPrototype.cast,
1964
- },
1965
- members: {
1966
- value: function () {
1967
- // We aren't using `Object.values` because that gets enumerable
1968
- // properties, and our properties aren't enumerable.
1969
- return Object.getOwnPropertyNames(this).values();
1970
- },
1971
- },
1972
- getName: {
1973
- value: function (value) {
1974
- return value;
1975
- }
1976
- }
1977
- })
1978
- );
1979
2366
 
1980
- // `members` is an array of names (which, are also the values).
1981
- Enum.Mirrored = function EnumMirrored(members) {
1982
- var o = Object.create(EnumMirroredPrototype);
1983
- for (var i = 0, len = members.length; i < len; ++i) {
1984
- // Value is same as key. Also, non-enumerable.
1985
- Object.defineProperty(o, members[i], {value: members[i]});
1986
- }
1987
- return Object.freeze(o);
1988
- };
1989
2367
 
1990
- Object.freeze(Enum.Mirrored);
1991
2368
 
1992
- module.exports = Object.freeze(Enum);
1993
2369
 
1994
2370
 
1995
2371
  /***/ })