@remix-run/server-runtime
Advanced tools
Comparing version 0.0.0-experimental-149e932f to 0.0.0-experimental-21ec8370
import type { CookieParseOptions, CookieSerializeOptions } from "cookie"; | ||
import "./cookieSigning"; | ||
import type { SignFunction, UnsignFunction } from "./crypto"; | ||
export type { CookieParseOptions, CookieSerializeOptions }; | ||
@@ -23,2 +23,4 @@ export interface CookieSignatureOptions { | ||
* parsing/encoding multiple different values. | ||
* | ||
* @see https://remix.run/api/remix#cookie-api | ||
*/ | ||
@@ -52,6 +54,18 @@ export interface Cookie { | ||
} | ||
export declare type CreateCookieFunction = (name: string, cookieOptions?: CookieOptions) => Cookie; | ||
/** | ||
* Creates and returns a new Cookie. | ||
* Creates a logical container for managing a browser cookie from the server. | ||
* | ||
* @see https://remix.run/api/remix#createcookie | ||
*/ | ||
export declare function createCookie(name: string, { secrets, ...options }?: CookieOptions): Cookie; | ||
export declare function isCookie(object: any): object is Cookie; | ||
export declare const createCookieFactory: ({ sign, unsign, }: { | ||
sign: SignFunction; | ||
unsign: UnsignFunction; | ||
}) => CreateCookieFunction; | ||
export declare type IsCookieFunction = (object: any) => object is Cookie; | ||
/** | ||
* Returns true if an object is a Remix cookie container. | ||
* | ||
* @see https://remix.run/api/remix#iscookie | ||
*/ | ||
export declare const isCookie: IsCookieFunction; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -18,8 +18,18 @@ * Copyright (c) Remix Software Inc. | ||
/** | ||
* Creates and returns a new Cookie. | ||
* Creates a logical container for managing a browser cookie from the server. | ||
* | ||
* @see https://remix.run/api/remix#createcookie | ||
*/ | ||
function createCookie(name, { | ||
secrets = [], | ||
...options | ||
} = {}) { | ||
const createCookieFactory = ({ | ||
sign, | ||
unsign | ||
}) => (name, cookieOptions = {}) => { | ||
let { | ||
secrets, | ||
...options | ||
} = { | ||
secrets: [], | ||
path: "/", | ||
...cookieOptions | ||
}; | ||
return { | ||
@@ -44,7 +54,7 @@ get name() { | ||
}); | ||
return name in cookies ? cookies[name] === "" ? "" : await decodeCookieValue(cookies[name], secrets) : null; | ||
return name in cookies ? cookies[name] === "" ? "" : await decodeCookieValue(unsign, cookies[name], secrets) : null; | ||
}, | ||
async serialize(value, serializeOptions) { | ||
return cookie.serialize(name, value === "" ? "" : await encodeCookieValue(value, secrets), { ...options, | ||
return cookie.serialize(name, value === "" ? "" : await encodeCookieValue(sign, value, secrets), { ...options, | ||
...serializeOptions | ||
@@ -55,8 +65,14 @@ }); | ||
}; | ||
} | ||
function isCookie(object) { | ||
}; | ||
/** | ||
* Returns true if an object is a Remix cookie container. | ||
* | ||
* @see https://remix.run/api/remix#iscookie | ||
*/ | ||
const isCookie = object => { | ||
return object != null && typeof object.name === "string" && typeof object.isSigned === "boolean" && typeof object.parse === "function" && typeof object.serialize === "function"; | ||
} | ||
}; | ||
async function encodeCookieValue(value, secrets) { | ||
async function encodeCookieValue(sign, value, secrets) { | ||
let encoded = encodeData(value); | ||
@@ -71,3 +87,3 @@ | ||
async function decodeCookieValue(value, secrets) { | ||
async function decodeCookieValue(unsign, value, secrets) { | ||
if (secrets.length > 0) { | ||
@@ -100,3 +116,3 @@ for (let secret of secrets) { | ||
exports.createCookie = createCookie; | ||
exports.createCookieFactory = createCookieFactory; | ||
exports.isCookie = isCookie; |
@@ -12,3 +12,3 @@ import type { RouteMatch } from "./routeMatching"; | ||
export declare type AppData = any; | ||
export declare function callRouteAction({ loadContext, match, request }: { | ||
export declare function callRouteAction({ loadContext, match, request, }: { | ||
loadContext: unknown; | ||
@@ -18,3 +18,3 @@ match: RouteMatch<ServerRoute>; | ||
}): Promise<Response>; | ||
export declare function callRouteLoader({ loadContext, match, request }: { | ||
export declare function callRouteLoader({ loadContext, match, request, }: { | ||
request: Request; | ||
@@ -21,0 +21,0 @@ match: RouteMatch<ServerRoute>; |
16
data.js
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -30,3 +30,7 @@ * Copyright (c) Remix Software Inc. | ||
if (!action) { | ||
throw new Error(`You made a ${request.method} request to ${request.url} but did not provide ` + `an \`action\` for route "${match.route.id}", so there is no way to handle the ` + `request.`); | ||
let response = new Response(null, { | ||
status: 405 | ||
}); | ||
response.headers.set("X-Remix-Catch", "yes"); | ||
return response; | ||
} | ||
@@ -38,3 +42,3 @@ | ||
result = await action({ | ||
request: stripDataParam(stripIndexParam(request.clone())), | ||
request: stripDataParam(stripIndexParam(request)), | ||
context: loadContext, | ||
@@ -93,3 +97,3 @@ params: match.params | ||
if (result === undefined) { | ||
throw new Error(`You defined an action for route "${match.route.id}" but didn't return ` + `anything from your \`action\` function. Please return a value or \`null\`.`); | ||
throw new Error(`You defined a loader for route "${match.route.id}" but didn't return ` + `anything from your \`loader\` function. Please return a value or \`null\`.`); | ||
} | ||
@@ -116,3 +120,3 @@ | ||
return new Request(url.toString(), request); | ||
return new Request(url.href, request); | ||
} | ||
@@ -123,3 +127,3 @@ | ||
url.searchParams.delete("_data"); | ||
return new Request(url.toString(), request); | ||
return new Request(url.href, request); | ||
} | ||
@@ -126,0 +130,0 @@ |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -14,8 +14,18 @@ * Copyright (c) Remix Software Inc. | ||
/** | ||
* Creates and returns a new Cookie. | ||
* Creates a logical container for managing a browser cookie from the server. | ||
* | ||
* @see https://remix.run/api/remix#createcookie | ||
*/ | ||
function createCookie(name, { | ||
secrets = [], | ||
...options | ||
} = {}) { | ||
const createCookieFactory = ({ | ||
sign, | ||
unsign | ||
}) => (name, cookieOptions = {}) => { | ||
let { | ||
secrets, | ||
...options | ||
} = { | ||
secrets: [], | ||
path: "/", | ||
...cookieOptions | ||
}; | ||
return { | ||
@@ -40,7 +50,7 @@ get name() { | ||
}); | ||
return name in cookies ? cookies[name] === "" ? "" : await decodeCookieValue(cookies[name], secrets) : null; | ||
return name in cookies ? cookies[name] === "" ? "" : await decodeCookieValue(unsign, cookies[name], secrets) : null; | ||
}, | ||
async serialize(value, serializeOptions) { | ||
return serialize(name, value === "" ? "" : await encodeCookieValue(value, secrets), { ...options, | ||
return serialize(name, value === "" ? "" : await encodeCookieValue(sign, value, secrets), { ...options, | ||
...serializeOptions | ||
@@ -51,8 +61,14 @@ }); | ||
}; | ||
} | ||
function isCookie(object) { | ||
}; | ||
/** | ||
* Returns true if an object is a Remix cookie container. | ||
* | ||
* @see https://remix.run/api/remix#iscookie | ||
*/ | ||
const isCookie = object => { | ||
return object != null && typeof object.name === "string" && typeof object.isSigned === "boolean" && typeof object.parse === "function" && typeof object.serialize === "function"; | ||
} | ||
}; | ||
async function encodeCookieValue(value, secrets) { | ||
async function encodeCookieValue(sign, value, secrets) { | ||
let encoded = encodeData(value); | ||
@@ -67,3 +83,3 @@ | ||
async function decodeCookieValue(value, secrets) { | ||
async function decodeCookieValue(unsign, value, secrets) { | ||
if (secrets.length > 0) { | ||
@@ -96,2 +112,2 @@ for (let secret of secrets) { | ||
export { createCookie, isCookie }; | ||
export { createCookieFactory, isCookie }; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -26,3 +26,7 @@ * Copyright (c) Remix Software Inc. | ||
if (!action) { | ||
throw new Error(`You made a ${request.method} request to ${request.url} but did not provide ` + `an \`action\` for route "${match.route.id}", so there is no way to handle the ` + `request.`); | ||
let response = new Response(null, { | ||
status: 405 | ||
}); | ||
response.headers.set("X-Remix-Catch", "yes"); | ||
return response; | ||
} | ||
@@ -34,3 +38,3 @@ | ||
result = await action({ | ||
request: stripDataParam(stripIndexParam(request.clone())), | ||
request: stripDataParam(stripIndexParam(request)), | ||
context: loadContext, | ||
@@ -89,3 +93,3 @@ params: match.params | ||
if (result === undefined) { | ||
throw new Error(`You defined an action for route "${match.route.id}" but didn't return ` + `anything from your \`action\` function. Please return a value or \`null\`.`); | ||
throw new Error(`You defined a loader for route "${match.route.id}" but didn't return ` + `anything from your \`loader\` function. Please return a value or \`null\`.`); | ||
} | ||
@@ -112,3 +116,3 @@ | ||
return new Request(url.toString(), request); | ||
return new Request(url.href, request); | ||
} | ||
@@ -119,3 +123,3 @@ | ||
url.searchParams.delete("_data"); | ||
return new Request(url.toString(), request); | ||
return new Request(url.href, request); | ||
} | ||
@@ -122,0 +126,0 @@ |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -16,3 +16,4 @@ * Copyright (c) Remix Software Inc. | ||
let routeModule = build.routes[match.route.id].module; | ||
let loaderHeaders = routeLoaderResponses[index] ? routeLoaderResponses[index].headers : new Headers(); | ||
let routeLoaderResponse = routeLoaderResponses[match.route.id]; | ||
let loaderHeaders = routeLoaderResponse ? routeLoaderResponse.headers : new Headers(); | ||
let actionHeaders = actionResponse ? actionResponse.headers : new Headers(); | ||
@@ -19,0 +20,0 @@ let headers = new Headers(routeModule.headers ? typeof routeModule.headers === "function" ? routeModule.headers({ |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -11,7 +11,7 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
export { createCookie, isCookie } from './cookies.js'; | ||
export { createCookieFactory, isCookie } from './cookies.js'; | ||
export { json, redirect } from './responses.js'; | ||
export { createRequestHandler } from './server.js'; | ||
export { createSession, createSessionStorage, isSession } from './sessions.js'; | ||
export { createCookieSessionStorage } from './sessions/cookieStorage.js'; | ||
export { createMemorySessionStorage } from './sessions/memoryStorage.js'; | ||
export { createSession, createSessionStorageFactory, isSession } from './sessions.js'; | ||
export { createCookieSessionStorageFactory } from './sessions/cookieStorage.js'; | ||
export { createMemorySessionStorageFactory } from './sessions/memoryStorage.js'; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -12,5 +12,8 @@ * Copyright (c) Remix Software Inc. | ||
/** | ||
* A JSON response. Converts `data` to JSON and sets the `Content-Type` header. | ||
* This is a shortcut for creating `application/json` responses. Converts `data` | ||
* to JSON and sets the `Content-Type` header. | ||
* | ||
* @see https://remix.run/api/remix#json | ||
*/ | ||
function json(data, init = {}) { | ||
const json = (data, init = {}) => { | ||
let responseInit = init; | ||
@@ -33,9 +36,11 @@ | ||
}); | ||
} | ||
}; | ||
/** | ||
* A redirect response. Sets the status code and the `Location` header. | ||
* Defaults to "302 Found". | ||
* | ||
* @see https://remix.run/api/remix#redirect | ||
*/ | ||
function redirect(url, init = 302) { | ||
const redirect = (url, init = 302) => { | ||
let responseInit = init; | ||
@@ -56,3 +61,3 @@ | ||
}); | ||
} | ||
}; | ||
function isResponse(value) { | ||
@@ -59,0 +64,0 @@ return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined"; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -15,4 +15,4 @@ * Copyright (c) Remix Software Inc. | ||
import { getDocumentHeaders } from './headers.js'; | ||
import { isServerMode, ServerMode } from './mode.js'; | ||
import { matchServerRoutes } from './routeMatching.js'; | ||
import { isServerMode, ServerMode } from './mode.js'; | ||
import { createRoutes } from './routes.js'; | ||
@@ -22,12 +22,3 @@ import { isRedirectResponse, isCatchResponse, json } from './responses.js'; | ||
/** | ||
* The main request handler for a Remix server. This handler runs in the context | ||
* of a cloud provider's server (e.g. Express on Firebase) or locally via their | ||
* dev tools. | ||
*/ | ||
/** | ||
* Creates a function that serves HTTP requests. | ||
*/ | ||
function createRequestHandler(build, platform, mode) { | ||
const createRequestHandler = (build, mode) => { | ||
let routes = createRoutes(build.routes); | ||
@@ -38,35 +29,28 @@ let serverMode = isServerMode(mode) ? mode : ServerMode.Production; | ||
let matches = matchServerRoutes(routes, url.pathname); | ||
let requestType = getRequestType(url, matches); | ||
let response; | ||
switch (requestType) { | ||
case "data": | ||
response = await handleDataRequest({ | ||
request, | ||
loadContext, | ||
matches: matches, | ||
handleDataRequest: build.entry.module.handleDataRequest, | ||
serverMode | ||
}); | ||
break; | ||
case "document": | ||
response = await renderDocumentRequest({ | ||
build, | ||
loadContext, | ||
matches, | ||
request, | ||
routes, | ||
serverMode | ||
}); | ||
break; | ||
case "resource": | ||
response = await handleResourceRequest({ | ||
request, | ||
loadContext, | ||
matches: matches, | ||
serverMode | ||
}); | ||
break; | ||
if (url.searchParams.has("_data")) { | ||
response = await handleDataRequest({ | ||
request, | ||
loadContext, | ||
matches: matches, | ||
handleDataRequest: build.entry.module.handleDataRequest, | ||
serverMode | ||
}); | ||
} else if (matches && !matches[matches.length - 1].route.module.default) { | ||
response = await handleResourceRequest({ | ||
request, | ||
loadContext, | ||
matches, | ||
serverMode | ||
}); | ||
} else { | ||
response = await handleDocumentRequest({ | ||
build, | ||
loadContext, | ||
matches, | ||
request, | ||
routes, | ||
serverMode | ||
}); | ||
} | ||
@@ -84,3 +68,3 @@ | ||
}; | ||
} | ||
}; | ||
@@ -109,3 +93,3 @@ async function handleDataRequest({ | ||
if (isActionRequest(request)) { | ||
match = getActionRequestMatch(url, matches); | ||
match = getRequestMatch(url, matches); | ||
response = await callRouteAction({ | ||
@@ -144,2 +128,7 @@ loadContext, | ||
headers.delete("Location"); | ||
if (response.headers.get("Set-Cookie") !== null) { | ||
headers.set("X-Remix-Revalidate", "yes"); | ||
} | ||
return new Response(null, { | ||
@@ -173,3 +162,3 @@ status: 204, | ||
async function renderDocumentRequest({ | ||
async function handleDocumentRequest({ | ||
build, | ||
@@ -216,3 +205,3 @@ loadContext, | ||
if (matches && isActionRequest(request)) { | ||
actionMatch = getActionRequestMatch(url, matches); | ||
actionMatch = getRequestMatch(url, matches); | ||
@@ -286,3 +275,3 @@ try { | ||
let actionCatchBoundaryRouteId = appState.catchBoundaryRouteId; | ||
let actionLoaderBoundaryRouteId = appState.loaderBoundaryRouteId; // Reset the app error and catch state to propogate the loader states | ||
let actionLoaderBoundaryRouteId = appState.loaderBoundaryRouteId; // Reset the app error and catch state to propagate the loader states | ||
// from the results into the app state. | ||
@@ -292,3 +281,3 @@ | ||
appState.error = undefined; | ||
let routeLoaderResponses = []; | ||
let routeLoaderResponses = {}; | ||
let loaderStatusCodes = []; | ||
@@ -339,3 +328,3 @@ let routeData = {}; | ||
} else if (response) { | ||
routeLoaderResponses.push(response); | ||
routeLoaderResponses[match.route.id] = response; | ||
loaderStatusCodes.push(response.status); | ||
@@ -491,20 +480,2 @@ | ||
function getRequestType(url, matches) { | ||
if (url.searchParams.has("_data")) { | ||
return "data"; | ||
} | ||
if (!matches) { | ||
return "document"; | ||
} | ||
let match = matches.slice(-1)[0]; | ||
if (!match.route.module.default) { | ||
return "resource"; | ||
} | ||
return "document"; | ||
} | ||
function isActionRequest(request) { | ||
@@ -533,14 +504,17 @@ let method = request.method.toLowerCase(); | ||
function isIndexRequestUrl(url) { | ||
let indexRequest = false; | ||
for (let param of url.searchParams.getAll("index")) { | ||
if (!param) { | ||
indexRequest = true; | ||
// only use bare `?index` params without a value | ||
// ✅ /foo?index | ||
// ✅ /foo?index&index=123 | ||
// ✅ /foo?index=123&index | ||
// ❌ /foo?index=123 | ||
if (param === "") { | ||
return true; | ||
} | ||
} | ||
return indexRequest; | ||
return false; | ||
} | ||
function getActionRequestMatch(url, matches) { | ||
function getRequestMatch(url, matches) { | ||
let match = matches.slice(-1)[0]; | ||
@@ -547,0 +521,0 @@ |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -11,3 +11,3 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
import { isCookie, createCookie } from './cookies.js'; | ||
import { isCookie } from './cookies.js'; | ||
import { warnOnce } from './warnings.js'; | ||
@@ -22,2 +22,3 @@ | ||
} | ||
/** | ||
@@ -28,6 +29,6 @@ * Creates a new Session object. | ||
* Instead, use a `SessionStorage` object's `getSession` method. | ||
* | ||
* @see https://remix.run/api/remix#createsession | ||
*/ | ||
function createSession(initialData = {}, id = "") { | ||
const createSession = (initialData = {}, id = "") => { | ||
let map = new Map(Object.entries(initialData)); | ||
@@ -73,6 +74,12 @@ return { | ||
}; | ||
} | ||
function isSession(object) { | ||
}; | ||
/** | ||
* Returns true if an object is a Remix session. | ||
* | ||
* @see https://remix.run/api/remix#issession | ||
*/ | ||
const isSession = object => { | ||
return object != null && typeof object.id === "string" && typeof object.data !== "undefined" && typeof object.has === "function" && typeof object.get === "function" && typeof object.set === "function" && typeof object.flash === "function" && typeof object.unset === "function"; | ||
} | ||
}; | ||
/** | ||
@@ -91,4 +98,6 @@ * SessionStorage stores session data between HTTP requests and knows how to | ||
* existing session storage options meet your requirements. | ||
* | ||
* @see https://remix.run/api/remix#createsessionstorage | ||
*/ | ||
function createSessionStorage({ | ||
const createSessionStorageFactory = createCookie => ({ | ||
cookie: cookieArg, | ||
@@ -99,3 +108,3 @@ createData, | ||
deleteData | ||
}) { | ||
}) => { | ||
let cookie = isCookie(cookieArg) ? cookieArg : createCookie((cookieArg === null || cookieArg === void 0 ? void 0 : cookieArg.name) || "__session", cookieArg); | ||
@@ -133,7 +142,7 @@ warnOnceAboutSigningSessionCookie(cookie); | ||
}; | ||
} | ||
}; | ||
function warnOnceAboutSigningSessionCookie(cookie) { | ||
warnOnce(cookie.isSigned, `The "${cookie.name}" cookie is not signed, but session cookies should be ` + `signed to prevent tampering on the client before they are sent back to the ` + `server. See https://remix.run/docs/en/v1/api/remix#signing-cookies ` + `for more information.`); | ||
warnOnce(cookie.isSigned, `The "${cookie.name}" cookie is not signed, but session cookies should be ` + `signed to prevent tampering on the client before they are sent back to the ` + `server. See https://remix.run/api/remix#signing-cookies ` + `for more information.`); | ||
} | ||
export { createSession, createSessionStorage, isSession, warnOnceAboutSigningSessionCookie }; | ||
export { createSession, createSessionStorageFactory, isSession, warnOnceAboutSigningSessionCookie }; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -11,3 +11,3 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
import { isCookie, createCookie } from '../cookies.js'; | ||
import { isCookie } from '../cookies.js'; | ||
import { warnOnceAboutSigningSessionCookie, createSession } from '../sessions.js'; | ||
@@ -23,6 +23,8 @@ | ||
* browser's maximum cookie size. Trade-offs! | ||
* | ||
* @see https://remix.run/api/remix#createcookiesessionstorage | ||
*/ | ||
function createCookieSessionStorage({ | ||
const createCookieSessionStorageFactory = createCookie => ({ | ||
cookie: cookieArg | ||
} = {}) { | ||
} = {}) => { | ||
let cookie = isCookie(cookieArg) ? cookieArg : createCookie((cookieArg === null || cookieArg === void 0 ? void 0 : cookieArg.name) || "__session", cookieArg); | ||
@@ -36,3 +38,9 @@ warnOnceAboutSigningSessionCookie(cookie); | ||
async commitSession(session, options) { | ||
return cookie.serialize(session.data, options); | ||
let serializedCookie = await cookie.serialize(session.data, options); | ||
if (serializedCookie.length > 4096) { | ||
throw new Error("Cookie length will exceed browser maximum. Length: " + serializedCookie.length); | ||
} | ||
return serializedCookie; | ||
}, | ||
@@ -47,4 +55,4 @@ | ||
}; | ||
} | ||
}; | ||
export { createCookieSessionStorage }; | ||
export { createCookieSessionStorageFactory }; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -11,4 +11,2 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
import { createSessionStorage } from '../sessions.js'; | ||
/** | ||
@@ -20,6 +18,8 @@ * Creates and returns a simple in-memory SessionStorage object, mostly useful | ||
* suitable for most production scenarios. | ||
* | ||
* @see https://remix.run/api/remix#creatememorysessionstorage | ||
*/ | ||
function createMemorySessionStorage({ | ||
const createMemorySessionStorageFactory = createSessionStorage => ({ | ||
cookie | ||
} = {}) { | ||
} = {}) => { | ||
let uniqueId = 0; | ||
@@ -69,4 +69,4 @@ let map = new Map(); | ||
}); | ||
} | ||
}; | ||
export { createMemorySessionStorage }; | ||
export { createMemorySessionStorageFactory }; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
import type { ServerBuild } from "./build"; | ||
import type { ServerRoute } from "./routes"; | ||
import type { RouteMatch } from "./routeMatching"; | ||
export declare function getDocumentHeaders(build: ServerBuild, matches: RouteMatch<ServerRoute>[], routeLoaderResponses: Response[], actionResponse?: Response): Headers; | ||
export declare function getDocumentHeaders(build: ServerBuild, matches: RouteMatch<ServerRoute>[], routeLoaderResponses: Record<string, Response>, actionResponse?: Response): Headers; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -20,3 +20,4 @@ * Copyright (c) Remix Software Inc. | ||
let routeModule = build.routes[match.route.id].module; | ||
let loaderHeaders = routeLoaderResponses[index] ? routeLoaderResponses[index].headers : new Headers(); | ||
let routeLoaderResponse = routeLoaderResponses[match.route.id]; | ||
let loaderHeaders = routeLoaderResponse ? routeLoaderResponse.headers : new Headers(); | ||
let actionHeaders = actionResponse ? actionResponse.headers : new Headers(); | ||
@@ -23,0 +24,0 @@ let headers = new Headers(routeModule.headers ? typeof routeModule.headers === "function" ? routeModule.headers({ |
@@ -1,15 +0,8 @@ | ||
export type { ServerBuild, ServerEntryModule, HandleDataRequestFunction, HandleDocumentRequestFunction } from "./build"; | ||
export type { CookieParseOptions, CookieSerializeOptions, CookieSignatureOptions, CookieOptions, Cookie } from "./cookies"; | ||
export { createCookie, isCookie } from "./cookies"; | ||
export type { AppLoadContext, AppData } from "./data"; | ||
export type { EntryContext } from "./entry"; | ||
export type { LinkDescriptor, HtmlLinkDescriptor, PageLinkDescriptor } from "./links"; | ||
export type { ServerPlatform } from "./platform"; | ||
export type { ActionFunction, DataFunctionArgs, ErrorBoundaryComponent, HeadersFunction, HtmlMetaDescriptor, LinksFunction, LoaderFunction, MetaDescriptor, MetaFunction, RouteComponent, RouteHandle } from "./routeModules"; | ||
export { createCookieFactory, isCookie } from "./cookies"; | ||
export { json, redirect } from "./responses"; | ||
export type { RequestHandler } from "./server"; | ||
export { createRequestHandler } from "./server"; | ||
export type { SessionData, Session, SessionStorage, SessionIdStorageStrategy } from "./sessions"; | ||
export { createSession, isSession, createSessionStorage } from "./sessions"; | ||
export { createCookieSessionStorage } from "./sessions/cookieStorage"; | ||
export { createMemorySessionStorage } from "./sessions/memoryStorage"; | ||
export { createSession, isSession, createSessionStorageFactory, } from "./sessions"; | ||
export { createCookieSessionStorageFactory } from "./sessions/cookieStorage"; | ||
export { createMemorySessionStorageFactory } from "./sessions/memoryStorage"; | ||
export type { CreateCookieFunction, CreateCookieSessionStorageFunction, CreateMemorySessionStorageFunction, CreateRequestHandlerFunction, CreateSessionFunction, CreateSessionStorageFunction, IsCookieFunction, IsSessionFunction, JsonFunction, RedirectFunction, } from "./interface"; | ||
export type { ActionFunction, AppData, AppLoadContext, Cookie, CookieOptions, CookieParseOptions, CookieSerializeOptions, CookieSignatureOptions, DataFunctionArgs, EntryContext, ErrorBoundaryComponent, HandleDataRequestFunction, HandleDocumentRequestFunction, HeadersFunction, HtmlLinkDescriptor, HtmlMetaDescriptor, LinkDescriptor, LinksFunction, LoaderFunction, MetaDescriptor, MetaFunction, PageLinkDescriptor, RequestHandler, RouteComponent, RouteHandle, ServerBuild, ServerEntryModule, Session, SessionData, SessionIdStorageStrategy, SessionStorage, SignFunction, UnsignFunction, } from "./reexport"; |
10
index.js
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -24,3 +24,3 @@ * Copyright (c) Remix Software Inc. | ||
exports.createCookie = cookies.createCookie; | ||
exports.createCookieFactory = cookies.createCookieFactory; | ||
exports.isCookie = cookies.isCookie; | ||
@@ -31,5 +31,5 @@ exports.json = responses.json; | ||
exports.createSession = sessions.createSession; | ||
exports.createSessionStorage = sessions.createSessionStorage; | ||
exports.createSessionStorageFactory = sessions.createSessionStorageFactory; | ||
exports.isSession = sessions.isSession; | ||
exports.createCookieSessionStorage = cookieStorage.createCookieSessionStorage; | ||
exports.createMemorySessionStorage = memoryStorage.createMemorySessionStorage; | ||
exports.createCookieSessionStorageFactory = cookieStorage.createCookieSessionStorageFactory; | ||
exports.createMemorySessionStorageFactory = memoryStorage.createMemorySessionStorageFactory; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
{ | ||
"name": "@remix-run/server-runtime", | ||
"description": "Server runtime for Remix", | ||
"version": "0.0.0-experimental-149e932f", | ||
"version": "0.0.0-experimental-21ec8370", | ||
"license": "MIT", | ||
@@ -20,3 +20,3 @@ "main": "./index.js", | ||
"jsesc": "^3.0.1", | ||
"react-router-dom": "^6.1.1", | ||
"react-router-dom": "^6.2.2", | ||
"set-cookie-parser": "^2.4.8", | ||
@@ -23,0 +23,0 @@ "source-map": "^0.7.3" |
@@ -1,13 +0,26 @@ | ||
# Welcome to Remix! | ||
# @remix-run/server-runtime | ||
[Remix](https://remix.run) is a web framework that helps you build better websites with React. | ||
[Remix](https://remix.run) supports multiple server runtimes: | ||
To get started, open a new shell and run: | ||
- [Node](https://nodejs.org/en/) | ||
- [Cloudflare](https://developers.cloudflare.com/workers/learning/how-workers-works/) | ||
- [Deno](https://deno.land/) (Experimental 🧪) | ||
```sh | ||
$ npx create-remix@latest | ||
``` | ||
Support for each runtime is provided by a corresponding Remix package: | ||
Then follow the prompts you see in your terminal. | ||
- [`@remix-run/node`](https://github.com/remix-run/remix/tree/main/packages/remix-node) | ||
- [`@remix-run/cloudflare`](https://github.com/remix-run/remix/tree/main/packages/remix-cloudflare) | ||
- [`remix-deno`](https://github.com/remix-run/remix/tree/main/templates/deno-ts/remix-deno) (will be renamed to `@remix-run/deno` when Deno support is stable) | ||
For more information about Remix, [visit remix.run](https://remix.run)! | ||
This package defines a "Remix server runtime interface" that each runtime package must conform to. | ||
Each Remix server runtime package MUST: | ||
- Implement and export values for each type in [`interface.ts`](./interface.ts) | ||
- Re-export types in [`reexport.ts`](./reexport.ts) | ||
Each Remix server runtime package MAY: | ||
- Re-export the [default implementations](./index.ts) as its implementations | ||
- Export custom implementations adhering to the [interface types](./interface.ts) | ||
- Provide additional exports relevant for that runtime |
@@ -0,10 +1,17 @@ | ||
export declare type JsonFunction = <Data>(data: Data, init?: number | ResponseInit) => Response; | ||
/** | ||
* A JSON response. Converts `data` to JSON and sets the `Content-Type` header. | ||
* This is a shortcut for creating `application/json` responses. Converts `data` | ||
* to JSON and sets the `Content-Type` header. | ||
* | ||
* @see https://remix.run/api/remix#json | ||
*/ | ||
export declare function json<Data>(data: Data, init?: number | ResponseInit): Response; | ||
export declare const json: JsonFunction; | ||
export declare type RedirectFunction = (url: string, init?: number | ResponseInit) => Response; | ||
/** | ||
* A redirect response. Sets the status code and the `Location` header. | ||
* Defaults to "302 Found". | ||
* | ||
* @see https://remix.run/api/remix#redirect | ||
*/ | ||
export declare function redirect(url: string, init?: number | ResponseInit): Response; | ||
export declare const redirect: RedirectFunction; | ||
export declare function isResponse(value: any): value is Response; | ||
@@ -11,0 +18,0 @@ export declare function isRedirectResponse(response: Response): boolean; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -16,5 +16,8 @@ * Copyright (c) Remix Software Inc. | ||
/** | ||
* A JSON response. Converts `data` to JSON and sets the `Content-Type` header. | ||
* This is a shortcut for creating `application/json` responses. Converts `data` | ||
* to JSON and sets the `Content-Type` header. | ||
* | ||
* @see https://remix.run/api/remix#json | ||
*/ | ||
function json(data, init = {}) { | ||
const json = (data, init = {}) => { | ||
let responseInit = init; | ||
@@ -37,9 +40,11 @@ | ||
}); | ||
} | ||
}; | ||
/** | ||
* A redirect response. Sets the status code and the `Location` header. | ||
* Defaults to "302 Found". | ||
* | ||
* @see https://remix.run/api/remix#redirect | ||
*/ | ||
function redirect(url, init = 302) { | ||
const redirect = (url, init = 302) => { | ||
let responseInit = init; | ||
@@ -60,3 +65,3 @@ | ||
}); | ||
} | ||
}; | ||
function isResponse(value) { | ||
@@ -63,0 +68,0 @@ return value != null && typeof value.status === "number" && typeof value.statusText === "string" && typeof value.headers === "object" && typeof value.body !== "undefined"; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
@@ -78,3 +78,6 @@ import type { Location } from "history"; | ||
export interface HtmlMetaDescriptor { | ||
[name: string]: string | string[]; | ||
charset?: "utf-8"; | ||
charSet?: "utf-8"; | ||
title?: string; | ||
[name: string]: null | string | string[] | undefined | Record<string, string> | Record<string, string>[]; | ||
} | ||
@@ -81,0 +84,0 @@ export declare type MetaDescriptor = HtmlMetaDescriptor; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
import type { AppLoadContext } from "./data"; | ||
import type { ServerBuild } from "./build"; | ||
import type { ServerPlatform } from "./platform"; | ||
/** | ||
* The main request handler for a Remix server. This handler runs in the context | ||
* of a cloud provider's server (e.g. Express on Firebase) or locally via their | ||
* dev tools. | ||
*/ | ||
export interface RequestHandler { | ||
(request: Request, loadContext?: AppLoadContext): Promise<Response>; | ||
} | ||
/** | ||
* Creates a function that serves HTTP requests. | ||
*/ | ||
export declare function createRequestHandler(build: ServerBuild, platform: ServerPlatform, mode?: string): RequestHandler; | ||
export declare type RequestHandler = (request: Request, loadContext?: AppLoadContext) => Promise<Response>; | ||
export declare type CreateRequestHandlerFunction = (build: ServerBuild, mode?: string) => RequestHandler; | ||
export declare const createRequestHandler: CreateRequestHandlerFunction; |
122
server.js
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -19,4 +19,4 @@ * Copyright (c) Remix Software Inc. | ||
var headers = require('./headers.js'); | ||
var mode = require('./mode.js'); | ||
var routeMatching = require('./routeMatching.js'); | ||
var mode = require('./mode.js'); | ||
var routes = require('./routes.js'); | ||
@@ -26,12 +26,3 @@ var responses = require('./responses.js'); | ||
/** | ||
* The main request handler for a Remix server. This handler runs in the context | ||
* of a cloud provider's server (e.g. Express on Firebase) or locally via their | ||
* dev tools. | ||
*/ | ||
/** | ||
* Creates a function that serves HTTP requests. | ||
*/ | ||
function createRequestHandler(build, platform, mode$1) { | ||
const createRequestHandler = (build, mode$1) => { | ||
let routes$1 = routes.createRoutes(build.routes); | ||
@@ -42,35 +33,28 @@ let serverMode = mode.isServerMode(mode$1) ? mode$1 : mode.ServerMode.Production; | ||
let matches = routeMatching.matchServerRoutes(routes$1, url.pathname); | ||
let requestType = getRequestType(url, matches); | ||
let response; | ||
switch (requestType) { | ||
case "data": | ||
response = await handleDataRequest({ | ||
request, | ||
loadContext, | ||
matches: matches, | ||
handleDataRequest: build.entry.module.handleDataRequest, | ||
serverMode | ||
}); | ||
break; | ||
case "document": | ||
response = await renderDocumentRequest({ | ||
build, | ||
loadContext, | ||
matches, | ||
request, | ||
routes: routes$1, | ||
serverMode | ||
}); | ||
break; | ||
case "resource": | ||
response = await handleResourceRequest({ | ||
request, | ||
loadContext, | ||
matches: matches, | ||
serverMode | ||
}); | ||
break; | ||
if (url.searchParams.has("_data")) { | ||
response = await handleDataRequest({ | ||
request, | ||
loadContext, | ||
matches: matches, | ||
handleDataRequest: build.entry.module.handleDataRequest, | ||
serverMode | ||
}); | ||
} else if (matches && !matches[matches.length - 1].route.module.default) { | ||
response = await handleResourceRequest({ | ||
request, | ||
loadContext, | ||
matches, | ||
serverMode | ||
}); | ||
} else { | ||
response = await handleDocumentRequest({ | ||
build, | ||
loadContext, | ||
matches, | ||
request, | ||
routes: routes$1, | ||
serverMode | ||
}); | ||
} | ||
@@ -88,3 +72,3 @@ | ||
}; | ||
} | ||
}; | ||
@@ -113,3 +97,3 @@ async function handleDataRequest({ | ||
if (isActionRequest(request)) { | ||
match = getActionRequestMatch(url, matches); | ||
match = getRequestMatch(url, matches); | ||
response = await data.callRouteAction({ | ||
@@ -148,2 +132,7 @@ loadContext, | ||
headers.delete("Location"); | ||
if (response.headers.get("Set-Cookie") !== null) { | ||
headers.set("X-Remix-Revalidate", "yes"); | ||
} | ||
return new Response(null, { | ||
@@ -177,3 +166,3 @@ status: 204, | ||
async function renderDocumentRequest({ | ||
async function handleDocumentRequest({ | ||
build, | ||
@@ -220,3 +209,3 @@ loadContext, | ||
if (matches && isActionRequest(request)) { | ||
actionMatch = getActionRequestMatch(url, matches); | ||
actionMatch = getRequestMatch(url, matches); | ||
@@ -290,3 +279,3 @@ try { | ||
let actionCatchBoundaryRouteId = appState.catchBoundaryRouteId; | ||
let actionLoaderBoundaryRouteId = appState.loaderBoundaryRouteId; // Reset the app error and catch state to propogate the loader states | ||
let actionLoaderBoundaryRouteId = appState.loaderBoundaryRouteId; // Reset the app error and catch state to propagate the loader states | ||
// from the results into the app state. | ||
@@ -296,3 +285,3 @@ | ||
appState.error = undefined; | ||
let routeLoaderResponses = []; | ||
let routeLoaderResponses = {}; | ||
let loaderStatusCodes = []; | ||
@@ -343,3 +332,3 @@ let routeData = {}; | ||
} else if (response) { | ||
routeLoaderResponses.push(response); | ||
routeLoaderResponses[match.route.id] = response; | ||
loaderStatusCodes.push(response.status); | ||
@@ -495,20 +484,2 @@ | ||
function getRequestType(url, matches) { | ||
if (url.searchParams.has("_data")) { | ||
return "data"; | ||
} | ||
if (!matches) { | ||
return "document"; | ||
} | ||
let match = matches.slice(-1)[0]; | ||
if (!match.route.module.default) { | ||
return "resource"; | ||
} | ||
return "document"; | ||
} | ||
function isActionRequest(request) { | ||
@@ -537,14 +508,17 @@ let method = request.method.toLowerCase(); | ||
function isIndexRequestUrl(url) { | ||
let indexRequest = false; | ||
for (let param of url.searchParams.getAll("index")) { | ||
if (!param) { | ||
indexRequest = true; | ||
// only use bare `?index` params without a value | ||
// ✅ /foo?index | ||
// ✅ /foo?index&index=123 | ||
// ✅ /foo?index=123&index | ||
// ❌ /foo?index=123 | ||
if (param === "") { | ||
return true; | ||
} | ||
} | ||
return indexRequest; | ||
return false; | ||
} | ||
function getActionRequestMatch(url, matches) { | ||
function getRequestMatch(url, matches) { | ||
let match = matches.slice(-1)[0]; | ||
@@ -551,0 +525,0 @@ |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
import type { CookieParseOptions, CookieSerializeOptions } from "cookie"; | ||
import type { Cookie, CookieOptions } from "./cookies"; | ||
import type { Cookie, CookieOptions, CreateCookieFunction } from "./cookies"; | ||
/** | ||
@@ -11,2 +11,4 @@ * An object of name/value pairs to be used in the session. | ||
* Session persists data across HTTP requests. | ||
* | ||
* @see https://remix.run/api/remix#session-api | ||
*/ | ||
@@ -51,2 +53,3 @@ export interface Session { | ||
} | ||
export declare type CreateSessionFunction = (initialData?: SessionData, id?: string) => Session; | ||
/** | ||
@@ -57,6 +60,14 @@ * Creates a new Session object. | ||
* Instead, use a `SessionStorage` object's `getSession` method. | ||
* | ||
* @see https://remix.run/api/remix#createsession | ||
*/ | ||
export declare function createSession(initialData?: SessionData, id?: string): Session; | ||
export declare function isSession(object: any): object is Session; | ||
export declare const createSession: CreateSessionFunction; | ||
export declare type IsSessionFunction = (object: any) => object is Session; | ||
/** | ||
* Returns true if an object is a Remix session. | ||
* | ||
* @see https://remix.run/api/remix#issession | ||
*/ | ||
export declare const isSession: IsSessionFunction; | ||
/** | ||
* SessionStorage stores session data between HTTP requests and knows how to | ||
@@ -120,2 +131,3 @@ * parse and create cookies. | ||
} | ||
export declare type CreateSessionStorageFunction = (strategy: SessionIdStorageStrategy) => SessionStorage; | ||
/** | ||
@@ -126,4 +138,6 @@ * Creates a SessionStorage object using a SessionIdStorageStrategy. | ||
* existing session storage options meet your requirements. | ||
* | ||
* @see https://remix.run/api/remix#createsessionstorage | ||
*/ | ||
export declare function createSessionStorage({ cookie: cookieArg, createData, readData, updateData, deleteData }: SessionIdStorageStrategy): SessionStorage; | ||
export declare const createSessionStorageFactory: (createCookie: CreateCookieFunction) => CreateSessionStorageFunction; | ||
export declare function warnOnceAboutSigningSessionCookie(cookie: Cookie): void; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -25,2 +25,3 @@ * Copyright (c) Remix Software Inc. | ||
} | ||
/** | ||
@@ -31,6 +32,6 @@ * Creates a new Session object. | ||
* Instead, use a `SessionStorage` object's `getSession` method. | ||
* | ||
* @see https://remix.run/api/remix#createsession | ||
*/ | ||
function createSession(initialData = {}, id = "") { | ||
const createSession = (initialData = {}, id = "") => { | ||
let map = new Map(Object.entries(initialData)); | ||
@@ -76,6 +77,12 @@ return { | ||
}; | ||
} | ||
function isSession(object) { | ||
}; | ||
/** | ||
* Returns true if an object is a Remix session. | ||
* | ||
* @see https://remix.run/api/remix#issession | ||
*/ | ||
const isSession = object => { | ||
return object != null && typeof object.id === "string" && typeof object.data !== "undefined" && typeof object.has === "function" && typeof object.get === "function" && typeof object.set === "function" && typeof object.flash === "function" && typeof object.unset === "function"; | ||
} | ||
}; | ||
/** | ||
@@ -94,4 +101,6 @@ * SessionStorage stores session data between HTTP requests and knows how to | ||
* existing session storage options meet your requirements. | ||
* | ||
* @see https://remix.run/api/remix#createsessionstorage | ||
*/ | ||
function createSessionStorage({ | ||
const createSessionStorageFactory = createCookie => ({ | ||
cookie: cookieArg, | ||
@@ -102,4 +111,4 @@ createData, | ||
deleteData | ||
}) { | ||
let cookie = cookies.isCookie(cookieArg) ? cookieArg : cookies.createCookie((cookieArg === null || cookieArg === void 0 ? void 0 : cookieArg.name) || "__session", cookieArg); | ||
}) => { | ||
let cookie = cookies.isCookie(cookieArg) ? cookieArg : createCookie((cookieArg === null || cookieArg === void 0 ? void 0 : cookieArg.name) || "__session", cookieArg); | ||
warnOnceAboutSigningSessionCookie(cookie); | ||
@@ -136,10 +145,10 @@ return { | ||
}; | ||
} | ||
}; | ||
function warnOnceAboutSigningSessionCookie(cookie) { | ||
warnings.warnOnce(cookie.isSigned, `The "${cookie.name}" cookie is not signed, but session cookies should be ` + `signed to prevent tampering on the client before they are sent back to the ` + `server. See https://remix.run/docs/en/v1/api/remix#signing-cookies ` + `for more information.`); | ||
warnings.warnOnce(cookie.isSigned, `The "${cookie.name}" cookie is not signed, but session cookies should be ` + `signed to prevent tampering on the client before they are sent back to the ` + `server. See https://remix.run/api/remix#signing-cookies ` + `for more information.`); | ||
} | ||
exports.createSession = createSession; | ||
exports.createSessionStorage = createSessionStorage; | ||
exports.createSessionStorageFactory = createSessionStorageFactory; | ||
exports.isSession = isSession; | ||
exports.warnOnceAboutSigningSessionCookie = warnOnceAboutSigningSessionCookie; |
@@ -0,1 +1,2 @@ | ||
import type { CreateCookieFunction } from "../cookies"; | ||
import type { SessionStorage, SessionIdStorageStrategy } from "../sessions"; | ||
@@ -9,2 +10,3 @@ interface CookieSessionStorageOptions { | ||
} | ||
export declare type CreateCookieSessionStorageFunction = (options?: CookieSessionStorageOptions) => SessionStorage; | ||
/** | ||
@@ -18,4 +20,6 @@ * Creates and returns a SessionStorage object that stores all session data | ||
* browser's maximum cookie size. Trade-offs! | ||
* | ||
* @see https://remix.run/api/remix#createcookiesessionstorage | ||
*/ | ||
export declare function createCookieSessionStorage({ cookie: cookieArg }?: CookieSessionStorageOptions): SessionStorage; | ||
export declare const createCookieSessionStorageFactory: (createCookie: CreateCookieFunction) => CreateCookieSessionStorageFunction; | ||
export {}; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -26,7 +26,9 @@ * Copyright (c) Remix Software Inc. | ||
* browser's maximum cookie size. Trade-offs! | ||
* | ||
* @see https://remix.run/api/remix#createcookiesessionstorage | ||
*/ | ||
function createCookieSessionStorage({ | ||
const createCookieSessionStorageFactory = createCookie => ({ | ||
cookie: cookieArg | ||
} = {}) { | ||
let cookie = cookies.isCookie(cookieArg) ? cookieArg : cookies.createCookie((cookieArg === null || cookieArg === void 0 ? void 0 : cookieArg.name) || "__session", cookieArg); | ||
} = {}) => { | ||
let cookie = cookies.isCookie(cookieArg) ? cookieArg : createCookie((cookieArg === null || cookieArg === void 0 ? void 0 : cookieArg.name) || "__session", cookieArg); | ||
sessions.warnOnceAboutSigningSessionCookie(cookie); | ||
@@ -39,3 +41,9 @@ return { | ||
async commitSession(session, options) { | ||
return cookie.serialize(session.data, options); | ||
let serializedCookie = await cookie.serialize(session.data, options); | ||
if (serializedCookie.length > 4096) { | ||
throw new Error("Cookie length will exceed browser maximum. Length: " + serializedCookie.length); | ||
} | ||
return serializedCookie; | ||
}, | ||
@@ -50,4 +58,4 @@ | ||
}; | ||
} | ||
}; | ||
exports.createCookieSessionStorage = createCookieSessionStorage; | ||
exports.createCookieSessionStorageFactory = createCookieSessionStorageFactory; |
@@ -1,2 +0,2 @@ | ||
import type { SessionStorage, SessionIdStorageStrategy } from "../sessions"; | ||
import type { SessionStorage, SessionIdStorageStrategy, CreateSessionStorageFunction } from "../sessions"; | ||
interface MemorySessionStorageOptions { | ||
@@ -9,2 +9,3 @@ /** | ||
} | ||
export declare type CreateMemorySessionStorageFunction = (options?: MemorySessionStorageOptions) => SessionStorage; | ||
/** | ||
@@ -16,4 +17,6 @@ * Creates and returns a simple in-memory SessionStorage object, mostly useful | ||
* suitable for most production scenarios. | ||
* | ||
* @see https://remix.run/api/remix#creatememorysessionstorage | ||
*/ | ||
export declare function createMemorySessionStorage({ cookie }?: MemorySessionStorageOptions): SessionStorage; | ||
export declare const createMemorySessionStorageFactory: (createSessionStorage: CreateSessionStorageFunction) => CreateMemorySessionStorageFunction; | ||
export {}; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -15,4 +15,2 @@ * Copyright (c) Remix Software Inc. | ||
var sessions = require('../sessions.js'); | ||
/** | ||
@@ -24,9 +22,11 @@ * Creates and returns a simple in-memory SessionStorage object, mostly useful | ||
* suitable for most production scenarios. | ||
* | ||
* @see https://remix.run/api/remix#creatememorysessionstorage | ||
*/ | ||
function createMemorySessionStorage({ | ||
const createMemorySessionStorageFactory = createSessionStorage => ({ | ||
cookie | ||
} = {}) { | ||
} = {}) => { | ||
let uniqueId = 0; | ||
let map = new Map(); | ||
return sessions.createSessionStorage({ | ||
return createSessionStorage({ | ||
cookie, | ||
@@ -73,4 +73,4 @@ | ||
}); | ||
} | ||
}; | ||
exports.createMemorySessionStorage = createMemorySessionStorage; | ||
exports.createMemorySessionStorageFactory = createMemorySessionStorageFactory; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-149e932f | ||
* @remix-run/server-runtime v0.0.0-experimental-21ec8370 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
115928
62
3179
27
Updatedreact-router-dom@^6.2.2