/** * src/middleware/session.js — конфигурация express-session. * * Стор выбирается по наличию пула БД: * - pool передан → connect-pg-simple (PG): сессии переживают рестарт, работают * на нескольких подах. * - pool не передан → MemoryStore: только для юнит-тестов (не требует БД). * * Таблица session создаётся автоматически connect-pg-simple при первом старте * (createTableIfMissing: true). SQL-схема совместима с PostgreSQL 9.6+. * * Экспортирует одну функцию: createSessionMiddleware(pool) → express middleware. */ 'use strict'; const session = require('express-session'); const ConnectPgSimple = require('connect-pg-simple'); const SESSION_MAX_AGE = 8 * 60 * 60 * 1000; // 8 часов, в мс /** * Создаёт и возвращает сконфигурированный express-session middleware. * @param {import('pg').Pool|null} pool — pg Pool; null → MemoryStore (тесты) * @returns {import('express').RequestHandler} */ function createSessionMiddleware(pool) { const store = pool ? buildPgStore(pool) : undefined; // undefined → MemoryStore return session({ store, secret: process.env.SESSION_SECRET || 'dev-session-secret-change-me', resave: false, saveUninitialized: false, cookie: { httpOnly: true, secure: process.env.NODE_ENV === 'production', // HTTPS only в проде sameSite: 'lax', maxAge: SESSION_MAX_AGE, }, }); } /** * Создаёт connect-pg-simple Store поверх переданного пула. * Таблица `session` создаётся автоматически если отсутствует. * @param {import('pg').Pool} pool * @returns {session.Store} */ function buildPgStore(pool) { const PgSession = ConnectPgSimple(session); return new PgSession({ pool, createTableIfMissing: true, // Автоочистка протухших сессий раз в час (прунинг не блокирует запросы). pruneSessionInterval: 60 * 60, // секунды }); } module.exports = { createSessionMiddleware };