← back to Rigo Line Viewer

server.js

56 lines

/* RIGO line viewer — INTERNAL curation surface for the RIGO → Phillipe Romano Vinyls
   private-label line (internal-line-viewer spec; astek-landing :9944 is the reference).
   Real RIGO names are visible HERE ONLY (basic-auth internal tool, never public).
   Data: dw_unified.rigo_catalog (local mirror, host=/tmp), reloaded every 5 min.
   Images: served from the rigo-onboard local image store. */
const express = require('express');
const { execFileSync } = require('child_process');
const path = require('path');
const os = require('os');

const PORT = process.env.PORT || 9979; // override with PORT env
const IMG_DIR = path.join(os.homedir(), 'Projects/designerwallcoverings/scripts/rigo-onboard/images');

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="RIGO 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, pattern_name, color_name, collection,
              pr_pattern_name, pr_collection_name, width, weight_type, content,
              backing, match_type, fire_rating, ai_colors, ai_styles, ai_patterns,
              color_hex, status, product_url, local_image_path, created_at
       from rigo_catalog order by mfr_sku) t`],
    { encoding: 'utf8', maxBuffer: 128 * 1024 * 1024 });
  SNAP = JSON.parse(json.trim()).map((r) => ({
    ...r,
    img: r.local_image_path ? '/img/' + path.basename(r.local_image_path) : null,
    local_image_path: undefined,
  }));
  LOADED_AT = new Date().toISOString();
  console.log(`[rigo-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('/img', express.static(IMG_DIR, { maxAge: '1d' }));
app.use(express.static(path.join(__dirname, 'public')));

app.listen(PORT, () => console.log(`RIGO line viewer → http://127.0.0.1:${PORT}`));