@thoughtbot/superglue 1.0.1 → 2.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
6
  var __export = (target, all) => {
9
7
  for (var name in all)
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
17
15
  }
18
16
  return to;
19
17
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
19
 
30
20
  // lib/action_creators/index.ts
@@ -38,52 +28,39 @@ __export(action_creators_exports, {
38
28
  module.exports = __toCommonJS(action_creators_exports);
39
29
 
40
30
  // lib/utils/url.ts
41
- var import_url_parse = __toESM(require("url-parse"));
31
+ var FAKE_ORIGIN = "https://example.com";
42
32
  function pathQuery(url) {
43
- const { pathname, query } = new import_url_parse.default(url, {});
33
+ const { pathname, search: query } = new URL(url, FAKE_ORIGIN);
44
34
  return pathname + query;
45
35
  }
46
36
  function hasPropsAt(url) {
47
- const parsed = new import_url_parse.default(url, {}, true);
48
- const query = parsed.query;
49
- return !!query["props_at"];
37
+ const { searchParams } = new URL(url, FAKE_ORIGIN);
38
+ return searchParams.has("props_at");
50
39
  }
51
40
  function propsAtParam(url) {
52
- const parsed = new import_url_parse.default(url, {}, true);
53
- const query = parsed.query;
54
- return query["props_at"];
41
+ const { searchParams } = new URL(url, FAKE_ORIGIN);
42
+ return searchParams.get("props_at");
55
43
  }
56
44
  function withFormatJson(url) {
57
- const parsed = new import_url_parse.default(url, {}, true);
58
- parsed.query["format"] = "json";
59
- return parsed.toString();
45
+ const parsed = new URL(url, FAKE_ORIGIN);
46
+ parsed.searchParams.set("format", "json");
47
+ return parsed.href.replace(parsed.origin, "");
60
48
  }
61
49
  function removePropsAt(url) {
62
- const parsed = new import_url_parse.default(url, {}, true);
63
- const query = parsed.query;
64
- delete query["props_at"];
65
- parsed.set("query", query);
66
- return parsed.toString();
50
+ const parsed = new URL(url, FAKE_ORIGIN);
51
+ parsed.searchParams.delete("props_at");
52
+ return parsed.href.replace(parsed.origin, "");
67
53
  }
68
54
  function urlToPageKey(url) {
69
- const parsed = new import_url_parse.default(url, {}, true);
70
- const query = parsed.query;
71
- delete query["props_at"];
72
- delete query["format"];
73
- parsed.set("query", query);
55
+ const parsed = new URL(url, FAKE_ORIGIN);
56
+ parsed.searchParams.delete("props_at");
57
+ parsed.searchParams.delete("format");
74
58
  return pathQuery(parsed.toString());
75
59
  }
76
60
  function withoutHash(url) {
77
- const parsed = new import_url_parse.default(url, {}, true);
78
- parsed.set("hash", "");
79
- return parsed.toString();
80
- }
81
- function withoutBusters(url) {
82
- const parsed = new import_url_parse.default(url, {}, true);
83
- const query = parsed.query;
84
- delete query["format"];
85
- parsed.set("query", query);
86
- return pathQuery(parsed.toString());
61
+ const parsed = new URL(url, FAKE_ORIGIN);
62
+ parsed.hash = "";
63
+ return parsed.href.replace(parsed.origin, "");
87
64
  }
88
65
  function formatForXHR(url) {
89
66
  const formats = [withoutHash, withFormatJson];
@@ -123,6 +100,9 @@ function getIn(node, path) {
123
100
  return void 0;
124
101
  }
125
102
  }
103
+ function clone(node) {
104
+ return Array.isArray(node) ? [].slice.call(node) : { ...node };
105
+ }
126
106
  function getKey(node, key) {
127
107
  if (Array.isArray(node) && Number.isNaN(Number(key))) {
128
108
  const key_parts = Array.from(key.split("="));
@@ -171,9 +151,34 @@ function normalizeKeyPath(path) {
171
151
  return path;
172
152
  }
173
153
  }
174
-
175
- // lib/utils/request.ts
176
- var import_url_parse2 = __toESM(require("url-parse"));
154
+ function setIn(object, path, value) {
155
+ const keypath = normalizeKeyPath(path);
156
+ const results = { 0: object };
157
+ const parents = { 0: object };
158
+ let i;
159
+ for (i = 0; i < keypath.length; i++) {
160
+ const parent = parents[i];
161
+ if (!(typeof parent === "object" && parent !== null)) {
162
+ throw new KeyPathError(
163
+ `Expected to traverse an Array or Obj, got ${JSON.stringify(parent)}`
164
+ );
165
+ }
166
+ const child = atKey(parent, keypath[i]);
167
+ parents[i + 1] = child;
168
+ }
169
+ results[keypath.length] = value;
170
+ for (i = keypath.length - 1; i >= 0; i--) {
171
+ const target = clone(parents[i]);
172
+ results[i] = target;
173
+ const key = getKey(results[i], keypath[i]);
174
+ if (Array.isArray(target)) {
175
+ target[key] = results[i + 1];
176
+ } else {
177
+ target[key] = results[i + 1];
178
+ }
179
+ }
180
+ return results[0];
181
+ }
177
182
 
178
183
  // lib/config.ts
179
184
  var config = {
@@ -181,7 +186,26 @@ var config = {
181
186
  maxPages: 20
182
187
  };
183
188
 
189
+ // lib/utils/limited_set.ts
190
+ var LimitedSet = class extends Set {
191
+ constructor(maxSize) {
192
+ super();
193
+ this.maxSize = maxSize;
194
+ }
195
+ add(value) {
196
+ if (this.size >= this.maxSize) {
197
+ const iterator = this.values();
198
+ const oldestValue = iterator.next().value;
199
+ this.delete(oldestValue);
200
+ }
201
+ super.add(value);
202
+ return this;
203
+ }
204
+ };
205
+
184
206
  // lib/utils/request.ts
207
+ var import_uuid = require("uuid");
208
+ var lastRequestIds = new LimitedSet(20);
185
209
  function isValidResponse(xhr) {
186
210
  return isValidContent(xhr) && !downloadingFile(xhr);
187
211
  }
@@ -237,6 +261,9 @@ function argsForFetch(getState, pathQuery2, {
237
261
  nextHeaders["x-requested-with"] = "XMLHttpRequest";
238
262
  nextHeaders["accept"] = "application/json";
239
263
  nextHeaders["x-superglue-request"] = "true";
264
+ const requestId = (0, import_uuid.v4)();
265
+ lastRequestIds.add(requestId);
266
+ nextHeaders["X-Superglue-Request-Id"] = requestId;
240
267
  if (method != "GET" && method != "HEAD") {
241
268
  nextHeaders["content-type"] = "application/json";
242
269
  }
@@ -246,11 +273,7 @@ function argsForFetch(getState, pathQuery2, {
246
273
  if (currentState.csrfToken) {
247
274
  nextHeaders["x-csrf-token"] = currentState.csrfToken;
248
275
  }
249
- const fetchPath = new import_url_parse2.default(
250
- formatForXHR(pathQuery2),
251
- config.baseUrl || {},
252
- true
253
- );
276
+ const fetchPath = new URL(formatForXHR(pathQuery2), config.baseUrl);
254
277
  const credentials = "same-origin";
255
278
  if (!(method == "GET" || method == "HEAD")) {
256
279
  nextHeaders["x-http-method-override"] = method;
@@ -264,20 +287,16 @@ function argsForFetch(getState, pathQuery2, {
264
287
  signal
265
288
  };
266
289
  if (currentState.currentPageKey) {
267
- const referrer = new import_url_parse2.default(
268
- currentState.currentPageKey,
269
- config.baseUrl || {},
270
- false
271
- ).href;
272
- options.referrer = referrer;
290
+ const referrer = new URL(currentState.currentPageKey, config.baseUrl);
291
+ options.referrer = referrer.toString();
273
292
  }
274
293
  if (method == "GET" || method == "HEAD") {
275
294
  if (options.body instanceof FormData) {
276
295
  const allData = new URLSearchParams(
277
296
  options.body
278
297
  );
279
- const nextQuery = { ...fetchPath.query, ...Object.fromEntries(allData) };
280
- fetchPath.set("query", nextQuery);
298
+ allData.forEach((value, key) => fetchPath.searchParams.delete(key));
299
+ allData.forEach((value, key) => fetchPath.searchParams.append(key, value));
281
300
  }
282
301
  delete options.body;
283
302
  }
@@ -305,9 +324,6 @@ function needsRefresh(prevAssets, newAssets) {
305
324
  }
306
325
  }
307
326
 
308
- // lib/action_creators/index.ts
309
- var import_url_parse3 = __toESM(require("url-parse"));
310
-
311
327
  // lib/actions.ts
312
328
  var import_toolkit = require("@reduxjs/toolkit");
313
329
  var GRAFTING_ERROR = "@@superglue/GRAFTING_ERROR";
@@ -339,7 +355,6 @@ var handleGraft = (0, import_toolkit.createAction)(
339
355
  var superglueError = (0, import_toolkit.createAction)(
340
356
  "@@superglue/ERROR"
341
357
  );
342
- var updateFragments = (0, import_toolkit.createAction)("@@superglue/UPDATE_FRAGMENTS");
343
358
  var copyPage = (0, import_toolkit.createAction)(
344
359
  "@@superglue/COPY_PAGE"
345
360
  );
@@ -354,6 +369,53 @@ var beforeRemote = (0, import_toolkit.createAction)("@@superglue/BEFORE_REMOTE")
354
369
  var setCSRFToken = (0, import_toolkit.createAction)("@@superglue/SET_CSRF_TOKEN");
355
370
  var historyChange = (0, import_toolkit.createAction)("@@superglue/HISTORY_CHANGE");
356
371
  var setActivePage = (0, import_toolkit.createAction)("@@superglue/SET_ACTIVE_PAGE");
372
+ var handleFragmentGraft = (0, import_toolkit.createAction)(
373
+ "@@superglue/HANDLE_FRAGMENT_GRAFT",
374
+ ({
375
+ fragmentId,
376
+ response
377
+ }) => {
378
+ return {
379
+ payload: {
380
+ response,
381
+ fragmentId
382
+ }
383
+ };
384
+ }
385
+ );
386
+ var saveFragment = (0, import_toolkit.createAction)(
387
+ "@@superglue/SAVE_FRAGMENT",
388
+ ({ fragmentId, data }) => {
389
+ return {
390
+ payload: {
391
+ fragmentId,
392
+ data
393
+ }
394
+ };
395
+ }
396
+ );
397
+ var appendToFragment = (0, import_toolkit.createAction)(
398
+ "@@superglue/APPEND_TO_FRAGMENT",
399
+ ({ data, fragmentId }) => {
400
+ return {
401
+ payload: {
402
+ data,
403
+ fragmentId
404
+ }
405
+ };
406
+ }
407
+ );
408
+ var prependToFragment = (0, import_toolkit.createAction)(
409
+ "@@superglue/PREPEND_TO_FRAGMENT",
410
+ ({ data, fragmentId }) => {
411
+ return {
412
+ payload: {
413
+ data,
414
+ fragmentId
415
+ }
416
+ };
417
+ }
418
+ );
357
419
 
358
420
  // lib/action_creators/requests.ts
359
421
  function handleFetchErr(err, fetchArgs, dispatch) {
@@ -363,15 +425,18 @@ function handleFetchErr(err, fetchArgs, dispatch) {
363
425
  function buildMeta(pageKey, page, state, rsp, fetchArgs) {
364
426
  const { assets: prevAssets } = state;
365
427
  const { assets: nextAssets } = page;
366
- return {
428
+ const meta = {
367
429
  pageKey,
368
430
  page,
369
431
  redirected: rsp.redirected,
370
432
  rsp,
371
433
  fetchArgs,
372
- componentIdentifier: page.componentIdentifier,
373
434
  needsRefresh: needsRefresh(prevAssets, nextAssets)
374
435
  };
436
+ if (page.action !== "handleStreamResponse") {
437
+ meta.componentIdentifier = page.componentIdentifier;
438
+ }
439
+ return meta;
375
440
  }
376
441
  var MismatchedComponentError = class extends Error {
377
442
  constructor(message) {
@@ -379,13 +444,13 @@ var MismatchedComponentError = class extends Error {
379
444
  this.name = "MismatchedComponentError";
380
445
  }
381
446
  };
447
+ var defaultBeforeSave = (prevPage, receivedPage) => receivedPage;
382
448
  var remote = (path, {
383
449
  pageKey: targetPageKey,
384
450
  force = false,
385
- beforeSave = (prevPage, receivedPage) => receivedPage,
451
+ beforeSave = defaultBeforeSave,
386
452
  ...rest
387
453
  } = {}) => {
388
- path = withoutBusters(path);
389
454
  targetPageKey = targetPageKey && urlToPageKey(targetPageKey);
390
455
  return (dispatch, getState) => {
391
456
  const fetchArgs = argsForFetch(getState, path, rest);
@@ -402,10 +467,11 @@ var remote = (path, {
402
467
  pageKey = targetPageKey;
403
468
  }
404
469
  const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
405
- const existingId = pages[pageKey]?.componentIdentifier;
406
- const receivedId = json.componentIdentifier;
407
- if (!!existingId && existingId != receivedId && !force) {
408
- const message = `You cannot replace or update an existing page
470
+ if (json.action !== "handleStreamResponse") {
471
+ const existingId = pages[pageKey]?.componentIdentifier;
472
+ const receivedId = json.componentIdentifier;
473
+ if (!!existingId && existingId != receivedId && !force) {
474
+ const message = `You cannot replace or update an existing page
409
475
  located at pages["${currentPageKey}"] that has a componentIdentifier
410
476
  of "${existingId}" with the contents of a page response that has a
411
477
  componentIdentifier of "${receivedId}".
@@ -421,7 +487,8 @@ compatible with the page component associated with "${existingId}".
421
487
  Consider using data-sg-visit, the visit function, or redirect_back to
422
488
  the same page. Or if you're sure you want to proceed, use force: true.
423
489
  `;
424
- throw new MismatchedComponentError(message);
490
+ throw new MismatchedComponentError(message);
491
+ }
425
492
  }
426
493
  const page = beforeSave(pages[pageKey], json);
427
494
  return dispatch(saveAndProcessPage(pageKey, page)).then(() => meta);
@@ -439,7 +506,6 @@ var visit = (path, {
439
506
  revisit = false,
440
507
  ...rest
441
508
  } = {}) => {
442
- path = withoutBusters(path);
443
509
  return (dispatch, getState) => {
444
510
  const currentPageKey = getState().superglue.currentPageKey;
445
511
  placeholderKey = placeholderKey && urlToPageKey(placeholderKey) || currentPageKey;
@@ -466,11 +532,13 @@ var visit = (path, {
466
532
  const { superglue, pages = {} } = getState();
467
533
  const isGet = fetchArgs[1].method === "GET";
468
534
  const pageKey = calculatePageKey(rsp, isGet, currentPageKey);
469
- if (placeholderKey && hasPropsAt(path) && hasPlaceholder) {
470
- const existingId = pages[placeholderKey]?.componentIdentifier;
471
- const receivedId = json.componentIdentifier;
472
- if (!!existingId && existingId != receivedId) {
473
- const message = `You received a page response with a
535
+ const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
536
+ if (json.action !== "handleStreamResponse") {
537
+ if (placeholderKey && hasPropsAt(path) && hasPlaceholder) {
538
+ const existingId = pages[placeholderKey]?.componentIdentifier;
539
+ const receivedId = json.componentIdentifier;
540
+ if (!!existingId && existingId != receivedId) {
541
+ const message = `You received a page response with a
474
542
  componentIdentifier "${receivedId}" that is different than the
475
543
  componentIdentifier "${existingId}" located at ${placeholderKey}.
476
544
 
@@ -486,16 +554,17 @@ Check that you're rendering a page with a matching
486
554
  componentIdentifier, or consider using redirect_back_with_props_at
487
555
  to the same page.
488
556
  `;
489
- throw new MismatchedComponentError(message);
557
+ throw new MismatchedComponentError(message);
558
+ }
559
+ dispatch(copyPage({ from: placeholderKey, to: pageKey }));
490
560
  }
491
- dispatch(copyPage({ from: placeholderKey, to: pageKey }));
492
561
  }
493
- const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
494
562
  const visitMeta = {
495
563
  ...meta,
496
564
  navigationAction: calculateNavAction(
497
565
  meta,
498
566
  rsp,
567
+ json,
499
568
  isGet,
500
569
  pageKey,
501
570
  currentPageKey,
@@ -507,8 +576,11 @@ to the same page.
507
576
  }).catch((e) => handleFetchErr(e, fetchArgs, dispatch));
508
577
  };
509
578
  };
510
- function calculateNavAction(meta, rsp, isGet, pageKey, currentPageKey, revisit) {
579
+ function calculateNavAction(meta, rsp, json, isGet, pageKey, currentPageKey, revisit) {
511
580
  let navigationAction = "push";
581
+ if (json.action === "handleStreamResponse") {
582
+ return "none";
583
+ }
512
584
  if (!rsp.redirected && !isGet) {
513
585
  navigationAction = "replace";
514
586
  }
@@ -537,6 +609,113 @@ function calculatePageKey(rsp, isGet, currentPageKey) {
537
609
  return pageKey;
538
610
  }
539
611
 
612
+ // lib/action_creators/stream.ts
613
+ var streamPrepend = (fragments, data, options = {}) => {
614
+ return (dispatch) => {
615
+ if (options.saveAs) {
616
+ const { saveAs } = options;
617
+ dispatch(
618
+ saveFragment({
619
+ fragmentId: saveAs,
620
+ data
621
+ })
622
+ );
623
+ fragments.forEach((fragmentId) => {
624
+ dispatch(
625
+ prependToFragment({
626
+ fragmentId,
627
+ data: {
628
+ __id: saveAs
629
+ }
630
+ })
631
+ );
632
+ });
633
+ } else {
634
+ fragments.forEach((fragmentId) => {
635
+ dispatch(
636
+ prependToFragment({
637
+ fragmentId,
638
+ data
639
+ })
640
+ );
641
+ });
642
+ }
643
+ };
644
+ };
645
+ var streamAppend = (fragments, data, options = {}) => {
646
+ return (dispatch) => {
647
+ if (options.saveAs) {
648
+ const { saveAs } = options;
649
+ dispatch(
650
+ saveFragment({
651
+ fragmentId: saveAs,
652
+ data
653
+ })
654
+ );
655
+ fragments.forEach((fragmentId) => {
656
+ dispatch(
657
+ appendToFragment({
658
+ fragmentId,
659
+ data: {
660
+ __id: saveAs
661
+ }
662
+ })
663
+ );
664
+ });
665
+ } else {
666
+ fragments.forEach((fragmentId) => {
667
+ dispatch(
668
+ appendToFragment({
669
+ fragmentId,
670
+ data
671
+ })
672
+ );
673
+ });
674
+ }
675
+ };
676
+ };
677
+ var streamSave = (fragment, data) => {
678
+ return (dispatch) => {
679
+ dispatch(
680
+ saveFragment({
681
+ fragmentId: fragment,
682
+ data
683
+ })
684
+ );
685
+ };
686
+ };
687
+ var handleStreamResponse = (response) => {
688
+ return (dispatch) => {
689
+ let nextResponse = response;
690
+ nextResponse.fragments.reverse().forEach((fragment) => {
691
+ const { id, path } = fragment;
692
+ const node = getIn(nextResponse, path);
693
+ nextResponse = setIn(nextResponse, path, { __id: id });
694
+ dispatch(
695
+ saveFragment({
696
+ fragmentId: id,
697
+ data: node
698
+ })
699
+ );
700
+ });
701
+ nextResponse.data.forEach((message) => {
702
+ if (message.handler === "append") {
703
+ dispatch(
704
+ streamAppend(message.fragmentIds, message.data, message.options)
705
+ );
706
+ }
707
+ if (message.handler === "prepend") {
708
+ dispatch(
709
+ streamPrepend(message.fragmentIds, message.data, message.options)
710
+ );
711
+ }
712
+ if (message.handler === "save") {
713
+ dispatch(streamSave(message.fragmentIds[0], message.data));
714
+ }
715
+ });
716
+ };
717
+ };
718
+
540
719
  // lib/action_creators/index.ts
541
720
  function fetchDeferments(pageKey, defers = []) {
542
721
  pageKey = urlToPageKey(pageKey);
@@ -546,8 +725,7 @@ function fetchDeferments(pageKey, defers = []) {
546
725
  successAction = GRAFTING_SUCCESS,
547
726
  failAction = GRAFTING_ERROR
548
727
  }) {
549
- const parsedUrl = new import_url_parse3.default(url, true);
550
- const keyPath = parsedUrl.query.props_at;
728
+ const keyPath = propsAtParam(url);
551
729
  return dispatch(remote(url, { pageKey })).then(() => {
552
730
  dispatch({
553
731
  type: successAction,
@@ -572,57 +750,40 @@ function fetchDeferments(pageKey, defers = []) {
572
750
  };
573
751
  }
574
752
  function saveAndProcessPage(pageKey, page) {
575
- return (dispatch, getState) => {
753
+ return (dispatch) => {
576
754
  pageKey = urlToPageKey(pageKey);
577
- const { defers = [] } = page;
578
- if ("action" in page) {
579
- const prevPage = getState().pages[pageKey];
580
- dispatch(handleGraft({ pageKey, page }));
581
- const currentPage = getState().pages[pageKey];
582
- currentPage.fragments.forEach((fragment) => {
583
- const { type, path } = fragment;
584
- const currentFragment = getIn(currentPage, path);
585
- const prevFragment = getIn(prevPage, path);
586
- if (!prevFragment) {
587
- dispatch(
588
- updateFragments({
589
- name: type,
590
- pageKey,
591
- value: currentFragment,
592
- path
593
- })
594
- );
595
- } else if (currentFragment !== prevFragment) {
596
- dispatch(
597
- updateFragments({
598
- name: type,
599
- pageKey,
600
- value: currentFragment,
601
- previousValue: prevFragment,
602
- path
603
- })
604
- );
605
- }
606
- });
607
- } else {
608
- dispatch(saveResponse({ pageKey, page }));
609
- const currentPage = getState().pages[pageKey];
610
- currentPage.fragments.forEach((fragment) => {
611
- const { type, path } = fragment;
612
- const currentFragment = getIn(currentPage, path);
755
+ let nextPage = page;
756
+ page.fragments.reverse().forEach((fragment) => {
757
+ const { id, path } = fragment;
758
+ const node = getIn(nextPage, path);
759
+ nextPage = setIn(page, path, { __id: id });
760
+ dispatch(
761
+ saveFragment({
762
+ fragmentId: id,
763
+ data: node
764
+ })
765
+ );
766
+ });
767
+ if (nextPage.action === "graft") {
768
+ if (typeof nextPage.fragmentContext === "string") {
613
769
  dispatch(
614
- updateFragments({
615
- name: type,
616
- pageKey,
617
- value: currentFragment,
618
- path
770
+ handleFragmentGraft({
771
+ fragmentId: nextPage.fragmentContext,
772
+ response: nextPage
619
773
  })
620
774
  );
621
- });
775
+ } else {
776
+ dispatch(handleGraft({ pageKey, page: nextPage }));
777
+ }
778
+ } else if (nextPage.action === "handleStreamResponse") {
779
+ dispatch(handleStreamResponse(nextPage));
780
+ return Promise.resolve();
781
+ } else {
782
+ dispatch(saveResponse({ pageKey, page: nextPage }));
622
783
  }
623
784
  const hasFetch = typeof fetch != "undefined";
624
785
  if (hasFetch) {
625
- return dispatch(fetchDeferments(pageKey, defers)).then(
786
+ return dispatch(fetchDeferments(pageKey, nextPage.defers)).then(
626
787
  () => Promise.resolve()
627
788
  );
628
789
  } else {