UNPKG

3.89 kBJavaScriptView Raw
1/**
2 * react-router v8.3.0
3 *
4 * Copyright (c) Remix Software Inc.
5 *
6 * This source code is licensed under the MIT license found in the
7 * LICENSE.md file in the root directory of this source tree.
8 *
9 * @license MIT
10 */
11import { warnOnce } from "./warnings.js";
12import { createCookie, isCookie } from "./cookies.js";
13//#region lib/server-runtime/sessions.ts
14function flash(name) {
15 return `__flash_${name}__`;
16}
17/**
18* Creates a new Session object.
19*
20* Note: This function is typically not invoked directly by application code.
21* Instead, use a `SessionStorage` object's `getSession` method.
22*
23* @category Utils
24* @param initialData The initial data for the session.
25* @param id The identifier for the session. Defaults to an empty string for a
26* new session.
27* @returns A new {@link Session} object.
28*/
29const createSession = (initialData = {}, id = "") => {
30 let map = new Map(Object.entries(initialData));
31 return {
32 get id() {
33 return id;
34 },
35 get data() {
36 return Object.fromEntries(map);
37 },
38 has(name) {
39 return map.has(name) || map.has(flash(name));
40 },
41 get(name) {
42 if (map.has(name)) return map.get(name);
43 let flashName = flash(name);
44 if (map.has(flashName)) {
45 let value = map.get(flashName);
46 map.delete(flashName);
47 return value;
48 }
49 },
50 set(name, value) {
51 map.set(name, value);
52 },
53 flash(name, value) {
54 map.set(flash(name), value);
55 },
56 unset(name) {
57 map.delete(name);
58 }
59 };
60};
61/**
62* Returns `true` if a value is a React Router {@link Session} object.
63*
64* @public
65* @category Utils
66* @mode framework
67* @mode data
68* @param object The value to check.
69* @returns `true` if the value is a React Router {@link Session} object;
70* otherwise, `false`.
71*/
72const isSession = (object) => {
73 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";
74};
75/**
76* Creates a SessionStorage object using a SessionIdStorageStrategy.
77*
78* Note: This is a low-level API that should only be used if none of the
79* existing session storage options meet your requirements.
80*
81* @category Utils
82* @param strategy The strategy used to store session identifiers and data.
83* @returns A {@link SessionStorage} object that persists session data using the
84* provided strategy.
85*/
86function createSessionStorage({ cookie: cookieArg, createData, readData, updateData, deleteData }) {
87 let cookie = isCookie(cookieArg) ? cookieArg : createCookie(cookieArg?.name || "__session", cookieArg);
88 warnOnceAboutSigningSessionCookie(cookie);
89 return {
90 async getSession(cookieHeader, options) {
91 let id = cookieHeader && await cookie.parse(cookieHeader, options);
92 return createSession(id && await readData(id) || {}, id || "");
93 },
94 async commitSession(session, options) {
95 let { id, data } = session;
96 let expires = options?.maxAge != null ? new Date(Date.now() + options.maxAge * 1e3) : options?.expires != null ? options.expires : cookie.expires;
97 if (id) await updateData(id, data, expires);
98 else id = await createData(data, expires);
99 return cookie.serialize(id, options);
100 },
101 async destroySession(session, options) {
102 await deleteData(session.id);
103 return cookie.serialize("", {
104 ...options,
105 maxAge: void 0,
106 expires: /* @__PURE__ */ new Date(0)
107 });
108 }
109 };
110}
111function warnOnceAboutSigningSessionCookie(cookie) {
112 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://reactrouter.com/explanation/sessions-and-cookies#signing-cookies for more information.`);
113}
114//#endregion
115export { createSession, createSessionStorage, isSession, warnOnceAboutSigningSessionCookie };