mw10013 / remix-cf-20240202

0 stars 0 forks source link

Session #17

Closed mw10013 closed 10 months ago

mw10013 commented 10 months ago
mw10013 commented 10 months ago

remix-server-runtime > sessions.ts

/**
 * Creates a SessionStorage object using a SessionIdStorageStrategy.
 *
 * Note: This is a low-level API that should only be used if none of the
 * existing session storage options meet your requirements.
 *
 * @see https://remix.run/utils/sessions#createsessionstorage
 */
export const createSessionStorageFactory =
  (createCookie: CreateCookieFunction): CreateSessionStorageFunction =>
  ({ cookie: cookieArg, createData, readData, updateData, deleteData }) => {
    let cookie = isCookie(cookieArg)
      ? cookieArg
      : createCookie(cookieArg?.name || "__session", cookieArg);

    warnOnceAboutSigningSessionCookie(cookie);

    return {
      async getSession(cookieHeader, options) {
        let id = cookieHeader && (await cookie.parse(cookieHeader, options));
        let data = id && (await readData(id));
        return createSession(data || {}, id || "");
      },
      async commitSession(session, options) {
        let { id, data } = session;
        let expires =
          options?.maxAge != null
            ? new Date(Date.now() + options.maxAge * 1000)
            : options?.expires != null
            ? options.expires
            : cookie.expires;

        if (id) {
          await updateData(id, data, expires);
        } else {
          id = await createData(data, expires);
        }

        return cookie.serialize(id, options);
      },
      async destroySession(session, options) {
        await deleteData(session.id);
        return cookie.serialize("", {
          ...options,
          maxAge: undefined,
          expires: new Date(0),
        });
      },
    };
  };
mw10013 commented 10 months ago
/**
 * Returns true if an object is a Remix session.
 *
 * @see https://remix.run/utils/sessions#issession
 */
export const isSession: IsSessionFunction = (object): object is Session => {
  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"
  );
};
mw10013 commented 10 months ago
/**
 * Creates a new Session object.
 *
 * Note: This function is typically not invoked directly by application code.
 * Instead, use a `SessionStorage` object's `getSession` method.
 *
 * @see https://remix.run/utils/sessions#createsession
 */
export const createSession: CreateSessionFunction = <
  Data = SessionData,
  FlashData = Data
>(
  initialData: Partial<Data> = {},
  id = ""
): Session<Data, FlashData> => {
  let map = new Map(Object.entries(initialData)) as Map<
    keyof Data | FlashDataKey<keyof FlashData & string>,
    any
  >;

  return {
    get id() {
      return id;
    },
    get data() {
      return Object.fromEntries(map) as FlashSessionData<Data, FlashData>;
    },
    has(name) {
      return (
        map.has(name as keyof Data) ||
        map.has(flash(name as keyof FlashData & string))
      );
    },
    get(name) {
      if (map.has(name as keyof Data)) return map.get(name as keyof Data);

      let flashName = flash(name as keyof FlashData & string);
      if (map.has(flashName)) {
        let value = map.get(flashName);
        map.delete(flashName);
        return value;
      }

      return undefined;
    },
    set(name, value) {
      map.set(name, value);
    },
    flash(name, value) {
      map.set(flash(name), value);
    },
    unset(name) {
      map.delete(name);
    },
  };
};