[object Object]

← back to Fix Live Board

Add reusable isShowroomVendor() primitive keyed off showroom-vendors.json (TK-11186)

9ba8420b6db99e9f93912a8ff8a74c6a8812e13a · 2026-09-03 11:19:31 -0700 · Steve Abrams

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BgCcr9t5zNGdb43pS4f1ks

Files touched

Diff

commit 9ba8420b6db99e9f93912a8ff8a74c6a8812e13a
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Sep 3 11:19:31 2026 -0700

    Add reusable isShowroomVendor() primitive keyed off showroom-vendors.json (TK-11186)
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01BgCcr9t5zNGdb43pS4f1ks
---
 config/showroom-vendor.cjs | 59 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/config/showroom-vendor.cjs b/config/showroom-vendor.cjs
new file mode 100644
index 0000000..fa872fa
--- /dev/null
+++ b/config/showroom-vendor.cjs
@@ -0,0 +1,59 @@
+/**
+ * showroom-vendor.cjs — canonical `isShowroomVendor(vendor)` primitive. (TK-11186)
+ *
+ * Showroom-only vendors are "addressable but not discoverable": reachable via a
+ * direct /products/<handle> URL or on-site search, but HIDDEN from every push /
+ * browse surface and the Google feed. The one source of truth for WHICH vendors
+ * are showroom-only is the sibling `showroom-vendors.json` in this directory
+ * (currently ["Phillip Jeffries"]). NEVER hardcode a vendor name anywhere else —
+ * add/remove vendors by editing that JSON file only.
+ *
+ * Lives beside the list on purpose: one directory owns the showroom-vendor concept
+ * (list + logic). It is a plain CommonJS module so BOTH:
+ *   - CommonJS callers: const { isShowroomVendor } = require('.../showroom-vendor.cjs')
+ *   - ESM (.mjs) callers: import { createRequire } from 'node:module';
+ *       const require = createRequire(import.meta.url);
+ *       const { isShowroomVendor } = require('.../showroom-vendor.cjs');
+ * consume the SAME implementation and the SAME list.
+ *
+ * Reversible: delete this file / revert the commit. No side effects, read-only.
+ */
+'use strict';
+const fs = require('fs');
+const path = require('path');
+
+const LIST_PATH = path.join(__dirname, 'showroom-vendors.json');
+
+// Case-insensitive exact-match set, read once and memoized. Resilient: a missing or
+// malformed list yields an empty set (isShowroomVendor -> always false) rather than
+// throwing, so a config hiccup can never crash a feed build or a fleet server boot.
+let _set = null;
+function _load() {
+  if (_set) return _set;
+  try {
+    const raw = JSON.parse(fs.readFileSync(LIST_PATH, 'utf8'));
+    const arr = Array.isArray(raw) ? raw : [];
+    _set = new Set(arr.map(v => String(v == null ? '' : v).trim().toLowerCase()).filter(Boolean));
+  } catch {
+    _set = new Set();
+  }
+  return _set;
+}
+
+/** True iff `vendor` is on the showroom-only list (case-insensitive exact match). */
+function isShowroomVendor(vendor) {
+  if (vendor == null) return false;
+  return _load().has(String(vendor).trim().toLowerCase());
+}
+
+/** The raw showroom-vendor names, as authored in showroom-vendors.json. */
+function showroomVendors() {
+  try {
+    const raw = JSON.parse(fs.readFileSync(LIST_PATH, 'utf8'));
+    return Array.isArray(raw) ? raw.slice() : [];
+  } catch {
+    return [];
+  }
+}
+
+module.exports = { isShowroomVendor, showroomVendors, LIST_PATH };

← e6f437b board: movable/dockable nav — drag grip (float/move up-down-  ·  back to Fix Live Board  ·  showroom: add tag-aware isShowroomProduct primitive (TK-1130 2fe5fee →