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

@remix-run/server-runtime

Package Overview
Dependencies
Maintainers
2
Versions
1026
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@remix-run/server-runtime - npm Package Compare versions

Comparing version 0.0.0-experimental-419fc7d09 to 0.0.0-experimental-432fae462

dist/deprecations.d.ts

2

dist/cookies.js
/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

@@ -15,3 +15,3 @@ import type { ActionFunction, ActionFunctionArgs, LoaderFunction, LoaderFunctionArgs } from "./routeModules";

export type AppData = unknown;
export declare function callRouteActionRR({ loadContext, action, params, request, routeId, singleFetch, }: {
export declare function callRouteAction({ loadContext, action, params, request, routeId, singleFetch, }: {
request: Request;

@@ -24,3 +24,3 @@ action: ActionFunction;

}): Promise<{} | Response | null>;
export declare function callRouteLoaderRR({ loadContext, loader, params, request, routeId, singleFetch, }: {
export declare function callRouteLoader({ loadContext, loader, params, request, routeId, singleFetch, }: {
request: Request;

@@ -27,0 +27,0 @@ loader: LoaderFunction;

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

async function callRouteActionRR({
async function callRouteAction({
loadContext,

@@ -52,3 +52,3 @@ action,

}
async function callRouteLoaderRR({
async function callRouteLoader({
loadContext,

@@ -127,3 +127,3 @@ loader,

exports.callRouteActionRR = callRouteActionRR;
exports.callRouteLoaderRR = callRouteLoaderRR;
exports.callRouteAction = callRouteAction;
exports.callRouteLoader = callRouteLoader;
/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

@@ -30,2 +30,3 @@ import type { StaticHandlerContext } from "@remix-run/router";

v3_throwAbortReason: boolean;
unstable_lazyRouteDiscovery: boolean;
unstable_singleFetch: boolean;

@@ -32,0 +33,0 @@ }

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

async function callRouteActionRR({
async function callRouteAction({
loadContext,

@@ -48,3 +48,3 @@ action,

}
async function callRouteLoaderRR({
async function callRouteLoader({
loadContext,

@@ -123,2 +123,2 @@ loader,

export { callRouteActionRR, callRouteLoaderRR };
export { callRouteAction, callRouteLoader };
/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

function getDocumentHeadersRR(build, context) {
function getDocumentHeaders(build, context) {
let boundaryIdx = context.errors ? context.matches.findIndex(m => context.errors[m.route.id]) : -1;

@@ -91,2 +91,2 @@ let matches = boundaryIdx >= 0 ? context.matches.slice(0, boundaryIdx + 1) : context.matches;

export { getDocumentHeadersRR };
export { getDocumentHeaders };
/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

export { composeUploadHandlers as unstable_composeUploadHandlers, parseMultipartFormData as unstable_parseMultipartFormData } from './formData.js';
export { defer, json, redirect, redirectDocument } from './responses.js';
export { SingleFetchRedirectSymbol as UNSAFE_SingleFetchRedirectSymbol, createRequestHandler } from './server.js';
export { defer, json, redirect, redirectDocument, replace } from './responses.js';
export { SingleFetchRedirectSymbol as UNSAFE_SingleFetchRedirectSymbol, data as unstable_data, defineAction as unstable_defineAction, defineLoader as unstable_defineLoader } from './single-fetch.js';
export { createRequestHandler } from './server.js';
export { createSession, createSessionStorageFactory, isSession } from './sessions.js';

@@ -17,0 +18,0 @@ export { createCookieSessionStorageFactory } from './sessions/cookieStorage.js';

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

*/
import { json as json$1, defer as defer$1, redirect as redirect$1, redirectDocument as redirectDocument$1 } from '@remix-run/router';
import { json as json$1, defer as defer$1, redirect as redirect$1, replace as replace$1, redirectDocument as redirectDocument$1 } from '@remix-run/router';
import { serializeError } from './errors.js';

@@ -47,2 +47,12 @@

/**
* A redirect response. Sets the status code and the `Location` header.
* Defaults to "302 Found".
*
* @see https://remix.run/utils/redirect
*/
const replace = (url, init = 302) => {
return replace$1(url, init);
};
/**
* A redirect response that will force a document reload to the new location.

@@ -125,2 +135,2 @@ * Sets the status code and the `Location` header.

export { createDeferredReadableStream, defer, isDeferredData, isRedirectResponse, isRedirectStatusCode, isResponse, json, redirect, redirectDocument };
export { createDeferredReadableStream, defer, isDeferredData, isRedirectResponse, isRedirectStatusCode, isResponse, json, redirect, redirectDocument, replace };
/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

*/
import { callRouteLoaderRR, callRouteActionRR } from './data.js';
import { callRouteLoader, callRouteAction } from './data.js';

@@ -51,3 +51,3 @@ // NOTE: make sure to change the Route in remix-react if you change this

// though we know it'll always be provided in remix
args => callRouteLoaderRR({
(args, dataStrategyCtx) => callRouteLoader({
request: args.request,

@@ -60,3 +60,3 @@ params: args.params,

}) : undefined,
action: route.module.action ? args => callRouteActionRR({
action: route.module.action ? (args, dataStrategyCtx) => callRouteAction({
request: args.request,

@@ -63,0 +63,0 @@ params: args.params,

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

*/
import { stripBasename, UNSAFE_DEFERRED_SYMBOL, isRouteErrorResponse, json, UNSAFE_ErrorResponseImpl, getStaticContextFromError, createStaticHandler } from '@remix-run/router';
import { encode } from 'turbo-stream';
import { UNSAFE_DEFERRED_SYMBOL, isRouteErrorResponse, json as json$1, UNSAFE_ErrorResponseImpl, getStaticContextFromError, stripBasename, createStaticHandler } from '@remix-run/router';
import { createEntryRouteModules } from './entry.js';
import { serializeError, sanitizeError, sanitizeErrors, serializeErrors } from './errors.js';
import { getDocumentHeadersRR } from './headers.js';
import { serializeError, sanitizeErrors, serializeErrors } from './errors.js';
import { getDocumentHeaders } from './headers.js';
import invariant from './invariant.js';

@@ -21,5 +20,7 @@ import { ServerMode, isServerMode } from './mode.js';

import { createRoutes, createStaticHandlerDataRoutes } from './routes.js';
import { isRedirectResponse, createDeferredReadableStream, isResponse } from './responses.js';
import { isRedirectResponse, json, createDeferredReadableStream, isResponse } from './responses.js';
import { createServerHandoffString } from './serverHandoff.js';
import { getDevServerHooks } from './dev.js';
import { getSingleFetchRedirect, encodeViaTurboStream, SINGLE_FETCH_REDIRECT_STATUS, singleFetchAction, singleFetchLoaders, SingleFetchRedirectSymbol } from './single-fetch.js';
import { resourceRouteJsonWarning } from './deprecations.js';

@@ -78,4 +79,3 @@ function derive(build, mode) {

let url = new URL(request.url);
let matches = matchServerRoutes(routes, url.pathname, _build.basename);
let params = matches && matches.length > 0 ? matches[0].params : {};
let params = {};
let handleError = error => {

@@ -92,2 +92,21 @@ if (mode === ServerMode.Development) {

};
// Manifest request for fog of war
let manifestUrl = `${_build.basename ?? "/"}/__manifest`.replace(/\/+/g, "/");
if (url.pathname === manifestUrl) {
try {
let res = await handleManifestRequest(_build, routes, url);
return res;
} catch (e) {
handleError(e);
return new Response("Unknown Server Error", {
status: 500
});
}
}
let matches = matchServerRoutes(routes, url.pathname, _build.basename);
if (matches && matches.length > 0) {
Object.assign(params, matches[0].params);
}
let response;

@@ -106,2 +125,5 @@ if (url.searchParams.has("_data")) {

});
if (isRedirectResponse(response)) {
response = createRemixRedirectResponse(response, _build.basename);
}
}

@@ -111,13 +133,27 @@ } else if (_build.future.unstable_singleFetch && url.pathname.endsWith(".data")) {

handlerUrl.pathname = handlerUrl.pathname.replace(/\.data$/, "").replace(/^\/_root$/, "/");
let matches = matchServerRoutes(routes, handlerUrl.pathname, _build.basename);
response = await handleSingleFetchRequest(serverMode, _build, staticHandler, matches, request, handlerUrl, loadContext, handleError);
let singleFetchMatches = matchServerRoutes(routes, handlerUrl.pathname, _build.basename);
response = await handleSingleFetchRequest(serverMode, _build, staticHandler, request, handlerUrl, loadContext, handleError);
if (_build.entry.module.handleDataRequest) {
response = await _build.entry.module.handleDataRequest(response, {
context: loadContext,
params,
params: singleFetchMatches ? singleFetchMatches[0].params : {},
request
});
if (isRedirectResponse(response)) {
let result = getSingleFetchRedirect(response.status, response.headers, _build.basename);
if (request.method === "GET") {
result = {
[SingleFetchRedirectSymbol]: result
};
}
let headers = new Headers(response.headers);
headers.set("Content-Type", "text/x-script");
return new Response(encodeViaTurboStream(result, request.signal, _build.entry.module.streamTimeout, serverMode), {
status: SINGLE_FETCH_REDIRECT_STATUS,
headers
});
}
}
} else if (matches && matches[matches.length - 1].route.module.default == null && matches[matches.length - 1].route.module.ErrorBoundary == null) {
response = await handleResourceRequest(serverMode, staticHandler, matches.slice(-1)[0].route.id, request, loadContext, handleError);
response = await handleResourceRequest(serverMode, _build, staticHandler, matches.slice(-1)[0].route.id, request, loadContext, handleError);
} else {

@@ -138,2 +174,24 @@ var _getDevServerHooks2, _getDevServerHooks2$g;

};
async function handleManifestRequest(build, routes, url) {
let patches = {};
if (url.searchParams.has("p")) {
for (let path of url.searchParams.getAll("p")) {
let matches = matchServerRoutes(routes, path, build.basename);
if (matches) {
for (let match of matches) {
let routeId = match.route.id;
patches[routeId] = build.assets.routes[routeId];
}
}
}
return json(patches, {
headers: {
"Cache-Control": "public, max-age=31536000, immutable"
}
}); // Override the TypedResponse stuff from json()
}
return new Response("Invalid Request", {
status: 400
});
}
async function handleDataRequest(serverMode, build, staticHandler, routeId, request, loadContext, handleError) {

@@ -146,17 +204,3 @@ try {

if (isRedirectResponse(response)) {
// We don't have any way to prevent a fetch request from following
// redirects. So we use the `X-Remix-Redirect` header to indicate the
// next URL, and then "follow" the redirect manually on the client.
let headers = new Headers(response.headers);
let redirectUrl = headers.get("Location");
headers.set("X-Remix-Redirect", build.basename ? stripBasename(redirectUrl, build.basename) || redirectUrl : redirectUrl);
headers.set("X-Remix-Status", response.status);
headers.delete("Location");
if (response.headers.get("Set-Cookie") !== null) {
headers.set("X-Remix-Revalidate", "yes");
}
return new Response(null, {
status: 204,
headers
});
return createRemixRedirectResponse(response, build.basename);
}

@@ -178,8 +222,8 @@ if (UNSAFE_DEFERRED_SYMBOL in response) {

// network errors that are missing this header
response.headers.set("X-Remix-Response", "yes");
response = safelySetHeader(response, "X-Remix-Response", "yes");
return response;
} catch (error) {
if (isResponse(error)) {
error.headers.set("X-Remix-Catch", "yes");
return error;
let response = safelySetHeader(error, "X-Remix-Catch", "yes");
return response;
}

@@ -192,3 +236,3 @@ if (isRouteErrorResponse(error)) {

handleError(errorInstance);
return json(serializeError(errorInstance, serverMode), {
return json$1(serializeError(errorInstance, serverMode), {
status: 500,

@@ -201,4 +245,3 @@ headers: {

}
const SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
async function handleSingleFetchRequest(serverMode, build, staticHandler, matches, request, handlerUrl, loadContext, handleError) {
async function handleSingleFetchRequest(serverMode, build, staticHandler, request, handlerUrl, loadContext, handleError) {
let {

@@ -208,3 +251,3 @@ result,

status
} = request.method !== "GET" ? await singleFetchAction(request, handlerUrl, staticHandler, loadContext, handleError) : await singleFetchLoaders(request, handlerUrl, staticHandler, matches, loadContext, handleError, serverMode, build);
} = request.method !== "GET" ? await singleFetchAction(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError) : await singleFetchLoaders(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError);

@@ -215,4 +258,9 @@ // Mark all successful responses with a header so we can identify in-flight

resultHeaders.set("X-Remix-Response", "yes");
resultHeaders.set("Content-Type", "text/x-turbo");
// We use a less-descriptive `text/x-script` here instead of something like
// `text/x-turbo` to enable compression when deployed via Cloudflare. See:
// - https://github.com/remix-run/remix/issues/9884
// - https://developers.cloudflare.com/speed/optimization/content/brotli/content-compression/
resultHeaders.set("Content-Type", "text/x-script");
// Note: Deferred data is already just Promises, so we don't have to mess

@@ -225,134 +273,2 @@ // `activeDeferreds` or anything :)

}
async function singleFetchAction(request, handlerUrl, staticHandler, loadContext, handleError) {
try {
let handlerRequest = new Request(handlerUrl, {
method: request.method,
body: request.body,
headers: request.headers,
signal: request.signal,
...(request.body ? {
duplex: "half"
} : undefined)
});
let result = await staticHandler.queryRoute(handlerRequest, {
requestContext: loadContext
});
// Unlike `handleDataRequest`, when singleFetch is enabled, queryRoute does
// let non-Response return values through
if (!isResponse(result)) {
return {
result: {
data: result
},
headers: new Headers(),
status: 200
};
}
if (isRedirectResponse(result)) {
return {
result: getSingleFetchRedirect(result),
headers: result.headers,
status: 200 // Don't trigger a redirect on the `fetch`
};
}
return {
result: {
data: await unwrapResponse(result)
},
headers: result.headers,
status: result.status
};
} catch (error) {
if (isResponse(error)) {
return {
result: {
error: new UNSAFE_ErrorResponseImpl(error.status, error.statusText, await unwrapResponse(error))
},
headers: error.headers,
status: error.status
};
} else {
handleError(error);
return {
result: {
error
},
headers: new Headers(),
status: isRouteErrorResponse(error) ? error.status : 500
};
}
}
}
async function singleFetchLoaders(request, handlerUrl, staticHandler, matches, loadContext, handleError, serverMode, build) {
try {
var _URL$searchParams$get;
let handlerRequest = new Request(handlerUrl, {
headers: request.headers,
signal: request.signal
});
let loadRouteIds = ((_URL$searchParams$get = new URL(request.url).searchParams.get("_routes")) === null || _URL$searchParams$get === void 0 ? void 0 : _URL$searchParams$get.split(",")) || undefined;
let result = await staticHandler.query(handlerRequest, {
requestContext: loadContext,
loadRouteIds,
skipLoaderErrorBubbling: true
});
if (isResponse(result)) {
return {
result: {
[SingleFetchRedirectSymbol]: getSingleFetchRedirect(result)
},
headers: result.headers,
status: 200 // Don't want the `fetch` call to follow the redirect
};
}
let context = result;
// Sanitize errors outside of development environments
if (context.errors) {
Object.values(context.errors).forEach(err => {
// @ts-expect-error This is "private" from users but intended for internal use
if (!isRouteErrorResponse(err) || err.error) {
handleError(err);
}
});
context.errors = sanitizeErrors(context.errors, serverMode);
}
// Aggregate results based on the matches we intended to load since we get
// `null` values back in `context.loaderData` for routes we didn't load
let results = {};
let loadedMatches = loadRouteIds ? context.matches.filter(m => m.route.loader && loadRouteIds.includes(m.route.id)) : context.matches;
loadedMatches.forEach(m => {
var _context$loaderData, _context$errors;
let data = (_context$loaderData = context.loaderData) === null || _context$loaderData === void 0 ? void 0 : _context$loaderData[m.route.id];
let error = (_context$errors = context.errors) === null || _context$errors === void 0 ? void 0 : _context$errors[m.route.id];
if (error !== undefined) {
results[m.route.id] = {
error
};
} else if (data !== undefined) {
results[m.route.id] = {
data
};
}
});
return {
result: results,
headers: getDocumentHeadersRR(build, context),
status: context.statusCode
};
} catch (error) {
handleError(error);
return {
result: {
root: {
error
}
},
headers: new Headers(),
status: 500
};
}
}
async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, criticalCss) {

@@ -373,2 +289,3 @@ let context;

}
let headers = getDocumentHeaders(build, context);

@@ -378,3 +295,3 @@ // Sanitize errors outside of development environments

Object.values(context.errors).forEach(err => {
// @ts-expect-error This is "private" from users but intended for internal use
// @ts-expect-error `err.error` is "private" from users but intended for internal use
if (!isRouteErrorResponse(err) || err.error) {

@@ -386,3 +303,2 @@ handleError(err);

}
let headers = getDocumentHeadersRR(build, context);

@@ -403,3 +319,2 @@ // Server UI state to send to the client.

serverHandoffString: createServerHandoffString({
url: context.location.pathname,
basename: build.basename,

@@ -460,3 +375,2 @@ criticalCss,

serverHandoffString: createServerHandoffString({
url: context.location.pathname,
basename: build.basename,

@@ -482,3 +396,3 @@ future: build.future,

}
async function handleResourceRequest(serverMode, staticHandler, routeId, request, loadContext, handleError) {
async function handleResourceRequest(serverMode, build, staticHandler, routeId, request, loadContext, handleError) {
try {

@@ -492,5 +406,10 @@ // Note we keep the routeId here to align with the Remix handling of

});
if (typeof response === "object") {
if (typeof response === "object" && response !== null) {
invariant(!(UNSAFE_DEFERRED_SYMBOL in response), `You cannot return a \`defer()\` response from a Resource Route. Did you ` + `forget to export a default UI component from the "${routeId}" route?`);
}
if (build.future.unstable_singleFetch && !isResponse(response)) {
console.warn(resourceRouteJsonWarning(request.method === "GET" ? "loader" : "action", routeId));
response = json(response);
}
// callRouteLoader/callRouteAction always return responses (w/o single fetch).

@@ -504,4 +423,4 @@ // With single fetch, users should always be Responses from resource routes

// match identically to what Remix returns
error.headers.set("X-Remix-Catch", "yes");
return error;
let response = safelySetHeader(error, "X-Remix-Catch", "yes");
return response;
}

@@ -519,3 +438,3 @@ if (isRouteErrorResponse(error)) {

function errorResponseToJson(errorResponse, serverMode) {
return json(serializeError(
return json$1(serializeError(
// @ts-expect-error This is "private" from users but intended for internal use

@@ -550,60 +469,36 @@ errorResponse.error || new Error("Unexpected Server Error"), serverMode), {

}
function getSingleFetchRedirect(response) {
return {
redirect: response.headers.get("Location"),
status: response.status,
revalidate:
// Technically X-Remix-Revalidate isn't needed here - that was an implementation
// detail of ?_data requests as our way to tell the front end to revalidate when
// we didn't have a response body to include that information in.
// With single fetch, we tell the front end via this revalidate boolean field.
// However, we're respecting it for now because it may be something folks have
// used in their own responses
// TODO(v3): Consider removing or making this official public API
response.headers.has("X-Remix-Revalidate") || response.headers.has("Set-Cookie"),
reload: response.headers.has("X-Remix-Reload-Document")
};
function createRemixRedirectResponse(response, basename) {
// We don't have any way to prevent a fetch request from following
// redirects. So we use the `X-Remix-Redirect` header to indicate the
// next URL, and then "follow" the redirect manually on the client.
let headers = new Headers(response.headers);
let redirectUrl = headers.get("Location");
headers.set("X-Remix-Redirect", basename ? stripBasename(redirectUrl, basename) || redirectUrl : redirectUrl);
headers.set("X-Remix-Status", String(response.status));
headers.delete("Location");
if (response.headers.get("Set-Cookie") !== null) {
headers.set("X-Remix-Revalidate", "yes");
}
return new Response(null, {
status: 204,
headers
});
}
// Note: If you change this function please change the corresponding
// decodeViaTurboStream function in server-runtime
function encodeViaTurboStream(data, requestSignal, streamTimeout, serverMode) {
let controller = new AbortController();
// How long are we willing to wait for all of the promises in `data` to resolve
// before timing out? We default this to 50ms shorter than the default value for
// `ABORT_DELAY` in our built-in `entry.server.tsx` so that once we reject we
// have time to flush the rejections down through React's rendering stream before `
// we call abort() on that. If the user provides their own it's up to them to
// decouple the aborting of the stream from the aborting of React's renderToPipeableStream
let timeoutId = setTimeout(() => controller.abort(new Error("Server Timeout")), typeof streamTimeout === "number" ? streamTimeout : 4950);
requestSignal.addEventListener("abort", () => clearTimeout(timeoutId));
return encode(data, {
signal: controller.signal,
plugins: [value => {
// Even though we sanitized errors on context.errors prior to responding,
// we still need to handle this for any deferred data that rejects with an
// Error - as those will not be sanitized yet
if (value instanceof Error) {
let {
name,
message,
stack
} = serverMode === ServerMode.Production ? sanitizeError(value, serverMode) : value;
return ["SanitizedError", name, message, stack];
}
if (value instanceof UNSAFE_ErrorResponseImpl) {
let {
data,
status,
statusText
} = value;
return ["ErrorResponse", data, status, statusText];
}
if (value && typeof value === "object" && SingleFetchRedirectSymbol in value) {
return ["SingleFetchRedirect", value[SingleFetchRedirectSymbol]];
}
}]
// Anytime we are setting a header on a `Response` created in the loader/action,
// we have to so it in this manner since in an `undici` world, if the `Response`
// came directly from a `fetch` call, the headers are immutable will throw if
// we try to set a new header. This is a sort of shallow clone of the `Response`
// so we can safely set our own header.
function safelySetHeader(response, name, value) {
let headers = new Headers(response.headers);
headers.set(name, value);
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers,
duplex: response.body ? "half" : undefined
});
}
export { SingleFetchRedirectSymbol, createRequestHandler };
export { createRequestHandler };
/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

import type { StaticHandlerContext } from "@remix-run/router";
import type { ServerBuild } from "./build";
export declare function getDocumentHeadersRR(build: ServerBuild, context: StaticHandlerContext): Headers;
export declare function getDocumentHeaders(build: ServerBuild, context: StaticHandlerContext): Headers;
/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

function getDocumentHeadersRR(build, context) {
function getDocumentHeaders(build, context) {
let boundaryIdx = context.errors ? context.matches.findIndex(m => context.errors[m.route.id]) : -1;

@@ -95,2 +95,2 @@ let matches = boundaryIdx >= 0 ? context.matches.slice(0, boundaryIdx + 1) : context.matches;

exports.getDocumentHeadersRR = getDocumentHeadersRR;
exports.getDocumentHeaders = getDocumentHeaders;
export { createCookieFactory, isCookie } from "./cookies";
export { composeUploadHandlers as unstable_composeUploadHandlers, parseMultipartFormData as unstable_parseMultipartFormData, } from "./formData";
export { defer, json, redirect, redirectDocument } from "./responses";
export type { SingleFetchResult as UNSAFE_SingleFetchResult, SingleFetchResults as UNSAFE_SingleFetchResults, } from "./server";
export { createRequestHandler, SingleFetchRedirectSymbol as UNSAFE_SingleFetchRedirectSymbol, } from "./server";
export { defer, json, redirect, redirectDocument, replace } from "./responses";
export { SingleFetchRedirectSymbol as UNSAFE_SingleFetchRedirectSymbol, data as unstable_data, defineLoader as unstable_defineLoader, defineAction as unstable_defineAction, } from "./single-fetch";
export type { Loader as unstable_Loader, Action as unstable_Action, Serialize as unstable_Serialize, SingleFetchResult as UNSAFE_SingleFetchResult, SingleFetchResults as UNSAFE_SingleFetchResults, } from "./single-fetch";
export { createRequestHandler } from "./server";
export { createSession, createSessionStorageFactory, isSession, } from "./sessions";

@@ -7,0 +8,0 @@ export { createCookieSessionStorageFactory } from "./sessions/cookieStorage";

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

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

@@ -37,3 +38,7 @@ var sessions = require('./sessions.js');

exports.redirectDocument = responses.redirectDocument;
exports.UNSAFE_SingleFetchRedirectSymbol = server.SingleFetchRedirectSymbol;
exports.replace = responses.replace;
exports.UNSAFE_SingleFetchRedirectSymbol = singleFetch.SingleFetchRedirectSymbol;
exports.unstable_data = singleFetch.data;
exports.unstable_defineAction = singleFetch.defineAction;
exports.unstable_defineLoader = singleFetch.defineLoader;
exports.createRequestHandler = server.createRequestHandler;

@@ -40,0 +45,0 @@ exports.createSession = sessions.createSession;

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

@@ -35,2 +35,9 @@ import { type UNSAFE_DeferredData as DeferredData } from "@remix-run/router";

/**
* A redirect response. Sets the status code and the `Location` header.
* Defaults to "302 Found".
*
* @see https://remix.run/utils/redirect
*/
export declare const replace: RedirectFunction;
/**
* A redirect response that will force a document reload to the new location.

@@ -37,0 +44,0 @@ * Sets the status code and the `Location` header.

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* A redirect response. Sets the status code and the `Location` header.
* Defaults to "302 Found".
*
* @see https://remix.run/utils/redirect
*/
const replace = (url, init = 302) => {
return router.replace(url, init);
};
/**
* A redirect response that will force a document reload to the new location.

@@ -137,1 +147,2 @@ * Sets the status code and the `Location` header.

exports.redirectDocument = redirectDocument;
exports.replace = replace;
/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

// though we know it'll always be provided in remix
args => data.callRouteLoaderRR({
(args, dataStrategyCtx) => data.callRouteLoader({
request: args.request,

@@ -63,3 +63,3 @@ params: args.params,

}) : undefined,
action: route.module.action ? args => data.callRouteActionRR({
action: route.module.action ? (args, dataStrategyCtx) => data.callRouteAction({
request: args.request,

@@ -66,0 +66,0 @@ params: args.params,

@@ -6,18 +6,1 @@ import type { AppLoadContext } from "./data";

export declare const createRequestHandler: CreateRequestHandlerFunction;
export declare const SingleFetchRedirectSymbol: unique symbol;
type SingleFetchRedirectResult = {
redirect: string;
status: number;
revalidate: boolean;
reload: boolean;
};
export type SingleFetchResult = {
data: unknown;
} | {
error: unknown;
} | SingleFetchRedirectResult;
export type SingleFetchResults = {
[key: string]: SingleFetchResult;
[SingleFetchRedirectSymbol]?: SingleFetchRedirectResult;
};
export {};
/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

var router = require('@remix-run/router');
var turboStream = require('turbo-stream');
var entry = require('./entry.js');

@@ -28,2 +27,4 @@ var errors = require('./errors.js');

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

@@ -82,4 +83,3 @@ function derive(build, mode$1) {

let url = new URL(request.url);
let matches = routeMatching.matchServerRoutes(routes, url.pathname, _build.basename);
let params = matches && matches.length > 0 ? matches[0].params : {};
let params = {};
let handleError = error => {

@@ -96,2 +96,21 @@ if (mode$1 === mode.ServerMode.Development) {

};
// Manifest request for fog of war
let manifestUrl = `${_build.basename ?? "/"}/__manifest`.replace(/\/+/g, "/");
if (url.pathname === manifestUrl) {
try {
let res = await handleManifestRequest(_build, routes, url);
return res;
} catch (e) {
handleError(e);
return new Response("Unknown Server Error", {
status: 500
});
}
}
let matches = routeMatching.matchServerRoutes(routes, url.pathname, _build.basename);
if (matches && matches.length > 0) {
Object.assign(params, matches[0].params);
}
let response;

@@ -110,2 +129,5 @@ if (url.searchParams.has("_data")) {

});
if (responses.isRedirectResponse(response)) {
response = createRemixRedirectResponse(response, _build.basename);
}
}

@@ -115,13 +137,27 @@ } else if (_build.future.unstable_singleFetch && url.pathname.endsWith(".data")) {

handlerUrl.pathname = handlerUrl.pathname.replace(/\.data$/, "").replace(/^\/_root$/, "/");
let matches = routeMatching.matchServerRoutes(routes, handlerUrl.pathname, _build.basename);
response = await handleSingleFetchRequest(serverMode, _build, staticHandler, matches, request, handlerUrl, loadContext, handleError);
let singleFetchMatches = routeMatching.matchServerRoutes(routes, handlerUrl.pathname, _build.basename);
response = await handleSingleFetchRequest(serverMode, _build, staticHandler, request, handlerUrl, loadContext, handleError);
if (_build.entry.module.handleDataRequest) {
response = await _build.entry.module.handleDataRequest(response, {
context: loadContext,
params,
params: singleFetchMatches ? singleFetchMatches[0].params : {},
request
});
if (responses.isRedirectResponse(response)) {
let result = singleFetch.getSingleFetchRedirect(response.status, response.headers, _build.basename);
if (request.method === "GET") {
result = {
[singleFetch.SingleFetchRedirectSymbol]: result
};
}
let headers = new Headers(response.headers);
headers.set("Content-Type", "text/x-script");
return new Response(singleFetch.encodeViaTurboStream(result, request.signal, _build.entry.module.streamTimeout, serverMode), {
status: singleFetch.SINGLE_FETCH_REDIRECT_STATUS,
headers
});
}
}
} else if (matches && matches[matches.length - 1].route.module.default == null && matches[matches.length - 1].route.module.ErrorBoundary == null) {
response = await handleResourceRequest(serverMode, staticHandler, matches.slice(-1)[0].route.id, request, loadContext, handleError);
response = await handleResourceRequest(serverMode, _build, staticHandler, matches.slice(-1)[0].route.id, request, loadContext, handleError);
} else {

@@ -142,2 +178,24 @@ var _getDevServerHooks2, _getDevServerHooks2$g;

};
async function handleManifestRequest(build, routes, url) {
let patches = {};
if (url.searchParams.has("p")) {
for (let path of url.searchParams.getAll("p")) {
let matches = routeMatching.matchServerRoutes(routes, path, build.basename);
if (matches) {
for (let match of matches) {
let routeId = match.route.id;
patches[routeId] = build.assets.routes[routeId];
}
}
}
return responses.json(patches, {
headers: {
"Cache-Control": "public, max-age=31536000, immutable"
}
}); // Override the TypedResponse stuff from json()
}
return new Response("Invalid Request", {
status: 400
});
}
async function handleDataRequest(serverMode, build, staticHandler, routeId, request, loadContext, handleError) {

@@ -150,17 +208,3 @@ try {

if (responses.isRedirectResponse(response)) {
// We don't have any way to prevent a fetch request from following
// redirects. So we use the `X-Remix-Redirect` header to indicate the
// next URL, and then "follow" the redirect manually on the client.
let headers = new Headers(response.headers);
let redirectUrl = headers.get("Location");
headers.set("X-Remix-Redirect", build.basename ? router.stripBasename(redirectUrl, build.basename) || redirectUrl : redirectUrl);
headers.set("X-Remix-Status", response.status);
headers.delete("Location");
if (response.headers.get("Set-Cookie") !== null) {
headers.set("X-Remix-Revalidate", "yes");
}
return new Response(null, {
status: 204,
headers
});
return createRemixRedirectResponse(response, build.basename);
}

@@ -182,8 +226,8 @@ if (router.UNSAFE_DEFERRED_SYMBOL in response) {

// network errors that are missing this header
response.headers.set("X-Remix-Response", "yes");
response = safelySetHeader(response, "X-Remix-Response", "yes");
return response;
} catch (error) {
if (responses.isResponse(error)) {
error.headers.set("X-Remix-Catch", "yes");
return error;
let response = safelySetHeader(error, "X-Remix-Catch", "yes");
return response;
}

@@ -204,4 +248,3 @@ if (router.isRouteErrorResponse(error)) {

}
const SingleFetchRedirectSymbol = Symbol("SingleFetchRedirect");
async function handleSingleFetchRequest(serverMode, build, staticHandler, matches, request, handlerUrl, loadContext, handleError) {
async function handleSingleFetchRequest(serverMode, build, staticHandler, request, handlerUrl, loadContext, handleError) {
let {

@@ -211,3 +254,3 @@ result,

status
} = request.method !== "GET" ? await singleFetchAction(request, handlerUrl, staticHandler, loadContext, handleError) : await singleFetchLoaders(request, handlerUrl, staticHandler, matches, loadContext, handleError, serverMode, build);
} = request.method !== "GET" ? await singleFetch.singleFetchAction(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError) : await singleFetch.singleFetchLoaders(build, serverMode, staticHandler, request, handlerUrl, loadContext, handleError);

@@ -218,7 +261,12 @@ // Mark all successful responses with a header so we can identify in-flight

resultHeaders.set("X-Remix-Response", "yes");
resultHeaders.set("Content-Type", "text/x-turbo");
// We use a less-descriptive `text/x-script` here instead of something like
// `text/x-turbo` to enable compression when deployed via Cloudflare. See:
// - https://github.com/remix-run/remix/issues/9884
// - https://developers.cloudflare.com/speed/optimization/content/brotli/content-compression/
resultHeaders.set("Content-Type", "text/x-script");
// Note: Deferred data is already just Promises, so we don't have to mess
// `activeDeferreds` or anything :)
return new Response(encodeViaTurboStream(result, request.signal, build.entry.module.streamTimeout, serverMode), {
return new Response(singleFetch.encodeViaTurboStream(result, request.signal, build.entry.module.streamTimeout, serverMode), {
status: status || 200,

@@ -228,134 +276,2 @@ headers: resultHeaders

}
async function singleFetchAction(request, handlerUrl, staticHandler, loadContext, handleError) {
try {
let handlerRequest = new Request(handlerUrl, {
method: request.method,
body: request.body,
headers: request.headers,
signal: request.signal,
...(request.body ? {
duplex: "half"
} : undefined)
});
let result = await staticHandler.queryRoute(handlerRequest, {
requestContext: loadContext
});
// Unlike `handleDataRequest`, when singleFetch is enabled, queryRoute does
// let non-Response return values through
if (!responses.isResponse(result)) {
return {
result: {
data: result
},
headers: new Headers(),
status: 200
};
}
if (responses.isRedirectResponse(result)) {
return {
result: getSingleFetchRedirect(result),
headers: result.headers,
status: 200 // Don't trigger a redirect on the `fetch`
};
}
return {
result: {
data: await unwrapResponse(result)
},
headers: result.headers,
status: result.status
};
} catch (error) {
if (responses.isResponse(error)) {
return {
result: {
error: new router.UNSAFE_ErrorResponseImpl(error.status, error.statusText, await unwrapResponse(error))
},
headers: error.headers,
status: error.status
};
} else {
handleError(error);
return {
result: {
error
},
headers: new Headers(),
status: router.isRouteErrorResponse(error) ? error.status : 500
};
}
}
}
async function singleFetchLoaders(request, handlerUrl, staticHandler, matches, loadContext, handleError, serverMode, build) {
try {
var _URL$searchParams$get;
let handlerRequest = new Request(handlerUrl, {
headers: request.headers,
signal: request.signal
});
let loadRouteIds = ((_URL$searchParams$get = new URL(request.url).searchParams.get("_routes")) === null || _URL$searchParams$get === void 0 ? void 0 : _URL$searchParams$get.split(",")) || undefined;
let result = await staticHandler.query(handlerRequest, {
requestContext: loadContext,
loadRouteIds,
skipLoaderErrorBubbling: true
});
if (responses.isResponse(result)) {
return {
result: {
[SingleFetchRedirectSymbol]: getSingleFetchRedirect(result)
},
headers: result.headers,
status: 200 // Don't want the `fetch` call to follow the redirect
};
}
let context = result;
// Sanitize errors outside of development environments
if (context.errors) {
Object.values(context.errors).forEach(err => {
// @ts-expect-error This is "private" from users but intended for internal use
if (!router.isRouteErrorResponse(err) || err.error) {
handleError(err);
}
});
context.errors = errors.sanitizeErrors(context.errors, serverMode);
}
// Aggregate results based on the matches we intended to load since we get
// `null` values back in `context.loaderData` for routes we didn't load
let results = {};
let loadedMatches = loadRouteIds ? context.matches.filter(m => m.route.loader && loadRouteIds.includes(m.route.id)) : context.matches;
loadedMatches.forEach(m => {
var _context$loaderData, _context$errors;
let data = (_context$loaderData = context.loaderData) === null || _context$loaderData === void 0 ? void 0 : _context$loaderData[m.route.id];
let error = (_context$errors = context.errors) === null || _context$errors === void 0 ? void 0 : _context$errors[m.route.id];
if (error !== undefined) {
results[m.route.id] = {
error
};
} else if (data !== undefined) {
results[m.route.id] = {
data
};
}
});
return {
result: results,
headers: headers.getDocumentHeadersRR(build, context),
status: context.statusCode
};
} catch (error) {
handleError(error);
return {
result: {
root: {
error
}
},
headers: new Headers(),
status: 500
};
}
}
async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, criticalCss) {

@@ -376,2 +292,3 @@ let context;

}
let headers$1 = headers.getDocumentHeaders(build, context);

@@ -381,3 +298,3 @@ // Sanitize errors outside of development environments

Object.values(context.errors).forEach(err => {
// @ts-expect-error This is "private" from users but intended for internal use
// @ts-expect-error `err.error` is "private" from users but intended for internal use
if (!router.isRouteErrorResponse(err) || err.error) {

@@ -389,3 +306,2 @@ handleError(err);

}
let headers$1 = headers.getDocumentHeadersRR(build, context);

@@ -406,3 +322,2 @@ // Server UI state to send to the client.

serverHandoffString: serverHandoff.createServerHandoffString({
url: context.location.pathname,
basename: build.basename,

@@ -417,3 +332,3 @@ criticalCss,

...(build.future.unstable_singleFetch ? {
serverHandoffStream: encodeViaTurboStream(state, request.signal, build.entry.module.streamTimeout, serverMode),
serverHandoffStream: singleFetch.encodeViaTurboStream(state, request.signal, build.entry.module.streamTimeout, serverMode),
renderMeta: {}

@@ -464,3 +379,2 @@ } : null),

serverHandoffString: serverHandoff.createServerHandoffString({
url: context.location.pathname,
basename: build.basename,

@@ -474,3 +388,3 @@ future: build.future,

...(build.future.unstable_singleFetch ? {
serverHandoffStream: encodeViaTurboStream(state, request.signal, build.entry.module.streamTimeout, serverMode),
serverHandoffStream: singleFetch.encodeViaTurboStream(state, request.signal, build.entry.module.streamTimeout, serverMode),
renderMeta: {}

@@ -487,3 +401,3 @@ } : null)

}
async function handleResourceRequest(serverMode, staticHandler, routeId, request, loadContext, handleError) {
async function handleResourceRequest(serverMode, build, staticHandler, routeId, request, loadContext, handleError) {
try {

@@ -497,5 +411,10 @@ // Note we keep the routeId here to align with the Remix handling of

});
if (typeof response === "object") {
if (typeof response === "object" && response !== null) {
invariant["default"](!(router.UNSAFE_DEFERRED_SYMBOL in response), `You cannot return a \`defer()\` response from a Resource Route. Did you ` + `forget to export a default UI component from the "${routeId}" route?`);
}
if (build.future.unstable_singleFetch && !responses.isResponse(response)) {
console.warn(deprecations.resourceRouteJsonWarning(request.method === "GET" ? "loader" : "action", routeId));
response = responses.json(response);
}
// callRouteLoader/callRouteAction always return responses (w/o single fetch).

@@ -509,4 +428,4 @@ // With single fetch, users should always be Responses from resource routes

// match identically to what Remix returns
error.headers.set("X-Remix-Catch", "yes");
return error;
let response = safelySetHeader(error, "X-Remix-Catch", "yes");
return response;
}

@@ -554,61 +473,36 @@ if (router.isRouteErrorResponse(error)) {

}
function getSingleFetchRedirect(response) {
return {
redirect: response.headers.get("Location"),
status: response.status,
revalidate:
// Technically X-Remix-Revalidate isn't needed here - that was an implementation
// detail of ?_data requests as our way to tell the front end to revalidate when
// we didn't have a response body to include that information in.
// With single fetch, we tell the front end via this revalidate boolean field.
// However, we're respecting it for now because it may be something folks have
// used in their own responses
// TODO(v3): Consider removing or making this official public API
response.headers.has("X-Remix-Revalidate") || response.headers.has("Set-Cookie"),
reload: response.headers.has("X-Remix-Reload-Document")
};
function createRemixRedirectResponse(response, basename) {
// We don't have any way to prevent a fetch request from following
// redirects. So we use the `X-Remix-Redirect` header to indicate the
// next URL, and then "follow" the redirect manually on the client.
let headers = new Headers(response.headers);
let redirectUrl = headers.get("Location");
headers.set("X-Remix-Redirect", basename ? router.stripBasename(redirectUrl, basename) || redirectUrl : redirectUrl);
headers.set("X-Remix-Status", String(response.status));
headers.delete("Location");
if (response.headers.get("Set-Cookie") !== null) {
headers.set("X-Remix-Revalidate", "yes");
}
return new Response(null, {
status: 204,
headers
});
}
// Note: If you change this function please change the corresponding
// decodeViaTurboStream function in server-runtime
function encodeViaTurboStream(data, requestSignal, streamTimeout, serverMode) {
let controller = new AbortController();
// How long are we willing to wait for all of the promises in `data` to resolve
// before timing out? We default this to 50ms shorter than the default value for
// `ABORT_DELAY` in our built-in `entry.server.tsx` so that once we reject we
// have time to flush the rejections down through React's rendering stream before `
// we call abort() on that. If the user provides their own it's up to them to
// decouple the aborting of the stream from the aborting of React's renderToPipeableStream
let timeoutId = setTimeout(() => controller.abort(new Error("Server Timeout")), typeof streamTimeout === "number" ? streamTimeout : 4950);
requestSignal.addEventListener("abort", () => clearTimeout(timeoutId));
return turboStream.encode(data, {
signal: controller.signal,
plugins: [value => {
// Even though we sanitized errors on context.errors prior to responding,
// we still need to handle this for any deferred data that rejects with an
// Error - as those will not be sanitized yet
if (value instanceof Error) {
let {
name,
message,
stack
} = serverMode === mode.ServerMode.Production ? errors.sanitizeError(value, serverMode) : value;
return ["SanitizedError", name, message, stack];
}
if (value instanceof router.UNSAFE_ErrorResponseImpl) {
let {
data,
status,
statusText
} = value;
return ["ErrorResponse", data, status, statusText];
}
if (value && typeof value === "object" && SingleFetchRedirectSymbol in value) {
return ["SingleFetchRedirect", value[SingleFetchRedirectSymbol]];
}
}]
// Anytime we are setting a header on a `Response` created in the loader/action,
// we have to so it in this manner since in an `undici` world, if the `Response`
// came directly from a `fetch` call, the headers are immutable will throw if
// we try to set a new header. This is a sort of shallow clone of the `Response`
// so we can safely set our own header.
function safelySetHeader(response, name, value) {
let headers = new Headers(response.headers);
headers.set(name, value);
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers,
duplex: response.body ? "half" : undefined
});
}
exports.SingleFetchRedirectSymbol = SingleFetchRedirectSymbol;
exports.createRequestHandler = createRequestHandler;

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

criticalCss?: string;
url: string;
basename: string | undefined;

@@ -10,0 +9,0 @@ future: FutureConfig;

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

/**
* @remix-run/server-runtime v0.0.0-experimental-419fc7d09
* @remix-run/server-runtime v0.0.0-experimental-432fae462
*

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

{
"name": "@remix-run/server-runtime",
"version": "0.0.0-experimental-419fc7d09",
"version": "0.0.0-experimental-432fae462",
"description": "Server runtime for Remix",

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

"dependencies": {
"@remix-run/router": "0.0.0-experimental-c7dd3d3a",
"@remix-run/router": "1.19.1",
"@types/cookie": "^0.6.0",

@@ -26,3 +26,3 @@ "@web3-storage/multipart-parser": "^1.0.0",

"source-map": "^0.7.3",
"turbo-stream": "^2.0.0"
"turbo-stream": "2.3.0"
},

@@ -29,0 +29,0 @@ "devDependencies": {

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