← back to Wallco Ai
lib/mural-categories.js
50 lines
// mural-categories — canonical list of categories that are MURALS, not tiles.
//
// Hard rule (Steve directive 2026-05-27): rows in these categories MUST NEVER
// have kind='seamless_tile'. They're scenic murals — single oversized images
// meant to be viewed as one image, not tiled. Tile previews / room renders /
// listing cards / PDP toggles all key off `kind`; a misclassified row shows up
// as a small repeating tile preview and looks broken.
//
// Historical incident — 2026-05-27 audit found 12 misclassified rows
// (10 monterey-mural + 2 cactus-pine-scenic) inserted as seamless_tile;
// fixed in PG via UPDATE … SET kind='mural_panel'. Any generator that writes
// into these categories MUST call assertMuralKind() at insert time or use
// muralKindFor() to pick the right kind.
//
// Note: cactus-11ft-mural historically uses kind='mural' (not 'mural_panel').
// Both are valid mural kinds and the PDP/listing renderers handle both. The
// guard accepts either. Only 'seamless_tile' (and other tile kinds) is refused.
const MURAL_CATEGORIES = new Set([
'monterey-mural',
'cactus-pine-scenic',
'cactus-11ft-mural',
'cactus-accent-mural',
'tree-mural',
'mural-scenic',
]);
const TILE_KINDS = new Set(['seamless_tile', 'tile', 'repeat_tile']);
function isMuralCategory(category) {
return MURAL_CATEGORIES.has(String(category || '').toLowerCase().trim());
}
function assertMuralKind(kind, category) {
if (isMuralCategory(category) && TILE_KINDS.has(String(kind || '').toLowerCase().trim())) {
throw new Error(
`mural-categories: refusing to insert kind='${kind}' into category='${category}' — ` +
`mural categories are never tileable. Use kind='mural_panel' (or 'mural') instead. ` +
`See lib/mural-categories.js for the canonical list.`
);
}
}
function muralKindFor(category) {
if (!isMuralCategory(category)) return null;
return category === 'cactus-11ft-mural' ? 'mural' : 'mural_panel';
}
module.exports = { MURAL_CATEGORIES, TILE_KINDS, isMuralCategory, assertMuralKind, muralKindFor };