← back to Fabricut Landing
fix(fabricut): make build schema-resilient + build on canonical Mac2
41f035e549823de7701c97ae1d8850ff38b5c47f · 2026-08-24 18:56:22 -0700 · Steve
build-fabricut.js crashed on Kamatera ('column book_name does not exist') because
the Kamatera fabricut_catalog mirror is schema-drifted (only has 'collection').
Add an information_schema guard so the query degrades gracefully instead of crashing,
and move the data build to a PREDEPLOY_HOOK that runs on canonical Mac2 (where
book_name + real book labels live) — ship the finished products.json instead of
rebuilding on the drifted mirror. Verified local build: 1325 products, 11 books, 189 patterns.
Files touched
M .deploy.confM scripts/build-fabricut.js
Diff
commit 41f035e549823de7701c97ae1d8850ff38b5c47f
Author: Steve <steve@designerwallcoverings.com>
Date: Mon Aug 24 18:56:22 2026 -0700
fix(fabricut): make build schema-resilient + build on canonical Mac2
build-fabricut.js crashed on Kamatera ('column book_name does not exist') because
the Kamatera fabricut_catalog mirror is schema-drifted (only has 'collection').
Add an information_schema guard so the query degrades gracefully instead of crashing,
and move the data build to a PREDEPLOY_HOOK that runs on canonical Mac2 (where
book_name + real book labels live) — ship the finished products.json instead of
rebuilding on the drifted mirror. Verified local build: 1325 products, 11 books, 189 patterns.
---
.deploy.conf | 8 ++++++--
scripts/build-fabricut.js | 10 +++++++++-
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/.deploy.conf b/.deploy.conf
index bf44b14..d3ad26c 100644
--- a/.deploy.conf
+++ b/.deploy.conf
@@ -2,5 +2,9 @@
PROJECT_NAME="fabricut-landing"
DEPLOY_PATH="/var/www/fabricut.designerwallcoverings.com"
DOMAIN="fabricut.designerwallcoverings.com"
-HEALTH_URL="http://localhost:PORT/healthz"
-BUILD_CMD="MODE=public node scripts/build-fabricut.js"
+HEALTH_URL="http://localhost:35959/healthz"
+# Build the PUBLIC data on canonical Mac2 (has fabricut_catalog.book_name) BEFORE rsync,
+# then ship the finished data/products.json. Do NOT rebuild on Kamatera — its mirror is
+# schema-drifted (no book_name), which would blank every book label. (TK: fabricut-dedupe)
+PREDEPLOY_HOOK="MODE=public node scripts/build-fabricut.js"
+BUILD_CMD=""
diff --git a/scripts/build-fabricut.js b/scripts/build-fabricut.js
index b22d5d2..ec0cfed 100644
--- a/scripts/build-fabricut.js
+++ b/scripts/build-fabricut.js
@@ -46,8 +46,16 @@ function bucketFromHSV(hsv) {
}
async function main() {
+ // book_name is a Mac2-canonical *_catalog column; the Kamatera mirror can be schema-drifted
+ // (has `collection` only). Detect it so the build degrades gracefully instead of crashing.
+ // Correct data comes from building on canonical Mac2 (see .deploy.conf PREDEPLOY_HOOK).
+ const hasBook = (await pool.query(
+ `SELECT 1 FROM information_schema.columns WHERE table_name='fabricut_catalog' AND column_name='book_name' LIMIT 1`
+ )).rows.length > 0;
+ if (!hasBook) console.warn('[warn] fabricut_catalog.book_name absent on this host — falling back to collection (build on Mac2 for real book labels)');
+ const bookSel = hasBook ? 'book_name' : 'collection AS book_name';
const { rows } = await pool.query(`
- SELECT dw_sku, mfr_sku, pattern_name, color_name, product_type, collection, book_name,
+ SELECT dw_sku, mfr_sku, pattern_name, color_name, product_type, collection, ${bookSel},
width, length, repeat_v, material, match_type, finish, backing, fire_codes, scale,
country_origin, roll_yards, min_order_yards, msrp_unit, vendor_msrp,
price_retail, price_trade, ai_description, ai_styles, ai_patterns, ai_colors,
← bdb71d3 chore(fabricut): rebase onto live — add GA snippet + pin pro
·
back to Fabricut Landing
·
fabricut: filter dead _stylized_secondary room images (403 A e588706 →