[object Object]

← back to Wallsandfabrics

wire api-vendor-redact middleware + filter /api/facets + drop ?vendor= and vendor-field search

945023615b1fb503ee26069e232ef55937a26700 · 2026-05-25 21:40:40 -0700 · steve

Mounts _shared/api-vendor-redact above route registration so /api/* responses
have vendor field replaced with 'Designer Wallcoverings' and the top-level
vendors map dropped, and ?vendor= query param stripped from /api/products.

/api/facets now honours ?q= and ?surface= so surface counts + total reflect
the filtered list instead of the whole catalog.

/api/products no longer indexes the vendor field in text search and no longer
accepts ?vendor= (the upstream middleware also strips it; this is local
defense-in-depth).

Files touched

Diff

commit 945023615b1fb503ee26069e232ef55937a26700
Author: steve <steve@designerwallcoverings.com>
Date:   Mon May 25 21:40:40 2026 -0700

    wire api-vendor-redact middleware + filter /api/facets + drop ?vendor= and vendor-field search
    
    Mounts _shared/api-vendor-redact above route registration so /api/* responses
    have vendor field replaced with 'Designer Wallcoverings' and the top-level
    vendors map dropped, and ?vendor= query param stripped from /api/products.
    
    /api/facets now honours ?q= and ?surface= so surface counts + total reflect
    the filtered list instead of the whole catalog.
    
    /api/products no longer indexes the vendor field in text search and no longer
    accepts ?vendor= (the upstream middleware also strips it; this is local
    defense-in-depth).
---
 server.js | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/server.js b/server.js
index 09eab29..6e3f3f4 100644
--- a/server.js
+++ b/server.js
@@ -77,6 +77,10 @@ function buildCatalog(raw) {
 }
 
 const app = express();
+// Strip vendor names from /api/* responses (Steve standing rule — DW vendor
+// names NEVER in customer-facing UI). MUST sit above any route registration so
+// the res.json() wrapper installs before handlers run.
+app.use(require('../_shared/api-vendor-redact'));
 app.use(helmet({ contentSecurityPolicy: false }));
 app.use(express.json({ limit: '256kb' }));
 
@@ -169,14 +173,15 @@ function sortProducts(list, mode) {
 
 
 app.get('/api/products', (req, res) => {
-  const { q, surface, vendor, sort = 'newest', page = 1, limit = 24 } = req.query;
+  // ?vendor= is stripped upstream by _shared/api-vendor-redact and search no
+  // longer indexes the vendor field — DW vendor names stay off customer surfaces.
+  const { q, surface, sort = 'newest', page = 1, limit = 24 } = req.query;
   let list = PRODUCTS;
   if (q) {
     const needle = q.toLowerCase();
-    list = list.filter(p => (p.title || '').toLowerCase().includes(needle) || (p.tags || []).some(t => t.toLowerCase().includes(needle)) || (p.vendor || '').toLowerCase().includes(needle));
+    list = list.filter(p => (p.title || '').toLowerCase().includes(needle) || (p.tags || []).some(t => t.toLowerCase().includes(needle)));
   }
   if (surface && surface !== 'all') list = list.filter(p => p.__surface === surface);
-  if (vendor && vendor !== 'all') list = list.filter(p => p.vendor === vendor);
   list = sortProducts(list, sort);
   const total = list.length;
   const pageNum = Math.max(1, parseInt(page) || 1);
@@ -186,9 +191,20 @@ app.get('/api/products', (req, res) => {
 });
 
 app.get('/api/facets', (req, res) => {
+  // Honour the same filters /api/products honours so the surface counts +
+  // total reflect the FILTERED list (not the whole catalog). vendor filter
+  // is dropped upstream by api-vendor-redact middleware.
+  const { q, surface } = req.query;
+  let list = PRODUCTS;
+  if (q) {
+    const needle = String(q).toLowerCase();
+    list = list.filter(p => (p.title || '').toLowerCase().includes(needle) || (p.tags || []).some(t => String(t).toLowerCase().includes(needle)));
+  }
+  if (surface && surface !== 'all') list = list.filter(p => p.__surface === surface);
+  const surfaces = list.reduce((acc, p) => { acc[p.__surface] = (acc[p.__surface] || 0) + 1; return acc; }, {});
   const vendors = {};
-  for (const p of PRODUCTS) vendors[p.vendor] = (vendors[p.vendor] || 0) + 1;
-  res.json({ surfaces: SURFACE_COUNTS, vendors, total: PRODUCTS.length });
+  for (const p of list) vendors[p.vendor] = (vendors[p.vendor] || 0) + 1;
+  res.json({ surfaces, vendors, total: list.length });
 });
 
 app.get('/api/sliders', (req, res) => {

← d276b47 retag aesthetic from PG: 3663 rows updated  ·  back to Wallsandfabrics  ·  replace per-card vendor label with 'Designer Wallcoverings' 835b059 →