@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,72 +1,74 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
1
27
  // lib/utils/url.ts
2
- import parse from "url-parse";
28
+ var FAKE_ORIGIN = "https://example.com";
3
29
  function pathQuery(url) {
4
- const { pathname, query } = new parse(url, {});
30
+ const { pathname, search: query } = new URL(url, FAKE_ORIGIN);
5
31
  return pathname + query;
6
32
  }
7
- function pathQueryHash(url) {
8
- const { pathname, query, hash } = new parse(url, {});
9
- return pathname + query + hash;
10
- }
11
33
  function hasPropsAt(url) {
12
- const parsed = new parse(url, {}, true);
13
- const query = parsed.query;
14
- return !!query["props_at"];
34
+ const { searchParams } = new URL(url, FAKE_ORIGIN);
35
+ return searchParams.has("props_at");
15
36
  }
16
37
  function propsAtParam(url) {
17
- const parsed = new parse(url, {}, true);
18
- const query = parsed.query;
19
- return query["props_at"];
38
+ const { searchParams } = new URL(url, FAKE_ORIGIN);
39
+ return searchParams.get("props_at");
20
40
  }
21
41
  function withFormatJson(url) {
22
- const parsed = new parse(url, {}, true);
23
- parsed.query["format"] = "json";
24
- return parsed.toString();
25
- }
26
- function pathWithoutBZParams(url) {
27
- const parsed = new parse(url, {}, true);
28
- const query = parsed.query;
29
- delete query["props_at"];
30
- delete query["format"];
31
- parsed.set("query", query);
32
- return pathQueryHash(parsed.toString());
42
+ const parsed = new URL(url, FAKE_ORIGIN);
43
+ parsed.searchParams.set("format", "json");
44
+ return parsed.href.replace(parsed.origin, "");
33
45
  }
34
46
  function removePropsAt(url) {
35
- const parsed = new parse(url, {}, true);
36
- const query = parsed.query;
37
- delete query["props_at"];
38
- parsed.set("query", query);
39
- return parsed.toString();
47
+ const parsed = new URL(url, FAKE_ORIGIN);
48
+ parsed.searchParams.delete("props_at");
49
+ return parsed.href.replace(parsed.origin, "");
40
50
  }
41
51
  function urlToPageKey(url) {
42
- const parsed = new parse(url, {}, true);
43
- const query = parsed.query;
44
- delete query["props_at"];
45
- delete query["format"];
46
- parsed.set("query", query);
52
+ const parsed = new URL(url, FAKE_ORIGIN);
53
+ parsed.searchParams.delete("props_at");
54
+ parsed.searchParams.delete("format");
47
55
  return pathQuery(parsed.toString());
48
56
  }
49
57
  function withoutHash(url) {
50
- const parsed = new parse(url, {}, true);
51
- parsed.set("hash", "");
52
- return parsed.toString();
53
- }
54
- function withoutBusters(url) {
55
- const parsed = new parse(url, {}, true);
56
- const query = parsed.query;
57
- delete query["format"];
58
- parsed.set("query", query);
59
- return pathQuery(parsed.toString());
58
+ const parsed = new URL(url, FAKE_ORIGIN);
59
+ parsed.hash = "";
60
+ return parsed.href.replace(parsed.origin, "");
60
61
  }
61
62
  function formatForXHR(url) {
62
63
  const formats = [withoutHash, withFormatJson];
63
64
  return formats.reduce((memo, f) => f(memo), url);
64
65
  }
65
66
  function parsePageKey(pageKey) {
66
- const { pathname, query } = new parse(pageKey, {}, true);
67
+ const { pathname, searchParams } = new URL(pageKey, FAKE_ORIGIN);
68
+ const search = Object.fromEntries(searchParams);
67
69
  return {
68
70
  pathname,
69
- search: query
71
+ search
70
72
  };
71
73
  }
72
74
 
@@ -197,16 +199,32 @@ function setIn(object, path, value) {
197
199
  return results[0];
198
200
  }
199
201
 
200
- // lib/utils/request.ts
201
- import parse2 from "url-parse";
202
-
203
202
  // lib/config.ts
204
203
  var config = {
205
204
  baseUrl: "",
206
205
  maxPages: 20
207
206
  };
208
207
 
208
+ // lib/utils/limited_set.ts
209
+ var LimitedSet = class extends Set {
210
+ constructor(maxSize) {
211
+ super();
212
+ this.maxSize = maxSize;
213
+ }
214
+ add(value) {
215
+ if (this.size >= this.maxSize) {
216
+ const iterator = this.values();
217
+ const oldestValue = iterator.next().value;
218
+ this.delete(oldestValue);
219
+ }
220
+ super.add(value);
221
+ return this;
222
+ }
223
+ };
224
+
209
225
  // lib/utils/request.ts
226
+ import { v4 as uuidv4 } from "uuid";
227
+ var lastRequestIds = new LimitedSet(20);
210
228
  function isValidResponse(xhr) {
211
229
  return isValidContent(xhr) && !downloadingFile(xhr);
212
230
  }
@@ -262,6 +280,9 @@ function argsForFetch(getState, pathQuery2, {
262
280
  nextHeaders["x-requested-with"] = "XMLHttpRequest";
263
281
  nextHeaders["accept"] = "application/json";
264
282
  nextHeaders["x-superglue-request"] = "true";
283
+ const requestId = uuidv4();
284
+ lastRequestIds.add(requestId);
285
+ nextHeaders["X-Superglue-Request-Id"] = requestId;
265
286
  if (method != "GET" && method != "HEAD") {
266
287
  nextHeaders["content-type"] = "application/json";
267
288
  }
@@ -271,11 +292,7 @@ function argsForFetch(getState, pathQuery2, {
271
292
  if (currentState.csrfToken) {
272
293
  nextHeaders["x-csrf-token"] = currentState.csrfToken;
273
294
  }
274
- const fetchPath = new parse2(
275
- formatForXHR(pathQuery2),
276
- config.baseUrl || {},
277
- true
278
- );
295
+ const fetchPath = new URL(formatForXHR(pathQuery2), config.baseUrl);
279
296
  const credentials = "same-origin";
280
297
  if (!(method == "GET" || method == "HEAD")) {
281
298
  nextHeaders["x-http-method-override"] = method;
@@ -289,20 +306,16 @@ function argsForFetch(getState, pathQuery2, {
289
306
  signal
290
307
  };
291
308
  if (currentState.currentPageKey) {
292
- const referrer = new parse2(
293
- currentState.currentPageKey,
294
- config.baseUrl || {},
295
- false
296
- ).href;
297
- options.referrer = referrer;
309
+ const referrer = new URL(currentState.currentPageKey, config.baseUrl);
310
+ options.referrer = referrer.toString();
298
311
  }
299
312
  if (method == "GET" || method == "HEAD") {
300
313
  if (options.body instanceof FormData) {
301
314
  const allData = new URLSearchParams(
302
315
  options.body
303
316
  );
304
- const nextQuery = { ...fetchPath.query, ...Object.fromEntries(allData) };
305
- fetchPath.set("query", nextQuery);
317
+ allData.forEach((value, key) => fetchPath.searchParams.delete(key));
318
+ allData.forEach((value, key) => fetchPath.searchParams.append(key, value));
306
319
  }
307
320
  delete options.body;
308
321
  }
@@ -360,12 +373,11 @@ var HandlerBuilder = class {
360
373
  return;
361
374
  }
362
375
  event.preventDefault();
363
- let url = form.getAttribute("action");
376
+ const url = form.getAttribute("action");
364
377
  if (!url) {
365
378
  return;
366
379
  }
367
380
  const method = (form.getAttribute("method") || "POST").toUpperCase();
368
- url = withoutBusters(url);
369
381
  this.visitOrRemote(form, url, {
370
382
  method,
371
383
  body: new FormData(form)
@@ -381,11 +393,10 @@ var HandlerBuilder = class {
381
393
  return;
382
394
  }
383
395
  event.preventDefault();
384
- let url = link.getAttribute("href");
396
+ const url = link.getAttribute("href");
385
397
  if (!url) {
386
398
  return;
387
399
  }
388
- url = withoutBusters(url);
389
400
  this.visitOrRemote(link, url, { method: "GET" });
390
401
  }
391
402
  visitOrRemote(linkOrForm, url, opts) {
@@ -434,9 +445,6 @@ function needsRefresh(prevAssets, newAssets) {
434
445
  }
435
446
  }
436
447
 
437
- // lib/action_creators/index.ts
438
- import parse3 from "url-parse";
439
-
440
448
  // lib/actions.ts
441
449
  import { createAction } from "@reduxjs/toolkit";
442
450
  var GRAFTING_ERROR = "@@superglue/GRAFTING_ERROR";
@@ -468,7 +476,6 @@ var handleGraft = createAction(
468
476
  var superglueError = createAction(
469
477
  "@@superglue/ERROR"
470
478
  );
471
- var updateFragments = createAction("@@superglue/UPDATE_FRAGMENTS");
472
479
  var copyPage = createAction(
473
480
  "@@superglue/COPY_PAGE"
474
481
  );
@@ -483,6 +490,53 @@ var beforeRemote = createAction("@@superglue/BEFORE_REMOTE");
483
490
  var setCSRFToken = createAction("@@superglue/SET_CSRF_TOKEN");
484
491
  var historyChange = createAction("@@superglue/HISTORY_CHANGE");
485
492
  var setActivePage = createAction("@@superglue/SET_ACTIVE_PAGE");
493
+ var handleFragmentGraft = createAction(
494
+ "@@superglue/HANDLE_FRAGMENT_GRAFT",
495
+ ({
496
+ fragmentId,
497
+ response
498
+ }) => {
499
+ return {
500
+ payload: {
501
+ response,
502
+ fragmentId
503
+ }
504
+ };
505
+ }
506
+ );
507
+ var saveFragment = createAction(
508
+ "@@superglue/SAVE_FRAGMENT",
509
+ ({ fragmentId, data }) => {
510
+ return {
511
+ payload: {
512
+ fragmentId,
513
+ data
514
+ }
515
+ };
516
+ }
517
+ );
518
+ var appendToFragment = createAction(
519
+ "@@superglue/APPEND_TO_FRAGMENT",
520
+ ({ data, fragmentId }) => {
521
+ return {
522
+ payload: {
523
+ data,
524
+ fragmentId
525
+ }
526
+ };
527
+ }
528
+ );
529
+ var prependToFragment = createAction(
530
+ "@@superglue/PREPEND_TO_FRAGMENT",
531
+ ({ data, fragmentId }) => {
532
+ return {
533
+ payload: {
534
+ data,
535
+ fragmentId
536
+ }
537
+ };
538
+ }
539
+ );
486
540
 
487
541
  // lib/action_creators/requests.ts
488
542
  function handleFetchErr(err, fetchArgs, dispatch) {
@@ -492,15 +546,18 @@ function handleFetchErr(err, fetchArgs, dispatch) {
492
546
  function buildMeta(pageKey, page, state, rsp, fetchArgs) {
493
547
  const { assets: prevAssets } = state;
494
548
  const { assets: nextAssets } = page;
495
- return {
549
+ const meta = {
496
550
  pageKey,
497
551
  page,
498
552
  redirected: rsp.redirected,
499
553
  rsp,
500
554
  fetchArgs,
501
- componentIdentifier: page.componentIdentifier,
502
555
  needsRefresh: needsRefresh(prevAssets, nextAssets)
503
556
  };
557
+ if (page.action !== "handleStreamResponse") {
558
+ meta.componentIdentifier = page.componentIdentifier;
559
+ }
560
+ return meta;
504
561
  }
505
562
  var MismatchedComponentError = class extends Error {
506
563
  constructor(message) {
@@ -508,13 +565,13 @@ var MismatchedComponentError = class extends Error {
508
565
  this.name = "MismatchedComponentError";
509
566
  }
510
567
  };
568
+ var defaultBeforeSave = (prevPage, receivedPage) => receivedPage;
511
569
  var remote = (path, {
512
570
  pageKey: targetPageKey,
513
571
  force = false,
514
- beforeSave = (prevPage, receivedPage) => receivedPage,
572
+ beforeSave = defaultBeforeSave,
515
573
  ...rest
516
574
  } = {}) => {
517
- path = withoutBusters(path);
518
575
  targetPageKey = targetPageKey && urlToPageKey(targetPageKey);
519
576
  return (dispatch, getState) => {
520
577
  const fetchArgs = argsForFetch(getState, path, rest);
@@ -531,10 +588,11 @@ var remote = (path, {
531
588
  pageKey = targetPageKey;
532
589
  }
533
590
  const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
534
- const existingId = pages[pageKey]?.componentIdentifier;
535
- const receivedId = json.componentIdentifier;
536
- if (!!existingId && existingId != receivedId && !force) {
537
- const message = `You cannot replace or update an existing page
591
+ if (json.action !== "handleStreamResponse") {
592
+ const existingId = pages[pageKey]?.componentIdentifier;
593
+ const receivedId = json.componentIdentifier;
594
+ if (!!existingId && existingId != receivedId && !force) {
595
+ const message = `You cannot replace or update an existing page
538
596
  located at pages["${currentPageKey}"] that has a componentIdentifier
539
597
  of "${existingId}" with the contents of a page response that has a
540
598
  componentIdentifier of "${receivedId}".
@@ -550,7 +608,8 @@ compatible with the page component associated with "${existingId}".
550
608
  Consider using data-sg-visit, the visit function, or redirect_back to
551
609
  the same page. Or if you're sure you want to proceed, use force: true.
552
610
  `;
553
- throw new MismatchedComponentError(message);
611
+ throw new MismatchedComponentError(message);
612
+ }
554
613
  }
555
614
  const page = beforeSave(pages[pageKey], json);
556
615
  return dispatch(saveAndProcessPage(pageKey, page)).then(() => meta);
@@ -568,7 +627,6 @@ var visit = (path, {
568
627
  revisit = false,
569
628
  ...rest
570
629
  } = {}) => {
571
- path = withoutBusters(path);
572
630
  return (dispatch, getState) => {
573
631
  const currentPageKey = getState().superglue.currentPageKey;
574
632
  placeholderKey = placeholderKey && urlToPageKey(placeholderKey) || currentPageKey;
@@ -595,11 +653,13 @@ var visit = (path, {
595
653
  const { superglue, pages = {} } = getState();
596
654
  const isGet = fetchArgs[1].method === "GET";
597
655
  const pageKey = calculatePageKey(rsp, isGet, currentPageKey);
598
- if (placeholderKey && hasPropsAt(path) && hasPlaceholder) {
599
- const existingId = pages[placeholderKey]?.componentIdentifier;
600
- const receivedId = json.componentIdentifier;
601
- if (!!existingId && existingId != receivedId) {
602
- const message = `You received a page response with a
656
+ const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
657
+ if (json.action !== "handleStreamResponse") {
658
+ if (placeholderKey && hasPropsAt(path) && hasPlaceholder) {
659
+ const existingId = pages[placeholderKey]?.componentIdentifier;
660
+ const receivedId = json.componentIdentifier;
661
+ if (!!existingId && existingId != receivedId) {
662
+ const message = `You received a page response with a
603
663
  componentIdentifier "${receivedId}" that is different than the
604
664
  componentIdentifier "${existingId}" located at ${placeholderKey}.
605
665
 
@@ -615,16 +675,17 @@ Check that you're rendering a page with a matching
615
675
  componentIdentifier, or consider using redirect_back_with_props_at
616
676
  to the same page.
617
677
  `;
618
- throw new MismatchedComponentError(message);
678
+ throw new MismatchedComponentError(message);
679
+ }
680
+ dispatch(copyPage({ from: placeholderKey, to: pageKey }));
619
681
  }
620
- dispatch(copyPage({ from: placeholderKey, to: pageKey }));
621
682
  }
622
- const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
623
683
  const visitMeta = {
624
684
  ...meta,
625
685
  navigationAction: calculateNavAction(
626
686
  meta,
627
687
  rsp,
688
+ json,
628
689
  isGet,
629
690
  pageKey,
630
691
  currentPageKey,
@@ -636,8 +697,11 @@ to the same page.
636
697
  }).catch((e) => handleFetchErr(e, fetchArgs, dispatch));
637
698
  };
638
699
  };
639
- function calculateNavAction(meta, rsp, isGet, pageKey, currentPageKey, revisit) {
700
+ function calculateNavAction(meta, rsp, json, isGet, pageKey, currentPageKey, revisit) {
640
701
  let navigationAction = "push";
702
+ if (json.action === "handleStreamResponse") {
703
+ return "none";
704
+ }
641
705
  if (!rsp.redirected && !isGet) {
642
706
  navigationAction = "replace";
643
707
  }
@@ -666,6 +730,155 @@ function calculatePageKey(rsp, isGet, currentPageKey) {
666
730
  return pageKey;
667
731
  }
668
732
 
733
+ // lib/action_creators/stream.ts
734
+ var streamPrepend = (fragments, data, options = {}) => {
735
+ return (dispatch) => {
736
+ if (options.saveAs) {
737
+ const { saveAs } = options;
738
+ dispatch(
739
+ saveFragment({
740
+ fragmentId: saveAs,
741
+ data
742
+ })
743
+ );
744
+ fragments.forEach((fragmentId) => {
745
+ dispatch(
746
+ prependToFragment({
747
+ fragmentId,
748
+ data: {
749
+ __id: saveAs
750
+ }
751
+ })
752
+ );
753
+ });
754
+ } else {
755
+ fragments.forEach((fragmentId) => {
756
+ dispatch(
757
+ prependToFragment({
758
+ fragmentId,
759
+ data
760
+ })
761
+ );
762
+ });
763
+ }
764
+ };
765
+ };
766
+ var streamAppend = (fragments, data, options = {}) => {
767
+ return (dispatch) => {
768
+ if (options.saveAs) {
769
+ const { saveAs } = options;
770
+ dispatch(
771
+ saveFragment({
772
+ fragmentId: saveAs,
773
+ data
774
+ })
775
+ );
776
+ fragments.forEach((fragmentId) => {
777
+ dispatch(
778
+ appendToFragment({
779
+ fragmentId,
780
+ data: {
781
+ __id: saveAs
782
+ }
783
+ })
784
+ );
785
+ });
786
+ } else {
787
+ fragments.forEach((fragmentId) => {
788
+ dispatch(
789
+ appendToFragment({
790
+ fragmentId,
791
+ data
792
+ })
793
+ );
794
+ });
795
+ }
796
+ };
797
+ };
798
+ var streamSave = (fragment, data) => {
799
+ return (dispatch) => {
800
+ dispatch(
801
+ saveFragment({
802
+ fragmentId: fragment,
803
+ data
804
+ })
805
+ );
806
+ };
807
+ };
808
+ var handleStreamMessage = (rawMessage) => {
809
+ return (dispatch) => {
810
+ const message = JSON.parse(rawMessage);
811
+ let nextMessage = message;
812
+ if (message.handler !== "refresh") {
813
+ message.fragments.reverse().forEach((fragment) => {
814
+ const { id, path } = fragment;
815
+ const node = getIn(nextMessage, path);
816
+ nextMessage = setIn(nextMessage, path, { __id: id });
817
+ dispatch(
818
+ saveFragment({
819
+ fragmentId: id,
820
+ data: node
821
+ })
822
+ );
823
+ });
824
+ }
825
+ if (nextMessage.action === "handleStreamMessage") {
826
+ if (nextMessage.handler === "append") {
827
+ dispatch(
828
+ streamAppend(
829
+ nextMessage.fragmentIds,
830
+ nextMessage.data,
831
+ nextMessage.options
832
+ )
833
+ );
834
+ }
835
+ if (nextMessage.handler === "prepend") {
836
+ dispatch(
837
+ streamPrepend(
838
+ nextMessage.fragmentIds,
839
+ nextMessage.data,
840
+ nextMessage.options
841
+ )
842
+ );
843
+ }
844
+ if (nextMessage.handler === "save") {
845
+ dispatch(streamSave(nextMessage.fragmentIds[0], nextMessage.data));
846
+ }
847
+ }
848
+ };
849
+ };
850
+ var handleStreamResponse = (response) => {
851
+ return (dispatch) => {
852
+ let nextResponse = response;
853
+ nextResponse.fragments.reverse().forEach((fragment) => {
854
+ const { id, path } = fragment;
855
+ const node = getIn(nextResponse, path);
856
+ nextResponse = setIn(nextResponse, path, { __id: id });
857
+ dispatch(
858
+ saveFragment({
859
+ fragmentId: id,
860
+ data: node
861
+ })
862
+ );
863
+ });
864
+ nextResponse.data.forEach((message) => {
865
+ if (message.handler === "append") {
866
+ dispatch(
867
+ streamAppend(message.fragmentIds, message.data, message.options)
868
+ );
869
+ }
870
+ if (message.handler === "prepend") {
871
+ dispatch(
872
+ streamPrepend(message.fragmentIds, message.data, message.options)
873
+ );
874
+ }
875
+ if (message.handler === "save") {
876
+ dispatch(streamSave(message.fragmentIds[0], message.data));
877
+ }
878
+ });
879
+ };
880
+ };
881
+
669
882
  // lib/action_creators/index.ts
670
883
  function fetchDeferments(pageKey, defers = []) {
671
884
  pageKey = urlToPageKey(pageKey);
@@ -675,8 +888,7 @@ function fetchDeferments(pageKey, defers = []) {
675
888
  successAction = GRAFTING_SUCCESS,
676
889
  failAction = GRAFTING_ERROR
677
890
  }) {
678
- const parsedUrl = new parse3(url, true);
679
- const keyPath = parsedUrl.query.props_at;
891
+ const keyPath = propsAtParam(url);
680
892
  return dispatch(remote(url, { pageKey })).then(() => {
681
893
  dispatch({
682
894
  type: successAction,
@@ -701,57 +913,40 @@ function fetchDeferments(pageKey, defers = []) {
701
913
  };
702
914
  }
703
915
  function saveAndProcessPage(pageKey, page) {
704
- return (dispatch, getState) => {
916
+ return (dispatch) => {
705
917
  pageKey = urlToPageKey(pageKey);
706
- const { defers = [] } = page;
707
- if ("action" in page) {
708
- const prevPage = getState().pages[pageKey];
709
- dispatch(handleGraft({ pageKey, page }));
710
- const currentPage = getState().pages[pageKey];
711
- currentPage.fragments.forEach((fragment) => {
712
- const { type, path } = fragment;
713
- const currentFragment = getIn(currentPage, path);
714
- const prevFragment = getIn(prevPage, path);
715
- if (!prevFragment) {
716
- dispatch(
717
- updateFragments({
718
- name: type,
719
- pageKey,
720
- value: currentFragment,
721
- path
722
- })
723
- );
724
- } else if (currentFragment !== prevFragment) {
725
- dispatch(
726
- updateFragments({
727
- name: type,
728
- pageKey,
729
- value: currentFragment,
730
- previousValue: prevFragment,
731
- path
732
- })
733
- );
734
- }
735
- });
736
- } else {
737
- dispatch(saveResponse({ pageKey, page }));
738
- const currentPage = getState().pages[pageKey];
739
- currentPage.fragments.forEach((fragment) => {
740
- const { type, path } = fragment;
741
- const currentFragment = getIn(currentPage, path);
918
+ let nextPage = page;
919
+ page.fragments.reverse().forEach((fragment) => {
920
+ const { id, path } = fragment;
921
+ const node = getIn(nextPage, path);
922
+ nextPage = setIn(page, path, { __id: id });
923
+ dispatch(
924
+ saveFragment({
925
+ fragmentId: id,
926
+ data: node
927
+ })
928
+ );
929
+ });
930
+ if (nextPage.action === "graft") {
931
+ if (typeof nextPage.fragmentContext === "string") {
742
932
  dispatch(
743
- updateFragments({
744
- name: type,
745
- pageKey,
746
- value: currentFragment,
747
- path
933
+ handleFragmentGraft({
934
+ fragmentId: nextPage.fragmentContext,
935
+ response: nextPage
748
936
  })
749
937
  );
750
- });
938
+ } else {
939
+ dispatch(handleGraft({ pageKey, page: nextPage }));
940
+ }
941
+ } else if (nextPage.action === "handleStreamResponse") {
942
+ dispatch(handleStreamResponse(nextPage));
943
+ return Promise.resolve();
944
+ } else {
945
+ dispatch(saveResponse({ pageKey, page: nextPage }));
751
946
  }
752
947
  const hasFetch = typeof fetch != "undefined";
753
948
  if (hasFetch) {
754
- return dispatch(fetchDeferments(pageKey, defers)).then(
949
+ return dispatch(fetchDeferments(pageKey, nextPage.defers)).then(
755
950
  () => Promise.resolve()
756
951
  );
757
952
  } else {
@@ -761,19 +956,20 @@ function saveAndProcessPage(pageKey, page) {
761
956
  }
762
957
 
763
958
  export {
959
+ __commonJS,
960
+ __toESM,
764
961
  config,
765
- pathWithoutBZParams,
766
962
  urlToPageKey,
767
963
  parsePageKey,
768
964
  argsForHistory,
769
965
  getIn,
770
966
  setIn,
967
+ lastRequestIds,
771
968
  ujsHandlers,
772
969
  GRAFTING_ERROR,
773
970
  GRAFTING_SUCCESS,
774
971
  saveResponse,
775
972
  handleGraft,
776
- updateFragments,
777
973
  copyPage,
778
974
  removePage,
779
975
  beforeFetch,
@@ -782,9 +978,17 @@ export {
782
978
  setCSRFToken,
783
979
  historyChange,
784
980
  setActivePage,
981
+ handleFragmentGraft,
982
+ saveFragment,
983
+ appendToFragment,
984
+ prependToFragment,
785
985
  MismatchedComponentError,
786
986
  remote,
787
987
  visit,
988
+ streamPrepend,
989
+ streamAppend,
990
+ streamSave,
991
+ handleStreamMessage,
788
992
  saveAndProcessPage
789
993
  };
790
- //# sourceMappingURL=chunk-LGUVOEZ3.mjs.map
994
+ //# sourceMappingURL=chunk-YS477OKK.mjs.map