"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isTypedSession = exports.createTypedSessionStorage = void 0;
const server_runtime_1 = require("@remix-run/server-runtime");
function createTypedSessionStorage({ sessionStorage, schema, }) {
    return {
        async getSession(cookieHeader, options) {
            let session = await sessionStorage.getSession(cookieHeader, options);
            return await createTypedSession({ session, schema });
        },
        async commitSession(session, options) {
            // check if session.data is valid
            await schema.parseAsync(session.data);
            return await sessionStorage.commitSession(session, options);
        },
        async destroySession(session) {
            // check if session.data is valid
            await schema.parseAsync(session.data);
            return await sessionStorage.destroySession(session);
        },
    };
}
exports.createTypedSessionStorage = createTypedSessionStorage;
async function createTypedSession({ session, schema, }) {
    // get a raw shape version of the schema but converting all the keys to their
    // flash versions.
    let flashSchema = {};
    for (let key in schema.shape) {
        flashSchema[flash(key)] = schema.shape[key].optional();
    }
    // parse session.data to add default values and remove invalid ones
    // we use strict mode here so we can throw an error if the session data
    // contains any invalid key, which is a sign that the session data is
    // corrupted.
    let data = await schema.extend(flashSchema).strict().parseAsync(session.data);
    return {
        get isTyped() {
            return true;
        },
        get id() {
            return session.id;
        },
        get data() {
            return data;
        },
        has(name) {
            let key = String(safeKey(schema, name));
            return key in data || flash(key) in data;
        },
        get(name) {
            let key = String(safeKey(schema, name));
            if (key in data)
                return data[key];
            let flashKey = flash(key);
            if (flashKey in data) {
                let value = data[flashKey];
                delete data[flashKey];
                return value;
            }
            return;
        },
        set(name, value) {
            let key = String(safeKey(schema, name));
            data[key] = value;
        },
        flash(name, value) {
            let key = String(safeKey(schema, name));
            let flashKey = flash(key);
            data[flashKey] = value;
        },
        unset(name) {
            let key = String(safeKey(schema, name));
            delete data[key];
        },
    };
}
/**
 * ReReturns true if an object is a Remix Utils typed session.
 *
 * @see https://github.com/sergiodxa/remix-utils#typed-session
 */
function isTypedSession(value) {
    return ((0, server_runtime_1.isSession)(value) &&
        value.isTyped === true);
}
exports.isTypedSession = isTypedSession;
function flash(name) {
    return `__flash_${name}__`;
}
// checks that the key is a valid key of the schema
function safeKey(schema, key) {
    return schema.keyof().parse(key);
}
