← back to Dw Vendor Microsites
vendors/gracie/export.mjs
70 lines
#!/usr/bin/env node
/**
* Gracie catalog → staging/gracie.jsonl (LOCAL dw_unified, READ-ONLY).
* Normalizes gracie_catalog to the canonical microsite JSONL shape (same fields
* the template viewer expects). QUOTE-ONLY: no prices emitted. Product URLs are
* DROPPED (customer-facing microsite links into the DW store, never graciestudio.com).
* Cost: $0 (local).
*/
import { Client } from 'pg';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const OUT = path.join(__dirname, '..', '..', 'staging', 'gracie.jsonl');
const sanitize = (s) => typeof s === 'string'
? s.replace(/\bwallpapers\b/gi, 'wallcoverings').replace(/\bwallpaper\b/gi, 'wallcovering')
: s;
async function main() {
const c = new Client({ connectionString: process.env.PG || 'postgresql://localhost/dw_unified' });
await c.connect();
const { rows } = await c.query(`
SELECT mfr_sku, pattern_name, color_name, collection, width, roll_length, pattern_repeat,
image_url, all_images, product_type, material, composition, specs,
ai_description, description, ai_colors, ai_background_color, ai_styles, ai_tags,
color_hex, dominant_color_hex, crawled_at
FROM gracie_catalog WHERE image_url IS NOT NULL ORDER BY collection, pattern_name`);
await c.end();
const out = rows.map((r, i) => {
let colors = []; let styles = []; let tags = [];
try { colors = Array.isArray(r.ai_colors) ? r.ai_colors : JSON.parse(r.ai_colors || '[]'); } catch {}
try { styles = Array.isArray(r.ai_styles) ? r.ai_styles : JSON.parse(r.ai_styles || '[]'); } catch {}
try { tags = Array.isArray(r.ai_tags) ? r.ai_tags : JSON.parse(r.ai_tags || '[]'); } catch {}
const gallery = (r.all_images || '').split('|').filter(Boolean);
return {
id: i + 1,
mfr_sku: r.mfr_sku,
pattern_name: sanitize(r.pattern_name),
color_name: r.color_name || (colors[0] && colors[0].name) || '',
collection: sanitize(r.collection),
width: r.width || null,
roll_length: r.roll_length || null,
pattern_repeat: r.pattern_repeat || null,
image_url: r.image_url,
all_images: gallery,
product_type: r.product_type || 'wallcovering',
material: r.material || 'Handpainted',
composition: r.composition || null,
// QUOTE-ONLY — no price fields
quote_only: true,
specs: r.specs || {},
ai_description: sanitize(r.ai_description || r.description || ''),
ai_colors: colors,
ai_background_color: r.ai_background_color || null,
ai_styles: styles,
ai_tags: tags,
color_hex: r.color_hex || r.dominant_color_hex || null,
// product_url intentionally DROPPED (no link to graciestudio.com)
};
});
fs.mkdirSync(path.dirname(OUT), { recursive: true });
fs.writeFileSync(OUT, out.map((o) => JSON.stringify(o)).join('\n') + '\n');
console.log(`[gracie-export] wrote ${out.length} rows → ${OUT}. Cost: $0 (local)`);
}
main().catch((e) => { console.error('[gracie-export] FATAL', e); process.exit(1); });