// lib/headers.js // headers(cfg) injection + per-role / layout-mode suppression (ARCHITECTURE.md 7.6) // // Grounding (real Saltcorn source under packages/): // - server/wrapper.js:137 -- a header is emitted only when `h.only_if(req) === true` // (strict equality), so every predicate here returns an explicit boolean. // - saltcorn-data/db/state.ts:1122-1135 -- only `script` URLs are de-duped; `css` // headers are not, so distinct per-role ?v/&theme/&role links coexist. const { CSS_ROUTE } = require("./constants"); const { getActiveThemeId, getActiveByRole, activeHashHint, isLayoutMode, requestRendersViaThemeBuilder, } = require("./cfgReaders"); function headers(cfg) { const def = getActiveThemeId(cfg); const byRole = getActiveByRole(cfg); const list = []; if (!def) return list; // ONE header; only_if decides per-request whether this role gets the overlay. list.push({ css: `${CSS_ROUTE}?v=${activeHashHint(cfg)}`, only_if: (req) => { const role = req.user?.role_id ?? 100; // LAYOUT MODE: suppress ONLY for requests that actually render via theme-builder. // Detected by replicating getLayout's fallback precedence (cfgReaders), NOT by reading // getLayout().pluginName -- the last-installed fallback omits pluginName, so an uncovered // role would otherwise be double-themed (overlay + wrap()). (folded review fix) if (isLayoutMode(cfg) && requestRendersViaThemeBuilder(req)) return false; // role with an explicit override gets its own header below, not this one return byRole[role] === undefined || byRole[role] === def; }, }); // per-role overlays for explicit overrides (Phase 1) for (const [roleStr, tid] of Object.entries(byRole)) { if (tid === def) continue; const role = Number(roleStr); list.push({ css: `${CSS_ROUTE}?v=${activeHashHint(cfg)}&theme=${encodeURIComponent(tid)}&role=${role}`, only_if: (req) => { if (isLayoutMode(cfg) && requestRendersViaThemeBuilder(req)) return false; return (req.user?.role_id ?? 100) === role; // MUST strictly return true (wrapper.js:137) }, }); } return list; } module.exports = { headers };