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

53 lines
2.3 KiB
JavaScript

// lib/activePointer.js
// Active-pointer write: persist -> re-register -> propagate -> refresh assets (ARCHITECTURE.md 5.5)
const Plugin = require("@saltcorn/data/models/plugin");
const { getState } = require("@saltcorn/data/db/state");
const db = require("@saltcorn/data/db");
const { PLUGIN_NAME } = require("./constants");
// Resolve the install-name row defensively: _sc_plugins.name is the INSTALL name, which
// is NOT guaranteed to equal plugin_name. Try the canonical name, then fall back to scanning
// for the row whose module resolves to plugin_name. (folded review fix: read/write name-space split)
async function findPluginRow() {
let p = await Plugin.findOne({ name: PLUGIN_NAME });
if (p) return p;
const all = await Plugin.find({});
return all.find((r) => {
const mod = getState().plugins[PLUGIN_NAME];
return mod && (getState().plugin_module_names[r.name] === PLUGIN_NAME || r.name === PLUGIN_NAME);
}) || null;
}
async function setActivePointer(patch /* {activeThemeId?|activeByRole?|activeHash?} */) {
const plugin = await findPluginRow();
if (!plugin) throw new Error("theme-builder plugin row not found");
plugin.configuration = { ...(plugin.configuration || {}), ...patch };
await plugin.upsert(); // _sc_plugins (plugin.ts:104-119)
await Plugin.loadPlugin(plugin); // re-register -> re-run headers(cfg)
await getState().refresh_views(); // REBUILD assets_by_role (Fix 1)
getState().processSend({ refresh_plugin_cfg: PLUGIN_NAME, tenant: db.getTenantSchema() });
return plugin.configuration;
}
// READ: live merged cfg, no DB hit.
function getActivePointer() {
const cfg = getState().plugin_cfgs[PLUGIN_NAME] || {};
return { activeThemeId: cfg.activeThemeId || null, activeByRole: cfg.activeByRole || {},
activeHash: cfg.activeHash || "0" };
}
// Remove every activeByRole entry whose value === id, then persist the scrubbed map.
async function dropRoleRefs(id) {
const { activeByRole } = getActivePointer();
const scrubbed = {};
for (const role of Object.keys(activeByRole)) {
if (activeByRole[role] !== id) scrubbed[role] = activeByRole[role];
}
return setActivePointer({ activeByRole: scrubbed });
}
module.exports = { setActivePointer, getActivePointer, findPluginRow, dropRoleRefs };