@remix-run/server-runtime
Advanced tools
Comparing version 0.0.0-experimental-5ddceecc to 0.0.0-experimental-5f7f6655
import type { CookieParseOptions, CookieSerializeOptions } from "cookie"; | ||
import "./cookieSigning"; | ||
import type { SignFunction, UnsignFunction } from "./crypto"; | ||
export type { CookieParseOptions, CookieSerializeOptions }; | ||
@@ -53,2 +53,3 @@ export interface CookieSignatureOptions { | ||
} | ||
export declare type CreateCookieFunction = (name: string, cookieOptions?: CookieOptions) => Cookie; | ||
/** | ||
@@ -59,3 +60,7 @@ * Creates a logical container for managing a browser cookie from the server. | ||
*/ | ||
export declare function createCookie(name: string, cookieOptions?: CookieOptions): Cookie; | ||
export declare const createCookieFactory: ({ sign, unsign, }: { | ||
sign: SignFunction; | ||
unsign: UnsignFunction; | ||
}) => CreateCookieFunction; | ||
export declare type IsCookieFunction = (object: any) => object is Cookie; | ||
/** | ||
@@ -66,2 +71,2 @@ * Returns true if an object is a Remix cookie container. | ||
*/ | ||
export declare function isCookie(object: any): object is Cookie; | ||
export declare const isCookie: IsCookieFunction; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -22,3 +22,6 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
function createCookie(name, cookieOptions = {}) { | ||
const createCookieFactory = ({ | ||
sign, | ||
unsign | ||
}) => (name, cookieOptions = {}) => { | ||
let { | ||
@@ -51,7 +54,7 @@ secrets, | ||
}); | ||
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 | ||
@@ -62,3 +65,4 @@ }); | ||
}; | ||
} | ||
}; | ||
/** | ||
@@ -69,8 +73,7 @@ * Returns true if an object is a Remix cookie container. | ||
*/ | ||
function isCookie(object) { | ||
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); | ||
@@ -85,3 +88,3 @@ | ||
async function decodeCookieValue(value, secrets) { | ||
async function decodeCookieValue(unsign, value, secrets) { | ||
if (secrets.length > 0) { | ||
@@ -103,3 +106,3 @@ for (let secret of secrets) { | ||
function encodeData(value) { | ||
return btoa(JSON.stringify(value)); | ||
return btoa(myUnescape(encodeURIComponent(JSON.stringify(value)))); | ||
} | ||
@@ -109,9 +112,79 @@ | ||
try { | ||
return JSON.parse(atob(value)); | ||
return JSON.parse(decodeURIComponent(myEscape(atob(value)))); | ||
} catch (error) { | ||
return {}; | ||
} | ||
} // See: https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.escape.js | ||
function myEscape(value) { | ||
let str = value.toString(); | ||
let result = ""; | ||
let index = 0; | ||
let chr, code; | ||
while (index < str.length) { | ||
chr = str.charAt(index++); | ||
if (/[\w*+\-./@]/.exec(chr)) { | ||
result += chr; | ||
} else { | ||
code = chr.charCodeAt(0); | ||
if (code < 256) { | ||
result += "%" + hex(code, 2); | ||
} else { | ||
result += "%u" + hex(code, 4).toUpperCase(); | ||
} | ||
} | ||
} | ||
return result; | ||
} | ||
exports.createCookie = createCookie; | ||
function hex(code, length) { | ||
let result = code.toString(16); | ||
while (result.length < length) result = "0" + result; | ||
return result; | ||
} // See: https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.unescape.js | ||
function myUnescape(value) { | ||
let str = value.toString(); | ||
let result = ""; | ||
let index = 0; | ||
let chr, part; | ||
while (index < str.length) { | ||
chr = str.charAt(index++); | ||
if (chr === "%") { | ||
if (str.charAt(index) === "u") { | ||
part = str.slice(index + 1, index + 5); | ||
if (/^[\da-f]{4}$/i.exec(part)) { | ||
result += String.fromCharCode(parseInt(part, 16)); | ||
index += 5; | ||
continue; | ||
} | ||
} else { | ||
part = str.slice(index, index + 2); | ||
if (/^[\da-f]{2}$/i.exec(part)) { | ||
result += String.fromCharCode(parseInt(part, 16)); | ||
index += 2; | ||
continue; | ||
} | ||
} | ||
} | ||
result += chr; | ||
} | ||
return result; | ||
} | ||
exports.createCookieFactory = createCookieFactory; | ||
exports.isCookie = isCookie; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -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; | ||
} | ||
@@ -33,0 +37,0 @@ |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -18,3 +18,6 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
function createCookie(name, cookieOptions = {}) { | ||
const createCookieFactory = ({ | ||
sign, | ||
unsign | ||
}) => (name, cookieOptions = {}) => { | ||
let { | ||
@@ -47,7 +50,7 @@ secrets, | ||
}); | ||
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 | ||
@@ -58,3 +61,4 @@ }); | ||
}; | ||
} | ||
}; | ||
/** | ||
@@ -65,8 +69,7 @@ * Returns true if an object is a Remix cookie container. | ||
*/ | ||
function isCookie(object) { | ||
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); | ||
@@ -81,3 +84,3 @@ | ||
async function decodeCookieValue(value, secrets) { | ||
async function decodeCookieValue(unsign, value, secrets) { | ||
if (secrets.length > 0) { | ||
@@ -99,3 +102,3 @@ for (let secret of secrets) { | ||
function encodeData(value) { | ||
return btoa(JSON.stringify(value)); | ||
return btoa(myUnescape(encodeURIComponent(JSON.stringify(value)))); | ||
} | ||
@@ -105,8 +108,78 @@ | ||
try { | ||
return JSON.parse(atob(value)); | ||
return JSON.parse(decodeURIComponent(myEscape(atob(value)))); | ||
} catch (error) { | ||
return {}; | ||
} | ||
} // See: https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.escape.js | ||
function myEscape(value) { | ||
let str = value.toString(); | ||
let result = ""; | ||
let index = 0; | ||
let chr, code; | ||
while (index < str.length) { | ||
chr = str.charAt(index++); | ||
if (/[\w*+\-./@]/.exec(chr)) { | ||
result += chr; | ||
} else { | ||
code = chr.charCodeAt(0); | ||
if (code < 256) { | ||
result += "%" + hex(code, 2); | ||
} else { | ||
result += "%u" + hex(code, 4).toUpperCase(); | ||
} | ||
} | ||
} | ||
return result; | ||
} | ||
export { createCookie, isCookie }; | ||
function hex(code, length) { | ||
let result = code.toString(16); | ||
while (result.length < length) result = "0" + result; | ||
return result; | ||
} // See: https://github.com/zloirock/core-js/blob/master/packages/core-js/modules/es.unescape.js | ||
function myUnescape(value) { | ||
let str = value.toString(); | ||
let result = ""; | ||
let index = 0; | ||
let chr, part; | ||
while (index < str.length) { | ||
chr = str.charAt(index++); | ||
if (chr === "%") { | ||
if (str.charAt(index) === "u") { | ||
part = str.slice(index + 1, index + 5); | ||
if (/^[\da-f]{4}$/i.exec(part)) { | ||
result += String.fromCharCode(parseInt(part, 16)); | ||
index += 5; | ||
continue; | ||
} | ||
} else { | ||
part = str.slice(index, index + 2); | ||
if (/^[\da-f]{2}$/i.exec(part)) { | ||
result += String.fromCharCode(parseInt(part, 16)); | ||
index += 2; | ||
continue; | ||
} | ||
} | ||
} | ||
result += chr; | ||
} | ||
return result; | ||
} | ||
export { createCookieFactory, isCookie }; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -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; | ||
} | ||
@@ -29,0 +33,0 @@ |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -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-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -17,11 +17,6 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
function json(data, init = {}) { | ||
let responseInit = init; | ||
if (typeof init === "number") { | ||
responseInit = { | ||
status: init | ||
}; | ||
} | ||
const json = (data, init = {}) => { | ||
let responseInit = typeof init === "number" ? { | ||
status: init | ||
} : init; | ||
let headers = new Headers(responseInit.headers); | ||
@@ -36,3 +31,4 @@ | ||
}); | ||
} | ||
}; | ||
/** | ||
@@ -44,4 +40,3 @@ * A redirect response. Sets the status code and the `Location` header. | ||
*/ | ||
function redirect(url, init = 302) { | ||
const redirect = (url, init = 302) => { | ||
let responseInit = init; | ||
@@ -62,3 +57,3 @@ | ||
}); | ||
} | ||
}; | ||
function isResponse(value) { | ||
@@ -65,0 +60,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-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -14,3 +14,3 @@ * Copyright (c) Remix Software Inc. | ||
function createRoutes(manifest, parentId) { | ||
return Object.keys(manifest).filter(key => manifest[key].parentId === parentId).map(id => ({ ...manifest[id], | ||
return Object.entries(manifest).filter(([, route]) => route.parentId === parentId).map(([id, route]) => ({ ...route, | ||
children: createRoutes(manifest, id) | ||
@@ -17,0 +17,0 @@ })); |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -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,38 +29,31 @@ 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 | ||
}); | ||
} | ||
if (request.method.toLowerCase() === "head") { | ||
if (request.method === "HEAD") { | ||
return new Response(null, { | ||
@@ -84,3 +68,3 @@ headers: response.headers, | ||
}; | ||
} | ||
}; | ||
@@ -143,2 +127,7 @@ async function handleDataRequest({ | ||
headers.delete("Location"); | ||
if (response.headers.get("Set-Cookie") !== null) { | ||
headers.set("X-Remix-Revalidate", "yes"); | ||
} | ||
return new Response(null, { | ||
@@ -172,3 +161,3 @@ status: 204, | ||
async function renderDocumentRequest({ | ||
async function handleDocumentRequest({ | ||
build, | ||
@@ -284,3 +273,3 @@ loadContext, | ||
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. | ||
@@ -487,33 +476,18 @@ | ||
function getRequestType(url, matches) { | ||
if (url.searchParams.has("_data")) { | ||
return "data"; | ||
} | ||
const validActionMethods = new Set(["POST", "PUT", "PATCH", "DELETE"]); | ||
if (!matches) { | ||
return "document"; | ||
} | ||
let match = matches.slice(-1)[0]; | ||
if (!match.route.module.default) { | ||
return "resource"; | ||
} | ||
return "document"; | ||
function isActionRequest({ | ||
method | ||
}) { | ||
return validActionMethods.has(method.toUpperCase()); | ||
} | ||
function isActionRequest(request) { | ||
let method = request.method.toLowerCase(); | ||
return method === "post" || method === "put" || method === "patch" || method === "delete"; | ||
} | ||
const validRequestMethods = new Set(["GET", "HEAD", ...validActionMethods]); | ||
function isHeadRequest(request) { | ||
return request.method.toLowerCase() === "head"; | ||
function isValidRequestMethod({ | ||
method | ||
}) { | ||
return validRequestMethods.has(method.toUpperCase()); | ||
} | ||
function isValidRequestMethod(request) { | ||
return request.method.toLowerCase() === "get" || isHeadRequest(request) || isActionRequest(request); | ||
} | ||
async function errorBoundaryError(error, status) { | ||
@@ -520,0 +494,0 @@ return json(await serializeError(error), { |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -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 @@ | ||
} | ||
/** | ||
@@ -31,5 +32,3 @@ * Creates a new Session object. | ||
*/ | ||
function createSession(initialData = {}, id = "") { | ||
const createSession = (initialData = {}, id = "") => { | ||
let map = new Map(Object.entries(initialData)); | ||
@@ -75,3 +74,4 @@ return { | ||
}; | ||
} | ||
}; | ||
/** | ||
@@ -82,6 +82,5 @@ * Returns true if an object is a Remix session. | ||
*/ | ||
function isSession(object) { | ||
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"; | ||
} | ||
}; | ||
/** | ||
@@ -103,3 +102,3 @@ * SessionStorage stores session data between HTTP requests and knows how to | ||
*/ | ||
function createSessionStorage({ | ||
const createSessionStorageFactory = createCookie => ({ | ||
cookie: cookieArg, | ||
@@ -110,3 +109,3 @@ createData, | ||
deleteData | ||
}) { | ||
}) => { | ||
let cookie = isCookie(cookieArg) ? cookieArg : createCookie((cookieArg === null || cookieArg === void 0 ? void 0 : cookieArg.name) || "__session", cookieArg); | ||
@@ -144,3 +143,3 @@ warnOnceAboutSigningSessionCookie(cookie); | ||
}; | ||
} | ||
}; | ||
function warnOnceAboutSigningSessionCookie(cookie) { | ||
@@ -150,2 +149,2 @@ 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-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -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'; | ||
@@ -26,5 +26,5 @@ | ||
*/ | ||
function createCookieSessionStorage({ | ||
const createCookieSessionStorageFactory = createCookie => ({ | ||
cookie: cookieArg | ||
} = {}) { | ||
} = {}) => { | ||
let cookie = isCookie(cookieArg) ? cookieArg : createCookie((cookieArg === null || cookieArg === void 0 ? void 0 : cookieArg.name) || "__session", cookieArg); | ||
@@ -38,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; | ||
}, | ||
@@ -49,4 +55,4 @@ | ||
}; | ||
} | ||
}; | ||
export { createCookieSessionStorage }; | ||
export { createCookieSessionStorageFactory }; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -11,4 +11,2 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
import { createSessionStorage } from '../sessions.js'; | ||
/** | ||
@@ -23,5 +21,5 @@ * Creates and returns a simple in-memory SessionStorage object, mostly useful | ||
*/ | ||
function createMemorySessionStorage({ | ||
const createMemorySessionStorageFactory = createSessionStorage => ({ | ||
cookie | ||
} = {}) { | ||
} = {}) => { | ||
let uniqueId = 0; | ||
@@ -71,4 +69,4 @@ let map = new Map(); | ||
}); | ||
} | ||
}; | ||
export { createMemorySessionStorage }; | ||
export { createMemorySessionStorageFactory }; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
@@ -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-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -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-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -11,2 +11,2 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
export { createCookie, createCookieSessionStorage, createMemorySessionStorage, createSession, createSessionStorage, isCookie, isSession, json, redirect } from '@remix-run/server-runtime'; | ||
export { createSession, isCookie, isSession, json, redirect } from '@remix-run/server-runtime'; |
export type { ServerBuild, ServerEntryModule, HandleDataRequestFunction, HandleDocumentRequestFunction, CookieParseOptions, CookieSerializeOptions, CookieSignatureOptions, CookieOptions, Cookie, AppLoadContext, AppData, EntryContext, LinkDescriptor, HtmlLinkDescriptor, PageLinkDescriptor, ErrorBoundaryComponent, ActionFunction, HeadersFunction, LinksFunction, LoaderFunction, MetaDescriptor, HtmlMetaDescriptor, MetaFunction, RouteComponent, RouteHandle, RequestHandler, SessionData, Session, SessionStorage, SessionIdStorageStrategy, } from "@remix-run/server-runtime"; | ||
export { createCookie, isCookie, createSession, isSession, createSessionStorage, createCookieSessionStorage, createMemorySessionStorage, json, redirect, } from "@remix-run/server-runtime"; | ||
export { isCookie, createSession, isSession, json, redirect, } from "@remix-run/server-runtime"; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -19,14 +19,2 @@ * Copyright (c) Remix Software Inc. | ||
Object.defineProperty(exports, 'createCookie', { | ||
enumerable: true, | ||
get: function () { return serverRuntime.createCookie; } | ||
}); | ||
Object.defineProperty(exports, 'createCookieSessionStorage', { | ||
enumerable: true, | ||
get: function () { return serverRuntime.createCookieSessionStorage; } | ||
}); | ||
Object.defineProperty(exports, 'createMemorySessionStorage', { | ||
enumerable: true, | ||
get: function () { return serverRuntime.createMemorySessionStorage; } | ||
}); | ||
Object.defineProperty(exports, 'createSession', { | ||
@@ -36,6 +24,2 @@ enumerable: true, | ||
}); | ||
Object.defineProperty(exports, 'createSessionStorage', { | ||
enumerable: true, | ||
get: function () { return serverRuntime.createSessionStorage; } | ||
}); | ||
Object.defineProperty(exports, 'isCookie', { | ||
@@ -42,0 +26,0 @@ enumerable: true, |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
{ | ||
"name": "@remix-run/server-runtime", | ||
"description": "Server runtime for Remix", | ||
"version": "0.0.0-experimental-5ddceecc", | ||
"version": "0.0.0-experimental-5f7f6655", | ||
"license": "MIT", | ||
@@ -6,0 +6,0 @@ "main": "./index.js", |
@@ -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,1 +1,2 @@ | ||
export declare type JsonFunction = <Data>(data: Data, init?: number | ResponseInit) => Response; | ||
/** | ||
@@ -7,3 +8,4 @@ * This is a shortcut for creating `application/json` responses. Converts `data` | ||
*/ | ||
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; | ||
/** | ||
@@ -15,3 +17,3 @@ * A redirect response. Sets the status code and the `Location` header. | ||
*/ | ||
export declare function redirect(url: string, init?: number | ResponseInit): Response; | ||
export declare const redirect: RedirectFunction; | ||
export declare function isResponse(value: any): value is Response; | ||
@@ -18,0 +20,0 @@ export declare function isRedirectResponse(response: Response): boolean; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -21,11 +21,6 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
function json(data, init = {}) { | ||
let responseInit = init; | ||
if (typeof init === "number") { | ||
responseInit = { | ||
status: init | ||
}; | ||
} | ||
const json = (data, init = {}) => { | ||
let responseInit = typeof init === "number" ? { | ||
status: init | ||
} : init; | ||
let headers = new Headers(responseInit.headers); | ||
@@ -40,3 +35,4 @@ | ||
}); | ||
} | ||
}; | ||
/** | ||
@@ -48,4 +44,3 @@ * A redirect response. Sets the status code and the `Location` header. | ||
*/ | ||
function redirect(url, init = 302) { | ||
const redirect = (url, init = 302) => { | ||
let responseInit = init; | ||
@@ -66,3 +61,3 @@ | ||
}); | ||
} | ||
}; | ||
function isResponse(value) { | ||
@@ -69,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-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -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 | undefined | Record<string, string> | Array<Record<string, string> | string>; | ||
} | ||
@@ -81,0 +84,0 @@ export declare type MetaDescriptor = HtmlMetaDescriptor; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -18,3 +18,3 @@ * Copyright (c) Remix Software Inc. | ||
function createRoutes(manifest, parentId) { | ||
return Object.keys(manifest).filter(key => manifest[key].parentId === parentId).map(id => ({ ...manifest[id], | ||
return Object.entries(manifest).filter(([, route]) => route.parentId === parentId).map(([id, route]) => ({ ...route, | ||
children: createRoutes(manifest, id) | ||
@@ -21,0 +21,0 @@ })); |
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; |
118
server.js
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -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,38 +33,31 @@ 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 | ||
}); | ||
} | ||
if (request.method.toLowerCase() === "head") { | ||
if (request.method === "HEAD") { | ||
return new Response(null, { | ||
@@ -88,3 +72,3 @@ headers: response.headers, | ||
}; | ||
} | ||
}; | ||
@@ -147,2 +131,7 @@ async function handleDataRequest({ | ||
headers.delete("Location"); | ||
if (response.headers.get("Set-Cookie") !== null) { | ||
headers.set("X-Remix-Revalidate", "yes"); | ||
} | ||
return new Response(null, { | ||
@@ -176,3 +165,3 @@ status: 204, | ||
async function renderDocumentRequest({ | ||
async function handleDocumentRequest({ | ||
build, | ||
@@ -288,3 +277,3 @@ loadContext, | ||
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. | ||
@@ -491,33 +480,18 @@ | ||
function getRequestType(url, matches) { | ||
if (url.searchParams.has("_data")) { | ||
return "data"; | ||
} | ||
const validActionMethods = new Set(["POST", "PUT", "PATCH", "DELETE"]); | ||
if (!matches) { | ||
return "document"; | ||
} | ||
let match = matches.slice(-1)[0]; | ||
if (!match.route.module.default) { | ||
return "resource"; | ||
} | ||
return "document"; | ||
function isActionRequest({ | ||
method | ||
}) { | ||
return validActionMethods.has(method.toUpperCase()); | ||
} | ||
function isActionRequest(request) { | ||
let method = request.method.toLowerCase(); | ||
return method === "post" || method === "put" || method === "patch" || method === "delete"; | ||
} | ||
const validRequestMethods = new Set(["GET", "HEAD", ...validActionMethods]); | ||
function isHeadRequest(request) { | ||
return request.method.toLowerCase() === "head"; | ||
function isValidRequestMethod({ | ||
method | ||
}) { | ||
return validRequestMethods.has(method.toUpperCase()); | ||
} | ||
function isValidRequestMethod(request) { | ||
return request.method.toLowerCase() === "get" || isHeadRequest(request) || isActionRequest(request); | ||
} | ||
async function errorBoundaryError(error, status) { | ||
@@ -524,0 +498,0 @@ return responses.json(await errors.serializeError(error), { |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -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"; | ||
/** | ||
@@ -52,2 +52,3 @@ * An object of name/value pairs to be used in the session. | ||
} | ||
export declare type CreateSessionFunction = (initialData?: SessionData, id?: string) => Session; | ||
/** | ||
@@ -61,3 +62,4 @@ * Creates a new Session object. | ||
*/ | ||
export declare function createSession(initialData?: SessionData, id?: string): Session; | ||
export declare const createSession: CreateSessionFunction; | ||
export declare type IsSessionFunction = (object: any) => object is Session; | ||
/** | ||
@@ -68,3 +70,3 @@ * Returns true if an object is a Remix session. | ||
*/ | ||
export declare function isSession(object: any): object is Session; | ||
export declare const isSession: IsSessionFunction; | ||
/** | ||
@@ -129,2 +131,3 @@ * SessionStorage stores session data between HTTP requests and knows how to | ||
} | ||
export declare type CreateSessionStorageFunction = (strategy: SessionIdStorageStrategy) => SessionStorage; | ||
/** | ||
@@ -138,3 +141,3 @@ * Creates a SessionStorage object using a SessionIdStorageStrategy. | ||
*/ | ||
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-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -25,2 +25,3 @@ * Copyright (c) Remix Software Inc. | ||
} | ||
/** | ||
@@ -34,5 +35,3 @@ * Creates a new Session object. | ||
*/ | ||
function createSession(initialData = {}, id = "") { | ||
const createSession = (initialData = {}, id = "") => { | ||
let map = new Map(Object.entries(initialData)); | ||
@@ -78,3 +77,4 @@ return { | ||
}; | ||
} | ||
}; | ||
/** | ||
@@ -85,6 +85,5 @@ * Returns true if an object is a Remix session. | ||
*/ | ||
function isSession(object) { | ||
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"; | ||
} | ||
}; | ||
/** | ||
@@ -106,3 +105,3 @@ * SessionStorage stores session data between HTTP requests and knows how to | ||
*/ | ||
function createSessionStorage({ | ||
const createSessionStorageFactory = createCookie => ({ | ||
cookie: cookieArg, | ||
@@ -113,4 +112,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); | ||
@@ -147,3 +146,3 @@ return { | ||
}; | ||
} | ||
}; | ||
function warnOnceAboutSigningSessionCookie(cookie) { | ||
@@ -154,4 +153,4 @@ 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; | ||
/** | ||
@@ -21,3 +23,3 @@ * Creates and returns a SessionStorage object that stores all session data | ||
*/ | ||
export declare function createCookieSessionStorage({ cookie: cookieArg, }?: CookieSessionStorageOptions): SessionStorage; | ||
export declare const createCookieSessionStorageFactory: (createCookie: CreateCookieFunction) => CreateCookieSessionStorageFunction; | ||
export {}; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -29,6 +29,6 @@ * Copyright (c) Remix Software Inc. | ||
*/ | ||
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); | ||
@@ -41,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; | ||
}, | ||
@@ -52,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; | ||
/** | ||
@@ -19,3 +20,3 @@ * Creates and returns a simple in-memory SessionStorage object, mostly useful | ||
*/ | ||
export declare function createMemorySessionStorage({ cookie, }?: MemorySessionStorageOptions): SessionStorage; | ||
export declare const createMemorySessionStorageFactory: (createSessionStorage: CreateSessionStorageFunction) => CreateMemorySessionStorageFunction; | ||
export {}; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -15,4 +15,2 @@ * Copyright (c) Remix Software Inc. | ||
var sessions = require('../sessions.js'); | ||
/** | ||
@@ -27,8 +25,8 @@ * Creates and returns a simple in-memory SessionStorage object, mostly useful | ||
*/ | ||
function createMemorySessionStorage({ | ||
const createMemorySessionStorageFactory = createSessionStorage => ({ | ||
cookie | ||
} = {}) { | ||
} = {}) => { | ||
let uniqueId = 0; | ||
let map = new Map(); | ||
return sessions.createSessionStorage({ | ||
return createSessionStorage({ | ||
cookie, | ||
@@ -75,4 +73,4 @@ | ||
}); | ||
} | ||
}; | ||
exports.createMemorySessionStorage = createMemorySessionStorage; | ||
exports.createMemorySessionStorageFactory = createMemorySessionStorageFactory; |
/** | ||
* @remix-run/server-runtime v0.0.0-experimental-5ddceecc | ||
* @remix-run/server-runtime v0.0.0-experimental-5f7f6655 | ||
* | ||
@@ -4,0 +4,0 @@ * Copyright (c) Remix Software Inc. |
118847
62
3283
27