← back to Vahallan Line Viewer

server.js

46 lines

/* Vahallan line viewer — INTERNAL curation surface for the Vahallan direct line
   (internal-line-viewer spec; rigo-line-viewer :9979 is the sibling).
   Vahallan is a customer-facing brand (NOT private-label) — no rename layer.
   Data: dw_unified.vahallan_catalog (local mirror, host=/tmp), reloaded every 5 min.
   Images: Vahallan's own Shopify CDN (remote; internal tool, low volume). */
const express = require('express');
const { execFileSync } = require('child_process');

const PORT = process.env.PORT || 9982;

const app = express();

app.get('/healthz', (_req, res) => res.json({ ok: true, products: SNAP.length, loadedAt: LOADED_AT }));

const [AUTH_USER, AUTH_PASS] = (process.env.BASIC_AUTH || 'admin:DW2024!').split(':');
app.use((req, res, next) => {
  const [scheme, b64] = (req.headers.authorization || '').split(' ');
  if (scheme === 'Basic' && b64) {
    const [u, p] = Buffer.from(b64, 'base64').toString('utf8').split(':');
    if (u === AUTH_USER && p === AUTH_PASS) return next();
  }
  res.set('WWW-Authenticate', 'Basic realm="Vahallan line (internal)"');
  return res.status(401).send('Authentication required.');
});

let SNAP = [];
let LOADED_AT = null;
function load() {
  const json = execFileSync('psql', ['host=/tmp dbname=dw_unified', '-Atc',
    `select coalesce(json_agg(row_to_json(t))::text,'[]') from (
       select mfr_sku, dw_sku, handle, pattern, colorway, title, tags,
              image_url, product_url, shopify_product_id, already_on_shopify,
              imported_at, created_at
       from vahallan_catalog order by dw_sku) t`],
    { encoding: 'utf8', maxBuffer: 128 * 1024 * 1024 });
  SNAP = JSON.parse(json.trim());
  LOADED_AT = new Date().toISOString();
  console.log(`[vahallan-viewer] loaded ${SNAP.length} rows`);
}
load();
setInterval(() => { try { load(); } catch (e) { console.error('reload failed:', e.message); } }, 5 * 60 * 1000);

app.get('/api/products', (_req, res) => res.json({ count: SNAP.length, loadedAt: LOADED_AT, products: SNAP }));
app.use(express.static('public'));
app.listen(PORT, () => console.log(`[vahallan-viewer] http://127.0.0.1:${PORT}`));