Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@remix-run/react

Package Overview
Dependencies
Maintainers
0
Versions
1029
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@remix-run/react - npm Package Compare versions

Comparing version 0.0.0-nightly-6f23bc960-20240821 to 0.0.0-nightly-6f8288990-20241030

2

dist/_virtual/_rollupPluginBabelHelpers.js
/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

@@ -24,2 +24,3 @@ import type { HydrationState, Router } from "@remix-run/router";

var __remixRevalidation: number | undefined;
var __remixHdrActive: boolean;
var __remixClearCriticalCss: (() => void) | undefined;

@@ -26,0 +27,0 @@ var $RefreshRuntime$: {

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -77,3 +77,3 @@ * Copyright (c) Remix Software Inc.

// snapshot is decoded into window.__remixContext.state
if (window.__remixContext.future.unstable_singleFetch) {
if (window.__remixContext.future.v3_singleFetch) {
// Note: `stateDecodingPromise` is not coupled to `router` - we'll reach this

@@ -155,8 +155,8 @@ // code potentially many times waiting for our state to arrive, but we'll

// Single fetch enables this underlying behavior
v7_skipActionErrorRevalidation: window.__remixContext.future.unstable_singleFetch === true
v7_skipActionErrorRevalidation: window.__remixContext.future.v3_singleFetch === true
},
hydrationData,
mapRouteProperties: reactRouter.UNSAFE_mapRouteProperties,
unstable_dataStrategy: window.__remixContext.future.unstable_singleFetch ? singleFetch.getSingleFetchDataStrategy(window.__remixManifest, window.__remixRouteModules) : undefined,
unstable_patchRoutesOnNavigation: fogOfWar.getPatchRoutesOnNavigationFunction(window.__remixManifest, window.__remixRouteModules, window.__remixContext.future, window.__remixContext.isSpaMode, window.__remixContext.basename)
dataStrategy: window.__remixContext.future.v3_singleFetch ? singleFetch.getSingleFetchDataStrategy(window.__remixManifest, window.__remixRouteModules, () => router) : undefined,
patchRoutesOnNavigation: fogOfWar.getPatchRoutesOnNavigationFunction(window.__remixManifest, window.__remixRouteModules, window.__remixContext.future, window.__remixContext.isSpaMode, window.__remixContext.basename)
});

@@ -236,3 +236,3 @@

}
}))), window.__remixContext.future.unstable_singleFetch ? /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null) : null)
}))), window.__remixContext.future.v3_singleFetch ? /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null) : null)
);

@@ -239,0 +239,0 @@ }

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -328,7 +328,46 @@ * Copyright (c) Remix Software Inc.

let {
loaderData,
matches
} = useDataRouterStateContext();
let newMatchesForData = React__namespace.useMemo(() => links.getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "data"), [page, nextMatches, matches, manifest, location]);
let newMatchesForAssets = React__namespace.useMemo(() => links.getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "assets"), [page, nextMatches, matches, manifest, location]);
let dataHrefs = React__namespace.useMemo(() => links.getDataLinkHrefs(page, newMatchesForData, manifest), [newMatchesForData, page, manifest]);
let newMatchesForData = React__namespace.useMemo(() => links.getNewMatchesForLinks(page, nextMatches, matches, manifest, location, future, "data"), [page, nextMatches, matches, manifest, location, future]);
let dataHrefs = React__namespace.useMemo(() => {
if (!future.v3_singleFetch) {
return links.getDataLinkHrefs(page, newMatchesForData, manifest);
}
if (page === location.pathname + location.search + location.hash) {
// Because we opt-into revalidation, don't compute this for the current page
// since it would always trigger a prefetch of the existing loaders
return [];
}
// Single-fetch is harder :)
// This parallels the logic in the single fetch data strategy
let routesParams = new Set();
let foundOptOutRoute = false;
nextMatches.forEach(m => {
var _routeModules$m$route;
if (!manifest.routes[m.route.id].hasLoader) {
return;
}
if (!newMatchesForData.some(m2 => m2.route.id === m.route.id) && m.route.id in loaderData && (_routeModules$m$route = routeModules[m.route.id]) !== null && _routeModules$m$route !== void 0 && _routeModules$m$route.shouldRevalidate) {
foundOptOutRoute = true;
} else if (manifest.routes[m.route.id].hasClientLoader) {
foundOptOutRoute = true;
} else {
routesParams.add(m.route.id);
}
});
if (routesParams.size === 0) {
return [];
}
let url = singleFetch.singleFetchUrl(page);
// When one or more routes have opted out, we add a _routes param to
// limit the loaders to those that have a server loader and did not
// opt out
if (foundOptOutRoute && routesParams.size > 0) {
url.searchParams.set("_routes", nextMatches.filter(m => routesParams.has(m.route.id)).map(m => m.route.id).join(","));
}
return [url.pathname + url.search];
}, [future.v3_singleFetch, loaderData, location, manifest, newMatchesForData, nextMatches, page, routeModules]);
let newMatchesForAssets = React__namespace.useMemo(() => links.getNewMatchesForLinks(page, nextMatches, matches, manifest, location, future, "assets"), [page, nextMatches, matches, manifest, location, future]);
let moduleHrefs = React__namespace.useMemo(() => links.getModuleLinkHrefs(newMatchesForAssets, manifest), [newMatchesForAssets, manifest]);

@@ -339,25 +378,9 @@

let keyedPrefetchLinks = useKeyedPrefetchLinks(newMatchesForAssets);
let linksToRender = null;
if (!future.unstable_singleFetch) {
// Non-single-fetch prefetching
linksToRender = dataHrefs.map(href => /*#__PURE__*/React__namespace.createElement("link", _rollupPluginBabelHelpers["extends"]({
key: href,
rel: "prefetch",
as: "fetch",
href: href
}, linkProps)));
} else if (newMatchesForData.length > 0) {
// Single-fetch with routes that require data
let url = singleFetch.addRevalidationParam(manifest, routeModules, nextMatches.map(m => m.route), newMatchesForData.map(m => m.route), singleFetch.singleFetchUrl(page));
if (url.searchParams.get("_routes") !== "") {
linksToRender = /*#__PURE__*/React__namespace.createElement("link", _rollupPluginBabelHelpers["extends"]({
key: url.pathname + url.search,
rel: "prefetch",
as: "fetch",
href: url.pathname + url.search
}, linkProps));
}
} else ;
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, linksToRender, moduleHrefs.map(href => /*#__PURE__*/React__namespace.createElement("link", _rollupPluginBabelHelpers["extends"]({
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, dataHrefs.map(href => /*#__PURE__*/React__namespace.createElement("link", _rollupPluginBabelHelpers["extends"]({
key: href,
rel: "prefetch",
as: "fetch",
href: href
}, linkProps))), moduleHrefs.map(href => /*#__PURE__*/React__namespace.createElement("link", _rollupPluginBabelHelpers["extends"]({
key: href,
rel: "modulepreload",

@@ -583,3 +606,3 @@ href: href

var _manifest$hmr;
let streamScript = future.unstable_singleFetch ?
let streamScript = future.v3_singleFetch ?
// prettier-ignore

@@ -590,3 +613,3 @@ "window.__remixContext.stream = new ReadableStream({" + "start(controller){" + "window.__remixContext.streamController = controller;" + "}" + "}).pipeThrough(new TextEncoderStream());" : "";

// When single fetch is enabled, deferred is handled by turbo-stream
let activeDeferreds = future.unstable_singleFetch ? undefined : staticContext === null || staticContext === void 0 ? void 0 : staticContext.activeDeferreds;
let activeDeferreds = future.v3_singleFetch ? undefined : staticContext === null || staticContext === void 0 ? void 0 : staticContext.activeDeferreds;

@@ -593,0 +616,0 @@ // This sets up the __remixContext with utility functions used by the

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

@@ -35,4 +35,4 @@ import type { StaticHandlerContext } from "@remix-run/router";

v3_relativeSplatPath: boolean;
unstable_lazyRouteDiscovery: boolean;
unstable_singleFetch: boolean;
v3_lazyRouteDiscovery: boolean;
v3_singleFetch: boolean;
}

@@ -39,0 +39,0 @@ export interface AssetsManifest {

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -117,3 +117,3 @@ * Copyright (c) Remix Software Inc.

// snapshot is decoded into window.__remixContext.state
if (window.__remixContext.future.unstable_singleFetch) {
if (window.__remixContext.future.v3_singleFetch) {
// Note: `stateDecodingPromise` is not coupled to `router` - we'll reach this

@@ -195,8 +195,8 @@ // code potentially many times waiting for our state to arrive, but we'll

// Single fetch enables this underlying behavior
v7_skipActionErrorRevalidation: window.__remixContext.future.unstable_singleFetch === true
v7_skipActionErrorRevalidation: window.__remixContext.future.v3_singleFetch === true
},
hydrationData,
mapRouteProperties: UNSAFE_mapRouteProperties,
unstable_dataStrategy: window.__remixContext.future.unstable_singleFetch ? getSingleFetchDataStrategy(window.__remixManifest, window.__remixRouteModules) : undefined,
unstable_patchRoutesOnNavigation: getPatchRoutesOnNavigationFunction(window.__remixManifest, window.__remixRouteModules, window.__remixContext.future, window.__remixContext.isSpaMode, window.__remixContext.basename)
dataStrategy: window.__remixContext.future.v3_singleFetch ? getSingleFetchDataStrategy(window.__remixManifest, window.__remixRouteModules, () => router) : undefined,
patchRoutesOnNavigation: getPatchRoutesOnNavigationFunction(window.__remixManifest, window.__remixRouteModules, window.__remixContext.future, window.__remixContext.isSpaMode, window.__remixContext.basename)
});

@@ -276,3 +276,3 @@

}
}))), window.__remixContext.future.unstable_singleFetch ? /*#__PURE__*/React.createElement(React.Fragment, null) : null)
}))), window.__remixContext.future.v3_singleFetch ? /*#__PURE__*/React.createElement(React.Fragment, null) : null)
);

@@ -279,0 +279,0 @@ }

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -17,3 +17,3 @@ * Copyright (c) Remix Software Inc.

import { escapeHtml, createHtml } from './markup.js';
import { addRevalidationParam, singleFetchUrl } from './single-fetch.js';
import { singleFetchUrl } from './single-fetch.js';
import { isFogOfWarEnabled, getPartialManifest } from './fog-of-war.js';

@@ -305,7 +305,46 @@

let {
loaderData,
matches
} = useDataRouterStateContext();
let newMatchesForData = React.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "data"), [page, nextMatches, matches, manifest, location]);
let newMatchesForAssets = React.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, "assets"), [page, nextMatches, matches, manifest, location]);
let dataHrefs = React.useMemo(() => getDataLinkHrefs(page, newMatchesForData, manifest), [newMatchesForData, page, manifest]);
let newMatchesForData = React.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, future, "data"), [page, nextMatches, matches, manifest, location, future]);
let dataHrefs = React.useMemo(() => {
if (!future.v3_singleFetch) {
return getDataLinkHrefs(page, newMatchesForData, manifest);
}
if (page === location.pathname + location.search + location.hash) {
// Because we opt-into revalidation, don't compute this for the current page
// since it would always trigger a prefetch of the existing loaders
return [];
}
// Single-fetch is harder :)
// This parallels the logic in the single fetch data strategy
let routesParams = new Set();
let foundOptOutRoute = false;
nextMatches.forEach(m => {
var _routeModules$m$route;
if (!manifest.routes[m.route.id].hasLoader) {
return;
}
if (!newMatchesForData.some(m2 => m2.route.id === m.route.id) && m.route.id in loaderData && (_routeModules$m$route = routeModules[m.route.id]) !== null && _routeModules$m$route !== void 0 && _routeModules$m$route.shouldRevalidate) {
foundOptOutRoute = true;
} else if (manifest.routes[m.route.id].hasClientLoader) {
foundOptOutRoute = true;
} else {
routesParams.add(m.route.id);
}
});
if (routesParams.size === 0) {
return [];
}
let url = singleFetchUrl(page);
// When one or more routes have opted out, we add a _routes param to
// limit the loaders to those that have a server loader and did not
// opt out
if (foundOptOutRoute && routesParams.size > 0) {
url.searchParams.set("_routes", nextMatches.filter(m => routesParams.has(m.route.id)).map(m => m.route.id).join(","));
}
return [url.pathname + url.search];
}, [future.v3_singleFetch, loaderData, location, manifest, newMatchesForData, nextMatches, page, routeModules]);
let newMatchesForAssets = React.useMemo(() => getNewMatchesForLinks(page, nextMatches, matches, manifest, location, future, "assets"), [page, nextMatches, matches, manifest, location, future]);
let moduleHrefs = React.useMemo(() => getModuleLinkHrefs(newMatchesForAssets, manifest), [newMatchesForAssets, manifest]);

@@ -316,25 +355,9 @@

let keyedPrefetchLinks = useKeyedPrefetchLinks(newMatchesForAssets);
let linksToRender = null;
if (!future.unstable_singleFetch) {
// Non-single-fetch prefetching
linksToRender = dataHrefs.map(href => /*#__PURE__*/React.createElement("link", _extends({
key: href,
rel: "prefetch",
as: "fetch",
href: href
}, linkProps)));
} else if (newMatchesForData.length > 0) {
// Single-fetch with routes that require data
let url = addRevalidationParam(manifest, routeModules, nextMatches.map(m => m.route), newMatchesForData.map(m => m.route), singleFetchUrl(page));
if (url.searchParams.get("_routes") !== "") {
linksToRender = /*#__PURE__*/React.createElement("link", _extends({
key: url.pathname + url.search,
rel: "prefetch",
as: "fetch",
href: url.pathname + url.search
}, linkProps));
}
} else ;
return /*#__PURE__*/React.createElement(React.Fragment, null, linksToRender, moduleHrefs.map(href => /*#__PURE__*/React.createElement("link", _extends({
return /*#__PURE__*/React.createElement(React.Fragment, null, dataHrefs.map(href => /*#__PURE__*/React.createElement("link", _extends({
key: href,
rel: "prefetch",
as: "fetch",
href: href
}, linkProps))), moduleHrefs.map(href => /*#__PURE__*/React.createElement("link", _extends({
key: href,
rel: "modulepreload",

@@ -560,3 +583,3 @@ href: href

var _manifest$hmr;
let streamScript = future.unstable_singleFetch ?
let streamScript = future.v3_singleFetch ?
// prettier-ignore

@@ -567,3 +590,3 @@ "window.__remixContext.stream = new ReadableStream({" + "start(controller){" + "window.__remixContext.streamController = controller;" + "}" + "}).pipeThrough(new TextEncoderStream());" : "";

// When single fetch is enabled, deferred is handled by turbo-stream
let activeDeferreds = future.unstable_singleFetch ? undefined : staticContext === null || staticContext === void 0 ? void 0 : staticContext.activeDeferreds;
let activeDeferreds = future.v3_singleFetch ? undefined : staticContext === null || staticContext === void 0 ? void 0 : staticContext.activeDeferreds;

@@ -570,0 +593,0 @@ // This sets up the __remixContext with utility functions used by the

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -27,4 +27,5 @@ * Copyright (c) Remix Software Inc.

"💿 Hey developer 👋. You can provide a way better UX than this " +
"when your app is running \`clientLoader\` functions on hydration. " +
"Check out https://remix.run/route/hydrate-fallback for more information."
"when your app is loading JS modules and/or running \`clientLoader\` " +
"functions. Check out https://remix.run/route/hydrate-fallback " +
"for more information."
);

@@ -31,0 +32,0 @@ `

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -27,3 +27,3 @@ * Copyright (c) Remix Software Inc.

function isFogOfWarEnabled(future, isSpaMode) {
return future.unstable_lazyRouteDiscovery === true && !isSpaMode;
return future.v3_lazyRouteDiscovery === true && !isSpaMode;
}

@@ -30,0 +30,0 @@ function getPartialManifest(manifest, router) {

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -11,4 +11,4 @@ * Copyright (c) Remix Software Inc.

*/
export { Navigate, NavigationType, Outlet, Route, Routes, createPath, createRoutesFromChildren, createRoutesFromElements, createSearchParams, generatePath, isRouteErrorResponse, matchPath, matchRoutes, parsePath, renderMatches, resolvePath, unstable_usePrompt, unstable_useViewTransitionState, useAsyncError, useAsyncValue, useBeforeUnload, useBlocker, useFetchers, useFormAction, useHref, useInRouterContext, useLinkClickHandler, useLocation, useMatch, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRoutes, useSearchParams, useSubmit } from 'react-router-dom';
export { defer, json, redirect, redirectDocument, replace, unstable_data } from '@remix-run/server-runtime';
export { Navigate, NavigationType, Outlet, Route, Routes, createPath, createRoutesFromChildren, createRoutesFromElements, createSearchParams, generatePath, isRouteErrorResponse, matchPath, matchRoutes, parsePath, renderMatches, resolvePath, unstable_usePrompt, useAsyncError, useAsyncValue, useBeforeUnload, useBlocker, useFetchers, useFormAction, useHref, useInRouterContext, useLinkClickHandler, useLocation, useMatch, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRoutes, useSearchParams, useSubmit, useViewTransitionState } from 'react-router-dom';
export { data, defer, json, redirect, redirectDocument, replace } from '@remix-run/server-runtime';
export { RemixBrowser } from './browser.js';

@@ -18,2 +18,1 @@ export { Await, Form, Link, Links, LiveReload, Meta, NavLink, PrefetchPageLinks, Scripts, RemixContext as UNSAFE_RemixContext, useActionData, useFetcher, useLoaderData, useMatches, useRouteLoaderData } from './components.js';

export { RemixServer } from './server.js';
export { defineClientAction as unstable_defineClientAction, defineClientLoader as unstable_defineClientLoader } from './single-fetch.js';
/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -120,3 +120,3 @@ * Copyright (c) Remix Software Inc.

// This is ridiculously identical to transition.ts `filterMatchesToLoad`
function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, location, mode) {
function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, location, future, mode) {
let path = parsePathPatch(page);

@@ -140,3 +140,3 @@ let isNew = (match, index) => {

// version doesn't care about submissions
let newMatches = mode === "data" && location.search !== path.search ?
let newMatches = mode === "data" && (future.v3_singleFetch || location.search !== path.search) ?
// this is really similar to stuff in transition.ts, maybe somebody smarter

@@ -152,2 +152,7 @@ // than me (or in less of a hurry) can share some of it. You're the best.

}
// For reused routes on GET navigations, by default:
// - Single fetch always revalidates
// - Multi fetch revalidates if search params changed
let defaultShouldRevalidate = future.v3_singleFetch || location.search !== path.search;
if (match.route.shouldRevalidate) {

@@ -160,3 +165,3 @@ var _currentMatches$;

nextParams: match.params,
defaultShouldRevalidate: true
defaultShouldRevalidate
});

@@ -167,3 +172,3 @@ if (typeof routeChoice === "boolean") {

}
return true;
return defaultShouldRevalidate;
}) : nextMatches.filter((match, index) => {

@@ -170,0 +175,0 @@ let manifestRoute = manifest.routes[match.route.id];

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -174,3 +174,3 @@ * Copyright (c) Remix Software Inc.

handle: routeModule.handle,
shouldRevalidate: needsRevalidation ? wrapShouldRevalidateForHdr(route.id, routeModule.shouldRevalidate, needsRevalidation) : routeModule.shouldRevalidate
shouldRevalidate: getShouldRevalidateFunction(future, routeModule, route.id, needsRevalidation)
});

@@ -200,6 +200,9 @@ let initialData = initialState === null || initialState === void 0 ? void 0 : (_initialState$loaderD = initialState.loaderData) === null || _initialState$loaderD === void 0 ? void 0 : _initialState$loaderD[route.id];

if (isHydrationRequest) {
if (initialData !== undefined) {
return initialData;
}
if (initialError !== undefined) {
throw initialError;
}
return initialData;
return null;
}

@@ -293,5 +296,2 @@

}
if (needsRevalidation) {
lazyRoute.shouldRevalidate = wrapShouldRevalidateForHdr(route.id, mod.shouldRevalidate, needsRevalidation);
}
return {

@@ -305,3 +305,3 @@ ...(lazyRoute.loader ? {

hasErrorBoundary: lazyRoute.hasErrorBoundary,
shouldRevalidate: lazyRoute.shouldRevalidate,
shouldRevalidate: getShouldRevalidateFunction(future, lazyRoute, route.id, needsRevalidation),
handle: lazyRoute.handle,

@@ -320,3 +320,20 @@ // No need to wrap these in layout since the root route is never

}
function getShouldRevalidateFunction(future, route, routeId, needsRevalidation) {
// During HDR we force revalidation for updated routes
if (needsRevalidation) {
return wrapShouldRevalidateForHdr(routeId, route.shouldRevalidate, needsRevalidation);
}
// Single fetch revalidates by default, so override the RR default value which
// matches the multi-fetch behavior with `true`
if (future.v3_singleFetch && route.shouldRevalidate) {
let fn = route.shouldRevalidate;
return opts => fn({
...opts,
defaultShouldRevalidate: true
});
}
return route.shouldRevalidate;
}
// When an HMR / HDR update happens we opt out of all user-defined

@@ -323,0 +340,0 @@ // revalidation logic and force a revalidation on the first call

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -84,3 +84,3 @@ * Copyright (c) Remix Software Inc.

hydrate: false
}))), context.future.unstable_singleFetch && context.serverHandoffStream ? /*#__PURE__*/React.createElement(React.Suspense, null, /*#__PURE__*/React.createElement(StreamTransfer, {
}))), context.future.v3_singleFetch && context.serverHandoffStream ? /*#__PURE__*/React.createElement(React.Suspense, null, /*#__PURE__*/React.createElement(StreamTransfer, {
context: context,

@@ -87,0 +87,0 @@ identifier: 0,

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -12,3 +12,3 @@ * Copyright (c) Remix Software Inc.

import * as React from 'react';
import { UNSAFE_ErrorResponseImpl, isRouteErrorResponse, unstable_data, redirect } from '@remix-run/router';
import { isRouteErrorResponse, data, UNSAFE_ErrorResponseImpl, redirect } from '@remix-run/router';
import { UNSAFE_SingleFetchRedirectSymbol } from '@remix-run/server-runtime';

@@ -20,9 +20,2 @@ import { decode } from 'turbo-stream';

// clientLoader
let defineClientLoader = clientLoader => clientLoader;
// clientAction
let defineClientAction = clientAction => clientAction;
// StreamTransfer recursively renders down chunks of the `serverHandoffStream`

@@ -94,40 +87,56 @@ // into the client-side `streamController`

}
function getSingleFetchDataStrategy(manifest, routeModules) {
function getSingleFetchDataStrategy(manifest, routeModules, getRouter) {
return async ({
request,
matches
}) => request.method !== "GET" ? singleFetchActionStrategy(request, matches) : singleFetchLoaderStrategy(manifest, routeModules, request, matches);
matches,
fetcherKey
}) => {
// Actions are simple and behave the same for navigations and fetchers
if (request.method !== "GET") {
return singleFetchActionStrategy(request, matches);
}
// Fetcher loads are singular calls to one loader
if (fetcherKey) {
return singleFetchLoaderFetcherStrategy(request, matches);
}
// Navigational loads are more complex...
return singleFetchLoaderNavigationStrategy(manifest, routeModules, getRouter(), request, matches);
};
}
// Actions are simple since they're singular calls to the server
function singleFetchActionStrategy(request, matches) {
return Promise.all(matches.map(async m => {
let actionStatus;
let result = await m.resolve(async handler => {
let result = await handler(async () => {
let url = singleFetchUrl(request.url);
let init = await createRequestInit(request);
let {
data,
status
} = await fetchAndDecode(url, init);
actionStatus = status;
return unwrapSingleFetchResult(data, m.route.id);
});
return {
type: "data",
result
};
// Actions are simple since they're singular calls to the server for both
// navigations and fetchers)
async function singleFetchActionStrategy(request, matches) {
let actionMatch = matches.find(m => m.shouldLoad);
invariant(actionMatch, "No action match found");
let actionStatus = undefined;
let result = await actionMatch.resolve(async handler => {
let result = await handler(async () => {
let url = singleFetchUrl(request.url);
let init = await createRequestInit(request);
let {
data,
status
} = await fetchAndDecode(url, init);
actionStatus = status;
return unwrapSingleFetchResult(data, actionMatch.route.id);
});
if (isResponse(result.result) || isRouteErrorResponse(result.result)) {
return result;
}
return result;
});
if (isResponse(result.result) || isRouteErrorResponse(result.result)) {
return {
[actionMatch.route.id]: result
};
}
// For non-responses, proxy along the statusCode via unstable_data()
// (most notably for skipping action error revalidation)
return {
// For non-responses, proxy along the statusCode via data()
// (most notably for skipping action error revalidation)
return {
[actionMatch.route.id]: {
type: result.type,
result: unstable_data(result.result, actionStatus)
};
}));
result: data(result.result, actionStatus)
}
};
}

@@ -137,37 +146,144 @@

// create a singular promise for all server-loader routes to latch onto.
function singleFetchLoaderStrategy(manifest, routeModules, request, matches) {
let singleFetchPromise;
return Promise.all(matches.map(async m => m.resolve(async handler => {
let result;
let url = stripIndexParam(singleFetchUrl(request.url));
let init = await createRequestInit(request);
async function singleFetchLoaderNavigationStrategy(manifest, routeModules, router, request, matches) {
// Track which routes need a server load - in case we need to tack on a
// `_routes` param
let routesParams = new Set();
// When a route has a client loader, it calls it's singular server loader
// We only add `_routes` when one or more routes opts out of a load via
// `shouldRevalidate` or `clientLoader`
let foundOptOutRoute = false;
// Deferreds for each route so we can be sure they've all loaded via
// `match.resolve()`, and a singular promise that can tell us all routes
// have been resolved
let routeDfds = matches.map(() => createDeferred());
let routesLoadedPromise = Promise.all(routeDfds.map(d => d.promise));
// Deferred that we'll use for the call to the server that each match can
// await and parse out it's specific result
let singleFetchDfd = createDeferred();
// Base URL and RequestInit for calls to the server
let url = stripIndexParam(singleFetchUrl(request.url));
let init = await createRequestInit(request);
// We'll build up this results object as we loop through matches
let results = {};
let resolvePromise = Promise.all(matches.map(async (m, i) => m.resolve(async handler => {
routeDfds[i].resolve();
if (!m.shouldLoad) {
var _routeModules$m$route;
// If we're not yet initialized and this is the initial load, respect
// `shouldLoad` because we're only dealing with `clientLoader.hydrate`
// routes which will fall into the `clientLoader` section below.
if (!router.state.initialized) {
return;
}
// Otherwise, we opt out if we currently have data, a `loader`, and a
// `shouldRevalidate` function. This implies that the user opted out
// via `shouldRevalidate`
if (m.route.id in router.state.loaderData && manifest.routes[m.route.id].hasLoader && (_routeModules$m$route = routeModules[m.route.id]) !== null && _routeModules$m$route !== void 0 && _routeModules$m$route.shouldRevalidate) {
foundOptOutRoute = true;
return;
}
}
// When a route has a client loader, it opts out of the singular call and
// calls it's server loader via `serverLoader()` using a `?_routes` param
if (manifest.routes[m.route.id].hasClientLoader) {
result = await handler(async () => {
url.searchParams.set("_routes", m.route.id);
let {
data
} = await fetchAndDecode(url, init);
if (manifest.routes[m.route.id].hasLoader) {
foundOptOutRoute = true;
}
try {
let result = await fetchSingleLoader(handler, url, init, m.route.id);
results[m.route.id] = {
type: "data",
result
};
} catch (e) {
results[m.route.id] = {
type: "error",
result: e
};
}
return;
}
// Load this route on the server if it has a loader
if (manifest.routes[m.route.id].hasLoader) {
routesParams.add(m.route.id);
}
// Lump this match in with the others on a singular promise
try {
let result = await handler(async () => {
let data = await singleFetchDfd.promise;
return unwrapSingleFetchResults(data, m.route.id);
});
} else {
result = await handler(async () => {
// Otherwise we let multiple routes hook onto the same promise
if (!singleFetchPromise) {
url = addRevalidationParam(manifest, routeModules, matches.map(m => m.route), matches.filter(m => m.shouldLoad).map(m => m.route), url);
singleFetchPromise = fetchAndDecode(url, init).then(({
data
}) => data);
}
let results = await singleFetchPromise;
return unwrapSingleFetchResults(results, m.route.id);
});
results[m.route.id] = {
type: "data",
result
};
} catch (e) {
results[m.route.id] = {
type: "error",
result: e
};
}
return {
type: "data",
result
};
})));
// Wait for all routes to resolve above before we make the HTTP call
await routesLoadedPromise;
// We can skip the server call:
// - On initial hydration - only clientLoaders can pass through via `clientLoader.hydrate`
// - If there are no routes to fetch from the server
//
// One exception - if we are performing an HDR revalidation we have to call
// the server in case a new loader has shown up that the manifest doesn't yet
// know about
if ((!router.state.initialized || routesParams.size === 0) && !window.__remixHdrActive) {
singleFetchDfd.resolve({});
} else {
try {
// When one or more routes have opted out, we add a _routes param to
// limit the loaders to those that have a server loader and did not
// opt out
if (foundOptOutRoute && routesParams.size > 0) {
url.searchParams.set("_routes", matches.filter(m => routesParams.has(m.route.id)).map(m => m.route.id).join(","));
}
let data = await fetchAndDecode(url, init);
singleFetchDfd.resolve(data.data);
} catch (e) {
singleFetchDfd.reject(e);
}
}
await resolvePromise;
return results;
}
// Fetcher loader calls are much simpler than navigational loader calls
async function singleFetchLoaderFetcherStrategy(request, matches) {
let fetcherMatch = matches.find(m => m.shouldLoad);
invariant(fetcherMatch, "No fetcher match found");
let result = await fetcherMatch.resolve(async handler => {
let url = stripIndexParam(singleFetchUrl(request.url));
let init = await createRequestInit(request);
return fetchSingleLoader(handler, url, init, fetcherMatch.route.id);
});
return {
[fetcherMatch.route.id]: result
};
}
function fetchSingleLoader(handler, url, init, routeId) {
return handler(async () => {
let singleLoaderUrl = new URL(url);
singleLoaderUrl.searchParams.set("_routes", routeId);
let {
data
} = await fetchAndDecode(singleLoaderUrl, init);
return unwrapSingleFetchResults(data, routeId);
});
}
function stripIndexParam(url) {

@@ -187,42 +303,2 @@ let indexValues = url.searchParams.getAll("index");

}
// Determine which routes we want to load so we can add a `?_routes` search param
// for fine-grained revalidation if necessary. There's some nuance to this decision:
//
// - The presence of `shouldRevalidate` and `clientLoader` functions are the only
// way to trigger fine-grained single fetch loader calls. without either of
// these on the route matches we just always ask for the full `.data` request.
// - If any routes have a `shouldRevalidate` or `clientLoader` then we do a
// comparison of the routes we matched and the routes we're aiming to load
// - If they don't match up, then we add the `_routes` param or fine-grained
// loading
// - This is used by the single fetch implementation above and by the
// `<PrefetchPageLinksImpl>` component so we can prefetch routes using the
// same logic
function addRevalidationParam(manifest, routeModules, matchedRoutes, loadRoutes, url) {
let genRouteIds = arr => arr.filter(id => manifest.routes[id].hasLoader).join(",");
// Look at the `routeModules` for `shouldRevalidate` here instead of the manifest
// since HDR adds a wrapper for `shouldRevalidate` even if the route didn't have one
// initially.
// TODO: We probably can get rid of that wrapper once we're strictly on on
// single-fetch in v3 and just leverage a needsRevalidation data structure here
// to determine what to fetch
let needsParam = matchedRoutes.some(r => {
var _routeModules$r$id, _manifest$routes$r$id;
return ((_routeModules$r$id = routeModules[r.id]) === null || _routeModules$r$id === void 0 ? void 0 : _routeModules$r$id.shouldRevalidate) || ((_manifest$routes$r$id = manifest.routes[r.id]) === null || _manifest$routes$r$id === void 0 ? void 0 : _manifest$routes$r$id.hasClientLoader);
});
if (!needsParam) {
return url;
}
let matchedIds = genRouteIds(matchedRoutes.map(r => r.id));
let loadIds = genRouteIds(loadRoutes.filter(r => {
var _manifest$routes$r$id2;
return !((_manifest$routes$r$id2 = manifest.routes[r.id]) !== null && _manifest$routes$r$id2 !== void 0 && _manifest$routes$r$id2.hasClientLoader);
}).map(r => r.id));
if (matchedIds !== loadIds) {
url.searchParams.set("_routes", loadIds);
}
return url;
}
function singleFetchUrl(reqUrl) {

@@ -291,2 +367,13 @@ let url = typeof reqUrl === "string" ? new URL(reqUrl, window.location.origin) : reqUrl;

}
}, (type, value) => {
if (type === "SingleFetchFallback") {
return {
value: undefined
};
}
if (type === "SingleFetchClassInstance") {
return {
value
};
}
}]

@@ -326,3 +413,28 @@ });

}
function createDeferred() {
let resolve;
let reject;
let promise = new Promise((res, rej) => {
resolve = async val => {
res(val);
try {
await promise;
} catch (e) {}
};
reject = async error => {
rej(error);
try {
await promise;
} catch (e) {}
};
});
return {
promise,
//@ts-ignore
resolve,
//@ts-ignore
reject
};
}
export { StreamTransfer, addRevalidationParam, decodeViaTurboStream, defineClientAction, defineClientLoader, getSingleFetchDataStrategy, singleFetchUrl };
export { StreamTransfer, decodeViaTurboStream, getSingleFetchDataStrategy, singleFetchUrl };
/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -51,4 +51,5 @@ * Copyright (c) Remix Software Inc.

"💿 Hey developer 👋. You can provide a way better UX than this " +
"when your app is running \`clientLoader\` functions on hydration. " +
"Check out https://remix.run/route/hydrate-fallback for more information."
"when your app is loading JS modules and/or running \`clientLoader\` " +
"functions. Check out https://remix.run/route/hydrate-fallback " +
"for more information."
);

@@ -55,0 +56,0 @@ `

import type { Router } from "@remix-run/router";
import type { unstable_PatchRoutesOnNavigationFunction } from "react-router";
import type { PatchRoutesOnNavigationFunction } from "react-router";
import type { AssetsManifest, FutureConfig } from "./entry";

@@ -26,4 +26,4 @@ import type { RouteModules } from "./routeModules";

};
export declare function getPatchRoutesOnNavigationFunction(manifest: AssetsManifest, routeModules: RouteModules, future: FutureConfig, isSpaMode: boolean, basename: string | undefined): unstable_PatchRoutesOnNavigationFunction | undefined;
export declare function getPatchRoutesOnNavigationFunction(manifest: AssetsManifest, routeModules: RouteModules, future: FutureConfig, isSpaMode: boolean, basename: string | undefined): PatchRoutesOnNavigationFunction | undefined;
export declare function useFogOFWarDiscovery(router: Router, manifest: AssetsManifest, routeModules: RouteModules, future: FutureConfig, isSpaMode: boolean): void;
export declare function fetchAndApplyManifestPatches(paths: string[], manifest: AssetsManifest, routeModules: RouteModules, future: FutureConfig, isSpaMode: boolean, basename: string | undefined, patchRoutes: Router["patchRoutes"]): Promise<void>;
/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -51,3 +51,3 @@ * Copyright (c) Remix Software Inc.

function isFogOfWarEnabled(future, isSpaMode) {
return future.unstable_lazyRouteDiscovery === true && !isSpaMode;
return future.v3_lazyRouteDiscovery === true && !isSpaMode;
}

@@ -54,0 +54,0 @@ function getPartialManifest(manifest, router$1) {

export type { ErrorResponse, Fetcher, FetcherWithComponents, FormEncType, FormMethod, Location, NavigateFunction, Navigation, Params, Path, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, SubmitFunction, SubmitOptions, Blocker, BlockerFunction, } from "react-router-dom";
export { createPath, createRoutesFromChildren, createRoutesFromElements, createSearchParams, generatePath, matchPath, matchRoutes, parsePath, renderMatches, resolvePath, Navigate, NavigationType, Outlet, Route, Routes, useAsyncError, useAsyncValue, isRouteErrorResponse, useBeforeUnload, useFetchers, useFormAction, useHref, useInRouterContext, useLinkClickHandler, useLocation, useMatch, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRoutes, useSearchParams, useSubmit, useBlocker, unstable_usePrompt, unstable_useViewTransitionState, } from "react-router-dom";
export { defer, json, redirect, redirectDocument, replace, unstable_data, } from "@remix-run/server-runtime";
export { createPath, createRoutesFromChildren, createRoutesFromElements, createSearchParams, generatePath, matchPath, matchRoutes, parsePath, renderMatches, resolvePath, Navigate, NavigationType, Outlet, Route, Routes, useAsyncError, useAsyncValue, isRouteErrorResponse, useBeforeUnload, useFetchers, useFormAction, useHref, useInRouterContext, useLinkClickHandler, useLocation, useMatch, useNavigate, useNavigation, useNavigationType, useOutlet, useOutletContext, useParams, useResolvedPath, useRevalidator, useRouteError, useRoutes, useSearchParams, useSubmit, useBlocker, useViewTransitionState, unstable_usePrompt, } from "react-router-dom";
export { defer, json, redirect, redirectDocument, replace, data, } from "@remix-run/server-runtime";
export type { RemixBrowserProps } from "./browser";

@@ -13,5 +13,3 @@ export { RemixBrowser } from "./browser";

export { RemixServer } from "./server";
export type { ClientAction as unstable_ClientAction, ClientLoader as unstable_ClientLoader, } from "./single-fetch";
export { defineClientAction as unstable_defineClientAction, defineClientLoader as unstable_defineClientLoader, } from "./single-fetch";
export type { FutureConfig as UNSAFE_FutureConfig, AssetsManifest as UNSAFE_AssetsManifest, RemixContextObject as UNSAFE_RemixContextObject, } from "./entry";
export type { EntryRoute as UNSAFE_EntryRoute, RouteManifest as UNSAFE_RouteManifest, } from "./routes";
/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -21,3 +21,2 @@ * Copyright (c) Remix Software Inc.

var server = require('./server.js');
var singleFetch = require('./single-fetch.js');

@@ -94,6 +93,2 @@

});
Object.defineProperty(exports, 'unstable_useViewTransitionState', {
enumerable: true,
get: function () { return reactRouterDom.unstable_useViewTransitionState; }
});
Object.defineProperty(exports, 'useAsyncError', {

@@ -191,2 +186,10 @@ enumerable: true,

});
Object.defineProperty(exports, 'useViewTransitionState', {
enumerable: true,
get: function () { return reactRouterDom.useViewTransitionState; }
});
Object.defineProperty(exports, 'data', {
enumerable: true,
get: function () { return serverRuntime.data; }
});
Object.defineProperty(exports, 'defer', {

@@ -212,6 +215,2 @@ enumerable: true,

});
Object.defineProperty(exports, 'unstable_data', {
enumerable: true,
get: function () { return serverRuntime.unstable_data; }
});
exports.RemixBrowser = browser.RemixBrowser;

@@ -235,3 +234,1 @@ exports.Await = components.Await;

exports.RemixServer = server.RemixServer;
exports.unstable_defineClientAction = singleFetch.defineClientAction;
exports.unstable_defineClientLoader = singleFetch.defineClientLoader;
/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

import type { AgnosticDataRouteMatch } from "@remix-run/router";
import type { Location } from "react-router-dom";
import type { AssetsManifest } from "./entry";
import type { AssetsManifest, FutureConfig } from "./entry";
import type { RouteModules, RouteModule } from "./routeModules";

@@ -121,3 +121,3 @@ import type { EntryRoute } from "./routes";

export declare function getKeyedPrefetchLinks(matches: AgnosticDataRouteMatch[], manifest: AssetsManifest, routeModules: RouteModules): Promise<KeyedHtmlLinkDescriptor[]>;
export declare function getNewMatchesForLinks(page: string, nextMatches: AgnosticDataRouteMatch[], currentMatches: AgnosticDataRouteMatch[], manifest: AssetsManifest, location: Location, mode: "data" | "assets"): AgnosticDataRouteMatch[];
export declare function getNewMatchesForLinks(page: string, nextMatches: AgnosticDataRouteMatch[], currentMatches: AgnosticDataRouteMatch[], manifest: AssetsManifest, location: Location, future: FutureConfig, mode: "data" | "assets"): AgnosticDataRouteMatch[];
export declare function getDataLinkHrefs(page: string, matches: AgnosticDataRouteMatch[], manifest: AssetsManifest): string[];

@@ -124,0 +124,0 @@ export declare function getModuleLinkHrefs(matches: AgnosticDataRouteMatch[], manifestPatch: AssetsManifest): string[];

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -124,3 +124,3 @@ * Copyright (c) Remix Software Inc.

// This is ridiculously identical to transition.ts `filterMatchesToLoad`
function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, location, mode) {
function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, location, future, mode) {
let path = parsePathPatch(page);

@@ -144,3 +144,3 @@ let isNew = (match, index) => {

// version doesn't care about submissions
let newMatches = mode === "data" && location.search !== path.search ?
let newMatches = mode === "data" && (future.v3_singleFetch || location.search !== path.search) ?
// this is really similar to stuff in transition.ts, maybe somebody smarter

@@ -156,2 +156,7 @@ // than me (or in less of a hurry) can share some of it. You're the best.

}
// For reused routes on GET navigations, by default:
// - Single fetch always revalidates
// - Multi fetch revalidates if search params changed
let defaultShouldRevalidate = future.v3_singleFetch || location.search !== path.search;
if (match.route.shouldRevalidate) {

@@ -164,3 +169,3 @@ var _currentMatches$;

nextParams: match.params,
defaultShouldRevalidate: true
defaultShouldRevalidate
});

@@ -171,3 +176,3 @@ if (typeof routeChoice === "boolean") {

}
return true;
return defaultShouldRevalidate;
}) : nextMatches.filter((match, index) => {

@@ -174,0 +179,0 @@ let manifestRoute = manifest.routes[match.route.id];

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -198,3 +198,3 @@ * Copyright (c) Remix Software Inc.

handle: routeModule.handle,
shouldRevalidate: needsRevalidation ? wrapShouldRevalidateForHdr(route.id, routeModule.shouldRevalidate, needsRevalidation) : routeModule.shouldRevalidate
shouldRevalidate: getShouldRevalidateFunction(future, routeModule, route.id, needsRevalidation)
});

@@ -224,6 +224,9 @@ let initialData = initialState === null || initialState === void 0 ? void 0 : (_initialState$loaderD = initialState.loaderData) === null || _initialState$loaderD === void 0 ? void 0 : _initialState$loaderD[route.id];

if (isHydrationRequest) {
if (initialData !== undefined) {
return initialData;
}
if (initialError !== undefined) {
throw initialError;
}
return initialData;
return null;
}

@@ -317,5 +320,2 @@

}
if (needsRevalidation) {
lazyRoute.shouldRevalidate = wrapShouldRevalidateForHdr(route.id, mod.shouldRevalidate, needsRevalidation);
}
return {

@@ -329,3 +329,3 @@ ...(lazyRoute.loader ? {

hasErrorBoundary: lazyRoute.hasErrorBoundary,
shouldRevalidate: lazyRoute.shouldRevalidate,
shouldRevalidate: getShouldRevalidateFunction(future, lazyRoute, route.id, needsRevalidation),
handle: lazyRoute.handle,

@@ -344,3 +344,20 @@ // No need to wrap these in layout since the root route is never

}
function getShouldRevalidateFunction(future, route, routeId, needsRevalidation) {
// During HDR we force revalidation for updated routes
if (needsRevalidation) {
return wrapShouldRevalidateForHdr(routeId, route.shouldRevalidate, needsRevalidation);
}
// Single fetch revalidates by default, so override the RR default value which
// matches the multi-fetch behavior with `true`
if (future.v3_singleFetch && route.shouldRevalidate) {
let fn = route.shouldRevalidate;
return opts => fn({
...opts,
defaultShouldRevalidate: true
});
}
return route.shouldRevalidate;
}
// When an HMR / HDR update happens we opt out of all user-defined

@@ -347,0 +364,0 @@ // revalidation logic and force a revalidation on the first call

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc.

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -108,3 +108,3 @@ * Copyright (c) Remix Software Inc.

hydrate: false
}))), context.future.unstable_singleFetch && context.serverHandoffStream ? /*#__PURE__*/React__namespace.createElement(React__namespace.Suspense, null, /*#__PURE__*/React__namespace.createElement(singleFetch.StreamTransfer, {
}))), context.future.v3_singleFetch && context.serverHandoffStream ? /*#__PURE__*/React__namespace.createElement(React__namespace.Suspense, null, /*#__PURE__*/React__namespace.createElement(singleFetch.StreamTransfer, {
context: context,

@@ -111,0 +111,0 @@ identifier: 0,

import * as React from "react";
import type { ActionFunctionArgs as RRActionArgs, LoaderFunctionArgs as RRLoaderArgs, unstable_DataStrategyFunction as DataStrategyFunction } from "@remix-run/router";
import type { unstable_Action, unstable_Loader, unstable_Serialize } from "@remix-run/server-runtime";
import type { DataRouteObject } from "react-router-dom";
import type { DataStrategyFunction, Router as RemixRouter } from "@remix-run/router";
import type { AssetsManifest, EntryContext } from "./entry";
import type { RouteModules } from "./routeModules";
type ClientLoaderArgs = RRLoaderArgs<undefined> & {
serverLoader: <T extends unstable_Loader>() => Promise<unstable_Serialize<T>>;
};
export type ClientLoader = (args: ClientLoaderArgs) => unknown;
export declare let defineClientLoader: <T extends ClientLoader>(clientLoader: T) => T & {
hydrate?: boolean | undefined;
};
type ClientActionArgs = RRActionArgs<undefined> & {
serverAction: <T extends unstable_Action>() => Promise<unstable_Serialize<T>>;
};
export type ClientAction = (args: ClientActionArgs) => unknown;
export declare let defineClientAction: <T extends ClientAction>(clientAction: T) => T;
import { type RouteModules } from "./routeModules";
interface StreamTransferProps {

@@ -27,4 +13,3 @@ context: EntryContext;

export declare function StreamTransfer({ context, identifier, reader, textDecoder, nonce, }: StreamTransferProps): React.JSX.Element | null;
export declare function getSingleFetchDataStrategy(manifest: AssetsManifest, routeModules: RouteModules): DataStrategyFunction;
export declare function addRevalidationParam(manifest: AssetsManifest, routeModules: RouteModules, matchedRoutes: DataRouteObject[], loadRoutes: DataRouteObject[], url: URL): URL;
export declare function getSingleFetchDataStrategy(manifest: AssetsManifest, routeModules: RouteModules, getRouter: () => RemixRouter): DataStrategyFunction;
export declare function singleFetchUrl(reqUrl: URL | string): URL;

@@ -31,0 +16,0 @@ export declare function decodeViaTurboStream(body: ReadableStream<Uint8Array>, global: Window | typeof globalThis): Promise<{

/**
* @remix-run/react v0.0.0-nightly-6f23bc960-20240821
* @remix-run/react v0.0.0-nightly-6f8288990-20241030
*

@@ -43,9 +43,2 @@ * Copyright (c) Remix Software Inc.

// clientLoader
let defineClientLoader = clientLoader => clientLoader;
// clientAction
let defineClientAction = clientAction => clientAction;
// StreamTransfer recursively renders down chunks of the `serverHandoffStream`

@@ -117,40 +110,56 @@ // into the client-side `streamController`

}
function getSingleFetchDataStrategy(manifest, routeModules) {
function getSingleFetchDataStrategy(manifest, routeModules, getRouter) {
return async ({
request,
matches
}) => request.method !== "GET" ? singleFetchActionStrategy(request, matches) : singleFetchLoaderStrategy(manifest, routeModules, request, matches);
matches,
fetcherKey
}) => {
// Actions are simple and behave the same for navigations and fetchers
if (request.method !== "GET") {
return singleFetchActionStrategy(request, matches);
}
// Fetcher loads are singular calls to one loader
if (fetcherKey) {
return singleFetchLoaderFetcherStrategy(request, matches);
}
// Navigational loads are more complex...
return singleFetchLoaderNavigationStrategy(manifest, routeModules, getRouter(), request, matches);
};
}
// Actions are simple since they're singular calls to the server
function singleFetchActionStrategy(request, matches) {
return Promise.all(matches.map(async m => {
let actionStatus;
let result = await m.resolve(async handler => {
let result = await handler(async () => {
let url = singleFetchUrl(request.url);
let init = await data.createRequestInit(request);
let {
data: data$1,
status
} = await fetchAndDecode(url, init);
actionStatus = status;
return unwrapSingleFetchResult(data$1, m.route.id);
});
return {
type: "data",
result
};
// Actions are simple since they're singular calls to the server for both
// navigations and fetchers)
async function singleFetchActionStrategy(request, matches) {
let actionMatch = matches.find(m => m.shouldLoad);
invariant(actionMatch, "No action match found");
let actionStatus = undefined;
let result = await actionMatch.resolve(async handler => {
let result = await handler(async () => {
let url = singleFetchUrl(request.url);
let init = await data.createRequestInit(request);
let {
data: data$1,
status
} = await fetchAndDecode(url, init);
actionStatus = status;
return unwrapSingleFetchResult(data$1, actionMatch.route.id);
});
if (data.isResponse(result.result) || router.isRouteErrorResponse(result.result)) {
return result;
}
return result;
});
if (data.isResponse(result.result) || router.isRouteErrorResponse(result.result)) {
return {
[actionMatch.route.id]: result
};
}
// For non-responses, proxy along the statusCode via unstable_data()
// (most notably for skipping action error revalidation)
return {
// For non-responses, proxy along the statusCode via data()
// (most notably for skipping action error revalidation)
return {
[actionMatch.route.id]: {
type: result.type,
result: router.unstable_data(result.result, actionStatus)
};
}));
result: router.data(result.result, actionStatus)
}
};
}

@@ -160,37 +169,144 @@

// create a singular promise for all server-loader routes to latch onto.
function singleFetchLoaderStrategy(manifest, routeModules, request, matches) {
let singleFetchPromise;
return Promise.all(matches.map(async m => m.resolve(async handler => {
let result;
let url = stripIndexParam(singleFetchUrl(request.url));
let init = await data.createRequestInit(request);
async function singleFetchLoaderNavigationStrategy(manifest, routeModules, router, request, matches) {
// Track which routes need a server load - in case we need to tack on a
// `_routes` param
let routesParams = new Set();
// When a route has a client loader, it calls it's singular server loader
// We only add `_routes` when one or more routes opts out of a load via
// `shouldRevalidate` or `clientLoader`
let foundOptOutRoute = false;
// Deferreds for each route so we can be sure they've all loaded via
// `match.resolve()`, and a singular promise that can tell us all routes
// have been resolved
let routeDfds = matches.map(() => createDeferred());
let routesLoadedPromise = Promise.all(routeDfds.map(d => d.promise));
// Deferred that we'll use for the call to the server that each match can
// await and parse out it's specific result
let singleFetchDfd = createDeferred();
// Base URL and RequestInit for calls to the server
let url = stripIndexParam(singleFetchUrl(request.url));
let init = await data.createRequestInit(request);
// We'll build up this results object as we loop through matches
let results = {};
let resolvePromise = Promise.all(matches.map(async (m, i) => m.resolve(async handler => {
routeDfds[i].resolve();
if (!m.shouldLoad) {
var _routeModules$m$route;
// If we're not yet initialized and this is the initial load, respect
// `shouldLoad` because we're only dealing with `clientLoader.hydrate`
// routes which will fall into the `clientLoader` section below.
if (!router.state.initialized) {
return;
}
// Otherwise, we opt out if we currently have data, a `loader`, and a
// `shouldRevalidate` function. This implies that the user opted out
// via `shouldRevalidate`
if (m.route.id in router.state.loaderData && manifest.routes[m.route.id].hasLoader && (_routeModules$m$route = routeModules[m.route.id]) !== null && _routeModules$m$route !== void 0 && _routeModules$m$route.shouldRevalidate) {
foundOptOutRoute = true;
return;
}
}
// When a route has a client loader, it opts out of the singular call and
// calls it's server loader via `serverLoader()` using a `?_routes` param
if (manifest.routes[m.route.id].hasClientLoader) {
result = await handler(async () => {
url.searchParams.set("_routes", m.route.id);
let {
data
} = await fetchAndDecode(url, init);
if (manifest.routes[m.route.id].hasLoader) {
foundOptOutRoute = true;
}
try {
let result = await fetchSingleLoader(handler, url, init, m.route.id);
results[m.route.id] = {
type: "data",
result
};
} catch (e) {
results[m.route.id] = {
type: "error",
result: e
};
}
return;
}
// Load this route on the server if it has a loader
if (manifest.routes[m.route.id].hasLoader) {
routesParams.add(m.route.id);
}
// Lump this match in with the others on a singular promise
try {
let result = await handler(async () => {
let data = await singleFetchDfd.promise;
return unwrapSingleFetchResults(data, m.route.id);
});
} else {
result = await handler(async () => {
// Otherwise we let multiple routes hook onto the same promise
if (!singleFetchPromise) {
url = addRevalidationParam(manifest, routeModules, matches.map(m => m.route), matches.filter(m => m.shouldLoad).map(m => m.route), url);
singleFetchPromise = fetchAndDecode(url, init).then(({
data
}) => data);
}
let results = await singleFetchPromise;
return unwrapSingleFetchResults(results, m.route.id);
});
results[m.route.id] = {
type: "data",
result
};
} catch (e) {
results[m.route.id] = {
type: "error",
result: e
};
}
return {
type: "data",
result
};
})));
// Wait for all routes to resolve above before we make the HTTP call
await routesLoadedPromise;
// We can skip the server call:
// - On initial hydration - only clientLoaders can pass through via `clientLoader.hydrate`
// - If there are no routes to fetch from the server
//
// One exception - if we are performing an HDR revalidation we have to call
// the server in case a new loader has shown up that the manifest doesn't yet
// know about
if ((!router.state.initialized || routesParams.size === 0) && !window.__remixHdrActive) {
singleFetchDfd.resolve({});
} else {
try {
// When one or more routes have opted out, we add a _routes param to
// limit the loaders to those that have a server loader and did not
// opt out
if (foundOptOutRoute && routesParams.size > 0) {
url.searchParams.set("_routes", matches.filter(m => routesParams.has(m.route.id)).map(m => m.route.id).join(","));
}
let data = await fetchAndDecode(url, init);
singleFetchDfd.resolve(data.data);
} catch (e) {
singleFetchDfd.reject(e);
}
}
await resolvePromise;
return results;
}
// Fetcher loader calls are much simpler than navigational loader calls
async function singleFetchLoaderFetcherStrategy(request, matches) {
let fetcherMatch = matches.find(m => m.shouldLoad);
invariant(fetcherMatch, "No fetcher match found");
let result = await fetcherMatch.resolve(async handler => {
let url = stripIndexParam(singleFetchUrl(request.url));
let init = await data.createRequestInit(request);
return fetchSingleLoader(handler, url, init, fetcherMatch.route.id);
});
return {
[fetcherMatch.route.id]: result
};
}
function fetchSingleLoader(handler, url, init, routeId) {
return handler(async () => {
let singleLoaderUrl = new URL(url);
singleLoaderUrl.searchParams.set("_routes", routeId);
let {
data
} = await fetchAndDecode(singleLoaderUrl, init);
return unwrapSingleFetchResults(data, routeId);
});
}
function stripIndexParam(url) {

@@ -210,42 +326,2 @@ let indexValues = url.searchParams.getAll("index");

}
// Determine which routes we want to load so we can add a `?_routes` search param
// for fine-grained revalidation if necessary. There's some nuance to this decision:
//
// - The presence of `shouldRevalidate` and `clientLoader` functions are the only
// way to trigger fine-grained single fetch loader calls. without either of
// these on the route matches we just always ask for the full `.data` request.
// - If any routes have a `shouldRevalidate` or `clientLoader` then we do a
// comparison of the routes we matched and the routes we're aiming to load
// - If they don't match up, then we add the `_routes` param or fine-grained
// loading
// - This is used by the single fetch implementation above and by the
// `<PrefetchPageLinksImpl>` component so we can prefetch routes using the
// same logic
function addRevalidationParam(manifest, routeModules, matchedRoutes, loadRoutes, url) {
let genRouteIds = arr => arr.filter(id => manifest.routes[id].hasLoader).join(",");
// Look at the `routeModules` for `shouldRevalidate` here instead of the manifest
// since HDR adds a wrapper for `shouldRevalidate` even if the route didn't have one
// initially.
// TODO: We probably can get rid of that wrapper once we're strictly on on
// single-fetch in v3 and just leverage a needsRevalidation data structure here
// to determine what to fetch
let needsParam = matchedRoutes.some(r => {
var _routeModules$r$id, _manifest$routes$r$id;
return ((_routeModules$r$id = routeModules[r.id]) === null || _routeModules$r$id === void 0 ? void 0 : _routeModules$r$id.shouldRevalidate) || ((_manifest$routes$r$id = manifest.routes[r.id]) === null || _manifest$routes$r$id === void 0 ? void 0 : _manifest$routes$r$id.hasClientLoader);
});
if (!needsParam) {
return url;
}
let matchedIds = genRouteIds(matchedRoutes.map(r => r.id));
let loadIds = genRouteIds(loadRoutes.filter(r => {
var _manifest$routes$r$id2;
return !((_manifest$routes$r$id2 = manifest.routes[r.id]) !== null && _manifest$routes$r$id2 !== void 0 && _manifest$routes$r$id2.hasClientLoader);
}).map(r => r.id));
if (matchedIds !== loadIds) {
url.searchParams.set("_routes", loadIds);
}
return url;
}
function singleFetchUrl(reqUrl) {

@@ -314,2 +390,13 @@ let url = typeof reqUrl === "string" ? new URL(reqUrl, window.location.origin) : reqUrl;

}
}, (type, value) => {
if (type === "SingleFetchFallback") {
return {
value: undefined
};
}
if (type === "SingleFetchClassInstance") {
return {
value
};
}
}]

@@ -349,9 +436,31 @@ });

}
function createDeferred() {
let resolve;
let reject;
let promise = new Promise((res, rej) => {
resolve = async val => {
res(val);
try {
await promise;
} catch (e) {}
};
reject = async error => {
rej(error);
try {
await promise;
} catch (e) {}
};
});
return {
promise,
//@ts-ignore
resolve,
//@ts-ignore
reject
};
}
exports.StreamTransfer = StreamTransfer;
exports.addRevalidationParam = addRevalidationParam;
exports.decodeViaTurboStream = decodeViaTurboStream;
exports.defineClientAction = defineClientAction;
exports.defineClientLoader = defineClientLoader;
exports.getSingleFetchDataStrategy = getSingleFetchDataStrategy;
exports.singleFetchUrl = singleFetchUrl;
{
"name": "@remix-run/react",
"version": "0.0.0-nightly-6f23bc960-20240821",
"version": "0.0.0-nightly-6f8288990-20241030",
"description": "React DOM bindings for Remix",

@@ -19,11 +19,11 @@ "bugs": {

"dependencies": {
"@remix-run/router": "1.19.1",
"@remix-run/server-runtime": "0.0.0-nightly-6f23bc960-20240821",
"react-router": "6.26.1",
"react-router-dom": "6.26.1",
"turbo-stream": "2.3.0"
"@remix-run/router": "1.21.0-pre.0",
"@remix-run/server-runtime": "0.0.0-nightly-6f8288990-20241030",
"react-router": "6.28.0-pre.0",
"react-router-dom": "6.28.0-pre.0",
"turbo-stream": "2.4.0"
},
"devDependencies": {
"@remix-run/node": "0.0.0-nightly-6f23bc960-20240821",
"@remix-run/react": "0.0.0-nightly-6f23bc960-20240821",
"@remix-run/node": "0.0.0-nightly-6f8288990-20241030",
"@remix-run/react": "0.0.0-nightly-6f8288990-20241030",
"@testing-library/jest-dom": "^5.17.0",

@@ -30,0 +30,0 @@ "@testing-library/react": "^13.3.0",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc