@thoughtbot/superglue 1.0.3 → 2.0.0-alpha.10
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.
- package/.tool-versions +1 -2
- package/dist/action_creators.d.mts +1 -1
- package/dist/action_creators.mjs +1 -1
- package/dist/{chunk-ENOVWJUC.mjs → chunk-J2XH5QTK.mjs} +565 -68
- package/dist/chunk-J2XH5QTK.mjs.map +1 -0
- package/dist/cjs/action_creators.cjs +535 -66
- package/dist/cjs/action_creators.cjs.map +1 -1
- package/dist/cjs/superglue.cjs +780 -112
- package/dist/cjs/superglue.cjs.map +1 -1
- package/dist/{index-BYr1PoYr.d.mts → index-j0c-9ZLt.d.mts} +69 -18
- package/dist/superglue.d.mts +46 -14
- package/dist/superglue.mjs +267 -54
- package/dist/superglue.mjs.map +1 -1
- package/package.json +16 -8
- package/thoughtbot-superglue-2.0.0-alpha.10.tgz +0 -0
- package/typedoc.json +1 -0
- package/dist/chunk-ENOVWJUC.mjs.map +0 -1
|
@@ -179,7 +179,26 @@ var config = {
|
|
|
179
179
|
maxPages: 20
|
|
180
180
|
};
|
|
181
181
|
|
|
182
|
+
// lib/utils/limited_set.ts
|
|
183
|
+
var LimitedSet = class extends Set {
|
|
184
|
+
constructor(maxSize) {
|
|
185
|
+
super();
|
|
186
|
+
this.maxSize = maxSize;
|
|
187
|
+
}
|
|
188
|
+
add(value) {
|
|
189
|
+
if (this.size >= this.maxSize) {
|
|
190
|
+
const iterator = this.values();
|
|
191
|
+
const oldestValue = iterator.next().value;
|
|
192
|
+
this.delete(oldestValue);
|
|
193
|
+
}
|
|
194
|
+
super.add(value);
|
|
195
|
+
return this;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
182
199
|
// lib/utils/request.ts
|
|
200
|
+
import { v4 as uuidv4 } from "uuid";
|
|
201
|
+
var lastRequestIds = new LimitedSet(20);
|
|
183
202
|
function isValidResponse(xhr) {
|
|
184
203
|
return isValidContent(xhr) && !downloadingFile(xhr);
|
|
185
204
|
}
|
|
@@ -235,6 +254,9 @@ function argsForFetch(getState, pathQuery2, {
|
|
|
235
254
|
nextHeaders["x-requested-with"] = "XMLHttpRequest";
|
|
236
255
|
nextHeaders["accept"] = "application/json";
|
|
237
256
|
nextHeaders["x-superglue-request"] = "true";
|
|
257
|
+
const requestId = uuidv4();
|
|
258
|
+
lastRequestIds.add(requestId);
|
|
259
|
+
nextHeaders["X-Superglue-Request-Id"] = requestId;
|
|
238
260
|
if (method != "GET" && method != "HEAD") {
|
|
239
261
|
nextHeaders["content-type"] = "application/json";
|
|
240
262
|
}
|
|
@@ -274,7 +296,7 @@ function argsForFetch(getState, pathQuery2, {
|
|
|
274
296
|
return [fetchPath.toString(), { ...options, ...rest }];
|
|
275
297
|
}
|
|
276
298
|
function extractJSON(rsp) {
|
|
277
|
-
return rsp.
|
|
299
|
+
return rsp.json().then((json) => {
|
|
278
300
|
return { rsp, json };
|
|
279
301
|
}).catch((e) => {
|
|
280
302
|
e.response = rsp;
|
|
@@ -428,7 +450,6 @@ var handleGraft = createAction(
|
|
|
428
450
|
var superglueError = createAction(
|
|
429
451
|
"@@superglue/ERROR"
|
|
430
452
|
);
|
|
431
|
-
var updateFragments = createAction("@@superglue/UPDATE_FRAGMENTS");
|
|
432
453
|
var copyPage = createAction(
|
|
433
454
|
"@@superglue/COPY_PAGE"
|
|
434
455
|
);
|
|
@@ -443,24 +464,291 @@ var beforeRemote = createAction("@@superglue/BEFORE_REMOTE");
|
|
|
443
464
|
var setCSRFToken = createAction("@@superglue/SET_CSRF_TOKEN");
|
|
444
465
|
var historyChange = createAction("@@superglue/HISTORY_CHANGE");
|
|
445
466
|
var setActivePage = createAction("@@superglue/SET_ACTIVE_PAGE");
|
|
467
|
+
var handleFragmentGraft = createAction(
|
|
468
|
+
"@@superglue/HANDLE_FRAGMENT_GRAFT",
|
|
469
|
+
({
|
|
470
|
+
fragmentId,
|
|
471
|
+
response
|
|
472
|
+
}) => {
|
|
473
|
+
return {
|
|
474
|
+
payload: {
|
|
475
|
+
response,
|
|
476
|
+
fragmentId
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
);
|
|
481
|
+
var saveFragment = createAction(
|
|
482
|
+
"@@superglue/SAVE_FRAGMENT",
|
|
483
|
+
({ fragmentId, data }) => {
|
|
484
|
+
return {
|
|
485
|
+
payload: {
|
|
486
|
+
fragmentId,
|
|
487
|
+
data
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
);
|
|
492
|
+
var receiveResponse = createAction(
|
|
493
|
+
"@@superglue/RECEIVE_RESPONSE",
|
|
494
|
+
({ pageKey, response }) => {
|
|
495
|
+
pageKey = urlToPageKey(pageKey);
|
|
496
|
+
return {
|
|
497
|
+
payload: {
|
|
498
|
+
pageKey,
|
|
499
|
+
response
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
);
|
|
504
|
+
var appendToFragment = createAction(
|
|
505
|
+
"@@superglue/APPEND_TO_FRAGMENT",
|
|
506
|
+
({ data, fragmentId }) => {
|
|
507
|
+
return {
|
|
508
|
+
payload: {
|
|
509
|
+
data,
|
|
510
|
+
fragmentId
|
|
511
|
+
}
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
);
|
|
515
|
+
var prependToFragment = createAction(
|
|
516
|
+
"@@superglue/PREPEND_TO_FRAGMENT",
|
|
517
|
+
({ data, fragmentId }) => {
|
|
518
|
+
return {
|
|
519
|
+
payload: {
|
|
520
|
+
data,
|
|
521
|
+
fragmentId
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
);
|
|
526
|
+
|
|
527
|
+
// lib/utils/proxy.ts
|
|
528
|
+
var ORIGINAL_TARGET = Symbol("@@originalTarget");
|
|
529
|
+
var ARRAY_GETTER_METHODS = /* @__PURE__ */ new Set([
|
|
530
|
+
Symbol.iterator,
|
|
531
|
+
"at",
|
|
532
|
+
"concat",
|
|
533
|
+
"entries",
|
|
534
|
+
"every",
|
|
535
|
+
"filter",
|
|
536
|
+
"find",
|
|
537
|
+
"findIndex",
|
|
538
|
+
"flat",
|
|
539
|
+
"flatMap",
|
|
540
|
+
"forEach",
|
|
541
|
+
"includes",
|
|
542
|
+
"indexOf",
|
|
543
|
+
"join",
|
|
544
|
+
"keys",
|
|
545
|
+
"lastIndexOf",
|
|
546
|
+
"map",
|
|
547
|
+
"reduce",
|
|
548
|
+
"reduceRight",
|
|
549
|
+
"slice",
|
|
550
|
+
"some",
|
|
551
|
+
"toString",
|
|
552
|
+
"values"
|
|
553
|
+
]);
|
|
554
|
+
var ARRAY_SETTER_METHODS = /* @__PURE__ */ new Set([
|
|
555
|
+
"copyWithin",
|
|
556
|
+
"fill",
|
|
557
|
+
"pop",
|
|
558
|
+
"push",
|
|
559
|
+
"reverse",
|
|
560
|
+
"shift",
|
|
561
|
+
"sort",
|
|
562
|
+
"splice",
|
|
563
|
+
"unshift"
|
|
564
|
+
]);
|
|
565
|
+
function isArraySetter(prop) {
|
|
566
|
+
return ARRAY_SETTER_METHODS.has(prop);
|
|
567
|
+
}
|
|
568
|
+
function isArrayGetter(prop) {
|
|
569
|
+
return ARRAY_GETTER_METHODS.has(prop);
|
|
570
|
+
}
|
|
571
|
+
function convertToInt(prop) {
|
|
572
|
+
if (typeof prop === "symbol") return null;
|
|
573
|
+
const num = Number(prop);
|
|
574
|
+
return Number.isInteger(num) ? num : null;
|
|
575
|
+
}
|
|
576
|
+
function isFragmentReference(value) {
|
|
577
|
+
return !!value && typeof value === "object" && "__id" in value && typeof value.__id === "string";
|
|
578
|
+
}
|
|
579
|
+
function createArrayProxy(arrayData, fragments, dependencies, proxyCache) {
|
|
580
|
+
if (proxyCache && proxyCache.has(arrayData)) {
|
|
581
|
+
return proxyCache.get(arrayData);
|
|
582
|
+
}
|
|
583
|
+
const proxy = new Proxy(arrayData, {
|
|
584
|
+
get(target, prop) {
|
|
585
|
+
if (prop === ORIGINAL_TARGET) {
|
|
586
|
+
return target;
|
|
587
|
+
}
|
|
588
|
+
if (isArrayGetter(prop)) {
|
|
589
|
+
const method = target[prop];
|
|
590
|
+
if (typeof method === "function") {
|
|
591
|
+
return function(...args) {
|
|
592
|
+
return Reflect.apply(method, proxy, args);
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
return method;
|
|
596
|
+
}
|
|
597
|
+
if (isArraySetter(prop)) {
|
|
598
|
+
throw new Error(
|
|
599
|
+
`Cannot mutate proxy array. Use useSetFragment to update state.`
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
const index = convertToInt(prop);
|
|
603
|
+
if (index !== null && index >= 0 && index < target.length) {
|
|
604
|
+
const item = target[index];
|
|
605
|
+
if (isFragmentReference(item)) {
|
|
606
|
+
dependencies.add(item.__id);
|
|
607
|
+
const fragmentData = fragments.current[item.__id];
|
|
608
|
+
if (!fragmentData) {
|
|
609
|
+
return void 0;
|
|
610
|
+
}
|
|
611
|
+
return createProxy(fragmentData, fragments, dependencies, proxyCache);
|
|
612
|
+
}
|
|
613
|
+
if (typeof item === "object" && item !== null) {
|
|
614
|
+
if ("$$typeof" in item) {
|
|
615
|
+
return item;
|
|
616
|
+
} else {
|
|
617
|
+
return createProxy(
|
|
618
|
+
item,
|
|
619
|
+
fragments,
|
|
620
|
+
dependencies,
|
|
621
|
+
proxyCache
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return item;
|
|
626
|
+
}
|
|
627
|
+
return Reflect.get(target, prop);
|
|
628
|
+
},
|
|
629
|
+
has(target, prop) {
|
|
630
|
+
if (prop === ORIGINAL_TARGET) {
|
|
631
|
+
return true;
|
|
632
|
+
}
|
|
633
|
+
return Reflect.has(target, prop);
|
|
634
|
+
},
|
|
635
|
+
set() {
|
|
636
|
+
throw new Error(
|
|
637
|
+
"Cannot mutate proxy array. Use useSetFragment to update state."
|
|
638
|
+
);
|
|
639
|
+
},
|
|
640
|
+
deleteProperty() {
|
|
641
|
+
throw new Error(
|
|
642
|
+
"Cannot delete properties on proxy array. Use useSetFragment to update state."
|
|
643
|
+
);
|
|
644
|
+
},
|
|
645
|
+
defineProperty() {
|
|
646
|
+
throw new Error(
|
|
647
|
+
"Cannot define properties on proxy array. Use useSetFragment to update state."
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
if (proxyCache) {
|
|
652
|
+
proxyCache.set(arrayData, proxy);
|
|
653
|
+
}
|
|
654
|
+
return proxy;
|
|
655
|
+
}
|
|
656
|
+
function createObjectProxy(objectData, fragments, dependencies, proxyCache) {
|
|
657
|
+
if (proxyCache && proxyCache.has(objectData)) {
|
|
658
|
+
return proxyCache.get(objectData);
|
|
659
|
+
}
|
|
660
|
+
const proxy = new Proxy(objectData, {
|
|
661
|
+
get(target, prop) {
|
|
662
|
+
if (prop === ORIGINAL_TARGET) {
|
|
663
|
+
return target;
|
|
664
|
+
}
|
|
665
|
+
const value = target[prop];
|
|
666
|
+
if (isFragmentReference(value)) {
|
|
667
|
+
dependencies.add(value.__id);
|
|
668
|
+
const fragmentData = fragments.current[value.__id];
|
|
669
|
+
if (!fragmentData) {
|
|
670
|
+
return void 0;
|
|
671
|
+
}
|
|
672
|
+
return createProxy(fragmentData, fragments, dependencies, proxyCache);
|
|
673
|
+
}
|
|
674
|
+
if (typeof value === "object" && value !== null) {
|
|
675
|
+
if ("$$typeof" in value) {
|
|
676
|
+
return value;
|
|
677
|
+
} else if (Array.isArray(value)) {
|
|
678
|
+
return createArrayProxy(value, fragments, dependencies, proxyCache);
|
|
679
|
+
} else {
|
|
680
|
+
return createObjectProxy(value, fragments, dependencies, proxyCache);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
return value;
|
|
684
|
+
},
|
|
685
|
+
has(target, prop) {
|
|
686
|
+
if (prop === ORIGINAL_TARGET) {
|
|
687
|
+
return true;
|
|
688
|
+
}
|
|
689
|
+
return Reflect.has(target, prop);
|
|
690
|
+
},
|
|
691
|
+
set() {
|
|
692
|
+
throw new Error(
|
|
693
|
+
"Cannot mutate proxy object. Use useSetFragment to update state."
|
|
694
|
+
);
|
|
695
|
+
},
|
|
696
|
+
deleteProperty() {
|
|
697
|
+
throw new Error(
|
|
698
|
+
"Cannot delete properties on proxy object. Use useSetFragment to update state."
|
|
699
|
+
);
|
|
700
|
+
},
|
|
701
|
+
defineProperty() {
|
|
702
|
+
throw new Error(
|
|
703
|
+
"Cannot define properties on proxy object. Use useSetFragment to update state."
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
});
|
|
707
|
+
if (proxyCache) {
|
|
708
|
+
proxyCache.set(objectData, proxy);
|
|
709
|
+
}
|
|
710
|
+
return proxy;
|
|
711
|
+
}
|
|
712
|
+
function createProxy(content, fragments, dependencies, proxyCache) {
|
|
713
|
+
if (!content || typeof content !== "object") {
|
|
714
|
+
return content;
|
|
715
|
+
}
|
|
716
|
+
if ("$$typeof" in content) {
|
|
717
|
+
return content;
|
|
718
|
+
}
|
|
719
|
+
if (Array.isArray(content)) {
|
|
720
|
+
return createArrayProxy(content, fragments, dependencies, proxyCache);
|
|
721
|
+
}
|
|
722
|
+
return createObjectProxy(content, fragments, dependencies, proxyCache);
|
|
723
|
+
}
|
|
724
|
+
function unproxy(proxy) {
|
|
725
|
+
if (proxy && typeof proxy === "object" && ORIGINAL_TARGET in proxy) {
|
|
726
|
+
return proxy[ORIGINAL_TARGET];
|
|
727
|
+
}
|
|
728
|
+
return proxy;
|
|
729
|
+
}
|
|
446
730
|
|
|
447
731
|
// lib/action_creators/requests.ts
|
|
448
732
|
function handleFetchErr(err, fetchArgs, dispatch) {
|
|
449
733
|
dispatch(superglueError({ message: err.message }));
|
|
734
|
+
console.error(err);
|
|
450
735
|
throw err;
|
|
451
736
|
}
|
|
452
737
|
function buildMeta(pageKey, page, state, rsp, fetchArgs) {
|
|
453
738
|
const { assets: prevAssets } = state;
|
|
454
739
|
const { assets: nextAssets } = page;
|
|
455
|
-
|
|
740
|
+
const meta = {
|
|
456
741
|
pageKey,
|
|
457
742
|
page,
|
|
458
743
|
redirected: rsp.redirected,
|
|
459
744
|
rsp,
|
|
460
745
|
fetchArgs,
|
|
461
|
-
componentIdentifier: page.componentIdentifier,
|
|
462
746
|
needsRefresh: needsRefresh(prevAssets, nextAssets)
|
|
463
747
|
};
|
|
748
|
+
if (page.action !== "handleStreamResponse") {
|
|
749
|
+
meta.componentIdentifier = page.componentIdentifier;
|
|
750
|
+
}
|
|
751
|
+
return meta;
|
|
464
752
|
}
|
|
465
753
|
var MismatchedComponentError = class extends Error {
|
|
466
754
|
constructor(message) {
|
|
@@ -468,10 +756,11 @@ var MismatchedComponentError = class extends Error {
|
|
|
468
756
|
this.name = "MismatchedComponentError";
|
|
469
757
|
}
|
|
470
758
|
};
|
|
759
|
+
var defaultBeforeSave = (prevPage, receivedPage) => receivedPage;
|
|
471
760
|
var remote = (path, {
|
|
472
761
|
pageKey: targetPageKey,
|
|
473
762
|
force = false,
|
|
474
|
-
beforeSave =
|
|
763
|
+
beforeSave = defaultBeforeSave,
|
|
475
764
|
...rest
|
|
476
765
|
} = {}) => {
|
|
477
766
|
targetPageKey = targetPageKey && urlToPageKey(targetPageKey);
|
|
@@ -481,7 +770,7 @@ var remote = (path, {
|
|
|
481
770
|
dispatch(beforeRemote({ currentPageKey, fetchArgs }));
|
|
482
771
|
dispatch(beforeFetch({ fetchArgs }));
|
|
483
772
|
return fetch(...fetchArgs).then(parseResponse).then(({ rsp, json }) => {
|
|
484
|
-
const { superglue, pages = {} } = getState();
|
|
773
|
+
const { superglue, pages = {}, fragments } = getState();
|
|
485
774
|
let pageKey;
|
|
486
775
|
if (targetPageKey === void 0) {
|
|
487
776
|
const isGet = fetchArgs[1].method === "GET";
|
|
@@ -490,10 +779,11 @@ var remote = (path, {
|
|
|
490
779
|
pageKey = targetPageKey;
|
|
491
780
|
}
|
|
492
781
|
const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
782
|
+
if (json.action !== "handleStreamResponse") {
|
|
783
|
+
const existingId = pages[pageKey]?.componentIdentifier;
|
|
784
|
+
const receivedId = json.componentIdentifier;
|
|
785
|
+
if (!!existingId && existingId != receivedId && !force) {
|
|
786
|
+
const message = `You cannot replace or update an existing page
|
|
497
787
|
located at pages["${currentPageKey}"] that has a componentIdentifier
|
|
498
788
|
of "${existingId}" with the contents of a page response that has a
|
|
499
789
|
componentIdentifier of "${receivedId}".
|
|
@@ -509,9 +799,27 @@ compatible with the page component associated with "${existingId}".
|
|
|
509
799
|
Consider using data-sg-visit, the visit function, or redirect_back to
|
|
510
800
|
the same page. Or if you're sure you want to proceed, use force: true.
|
|
511
801
|
`;
|
|
512
|
-
|
|
802
|
+
throw new MismatchedComponentError(message);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
dispatch(
|
|
806
|
+
receiveResponse({
|
|
807
|
+
pageKey,
|
|
808
|
+
response: JSON.parse(JSON.stringify(json))
|
|
809
|
+
})
|
|
810
|
+
);
|
|
811
|
+
const existingPage = createProxy(
|
|
812
|
+
pages[pageKey],
|
|
813
|
+
{ current: fragments },
|
|
814
|
+
/* @__PURE__ */ new Set(),
|
|
815
|
+
/* @__PURE__ */ new WeakMap()
|
|
816
|
+
);
|
|
817
|
+
let page = json;
|
|
818
|
+
if (json.action === "savePage" || json.action === "graft") {
|
|
819
|
+
page = JSON.parse(
|
|
820
|
+
JSON.stringify(beforeSave(existingPage, json))
|
|
821
|
+
);
|
|
513
822
|
}
|
|
514
|
-
const page = beforeSave(pages[pageKey], json);
|
|
515
823
|
return dispatch(saveAndProcessPage(pageKey, page)).then(() => meta);
|
|
516
824
|
}).catch((e) => handleFetchErr(e, fetchArgs, dispatch));
|
|
517
825
|
};
|
|
@@ -550,14 +858,16 @@ var visit = (path, {
|
|
|
550
858
|
);
|
|
551
859
|
lastVisitController = controller;
|
|
552
860
|
return fetch(...fetchArgs).then(parseResponse).then(({ rsp, json }) => {
|
|
553
|
-
const { superglue, pages = {} } = getState();
|
|
861
|
+
const { superglue, pages = {}, fragments } = getState();
|
|
554
862
|
const isGet = fetchArgs[1].method === "GET";
|
|
555
863
|
const pageKey = calculatePageKey(rsp, isGet, currentPageKey);
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
const
|
|
864
|
+
const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
|
|
865
|
+
if (json.action !== "handleStreamResponse") {
|
|
866
|
+
if (placeholderKey && hasPropsAt(path) && hasPlaceholder) {
|
|
867
|
+
const existingId = pages[placeholderKey]?.componentIdentifier;
|
|
868
|
+
const receivedId = json.componentIdentifier;
|
|
869
|
+
if (!!existingId && existingId != receivedId) {
|
|
870
|
+
const message = `You received a page response with a
|
|
561
871
|
componentIdentifier "${receivedId}" that is different than the
|
|
562
872
|
componentIdentifier "${existingId}" located at ${placeholderKey}.
|
|
563
873
|
|
|
@@ -573,29 +883,50 @@ Check that you're rendering a page with a matching
|
|
|
573
883
|
componentIdentifier, or consider using redirect_back_with_props_at
|
|
574
884
|
to the same page.
|
|
575
885
|
`;
|
|
576
|
-
|
|
886
|
+
throw new MismatchedComponentError(message);
|
|
887
|
+
}
|
|
888
|
+
dispatch(copyPage({ from: placeholderKey, to: pageKey }));
|
|
577
889
|
}
|
|
578
|
-
dispatch(copyPage({ from: placeholderKey, to: pageKey }));
|
|
579
890
|
}
|
|
580
|
-
const meta = buildMeta(pageKey, json, superglue, rsp, fetchArgs);
|
|
581
891
|
const visitMeta = {
|
|
582
892
|
...meta,
|
|
583
893
|
navigationAction: calculateNavAction(
|
|
584
894
|
meta,
|
|
585
895
|
rsp,
|
|
896
|
+
json,
|
|
586
897
|
isGet,
|
|
587
898
|
pageKey,
|
|
588
899
|
currentPageKey,
|
|
589
900
|
revisit
|
|
590
901
|
)
|
|
591
902
|
};
|
|
592
|
-
|
|
903
|
+
dispatch(
|
|
904
|
+
receiveResponse({
|
|
905
|
+
pageKey,
|
|
906
|
+
response: JSON.parse(JSON.stringify(json))
|
|
907
|
+
})
|
|
908
|
+
);
|
|
909
|
+
const existingPage = createProxy(
|
|
910
|
+
pages[pageKey],
|
|
911
|
+
{ current: fragments },
|
|
912
|
+
/* @__PURE__ */ new Set(),
|
|
913
|
+
/* @__PURE__ */ new WeakMap()
|
|
914
|
+
);
|
|
915
|
+
let page = json;
|
|
916
|
+
if (json.action === "savePage" || json.action === "graft") {
|
|
917
|
+
page = JSON.parse(
|
|
918
|
+
JSON.stringify(beforeSave(existingPage, json))
|
|
919
|
+
);
|
|
920
|
+
}
|
|
593
921
|
return dispatch(saveAndProcessPage(pageKey, page)).then(() => visitMeta);
|
|
594
922
|
}).catch((e) => handleFetchErr(e, fetchArgs, dispatch));
|
|
595
923
|
};
|
|
596
924
|
};
|
|
597
|
-
function calculateNavAction(meta, rsp, isGet, pageKey, currentPageKey, revisit) {
|
|
925
|
+
function calculateNavAction(meta, rsp, json, isGet, pageKey, currentPageKey, revisit) {
|
|
598
926
|
let navigationAction = "push";
|
|
927
|
+
if (json.action === "handleStreamResponse") {
|
|
928
|
+
return "none";
|
|
929
|
+
}
|
|
599
930
|
if (!rsp.redirected && !isGet) {
|
|
600
931
|
navigationAction = "replace";
|
|
601
932
|
}
|
|
@@ -624,6 +955,155 @@ function calculatePageKey(rsp, isGet, currentPageKey) {
|
|
|
624
955
|
return pageKey;
|
|
625
956
|
}
|
|
626
957
|
|
|
958
|
+
// lib/action_creators/stream.ts
|
|
959
|
+
var streamPrepend = (fragments, data, options = {}) => {
|
|
960
|
+
return (dispatch) => {
|
|
961
|
+
if (options.saveAs) {
|
|
962
|
+
const { saveAs } = options;
|
|
963
|
+
dispatch(
|
|
964
|
+
saveFragment({
|
|
965
|
+
fragmentId: saveAs,
|
|
966
|
+
data
|
|
967
|
+
})
|
|
968
|
+
);
|
|
969
|
+
fragments.forEach((fragmentId) => {
|
|
970
|
+
dispatch(
|
|
971
|
+
prependToFragment({
|
|
972
|
+
fragmentId,
|
|
973
|
+
data: {
|
|
974
|
+
__id: saveAs
|
|
975
|
+
}
|
|
976
|
+
})
|
|
977
|
+
);
|
|
978
|
+
});
|
|
979
|
+
} else {
|
|
980
|
+
fragments.forEach((fragmentId) => {
|
|
981
|
+
dispatch(
|
|
982
|
+
prependToFragment({
|
|
983
|
+
fragmentId,
|
|
984
|
+
data
|
|
985
|
+
})
|
|
986
|
+
);
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
};
|
|
991
|
+
var streamAppend = (fragments, data, options = {}) => {
|
|
992
|
+
return (dispatch) => {
|
|
993
|
+
if (options.saveAs) {
|
|
994
|
+
const { saveAs } = options;
|
|
995
|
+
dispatch(
|
|
996
|
+
saveFragment({
|
|
997
|
+
fragmentId: saveAs,
|
|
998
|
+
data
|
|
999
|
+
})
|
|
1000
|
+
);
|
|
1001
|
+
fragments.forEach((fragmentId) => {
|
|
1002
|
+
dispatch(
|
|
1003
|
+
appendToFragment({
|
|
1004
|
+
fragmentId,
|
|
1005
|
+
data: {
|
|
1006
|
+
__id: saveAs
|
|
1007
|
+
}
|
|
1008
|
+
})
|
|
1009
|
+
);
|
|
1010
|
+
});
|
|
1011
|
+
} else {
|
|
1012
|
+
fragments.forEach((fragmentId) => {
|
|
1013
|
+
dispatch(
|
|
1014
|
+
appendToFragment({
|
|
1015
|
+
fragmentId,
|
|
1016
|
+
data
|
|
1017
|
+
})
|
|
1018
|
+
);
|
|
1019
|
+
});
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
};
|
|
1023
|
+
var streamSave = (fragment, data) => {
|
|
1024
|
+
return (dispatch) => {
|
|
1025
|
+
dispatch(
|
|
1026
|
+
saveFragment({
|
|
1027
|
+
fragmentId: fragment,
|
|
1028
|
+
data
|
|
1029
|
+
})
|
|
1030
|
+
);
|
|
1031
|
+
};
|
|
1032
|
+
};
|
|
1033
|
+
var handleStreamMessage = (rawMessage) => {
|
|
1034
|
+
return (dispatch) => {
|
|
1035
|
+
const message = JSON.parse(rawMessage);
|
|
1036
|
+
let nextMessage = message;
|
|
1037
|
+
if (message.handler !== "refresh") {
|
|
1038
|
+
message.fragments.reverse().forEach((fragment) => {
|
|
1039
|
+
const { id, path } = fragment;
|
|
1040
|
+
const node = getIn(nextMessage, path);
|
|
1041
|
+
nextMessage = setIn(nextMessage, path, { __id: id });
|
|
1042
|
+
dispatch(
|
|
1043
|
+
saveFragment({
|
|
1044
|
+
fragmentId: id,
|
|
1045
|
+
data: node
|
|
1046
|
+
})
|
|
1047
|
+
);
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
if (nextMessage.action === "handleStreamMessage") {
|
|
1051
|
+
if (nextMessage.handler === "append") {
|
|
1052
|
+
dispatch(
|
|
1053
|
+
streamAppend(
|
|
1054
|
+
nextMessage.fragmentIds,
|
|
1055
|
+
nextMessage.data,
|
|
1056
|
+
nextMessage.options
|
|
1057
|
+
)
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
1060
|
+
if (nextMessage.handler === "prepend") {
|
|
1061
|
+
dispatch(
|
|
1062
|
+
streamPrepend(
|
|
1063
|
+
nextMessage.fragmentIds,
|
|
1064
|
+
nextMessage.data,
|
|
1065
|
+
nextMessage.options
|
|
1066
|
+
)
|
|
1067
|
+
);
|
|
1068
|
+
}
|
|
1069
|
+
if (nextMessage.handler === "save") {
|
|
1070
|
+
dispatch(streamSave(nextMessage.fragmentIds[0], nextMessage.data));
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
};
|
|
1075
|
+
var handleStreamResponse = (response) => {
|
|
1076
|
+
return (dispatch) => {
|
|
1077
|
+
let nextResponse = response;
|
|
1078
|
+
nextResponse.fragments.reverse().forEach((fragment) => {
|
|
1079
|
+
const { id, path } = fragment;
|
|
1080
|
+
const node = getIn(nextResponse, path);
|
|
1081
|
+
nextResponse = setIn(nextResponse, path, { __id: id });
|
|
1082
|
+
dispatch(
|
|
1083
|
+
saveFragment({
|
|
1084
|
+
fragmentId: id,
|
|
1085
|
+
data: node
|
|
1086
|
+
})
|
|
1087
|
+
);
|
|
1088
|
+
});
|
|
1089
|
+
nextResponse.data.forEach((message) => {
|
|
1090
|
+
if (message.handler === "append") {
|
|
1091
|
+
dispatch(
|
|
1092
|
+
streamAppend(message.fragmentIds, message.data, message.options)
|
|
1093
|
+
);
|
|
1094
|
+
}
|
|
1095
|
+
if (message.handler === "prepend") {
|
|
1096
|
+
dispatch(
|
|
1097
|
+
streamPrepend(message.fragmentIds, message.data, message.options)
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
if (message.handler === "save") {
|
|
1101
|
+
dispatch(streamSave(message.fragmentIds[0], message.data));
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
};
|
|
1105
|
+
};
|
|
1106
|
+
|
|
627
1107
|
// lib/action_creators/index.ts
|
|
628
1108
|
function fetchDeferments(pageKey, defers = []) {
|
|
629
1109
|
pageKey = urlToPageKey(pageKey);
|
|
@@ -657,58 +1137,64 @@ function fetchDeferments(pageKey, defers = []) {
|
|
|
657
1137
|
return Promise.all(fetches);
|
|
658
1138
|
};
|
|
659
1139
|
}
|
|
1140
|
+
function addPlaceholdersToDeferredNodes(existingPage, page) {
|
|
1141
|
+
const { defers = [] } = existingPage;
|
|
1142
|
+
const prevDefers = defers.map(({ path }) => {
|
|
1143
|
+
const node = getIn(existingPage, path);
|
|
1144
|
+
const copy = JSON.stringify(node);
|
|
1145
|
+
return [path, JSON.parse(copy)];
|
|
1146
|
+
});
|
|
1147
|
+
return prevDefers.reduce((memo, [path, node]) => {
|
|
1148
|
+
return setIn(page, path, node);
|
|
1149
|
+
}, page);
|
|
1150
|
+
}
|
|
660
1151
|
function saveAndProcessPage(pageKey, page) {
|
|
661
1152
|
return (dispatch, getState) => {
|
|
662
1153
|
pageKey = urlToPageKey(pageKey);
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
})
|
|
690
|
-
);
|
|
691
|
-
}
|
|
692
|
-
});
|
|
693
|
-
} else {
|
|
694
|
-
dispatch(saveResponse({ pageKey, page }));
|
|
695
|
-
const currentPage = getState().pages[pageKey];
|
|
696
|
-
currentPage.fragments.forEach((fragment) => {
|
|
697
|
-
const { type, path } = fragment;
|
|
698
|
-
const currentFragment = getIn(currentPage, path);
|
|
1154
|
+
let nextPage = page;
|
|
1155
|
+
const state = getState();
|
|
1156
|
+
if (page.action === "savePage" && state.pages[pageKey]) {
|
|
1157
|
+
const existingPage = createProxy(
|
|
1158
|
+
state.pages[pageKey],
|
|
1159
|
+
{ current: state.fragments },
|
|
1160
|
+
/* @__PURE__ */ new Set(),
|
|
1161
|
+
/* @__PURE__ */ new WeakMap()
|
|
1162
|
+
);
|
|
1163
|
+
nextPage = JSON.parse(
|
|
1164
|
+
JSON.stringify(addPlaceholdersToDeferredNodes(existingPage, nextPage))
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
page.fragments.slice().reverse().forEach((fragment) => {
|
|
1168
|
+
const { id, path } = fragment;
|
|
1169
|
+
const node = getIn(nextPage, path);
|
|
1170
|
+
nextPage = setIn(nextPage, path, { __id: id });
|
|
1171
|
+
dispatch(
|
|
1172
|
+
saveFragment({
|
|
1173
|
+
fragmentId: id,
|
|
1174
|
+
data: node
|
|
1175
|
+
})
|
|
1176
|
+
);
|
|
1177
|
+
});
|
|
1178
|
+
if (nextPage.action === "graft") {
|
|
1179
|
+
if (typeof nextPage.fragmentContext === "string") {
|
|
699
1180
|
dispatch(
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
value: currentFragment,
|
|
704
|
-
path
|
|
1181
|
+
handleFragmentGraft({
|
|
1182
|
+
fragmentId: nextPage.fragmentContext,
|
|
1183
|
+
response: nextPage
|
|
705
1184
|
})
|
|
706
1185
|
);
|
|
707
|
-
}
|
|
1186
|
+
} else {
|
|
1187
|
+
dispatch(handleGraft({ pageKey, page: nextPage }));
|
|
1188
|
+
}
|
|
1189
|
+
} else if (nextPage.action === "handleStreamResponse") {
|
|
1190
|
+
dispatch(handleStreamResponse(nextPage));
|
|
1191
|
+
return Promise.resolve();
|
|
1192
|
+
} else {
|
|
1193
|
+
dispatch(saveResponse({ pageKey, page: nextPage }));
|
|
708
1194
|
}
|
|
709
1195
|
const hasFetch = typeof fetch != "undefined";
|
|
710
1196
|
if (hasFetch) {
|
|
711
|
-
return dispatch(fetchDeferments(pageKey, defers)).then(
|
|
1197
|
+
return dispatch(fetchDeferments(pageKey, nextPage.defers)).then(
|
|
712
1198
|
() => Promise.resolve()
|
|
713
1199
|
);
|
|
714
1200
|
} else {
|
|
@@ -724,12 +1210,12 @@ export {
|
|
|
724
1210
|
argsForHistory,
|
|
725
1211
|
getIn,
|
|
726
1212
|
setIn,
|
|
1213
|
+
lastRequestIds,
|
|
727
1214
|
ujsHandlers,
|
|
728
1215
|
GRAFTING_ERROR,
|
|
729
1216
|
GRAFTING_SUCCESS,
|
|
730
1217
|
saveResponse,
|
|
731
1218
|
handleGraft,
|
|
732
|
-
updateFragments,
|
|
733
1219
|
copyPage,
|
|
734
1220
|
removePage,
|
|
735
1221
|
beforeFetch,
|
|
@@ -738,9 +1224,20 @@ export {
|
|
|
738
1224
|
setCSRFToken,
|
|
739
1225
|
historyChange,
|
|
740
1226
|
setActivePage,
|
|
1227
|
+
handleFragmentGraft,
|
|
1228
|
+
saveFragment,
|
|
1229
|
+
receiveResponse,
|
|
1230
|
+
appendToFragment,
|
|
1231
|
+
prependToFragment,
|
|
1232
|
+
createProxy,
|
|
1233
|
+
unproxy,
|
|
741
1234
|
MismatchedComponentError,
|
|
742
1235
|
remote,
|
|
743
1236
|
visit,
|
|
1237
|
+
streamPrepend,
|
|
1238
|
+
streamAppend,
|
|
1239
|
+
streamSave,
|
|
1240
|
+
handleStreamMessage,
|
|
744
1241
|
saveAndProcessPage
|
|
745
1242
|
};
|
|
746
|
-
//# sourceMappingURL=chunk-
|
|
1243
|
+
//# sourceMappingURL=chunk-J2XH5QTK.mjs.map
|