import session from "express-session"; import { createClient } from "redis"; export async function createRedisSession({ redisUrl = process.env.REDIS_URL, cookieName = process.env.SESSION_COOKIE_NAME || "sc.sid", secret = process.env.SESSION_SECRET, trustProxy = process.env.TRUST_PROXY === "1", ttlSeconds = 60 * 60 * 12, // 12h } = {}) { if (!redisUrl) throw new Error("REDIS_URL no definido"); if (!secret) throw new Error("SESSION_SECRET no definido"); const redis = createClient({ url: redisUrl }); redis.on("error", (err) => console.error("[Redis]", err)); await redis.connect(); console.log("[Redis] conectado"); // Resolver RedisStore (v5 / v6 / v7) async function resolveRedisStore() { const mod = await import("connect-redis"); // v6/v7: named export class if (typeof mod.RedisStore === "function") return mod.RedisStore; // v5: default factory connectRedis(session) if (typeof mod.default === "function") { const maybe = mod.default; if (maybe.prototype && (maybe.prototype.get || maybe.prototype.set)) return maybe; // clase const factory = mod.default(session); return factory; } throw new Error("No se pudo resolver RedisStore de connect-redis"); } const RedisStore = await resolveRedisStore(); const store = new RedisStore({ client: redis, prefix: "sc:sess:", ttl: ttlSeconds }); const sessionMw = session({ name: cookieName, secret, resave: false, saveUninitialized: false, store, cookie: { httpOnly: true, sameSite: "lax", secure: process.env.NODE_ENV === "production", // requiere https maxAge: ttlSeconds * 1000, }, }); return { sessionMw, redis, store, trustProxy }; }