sc-theme-builder/lib/cfgReaders.js
2026-07-01 20:07:28 -05:00

50 lines
2.4 KiB
JavaScript

// lib/cfgReaders.js
// Config readers -- one resolution rule (ARCHITECTURE.md 5.4)
const { getState } = require("@saltcorn/data/db/state");
const { PLUGIN_NAME, ROLE_PUBLIC } = require("./constants");
const { DEFAULT_LAYOUT_TREE } = require("./layoutTree");
function getActiveThemeId(cfg) { return cfg?.activeThemeId || null; }
function getActiveByRole(cfg) { return cfg?.activeByRole || {}; }
function activeThemeIdForRole(cfg, roleId) { // role override then global
const byRole = getActiveByRole(cfg);
return byRole[roleId] != null ? byRole[roleId] : getActiveThemeId(cfg);
}
function isLayoutMode(cfg) { return !!cfg?.layoutMode; }
function activeHashHint(cfg, roleId){ return (cfg && cfg.activeHash) || "0"; }
// SYNC resolution of the active layout tree (so wrap() stays synchronous): the
// per-role tree, else the default tree, else the built-in default preset.
// activate.js persists these into cfg alongside the pointer when layout mode is on.
function activeLayoutTree(cfg, roleId) {
const byRole = (cfg && cfg.activeLayoutTreeByRole) || {};
const roleTree = roleId != null ? (byRole[roleId] ?? byRole[String(roleId)]) : null;
return roleTree || (cfg && cfg.activeLayoutTree) || DEFAULT_LAYOUT_TREE;
}
// Replicate getLayout's fallback precedence WITHOUT reading the pluginName field the
// last-installed fallback omits (state.ts:419-425). A request renders via theme-builder when
// layout_by_role[role] names us OR (no layout_by_role entry for that role AND theme-builder is
// the last-installed/only registered layout). (folded review fix -- see 5.7/7.6)
function requestRendersViaThemeBuilder(req) {
const state = getState();
if (!state.layouts[PLUGIN_NAME]) return false; // not registered as a layout (Phase 1)
const role = req.user?.role_id ?? ROLE_PUBLIC;
const byRole = state.getConfig("layout_by_role", {}) || {};
const mapped = byRole[role] ?? byRole[String(role)];
if (mapped != null) return mapped === PLUGIN_NAME; // role branch is authoritative
// no layout_by_role entry for this role -> falls through to per-user / last-installed.
// theme-builder is selected by the fallback iff it is the last-installed layout key.
const keys = Object.keys(state.layouts);
return keys.length > 0 && keys[keys.length - 1] === PLUGIN_NAME;
}
module.exports = {
getActiveThemeId,
getActiveByRole,
activeThemeIdForRole,
isLayoutMode,
activeHashHint,
activeLayoutTree,
requestRendersViaThemeBuilder,
};