Initial boiler plate project

This commit is contained in:
2024-09-24 03:52:46 +00:00
parent 6120b2d6c3
commit 154b93e267
10034 changed files with 2079352 additions and 2 deletions

View File

@ -0,0 +1,4 @@
import type { ReadonlyReducerState, ReducerState, FastRefreshAction } from '../router-reducer-types';
declare function fastRefreshReducerNoop(state: ReadonlyReducerState, _action: FastRefreshAction): ReducerState;
export declare const fastRefreshReducer: typeof fastRefreshReducerNoop;
export {};

View File

@ -0,0 +1,95 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "fastRefreshReducer", {
enumerable: true,
get: function() {
return fastRefreshReducer;
}
});
const _fetchserverresponse = require("../fetch-server-response");
const _createhreffromurl = require("../create-href-from-url");
const _applyrouterstatepatchtotree = require("../apply-router-state-patch-to-tree");
const _isnavigatingtonewrootlayout = require("../is-navigating-to-new-root-layout");
const _navigatereducer = require("./navigate-reducer");
const _handlemutable = require("../handle-mutable");
const _applyflightdata = require("../apply-flight-data");
const _approuter = require("../../app-router");
const _handlesegmentmismatch = require("../handle-segment-mismatch");
const _hasinterceptionrouteincurrenttree = require("./has-interception-route-in-current-tree");
// A version of refresh reducer that keeps the cache around instead of wiping all of it.
function fastRefreshReducerImpl(state, action) {
const { origin } = action;
const mutable = {};
const href = state.canonicalUrl;
mutable.preserveCustomHistoryState = false;
const cache = (0, _approuter.createEmptyCacheNode)();
// If the current tree was intercepted, the nextUrl should be included in the request.
// This is to ensure that the refresh request doesn't get intercepted, accidentally triggering the interception route.
const includeNextUrl = (0, _hasinterceptionrouteincurrenttree.hasInterceptionRouteInCurrentTree)(state.tree);
// TODO-APP: verify that `href` is not an external url.
// Fetch data from the root of the tree.
cache.lazyData = (0, _fetchserverresponse.fetchServerResponse)(new URL(href, origin), [
state.tree[0],
state.tree[1],
state.tree[2],
"refetch"
], includeNextUrl ? state.nextUrl : null, state.buildId);
return cache.lazyData.then((param)=>{
let [flightData, canonicalUrlOverride] = param;
// Handle case when navigating to page in `pages` from `app`
if (typeof flightData === "string") {
return (0, _navigatereducer.handleExternalUrl)(state, mutable, flightData, state.pushRef.pendingPush);
}
// Remove cache.lazyData as it has been resolved at this point.
cache.lazyData = null;
let currentTree = state.tree;
let currentCache = state.cache;
for (const flightDataPath of flightData){
// FlightDataPath with more than two items means unexpected Flight data was returned
if (flightDataPath.length !== 3) {
// TODO-APP: handle this case better
console.log("REFRESH FAILED");
return state;
}
// Given the path can only have two items the items are only the router state and rsc for the root.
const [treePatch] = flightDataPath;
const newTree = (0, _applyrouterstatepatchtotree.applyRouterStatePatchToTree)(// TODO-APP: remove ''
[
""
], currentTree, treePatch, state.canonicalUrl);
if (newTree === null) {
return (0, _handlesegmentmismatch.handleSegmentMismatch)(state, action, treePatch);
}
if ((0, _isnavigatingtonewrootlayout.isNavigatingToNewRootLayout)(currentTree, newTree)) {
return (0, _navigatereducer.handleExternalUrl)(state, mutable, href, state.pushRef.pendingPush);
}
const canonicalUrlOverrideHref = canonicalUrlOverride ? (0, _createhreffromurl.createHrefFromUrl)(canonicalUrlOverride) : undefined;
if (canonicalUrlOverride) {
mutable.canonicalUrl = canonicalUrlOverrideHref;
}
const applied = (0, _applyflightdata.applyFlightData)(currentCache, cache, flightDataPath);
if (applied) {
mutable.cache = cache;
currentCache = cache;
}
mutable.patchedTree = newTree;
mutable.canonicalUrl = href;
currentTree = newTree;
}
return (0, _handlemutable.handleMutable)(state, mutable);
}, ()=>state);
}
function fastRefreshReducerNoop(state, _action) {
return state;
}
const fastRefreshReducer = process.env.NODE_ENV === "production" ? fastRefreshReducerNoop : fastRefreshReducerImpl;
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=fast-refresh-reducer.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/fast-refresh-reducer.ts"],"names":["fastRefreshReducer","fastRefreshReducerImpl","state","action","origin","mutable","href","canonicalUrl","preserveCustomHistoryState","cache","createEmptyCacheNode","includeNextUrl","hasInterceptionRouteInCurrentTree","tree","lazyData","fetchServerResponse","URL","nextUrl","buildId","then","flightData","canonicalUrlOverride","handleExternalUrl","pushRef","pendingPush","currentTree","currentCache","flightDataPath","length","console","log","treePatch","newTree","applyRouterStatePatchToTree","handleSegmentMismatch","isNavigatingToNewRootLayout","canonicalUrlOverrideHref","createHrefFromUrl","undefined","applied","applyFlightData","patchedTree","handleMutable","fastRefreshReducerNoop","_action","process","env","NODE_ENV"],"mappings":";;;;+BA4HaA;;;eAAAA;;;qCA5HuB;mCACF;6CACU;6CACA;iCAOV;+BACJ;iCACE;2BAEK;uCACC;mDACY;AAElD,wFAAwF;AACxF,SAASC,uBACPC,KAA2B,EAC3BC,MAAyB;IAEzB,MAAM,EAAEC,MAAM,EAAE,GAAGD;IACnB,MAAME,UAAmB,CAAC;IAC1B,MAAMC,OAAOJ,MAAMK,YAAY;IAE/BF,QAAQG,0BAA0B,GAAG;IAErC,MAAMC,QAAmBC,IAAAA,+BAAoB;IAC7C,sFAAsF;IACtF,sHAAsH;IACtH,MAAMC,iBAAiBC,IAAAA,oEAAiC,EAACV,MAAMW,IAAI;IAEnE,uDAAuD;IACvD,wCAAwC;IACxCJ,MAAMK,QAAQ,GAAGC,IAAAA,wCAAmB,EAClC,IAAIC,IAAIV,MAAMF,SACd;QAACF,MAAMW,IAAI,CAAC,EAAE;QAAEX,MAAMW,IAAI,CAAC,EAAE;QAAEX,MAAMW,IAAI,CAAC,EAAE;QAAE;KAAU,EACxDF,iBAAiBT,MAAMe,OAAO,GAAG,MACjCf,MAAMgB,OAAO;IAGf,OAAOT,MAAMK,QAAQ,CAACK,IAAI,CACxB;YAAC,CAACC,YAAYC,qBAAqB;QACjC,4DAA4D;QAC5D,IAAI,OAAOD,eAAe,UAAU;YAClC,OAAOE,IAAAA,kCAAiB,EACtBpB,OACAG,SACAe,YACAlB,MAAMqB,OAAO,CAACC,WAAW;QAE7B;QAEA,+DAA+D;QAC/Df,MAAMK,QAAQ,GAAG;QAEjB,IAAIW,cAAcvB,MAAMW,IAAI;QAC5B,IAAIa,eAAexB,MAAMO,KAAK;QAE9B,KAAK,MAAMkB,kBAAkBP,WAAY;YACvC,oFAAoF;YACpF,IAAIO,eAAeC,MAAM,KAAK,GAAG;gBAC/B,oCAAoC;gBACpCC,QAAQC,GAAG,CAAC;gBACZ,OAAO5B;YACT;YAEA,mGAAmG;YACnG,MAAM,CAAC6B,UAAU,GAAGJ;YACpB,MAAMK,UAAUC,IAAAA,wDAA2B,EACzC,sBAAsB;YACtB;gBAAC;aAAG,EACJR,aACAM,WACA7B,MAAMK,YAAY;YAGpB,IAAIyB,YAAY,MAAM;gBACpB,OAAOE,IAAAA,4CAAqB,EAAChC,OAAOC,QAAQ4B;YAC9C;YAEA,IAAII,IAAAA,wDAA2B,EAACV,aAAaO,UAAU;gBACrD,OAAOV,IAAAA,kCAAiB,EACtBpB,OACAG,SACAC,MACAJ,MAAMqB,OAAO,CAACC,WAAW;YAE7B;YAEA,MAAMY,2BAA2Bf,uBAC7BgB,IAAAA,oCAAiB,EAAChB,wBAClBiB;YAEJ,IAAIjB,sBAAsB;gBACxBhB,QAAQE,YAAY,GAAG6B;YACzB;YACA,MAAMG,UAAUC,IAAAA,gCAAe,EAACd,cAAcjB,OAAOkB;YAErD,IAAIY,SAAS;gBACXlC,QAAQI,KAAK,GAAGA;gBAChBiB,eAAejB;YACjB;YAEAJ,QAAQoC,WAAW,GAAGT;YACtB3B,QAAQE,YAAY,GAAGD;YAEvBmB,cAAcO;QAChB;QACA,OAAOU,IAAAA,4BAAa,EAACxC,OAAOG;IAC9B,GACA,IAAMH;AAEV;AAEA,SAASyC,uBACPzC,KAA2B,EAC3B0C,OAA0B;IAE1B,OAAO1C;AACT;AAEO,MAAMF,qBACX6C,QAAQC,GAAG,CAACC,QAAQ,KAAK,eACrBJ,yBACA1C"}

View File

@ -0,0 +1,3 @@
import type { FlightRouterState } from '../../../../server/app-render/types';
import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime';
export declare function findHeadInCache(cache: CacheNode, parallelRoutes: FlightRouterState[1]): [CacheNode, string] | null;

View File

@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "findHeadInCache", {
enumerable: true,
get: function() {
return findHeadInCache;
}
});
const _createroutercachekey = require("../create-router-cache-key");
function findHeadInCache(cache, parallelRoutes) {
return findHeadInCacheImpl(cache, parallelRoutes, "");
}
function findHeadInCacheImpl(cache, parallelRoutes, keyPrefix) {
const isLastItem = Object.keys(parallelRoutes).length === 0;
if (isLastItem) {
// Returns the entire Cache Node of the segment whose head we will render.
return [
cache,
keyPrefix
];
}
for(const key in parallelRoutes){
const [segment, childParallelRoutes] = parallelRoutes[key];
const childSegmentMap = cache.parallelRoutes.get(key);
if (!childSegmentMap) {
continue;
}
const cacheKey = (0, _createroutercachekey.createRouterCacheKey)(segment);
const cacheNode = childSegmentMap.get(cacheKey);
if (!cacheNode) {
continue;
}
const item = findHeadInCacheImpl(cacheNode, childParallelRoutes, keyPrefix + "/" + cacheKey);
if (item) {
return item;
}
}
return null;
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=find-head-in-cache.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/find-head-in-cache.ts"],"names":["findHeadInCache","cache","parallelRoutes","findHeadInCacheImpl","keyPrefix","isLastItem","Object","keys","length","key","segment","childParallelRoutes","childSegmentMap","get","cacheKey","createRouterCacheKey","cacheNode","item"],"mappings":";;;;+BAIgBA;;;eAAAA;;;sCAFqB;AAE9B,SAASA,gBACdC,KAAgB,EAChBC,cAAoC;IAEpC,OAAOC,oBAAoBF,OAAOC,gBAAgB;AACpD;AAEA,SAASC,oBACPF,KAAgB,EAChBC,cAAoC,EACpCE,SAAiB;IAEjB,MAAMC,aAAaC,OAAOC,IAAI,CAACL,gBAAgBM,MAAM,KAAK;IAC1D,IAAIH,YAAY;QACd,0EAA0E;QAC1E,OAAO;YAACJ;YAAOG;SAAU;IAC3B;IACA,IAAK,MAAMK,OAAOP,eAAgB;QAChC,MAAM,CAACQ,SAASC,oBAAoB,GAAGT,cAAc,CAACO,IAAI;QAC1D,MAAMG,kBAAkBX,MAAMC,cAAc,CAACW,GAAG,CAACJ;QACjD,IAAI,CAACG,iBAAiB;YACpB;QACF;QAEA,MAAME,WAAWC,IAAAA,0CAAoB,EAACL;QAEtC,MAAMM,YAAYJ,gBAAgBC,GAAG,CAACC;QACtC,IAAI,CAACE,WAAW;YACd;QACF;QAEA,MAAMC,OAAOd,oBACXa,WACAL,qBACAP,YAAY,MAAMU;QAEpB,IAAIG,MAAM;YACR,OAAOA;QACT;IACF;IAEA,OAAO;AACT"}

View File

@ -0,0 +1 @@
export {};

View File

@ -0,0 +1,2 @@
import type { Segment } from '../../../../server/app-render/types';
export declare function getSegmentValue(segment: Segment): string;

View File

@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "getSegmentValue", {
enumerable: true,
get: function() {
return getSegmentValue;
}
});
function getSegmentValue(segment) {
return Array.isArray(segment) ? segment[1] : segment;
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=get-segment-value.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/get-segment-value.ts"],"names":["getSegmentValue","segment","Array","isArray"],"mappings":";;;;+BAEgBA;;;eAAAA;;;AAAT,SAASA,gBAAgBC,OAAgB;IAC9C,OAAOC,MAAMC,OAAO,CAACF,WAAWA,OAAO,CAAC,EAAE,GAAGA;AAC/C"}

View File

@ -0,0 +1,2 @@
import type { FlightRouterState } from '../../../../server/app-render/types';
export declare function hasInterceptionRouteInCurrentTree([segment, parallelRoutes,]: FlightRouterState): boolean;

View File

@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "hasInterceptionRouteInCurrentTree", {
enumerable: true,
get: function() {
return hasInterceptionRouteInCurrentTree;
}
});
const _interceptionroutes = require("../../../../server/future/helpers/interception-routes");
function hasInterceptionRouteInCurrentTree(param) {
let [segment, parallelRoutes] = param;
// If we have a dynamic segment, it's marked as an interception route by the presence of the `i` suffix.
if (Array.isArray(segment) && (segment[2] === "di" || segment[2] === "ci")) {
return true;
}
// If segment is not an array, apply the existing string-based check
if (typeof segment === "string" && (0, _interceptionroutes.isInterceptionRouteAppPath)(segment)) {
return true;
}
// Iterate through parallelRoutes if they exist
if (parallelRoutes) {
for(const key in parallelRoutes){
if (hasInterceptionRouteInCurrentTree(parallelRoutes[key])) {
return true;
}
}
}
return false;
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=has-interception-route-in-current-tree.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/has-interception-route-in-current-tree.ts"],"names":["hasInterceptionRouteInCurrentTree","segment","parallelRoutes","Array","isArray","isInterceptionRouteAppPath","key"],"mappings":";;;;+BAGgBA;;;eAAAA;;;oCAF2B;AAEpC,SAASA,kCAAkC,KAG9B;IAH8B,IAAA,CAChDC,SACAC,eACkB,GAH8B;IAIhD,wGAAwG;IACxG,IAAIC,MAAMC,OAAO,CAACH,YAAaA,CAAAA,OAAO,CAAC,EAAE,KAAK,QAAQA,OAAO,CAAC,EAAE,KAAK,IAAG,GAAI;QAC1E,OAAO;IACT;IAEA,oEAAoE;IACpE,IAAI,OAAOA,YAAY,YAAYI,IAAAA,8CAA0B,EAACJ,UAAU;QACtE,OAAO;IACT;IAEA,+CAA+C;IAC/C,IAAIC,gBAAgB;QAClB,IAAK,MAAMI,OAAOJ,eAAgB;YAChC,IAAIF,kCAAkCE,cAAc,CAACI,IAAI,GAAG;gBAC1D,OAAO;YACT;QACF;IACF;IAEA,OAAO;AACT"}

View File

@ -0,0 +1,5 @@
import { type Mutable, type NavigateAction, type ReadonlyReducerState, type ReducerState } from '../router-reducer-types';
export declare function handleExternalUrl(state: ReadonlyReducerState, mutable: Mutable, url: string, pendingPush: boolean): ReducerState;
export declare const navigateReducer: typeof navigateReducer_PPR;
declare function navigateReducer_PPR(state: ReadonlyReducerState, action: NavigateAction): ReducerState;
export {};

View File

@ -0,0 +1,390 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
handleExternalUrl: null,
navigateReducer: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
handleExternalUrl: function() {
return handleExternalUrl;
},
navigateReducer: function() {
return navigateReducer;
}
});
const _fetchserverresponse = require("../fetch-server-response");
const _createhreffromurl = require("../create-href-from-url");
const _invalidatecachebelowflightsegmentpath = require("../invalidate-cache-below-flight-segmentpath");
const _applyrouterstatepatchtotree = require("../apply-router-state-patch-to-tree");
const _shouldhardnavigate = require("../should-hard-navigate");
const _isnavigatingtonewrootlayout = require("../is-navigating-to-new-root-layout");
const _routerreducertypes = require("../router-reducer-types");
const _handlemutable = require("../handle-mutable");
const _applyflightdata = require("../apply-flight-data");
const _prefetchreducer = require("./prefetch-reducer");
const _approuter = require("../../app-router");
const _segment = require("../../../../shared/lib/segment");
const _pprnavigations = require("../ppr-navigations");
const _prefetchcacheutils = require("../prefetch-cache-utils");
const _clearcachenodedataforsegmentpath = require("../clear-cache-node-data-for-segment-path");
function handleExternalUrl(state, mutable, url, pendingPush) {
mutable.mpaNavigation = true;
mutable.canonicalUrl = url;
mutable.pendingPush = pendingPush;
mutable.scrollableSegments = undefined;
return (0, _handlemutable.handleMutable)(state, mutable);
}
function generateSegmentsFromPatch(flightRouterPatch) {
const segments = [];
const [segment, parallelRoutes] = flightRouterPatch;
if (Object.keys(parallelRoutes).length === 0) {
return [
[
segment
]
];
}
for (const [parallelRouteKey, parallelRoute] of Object.entries(parallelRoutes)){
for (const childSegment of generateSegmentsFromPatch(parallelRoute)){
// If the segment is empty, it means we are at the root of the tree
if (segment === "") {
segments.push([
parallelRouteKey,
...childSegment
]);
} else {
segments.push([
segment,
parallelRouteKey,
...childSegment
]);
}
}
}
return segments;
}
function triggerLazyFetchForLeafSegments(newCache, currentCache, flightSegmentPath, treePatch) {
let appliedPatch = false;
newCache.rsc = currentCache.rsc;
newCache.prefetchRsc = currentCache.prefetchRsc;
newCache.loading = currentCache.loading;
newCache.parallelRoutes = new Map(currentCache.parallelRoutes);
const segmentPathsToFill = generateSegmentsFromPatch(treePatch).map((segment)=>[
...flightSegmentPath,
...segment
]);
for (const segmentPaths of segmentPathsToFill){
(0, _clearcachenodedataforsegmentpath.clearCacheNodeDataForSegmentPath)(newCache, currentCache, segmentPaths);
appliedPatch = true;
}
return appliedPatch;
}
const navigateReducer = process.env.__NEXT_PPR ? navigateReducer_PPR : navigateReducer_noPPR;
// This is the implementation when PPR is disabled. We can assume its behavior
// is relatively stable because it's been running in production for a while.
function navigateReducer_noPPR(state, action) {
const { url, isExternalUrl, navigateType, shouldScroll } = action;
const mutable = {};
const { hash } = url;
const href = (0, _createhreffromurl.createHrefFromUrl)(url);
const pendingPush = navigateType === "push";
// we want to prune the prefetch cache on every navigation to avoid it growing too large
(0, _prefetchcacheutils.prunePrefetchCache)(state.prefetchCache);
mutable.preserveCustomHistoryState = false;
if (isExternalUrl) {
return handleExternalUrl(state, mutable, url.toString(), pendingPush);
}
const prefetchValues = (0, _prefetchcacheutils.getOrCreatePrefetchCacheEntry)({
url,
nextUrl: state.nextUrl,
tree: state.tree,
buildId: state.buildId,
prefetchCache: state.prefetchCache
});
const { treeAtTimeOfPrefetch, data } = prefetchValues;
_prefetchreducer.prefetchQueue.bump(data);
return data.then((param)=>{
let [flightData, canonicalUrlOverride] = param;
let isFirstRead = false;
// we only want to mark this once
if (!prefetchValues.lastUsedTime) {
// important: we should only mark the cache node as dirty after we unsuspend from the call above
prefetchValues.lastUsedTime = Date.now();
isFirstRead = true;
}
// Handle case when navigating to page in `pages` from `app`
if (typeof flightData === "string") {
return handleExternalUrl(state, mutable, flightData, pendingPush);
}
// Handles case where `<meta http-equiv="refresh">` tag is present,
// which will trigger an MPA navigation.
if (document.getElementById("__next-page-redirect")) {
return handleExternalUrl(state, mutable, href, pendingPush);
}
let currentTree = state.tree;
let currentCache = state.cache;
let scrollableSegments = [];
for (const flightDataPath of flightData){
const flightSegmentPath = flightDataPath.slice(0, -4);
// The one before last item is the router state tree patch
const treePatch = flightDataPath.slice(-3)[0];
// TODO-APP: remove ''
const flightSegmentPathWithLeadingEmpty = [
"",
...flightSegmentPath
];
// Create new tree based on the flightSegmentPath and router state patch
let newTree = (0, _applyrouterstatepatchtotree.applyRouterStatePatchToTree)(// TODO-APP: remove ''
flightSegmentPathWithLeadingEmpty, currentTree, treePatch, href);
// If the tree patch can't be applied to the current tree then we use the tree at time of prefetch
// TODO-APP: This should instead fill in the missing pieces in `currentTree` with the data from `treeAtTimeOfPrefetch`, then apply the patch.
if (newTree === null) {
newTree = (0, _applyrouterstatepatchtotree.applyRouterStatePatchToTree)(// TODO-APP: remove ''
flightSegmentPathWithLeadingEmpty, treeAtTimeOfPrefetch, treePatch, href);
}
if (newTree !== null) {
if ((0, _isnavigatingtonewrootlayout.isNavigatingToNewRootLayout)(currentTree, newTree)) {
return handleExternalUrl(state, mutable, href, pendingPush);
}
const cache = (0, _approuter.createEmptyCacheNode)();
let applied = false;
if (prefetchValues.status === _routerreducertypes.PrefetchCacheEntryStatus.stale && !isFirstRead) {
// When we have a stale prefetch entry, we only want to re-use the loading state of the route we're navigating to, to support instant loading navigations
// this will trigger a lazy fetch for the actual page data by nulling the `rsc` and `prefetchRsc` values for page data,
// while copying over the `loading` for the segment that contains the page data.
// We only do this on subsequent reads, as otherwise there'd be no loading data to re-use.
applied = triggerLazyFetchForLeafSegments(cache, currentCache, flightSegmentPath, treePatch);
// since we re-used the stale cache's loading state & refreshed the data,
// update the `lastUsedTime` so that it can continue to be re-used for the next 30s
prefetchValues.lastUsedTime = Date.now();
} else {
applied = (0, _applyflightdata.applyFlightData)(currentCache, cache, flightDataPath, prefetchValues);
}
const hardNavigate = (0, _shouldhardnavigate.shouldHardNavigate)(// TODO-APP: remove ''
flightSegmentPathWithLeadingEmpty, currentTree);
if (hardNavigate) {
// Copy rsc for the root node of the cache.
cache.rsc = currentCache.rsc;
cache.prefetchRsc = currentCache.prefetchRsc;
(0, _invalidatecachebelowflightsegmentpath.invalidateCacheBelowFlightSegmentPath)(cache, currentCache, flightSegmentPath);
// Ensure the existing cache value is used when the cache was not invalidated.
mutable.cache = cache;
} else if (applied) {
mutable.cache = cache;
// If we applied the cache, we update the "current cache" value so any other
// segments in the FlightDataPath will be able to reference the updated cache.
currentCache = cache;
}
currentTree = newTree;
for (const subSegment of generateSegmentsFromPatch(treePatch)){
const scrollableSegmentPath = [
...flightSegmentPath,
...subSegment
];
// Filter out the __DEFAULT__ paths as they shouldn't be scrolled to in this case.
if (scrollableSegmentPath[scrollableSegmentPath.length - 1] !== _segment.DEFAULT_SEGMENT_KEY) {
scrollableSegments.push(scrollableSegmentPath);
}
}
}
}
mutable.patchedTree = currentTree;
mutable.canonicalUrl = canonicalUrlOverride ? (0, _createhreffromurl.createHrefFromUrl)(canonicalUrlOverride) : href;
mutable.pendingPush = pendingPush;
mutable.scrollableSegments = scrollableSegments;
mutable.hashFragment = hash;
mutable.shouldScroll = shouldScroll;
return (0, _handlemutable.handleMutable)(state, mutable);
}, ()=>state);
}
// This is the experimental PPR implementation. It's closer to the behavior we
// want, but is likelier to include accidental regressions because it rewrites
// existing functionality.
function navigateReducer_PPR(state, action) {
const { url, isExternalUrl, navigateType, shouldScroll } = action;
const mutable = {};
const { hash } = url;
const href = (0, _createhreffromurl.createHrefFromUrl)(url);
const pendingPush = navigateType === "push";
// we want to prune the prefetch cache on every navigation to avoid it growing too large
(0, _prefetchcacheutils.prunePrefetchCache)(state.prefetchCache);
mutable.preserveCustomHistoryState = false;
if (isExternalUrl) {
return handleExternalUrl(state, mutable, url.toString(), pendingPush);
}
const prefetchValues = (0, _prefetchcacheutils.getOrCreatePrefetchCacheEntry)({
url,
nextUrl: state.nextUrl,
tree: state.tree,
buildId: state.buildId,
prefetchCache: state.prefetchCache
});
const { treeAtTimeOfPrefetch, data } = prefetchValues;
_prefetchreducer.prefetchQueue.bump(data);
return data.then((param)=>{
let [flightData, canonicalUrlOverride, _postponed] = param;
let isFirstRead = false;
// we only want to mark this once
if (!prefetchValues.lastUsedTime) {
// important: we should only mark the cache node as dirty after we unsuspend from the call above
prefetchValues.lastUsedTime = Date.now();
isFirstRead = true;
}
// Handle case when navigating to page in `pages` from `app`
if (typeof flightData === "string") {
return handleExternalUrl(state, mutable, flightData, pendingPush);
}
// Handles case where `<meta http-equiv="refresh">` tag is present,
// which will trigger an MPA navigation.
if (document.getElementById("__next-page-redirect")) {
return handleExternalUrl(state, mutable, href, pendingPush);
}
let currentTree = state.tree;
let currentCache = state.cache;
let scrollableSegments = [];
// TODO: In practice, this is always a single item array. We probably
// aren't going to every send multiple segments, at least not in this
// format. So we could remove the extra wrapper for now until
// that settles.
for (const flightDataPath of flightData){
const flightSegmentPath = flightDataPath.slice(0, -4);
// The one before last item is the router state tree patch
const treePatch = flightDataPath.slice(-3)[0];
// TODO-APP: remove ''
const flightSegmentPathWithLeadingEmpty = [
"",
...flightSegmentPath
];
// Create new tree based on the flightSegmentPath and router state patch
let newTree = (0, _applyrouterstatepatchtotree.applyRouterStatePatchToTree)(// TODO-APP: remove ''
flightSegmentPathWithLeadingEmpty, currentTree, treePatch, href);
// If the tree patch can't be applied to the current tree then we use the tree at time of prefetch
// TODO-APP: This should instead fill in the missing pieces in `currentTree` with the data from `treeAtTimeOfPrefetch`, then apply the patch.
if (newTree === null) {
newTree = (0, _applyrouterstatepatchtotree.applyRouterStatePatchToTree)(// TODO-APP: remove ''
flightSegmentPathWithLeadingEmpty, treeAtTimeOfPrefetch, treePatch, href);
}
if (newTree !== null) {
if ((0, _isnavigatingtonewrootlayout.isNavigatingToNewRootLayout)(currentTree, newTree)) {
return handleExternalUrl(state, mutable, href, pendingPush);
}
if (// This is just a paranoid check. When PPR is enabled, the server
// will always send back a static response that's rendered from
// the root. If for some reason it doesn't, we fall back to the
// non-PPR implementation.
// TODO: We should get rid of the else branch and do all navigations
// via updateCacheNodeOnNavigation. The current structure is just
// an incremental step.
flightDataPath.length === 3) {
const prefetchedTree = flightDataPath[0];
const seedData = flightDataPath[1];
const head = flightDataPath[2];
const task = (0, _pprnavigations.updateCacheNodeOnNavigation)(currentCache, currentTree, prefetchedTree, seedData, head);
if (task !== null && task.node !== null) {
// We've created a new Cache Node tree that contains a prefetched
// version of the next page. This can be rendered instantly.
// Use the tree computed by updateCacheNodeOnNavigation instead
// of the one computed by applyRouterStatePatchToTree.
// TODO: We should remove applyRouterStatePatchToTree
// from the PPR path entirely.
const patchedRouterState = task.route;
newTree = patchedRouterState;
const newCache = task.node;
// The prefetched tree has dynamic holes in it. We initiate a
// dynamic request to fill them in.
//
// Do not block on the result. We'll immediately render the Cache
// Node tree and suspend on the dynamic parts. When the request
// comes in, we'll fill in missing data and ping React to
// re-render. Unlike the lazy fetching model in the non-PPR
// implementation, this is modeled as a single React update +
// streaming, rather than multiple top-level updates. (However,
// even in the new model, we'll still need to sometimes update the
// root multiple times per navigation, like if the server sends us
// a different response than we expected. For now, we revert back
// to the lazy fetching mechanism in that case.)
(0, _pprnavigations.listenForDynamicRequest)(task, (0, _fetchserverresponse.fetchServerResponse)(url, currentTree, state.nextUrl, state.buildId));
mutable.cache = newCache;
} else {
// Nothing changed, so reuse the old cache.
// TODO: What if the head changed but not any of the segment data?
// Is that possible? If so, we should clone the whole tree and
// update the head.
newTree = prefetchedTree;
}
} else {
// The static response does not include any dynamic holes, so
// there's no need to do a second request.
// TODO: As an incremental step this just reverts back to the
// non-PPR implementation. We can simplify this branch further,
// given that PPR prefetches are always static and return the whole
// tree. Or in the meantime we could factor it out into a
// separate function.
const cache = (0, _approuter.createEmptyCacheNode)();
let applied = false;
if (prefetchValues.status === _routerreducertypes.PrefetchCacheEntryStatus.stale && !isFirstRead) {
// When we have a stale prefetch entry, we only want to re-use the loading state of the route we're navigating to, to support instant loading navigations
// this will trigger a lazy fetch for the actual page data by nulling the `rsc` and `prefetchRsc` values for page data,
// while copying over the `loading` for the segment that contains the page data.
// We only do this on subsequent reads, as otherwise there'd be no loading data to re-use.
applied = triggerLazyFetchForLeafSegments(cache, currentCache, flightSegmentPath, treePatch);
// since we re-used the stale cache's loading state & refreshed the data,
// update the `lastUsedTime` so that it can continue to be re-used for the next 30s
prefetchValues.lastUsedTime = Date.now();
} else {
applied = (0, _applyflightdata.applyFlightData)(currentCache, cache, flightDataPath, prefetchValues);
}
const hardNavigate = (0, _shouldhardnavigate.shouldHardNavigate)(// TODO-APP: remove ''
flightSegmentPathWithLeadingEmpty, currentTree);
if (hardNavigate) {
// Copy rsc for the root node of the cache.
cache.rsc = currentCache.rsc;
cache.prefetchRsc = currentCache.prefetchRsc;
(0, _invalidatecachebelowflightsegmentpath.invalidateCacheBelowFlightSegmentPath)(cache, currentCache, flightSegmentPath);
// Ensure the existing cache value is used when the cache was not invalidated.
mutable.cache = cache;
} else if (applied) {
mutable.cache = cache;
// If we applied the cache, we update the "current cache" value so any other
// segments in the FlightDataPath will be able to reference the updated cache.
currentCache = cache;
}
}
currentTree = newTree;
for (const subSegment of generateSegmentsFromPatch(treePatch)){
const scrollableSegmentPath = [
...flightSegmentPath,
...subSegment
];
// Filter out the __DEFAULT__ paths as they shouldn't be scrolled to in this case.
if (scrollableSegmentPath[scrollableSegmentPath.length - 1] !== _segment.DEFAULT_SEGMENT_KEY) {
scrollableSegments.push(scrollableSegmentPath);
}
}
}
}
mutable.patchedTree = currentTree;
mutable.canonicalUrl = canonicalUrlOverride ? (0, _createhreffromurl.createHrefFromUrl)(canonicalUrlOverride) : href;
mutable.pendingPush = pendingPush;
mutable.scrollableSegments = scrollableSegments;
mutable.hashFragment = hash;
mutable.shouldScroll = shouldScroll;
return (0, _handlemutable.handleMutable)(state, mutable);
}, ()=>state);
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=navigate-reducer.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
import type { PrefetchAction, ReducerState, ReadonlyReducerState } from '../router-reducer-types';
import { PromiseQueue } from '../../promise-queue';
export declare const prefetchQueue: PromiseQueue;
export declare function prefetchReducer(state: ReadonlyReducerState, action: PrefetchAction): ReducerState;

View File

@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
prefetchQueue: null,
prefetchReducer: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
prefetchQueue: function() {
return prefetchQueue;
},
prefetchReducer: function() {
return prefetchReducer;
}
});
const _approuterheaders = require("../../app-router-headers");
const _promisequeue = require("../../promise-queue");
const _prefetchcacheutils = require("../prefetch-cache-utils");
const prefetchQueue = new _promisequeue.PromiseQueue(5);
function prefetchReducer(state, action) {
// let's prune the prefetch cache before we do anything else
(0, _prefetchcacheutils.prunePrefetchCache)(state.prefetchCache);
const { url } = action;
url.searchParams.delete(_approuterheaders.NEXT_RSC_UNION_QUERY);
(0, _prefetchcacheutils.getOrCreatePrefetchCacheEntry)({
url,
nextUrl: state.nextUrl,
prefetchCache: state.prefetchCache,
kind: action.kind,
tree: state.tree,
buildId: state.buildId
});
return state;
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=prefetch-reducer.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/prefetch-reducer.ts"],"names":["prefetchQueue","prefetchReducer","PromiseQueue","state","action","prunePrefetchCache","prefetchCache","url","searchParams","delete","NEXT_RSC_UNION_QUERY","getOrCreatePrefetchCacheEntry","nextUrl","kind","tree","buildId"],"mappings":";;;;;;;;;;;;;;;IAYaA,aAAa;eAAbA;;IAEGC,eAAe;eAAfA;;;kCATqB;8BACR;oCAItB;AAEA,MAAMD,gBAAgB,IAAIE,0BAAY,CAAC;AAEvC,SAASD,gBACdE,KAA2B,EAC3BC,MAAsB;IAEtB,4DAA4D;IAC5DC,IAAAA,sCAAkB,EAACF,MAAMG,aAAa;IAEtC,MAAM,EAAEC,GAAG,EAAE,GAAGH;IAChBG,IAAIC,YAAY,CAACC,MAAM,CAACC,sCAAoB;IAE5CC,IAAAA,iDAA6B,EAAC;QAC5BJ;QACAK,SAAST,MAAMS,OAAO;QACtBN,eAAeH,MAAMG,aAAa;QAClCO,MAAMT,OAAOS,IAAI;QACjBC,MAAMX,MAAMW,IAAI;QAChBC,SAASZ,MAAMY,OAAO;IACxB;IAEA,OAAOZ;AACT"}

View File

@ -0,0 +1,2 @@
import type { ReadonlyReducerState, ReducerState, RefreshAction } from '../router-reducer-types';
export declare function refreshReducer(state: ReadonlyReducerState, action: RefreshAction): ReducerState;

View File

@ -0,0 +1,104 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "refreshReducer", {
enumerable: true,
get: function() {
return refreshReducer;
}
});
const _fetchserverresponse = require("../fetch-server-response");
const _createhreffromurl = require("../create-href-from-url");
const _applyrouterstatepatchtotree = require("../apply-router-state-patch-to-tree");
const _isnavigatingtonewrootlayout = require("../is-navigating-to-new-root-layout");
const _navigatereducer = require("./navigate-reducer");
const _handlemutable = require("../handle-mutable");
const _filllazyitemstillleafwithhead = require("../fill-lazy-items-till-leaf-with-head");
const _approuter = require("../../app-router");
const _handlesegmentmismatch = require("../handle-segment-mismatch");
const _hasinterceptionrouteincurrenttree = require("./has-interception-route-in-current-tree");
const _refetchinactiveparallelsegments = require("../refetch-inactive-parallel-segments");
function refreshReducer(state, action) {
const { origin } = action;
const mutable = {};
const href = state.canonicalUrl;
let currentTree = state.tree;
mutable.preserveCustomHistoryState = false;
const cache = (0, _approuter.createEmptyCacheNode)();
// If the current tree was intercepted, the nextUrl should be included in the request.
// This is to ensure that the refresh request doesn't get intercepted, accidentally triggering the interception route.
const includeNextUrl = (0, _hasinterceptionrouteincurrenttree.hasInterceptionRouteInCurrentTree)(state.tree);
// TODO-APP: verify that `href` is not an external url.
// Fetch data from the root of the tree.
cache.lazyData = (0, _fetchserverresponse.fetchServerResponse)(new URL(href, origin), [
currentTree[0],
currentTree[1],
currentTree[2],
"refetch"
], includeNextUrl ? state.nextUrl : null, state.buildId);
return cache.lazyData.then(async (param)=>{
let [flightData, canonicalUrlOverride] = param;
// Handle case when navigating to page in `pages` from `app`
if (typeof flightData === "string") {
return (0, _navigatereducer.handleExternalUrl)(state, mutable, flightData, state.pushRef.pendingPush);
}
// Remove cache.lazyData as it has been resolved at this point.
cache.lazyData = null;
for (const flightDataPath of flightData){
// FlightDataPath with more than two items means unexpected Flight data was returned
if (flightDataPath.length !== 3) {
// TODO-APP: handle this case better
console.log("REFRESH FAILED");
return state;
}
// Given the path can only have two items the items are only the router state and rsc for the root.
const [treePatch] = flightDataPath;
const newTree = (0, _applyrouterstatepatchtotree.applyRouterStatePatchToTree)(// TODO-APP: remove ''
[
""
], currentTree, treePatch, state.canonicalUrl);
if (newTree === null) {
return (0, _handlesegmentmismatch.handleSegmentMismatch)(state, action, treePatch);
}
if ((0, _isnavigatingtonewrootlayout.isNavigatingToNewRootLayout)(currentTree, newTree)) {
return (0, _navigatereducer.handleExternalUrl)(state, mutable, href, state.pushRef.pendingPush);
}
const canonicalUrlOverrideHref = canonicalUrlOverride ? (0, _createhreffromurl.createHrefFromUrl)(canonicalUrlOverride) : undefined;
if (canonicalUrlOverride) {
mutable.canonicalUrl = canonicalUrlOverrideHref;
}
// The one before last item is the router state tree patch
const [cacheNodeSeedData, head] = flightDataPath.slice(-2);
// Handles case where prefetch only returns the router tree patch without rendered components.
if (cacheNodeSeedData !== null) {
const rsc = cacheNodeSeedData[2];
cache.rsc = rsc;
cache.prefetchRsc = null;
(0, _filllazyitemstillleafwithhead.fillLazyItemsTillLeafWithHead)(cache, // Existing cache is not passed in as `router.refresh()` has to invalidate the entire cache.
undefined, treePatch, cacheNodeSeedData, head);
mutable.prefetchCache = new Map();
}
await (0, _refetchinactiveparallelsegments.refreshInactiveParallelSegments)({
state,
updatedTree: newTree,
updatedCache: cache,
includeNextUrl,
canonicalUrl: mutable.canonicalUrl || state.canonicalUrl
});
mutable.cache = cache;
mutable.patchedTree = newTree;
mutable.canonicalUrl = href;
currentTree = newTree;
}
return (0, _handlemutable.handleMutable)(state, mutable);
}, ()=>state);
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=refresh-reducer.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/refresh-reducer.ts"],"names":["refreshReducer","state","action","origin","mutable","href","canonicalUrl","currentTree","tree","preserveCustomHistoryState","cache","createEmptyCacheNode","includeNextUrl","hasInterceptionRouteInCurrentTree","lazyData","fetchServerResponse","URL","nextUrl","buildId","then","flightData","canonicalUrlOverride","handleExternalUrl","pushRef","pendingPush","flightDataPath","length","console","log","treePatch","newTree","applyRouterStatePatchToTree","handleSegmentMismatch","isNavigatingToNewRootLayout","canonicalUrlOverrideHref","createHrefFromUrl","undefined","cacheNodeSeedData","head","slice","rsc","prefetchRsc","fillLazyItemsTillLeafWithHead","prefetchCache","Map","refreshInactiveParallelSegments","updatedTree","updatedCache","patchedTree","handleMutable"],"mappings":";;;;+BAmBgBA;;;eAAAA;;;qCAnBoB;mCACF;6CACU;6CACA;iCAOV;+BACJ;+CAEgB;2BACT;uCACC;mDACY;iDACF;AAEzC,SAASA,eACdC,KAA2B,EAC3BC,MAAqB;IAErB,MAAM,EAAEC,MAAM,EAAE,GAAGD;IACnB,MAAME,UAAmB,CAAC;IAC1B,MAAMC,OAAOJ,MAAMK,YAAY;IAE/B,IAAIC,cAAcN,MAAMO,IAAI;IAE5BJ,QAAQK,0BAA0B,GAAG;IAErC,MAAMC,QAAmBC,IAAAA,+BAAoB;IAE7C,sFAAsF;IACtF,sHAAsH;IACtH,MAAMC,iBAAiBC,IAAAA,oEAAiC,EAACZ,MAAMO,IAAI;IAEnE,uDAAuD;IACvD,wCAAwC;IACxCE,MAAMI,QAAQ,GAAGC,IAAAA,wCAAmB,EAClC,IAAIC,IAAIX,MAAMF,SACd;QAACI,WAAW,CAAC,EAAE;QAAEA,WAAW,CAAC,EAAE;QAAEA,WAAW,CAAC,EAAE;QAAE;KAAU,EAC3DK,iBAAiBX,MAAMgB,OAAO,GAAG,MACjChB,MAAMiB,OAAO;IAGf,OAAOR,MAAMI,QAAQ,CAACK,IAAI,CACxB;YAAO,CAACC,YAAYC,qBAAqB;QACvC,4DAA4D;QAC5D,IAAI,OAAOD,eAAe,UAAU;YAClC,OAAOE,IAAAA,kCAAiB,EACtBrB,OACAG,SACAgB,YACAnB,MAAMsB,OAAO,CAACC,WAAW;QAE7B;QAEA,+DAA+D;QAC/Dd,MAAMI,QAAQ,GAAG;QAEjB,KAAK,MAAMW,kBAAkBL,WAAY;YACvC,oFAAoF;YACpF,IAAIK,eAAeC,MAAM,KAAK,GAAG;gBAC/B,oCAAoC;gBACpCC,QAAQC,GAAG,CAAC;gBACZ,OAAO3B;YACT;YAEA,mGAAmG;YACnG,MAAM,CAAC4B,UAAU,GAAGJ;YACpB,MAAMK,UAAUC,IAAAA,wDAA2B,EACzC,sBAAsB;YACtB;gBAAC;aAAG,EACJxB,aACAsB,WACA5B,MAAMK,YAAY;YAGpB,IAAIwB,YAAY,MAAM;gBACpB,OAAOE,IAAAA,4CAAqB,EAAC/B,OAAOC,QAAQ2B;YAC9C;YAEA,IAAII,IAAAA,wDAA2B,EAAC1B,aAAauB,UAAU;gBACrD,OAAOR,IAAAA,kCAAiB,EACtBrB,OACAG,SACAC,MACAJ,MAAMsB,OAAO,CAACC,WAAW;YAE7B;YAEA,MAAMU,2BAA2Bb,uBAC7Bc,IAAAA,oCAAiB,EAACd,wBAClBe;YAEJ,IAAIf,sBAAsB;gBACxBjB,QAAQE,YAAY,GAAG4B;YACzB;YAEA,0DAA0D;YAC1D,MAAM,CAACG,mBAAmBC,KAAK,GAAGb,eAAec,KAAK,CAAC,CAAC;YAExD,8FAA8F;YAC9F,IAAIF,sBAAsB,MAAM;gBAC9B,MAAMG,MAAMH,iBAAiB,CAAC,EAAE;gBAChC3B,MAAM8B,GAAG,GAAGA;gBACZ9B,MAAM+B,WAAW,GAAG;gBACpBC,IAAAA,4DAA6B,EAC3BhC,OACA,4FAA4F;gBAC5F0B,WACAP,WACAQ,mBACAC;gBAEFlC,QAAQuC,aAAa,GAAG,IAAIC;YAC9B;YAEA,MAAMC,IAAAA,gEAA+B,EAAC;gBACpC5C;gBACA6C,aAAahB;gBACbiB,cAAcrC;gBACdE;gBACAN,cAAcF,QAAQE,YAAY,IAAIL,MAAMK,YAAY;YAC1D;YAEAF,QAAQM,KAAK,GAAGA;YAChBN,QAAQ4C,WAAW,GAAGlB;YACtB1B,QAAQE,YAAY,GAAGD;YAEvBE,cAAcuB;QAChB;QAEA,OAAOmB,IAAAA,4BAAa,EAAChD,OAAOG;IAC9B,GACA,IAAMH;AAEV"}

View File

@ -0,0 +1,2 @@
import type { ReadonlyReducerState, ReducerState, RestoreAction } from '../router-reducer-types';
export declare function restoreReducer(state: ReadonlyReducerState, action: RestoreAction): ReducerState;

View File

@ -0,0 +1,55 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "restoreReducer", {
enumerable: true,
get: function() {
return restoreReducer;
}
});
const _createhreffromurl = require("../create-href-from-url");
const _computechangedpath = require("../compute-changed-path");
const _pprnavigations = require("../ppr-navigations");
function restoreReducer(state, action) {
const { url, tree } = action;
const href = (0, _createhreffromurl.createHrefFromUrl)(url);
// This action is used to restore the router state from the history state.
// However, it's possible that the history state no longer contains the `FlightRouterState`.
// We will copy over the internal state on pushState/replaceState events, but if a history entry
// occurred before hydration, or if the user navigated to a hash using a regular anchor link,
// the history state will not contain the `FlightRouterState`.
// In this case, we'll continue to use the existing tree so the router doesn't get into an invalid state.
const treeToRestore = tree || state.tree;
const oldCache = state.cache;
const newCache = process.env.__NEXT_PPR ? // data for any segment whose dynamic data was already received. This
// prevents an unnecessary flash back to PPR state during a
// back/forward navigation.
(0, _pprnavigations.updateCacheNodeOnPopstateRestoration)(oldCache, treeToRestore) : oldCache;
var _extractPathFromFlightRouterState;
return {
buildId: state.buildId,
// Set canonical url
canonicalUrl: href,
pushRef: {
pendingPush: false,
mpaNavigation: false,
// Ensures that the custom history state that was set is preserved when applying this update.
preserveCustomHistoryState: true
},
focusAndScrollRef: state.focusAndScrollRef,
cache: newCache,
prefetchCache: state.prefetchCache,
// Restore provided tree
tree: treeToRestore,
nextUrl: (_extractPathFromFlightRouterState = (0, _computechangedpath.extractPathFromFlightRouterState)(treeToRestore)) != null ? _extractPathFromFlightRouterState : url.pathname
};
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=restore-reducer.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/restore-reducer.ts"],"names":["restoreReducer","state","action","url","tree","href","createHrefFromUrl","treeToRestore","oldCache","cache","newCache","process","env","__NEXT_PPR","updateCacheNodeOnPopstateRestoration","extractPathFromFlightRouterState","buildId","canonicalUrl","pushRef","pendingPush","mpaNavigation","preserveCustomHistoryState","focusAndScrollRef","prefetchCache","nextUrl","pathname"],"mappings":";;;;+BASgBA;;;eAAAA;;;mCATkB;oCAMe;gCACI;AAE9C,SAASA,eACdC,KAA2B,EAC3BC,MAAqB;IAErB,MAAM,EAAEC,GAAG,EAAEC,IAAI,EAAE,GAAGF;IACtB,MAAMG,OAAOC,IAAAA,oCAAiB,EAACH;IAC/B,0EAA0E;IAC1E,4FAA4F;IAC5F,gGAAgG;IAChG,6FAA6F;IAC7F,8DAA8D;IAC9D,yGAAyG;IACzG,MAAMI,gBAAgBH,QAAQH,MAAMG,IAAI;IAExC,MAAMI,WAAWP,MAAMQ,KAAK;IAC5B,MAAMC,WAAWC,QAAQC,GAAG,CAACC,UAAU,GAEnC,qEAAqE;IACrE,2DAA2D;IAC3D,2BAA2B;IAC3BC,IAAAA,oDAAoC,EAACN,UAAUD,iBAC/CC;QAiBOO;IAfX,OAAO;QACLC,SAASf,MAAMe,OAAO;QACtB,oBAAoB;QACpBC,cAAcZ;QACda,SAAS;YACPC,aAAa;YACbC,eAAe;YACf,6FAA6F;YAC7FC,4BAA4B;QAC9B;QACAC,mBAAmBrB,MAAMqB,iBAAiB;QAC1Cb,OAAOC;QACPa,eAAetB,MAAMsB,aAAa;QAClC,wBAAwB;QACxBnB,MAAMG;QACNiB,SAAST,CAAAA,oCAAAA,IAAAA,oDAAgC,EAACR,0BAAjCQ,oCAAmDZ,IAAIsB,QAAQ;IAC1E;AACF"}

View File

@ -0,0 +1,2 @@
import type { ReadonlyReducerState, ReducerState, ServerActionAction } from '../router-reducer-types';
export declare function serverActionReducer(state: ReadonlyReducerState, action: ServerActionAction): ReducerState;

View File

@ -0,0 +1,188 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "serverActionReducer", {
enumerable: true,
get: function() {
return serverActionReducer;
}
});
const _appcallserver = require("../../../app-call-server");
const _approuterheaders = require("../../app-router-headers");
const _addbasepath = require("../../../add-base-path");
const _createhreffromurl = require("../create-href-from-url");
const _navigatereducer = require("./navigate-reducer");
const _applyrouterstatepatchtotree = require("../apply-router-state-patch-to-tree");
const _isnavigatingtonewrootlayout = require("../is-navigating-to-new-root-layout");
const _handlemutable = require("../handle-mutable");
const _filllazyitemstillleafwithhead = require("../fill-lazy-items-till-leaf-with-head");
const _approuter = require("../../app-router");
const _hasinterceptionrouteincurrenttree = require("./has-interception-route-in-current-tree");
const _handlesegmentmismatch = require("../handle-segment-mismatch");
const _refetchinactiveparallelsegments = require("../refetch-inactive-parallel-segments");
// // eslint-disable-next-line import/no-extraneous-dependencies
// import { createFromFetch } from 'react-server-dom-webpack/client'
// // eslint-disable-next-line import/no-extraneous-dependencies
// import { encodeReply } from 'react-server-dom-webpack/client'
const { createFromFetch, encodeReply } = !!process.env.NEXT_RUNTIME ? require("react-server-dom-webpack/client.edge") : require("react-server-dom-webpack/client");
async function fetchServerAction(state, nextUrl, param) {
let { actionId, actionArgs } = param;
const body = await encodeReply(actionArgs);
const res = await fetch("", {
method: "POST",
headers: {
Accept: _approuterheaders.RSC_CONTENT_TYPE_HEADER,
[_approuterheaders.ACTION]: actionId,
[_approuterheaders.NEXT_ROUTER_STATE_TREE]: encodeURIComponent(JSON.stringify(state.tree)),
...process.env.NEXT_DEPLOYMENT_ID ? {
"x-deployment-id": process.env.NEXT_DEPLOYMENT_ID
} : {},
...nextUrl ? {
[_approuterheaders.NEXT_URL]: nextUrl
} : {}
},
body
});
const location = res.headers.get("x-action-redirect");
let revalidatedParts;
try {
const revalidatedHeader = JSON.parse(res.headers.get("x-action-revalidated") || "[[],0,0]");
revalidatedParts = {
paths: revalidatedHeader[0] || [],
tag: !!revalidatedHeader[1],
cookie: revalidatedHeader[2]
};
} catch (e) {
revalidatedParts = {
paths: [],
tag: false,
cookie: false
};
}
const redirectLocation = location ? new URL((0, _addbasepath.addBasePath)(location), // Ensure relative redirects in Server Actions work, e.g. redirect('./somewhere-else')
new URL(state.canonicalUrl, window.location.href)) : undefined;
let isFlightResponse = res.headers.get("content-type") === _approuterheaders.RSC_CONTENT_TYPE_HEADER;
if (isFlightResponse) {
const response = await createFromFetch(Promise.resolve(res), {
callServer: _appcallserver.callServer
});
if (location) {
// if it was a redirection, then result is just a regular RSC payload
const [, actionFlightData] = response != null ? response : [];
return {
actionFlightData: actionFlightData,
redirectLocation,
revalidatedParts
};
}
// otherwise it's a tuple of [actionResult, actionFlightData]
const [actionResult, [, actionFlightData]] = response != null ? response : [];
return {
actionResult,
actionFlightData,
redirectLocation,
revalidatedParts
};
}
return {
redirectLocation,
revalidatedParts
};
}
function serverActionReducer(state, action) {
const { resolve, reject } = action;
const mutable = {};
const href = state.canonicalUrl;
let currentTree = state.tree;
mutable.preserveCustomHistoryState = false;
// only pass along the `nextUrl` param (used for interception routes) if the current route was intercepted.
// If the route has been intercepted, the action should be as well.
// Otherwise the server action might be intercepted with the wrong action id
// (ie, one that corresponds with the intercepted route)
const nextUrl = state.nextUrl && (0, _hasinterceptionrouteincurrenttree.hasInterceptionRouteInCurrentTree)(state.tree) ? state.nextUrl : null;
mutable.inFlightServerAction = fetchServerAction(state, nextUrl, action);
return mutable.inFlightServerAction.then(async (param)=>{
let { actionResult, actionFlightData: flightData, redirectLocation } = param;
// Make sure the redirection is a push instead of a replace.
// Issue: https://github.com/vercel/next.js/issues/53911
if (redirectLocation) {
state.pushRef.pendingPush = true;
mutable.pendingPush = true;
}
if (!flightData) {
resolve(actionResult);
// If there is a redirect but no flight data we need to do a mpaNavigation.
if (redirectLocation) {
return (0, _navigatereducer.handleExternalUrl)(state, mutable, redirectLocation.href, state.pushRef.pendingPush);
}
return state;
}
if (typeof flightData === "string") {
// Handle case when navigating to page in `pages` from `app`
return (0, _navigatereducer.handleExternalUrl)(state, mutable, flightData, state.pushRef.pendingPush);
}
// Remove cache.data as it has been resolved at this point.
mutable.inFlightServerAction = null;
if (redirectLocation) {
const newHref = (0, _createhreffromurl.createHrefFromUrl)(redirectLocation, false);
mutable.canonicalUrl = newHref;
}
for (const flightDataPath of flightData){
// FlightDataPath with more than two items means unexpected Flight data was returned
if (flightDataPath.length !== 3) {
// TODO-APP: handle this case better
console.log("SERVER ACTION APPLY FAILED");
return state;
}
// Given the path can only have two items the items are only the router state and rsc for the root.
const [treePatch] = flightDataPath;
const newTree = (0, _applyrouterstatepatchtotree.applyRouterStatePatchToTree)(// TODO-APP: remove ''
[
""
], currentTree, treePatch, redirectLocation ? (0, _createhreffromurl.createHrefFromUrl)(redirectLocation) : state.canonicalUrl);
if (newTree === null) {
return (0, _handlesegmentmismatch.handleSegmentMismatch)(state, action, treePatch);
}
if ((0, _isnavigatingtonewrootlayout.isNavigatingToNewRootLayout)(currentTree, newTree)) {
return (0, _navigatereducer.handleExternalUrl)(state, mutable, href, state.pushRef.pendingPush);
}
// The one before last item is the router state tree patch
const [cacheNodeSeedData, head] = flightDataPath.slice(-2);
const rsc = cacheNodeSeedData !== null ? cacheNodeSeedData[2] : null;
// Handles case where prefetch only returns the router tree patch without rendered components.
if (rsc !== null) {
const cache = (0, _approuter.createEmptyCacheNode)();
cache.rsc = rsc;
cache.prefetchRsc = null;
(0, _filllazyitemstillleafwithhead.fillLazyItemsTillLeafWithHead)(cache, // Existing cache is not passed in as `router.refresh()` has to invalidate the entire cache.
undefined, treePatch, cacheNodeSeedData, head);
await (0, _refetchinactiveparallelsegments.refreshInactiveParallelSegments)({
state,
updatedTree: newTree,
updatedCache: cache,
includeNextUrl: Boolean(nextUrl),
canonicalUrl: mutable.canonicalUrl || state.canonicalUrl
});
mutable.cache = cache;
mutable.prefetchCache = new Map();
}
mutable.patchedTree = newTree;
currentTree = newTree;
}
resolve(actionResult);
return (0, _handlemutable.handleMutable)(state, mutable);
}, (e)=>{
// When the server action is rejected we don't update the state and instead call the reject handler of the promise.
reject(e);
return state;
});
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=server-action-reducer.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
import type { ServerPatchAction, ReducerState, ReadonlyReducerState } from '../router-reducer-types';
export declare function serverPatchReducer(state: ReadonlyReducerState, action: ServerPatchAction): ReducerState;

View File

@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "serverPatchReducer", {
enumerable: true,
get: function() {
return serverPatchReducer;
}
});
const _createhreffromurl = require("../create-href-from-url");
const _applyrouterstatepatchtotree = require("../apply-router-state-patch-to-tree");
const _isnavigatingtonewrootlayout = require("../is-navigating-to-new-root-layout");
const _navigatereducer = require("./navigate-reducer");
const _applyflightdata = require("../apply-flight-data");
const _handlemutable = require("../handle-mutable");
const _approuter = require("../../app-router");
const _handlesegmentmismatch = require("../handle-segment-mismatch");
function serverPatchReducer(state, action) {
const { serverResponse } = action;
const [flightData, overrideCanonicalUrl] = serverResponse;
const mutable = {};
mutable.preserveCustomHistoryState = false;
// Handle case when navigating to page in `pages` from `app`
if (typeof flightData === "string") {
return (0, _navigatereducer.handleExternalUrl)(state, mutable, flightData, state.pushRef.pendingPush);
}
let currentTree = state.tree;
let currentCache = state.cache;
for (const flightDataPath of flightData){
// Slices off the last segment (which is at -4) as it doesn't exist in the tree yet
const flightSegmentPath = flightDataPath.slice(0, -4);
const [treePatch] = flightDataPath.slice(-3, -2);
const newTree = (0, _applyrouterstatepatchtotree.applyRouterStatePatchToTree)(// TODO-APP: remove ''
[
"",
...flightSegmentPath
], currentTree, treePatch, state.canonicalUrl);
if (newTree === null) {
return (0, _handlesegmentmismatch.handleSegmentMismatch)(state, action, treePatch);
}
if ((0, _isnavigatingtonewrootlayout.isNavigatingToNewRootLayout)(currentTree, newTree)) {
return (0, _navigatereducer.handleExternalUrl)(state, mutable, state.canonicalUrl, state.pushRef.pendingPush);
}
const canonicalUrlOverrideHref = overrideCanonicalUrl ? (0, _createhreffromurl.createHrefFromUrl)(overrideCanonicalUrl) : undefined;
if (canonicalUrlOverrideHref) {
mutable.canonicalUrl = canonicalUrlOverrideHref;
}
const cache = (0, _approuter.createEmptyCacheNode)();
(0, _applyflightdata.applyFlightData)(currentCache, cache, flightDataPath);
mutable.patchedTree = newTree;
mutable.cache = cache;
currentCache = cache;
currentTree = newTree;
}
return (0, _handlemutable.handleMutable)(state, mutable);
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=server-patch-reducer.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["../../../../../src/client/components/router-reducer/reducers/server-patch-reducer.ts"],"names":["serverPatchReducer","state","action","serverResponse","flightData","overrideCanonicalUrl","mutable","preserveCustomHistoryState","handleExternalUrl","pushRef","pendingPush","currentTree","tree","currentCache","cache","flightDataPath","flightSegmentPath","slice","treePatch","newTree","applyRouterStatePatchToTree","canonicalUrl","handleSegmentMismatch","isNavigatingToNewRootLayout","canonicalUrlOverrideHref","createHrefFromUrl","undefined","createEmptyCacheNode","applyFlightData","patchedTree","handleMutable"],"mappings":";;;;+BAgBgBA;;;eAAAA;;;mCAhBkB;6CACU;6CACA;iCAOV;iCACF;+BACF;2BAEO;uCACC;AAE/B,SAASA,mBACdC,KAA2B,EAC3BC,MAAyB;IAEzB,MAAM,EAAEC,cAAc,EAAE,GAAGD;IAC3B,MAAM,CAACE,YAAYC,qBAAqB,GAAGF;IAE3C,MAAMG,UAAmB,CAAC;IAE1BA,QAAQC,0BAA0B,GAAG;IAErC,4DAA4D;IAC5D,IAAI,OAAOH,eAAe,UAAU;QAClC,OAAOI,IAAAA,kCAAiB,EACtBP,OACAK,SACAF,YACAH,MAAMQ,OAAO,CAACC,WAAW;IAE7B;IAEA,IAAIC,cAAcV,MAAMW,IAAI;IAC5B,IAAIC,eAAeZ,MAAMa,KAAK;IAE9B,KAAK,MAAMC,kBAAkBX,WAAY;QACvC,mFAAmF;QACnF,MAAMY,oBAAoBD,eAAeE,KAAK,CAAC,GAAG,CAAC;QAEnD,MAAM,CAACC,UAAU,GAAGH,eAAeE,KAAK,CAAC,CAAC,GAAG,CAAC;QAC9C,MAAME,UAAUC,IAAAA,wDAA2B,EACzC,sBAAsB;QACtB;YAAC;eAAOJ;SAAkB,EAC1BL,aACAO,WACAjB,MAAMoB,YAAY;QAGpB,IAAIF,YAAY,MAAM;YACpB,OAAOG,IAAAA,4CAAqB,EAACrB,OAAOC,QAAQgB;QAC9C;QAEA,IAAIK,IAAAA,wDAA2B,EAACZ,aAAaQ,UAAU;YACrD,OAAOX,IAAAA,kCAAiB,EACtBP,OACAK,SACAL,MAAMoB,YAAY,EAClBpB,MAAMQ,OAAO,CAACC,WAAW;QAE7B;QAEA,MAAMc,2BAA2BnB,uBAC7BoB,IAAAA,oCAAiB,EAACpB,wBAClBqB;QAEJ,IAAIF,0BAA0B;YAC5BlB,QAAQe,YAAY,GAAGG;QACzB;QAEA,MAAMV,QAAmBa,IAAAA,+BAAoB;QAC7CC,IAAAA,gCAAe,EAACf,cAAcC,OAAOC;QAErCT,QAAQuB,WAAW,GAAGV;QACtBb,QAAQQ,KAAK,GAAGA;QAEhBD,eAAeC;QACfH,cAAcQ;IAChB;IAEA,OAAOW,IAAAA,4BAAa,EAAC7B,OAAOK;AAC9B"}