← back to Hollywood Import
momentum-probe-data.mjs
42 lines
// Find the embedded product-data array the Vue virtual grid hydrates from, and enumerate
// category/manufacturer filters for full-catalog coverage. Dumps authed /products HTML.
import { chromium } from 'playwright';
import fs from 'node:fs';
const STATE = new URL('momentum-auth.json', import.meta.url).pathname;
const BASE = 'https://momentumco.com';
const b = await chromium.launch({ channel: 'chrome', headless: true });
const ctx = await b.newContext({ storageState: STATE, viewport: { width: 1400, height: 1200 } });
const p = await ctx.newPage();
await p.goto(BASE + '/products?forceSync=1', { waitUntil: 'domcontentloaded', timeout: 60000 }).catch(()=>{});
await p.waitForTimeout(7000);
const html = await p.content();
fs.writeFileSync(new URL('products-authed.html', import.meta.url).pathname, html);
// Look for big embedded JSON arrays of products (slug/price/sku)
const report = { htmlBytes: html.length };
// common embeddings: window.__INITIAL__, x-data="...JSON.parse(...)", :products="[...]", wire:snapshot
report.hasInitial = /window\.__|__INITIAL|:products=|x-data=|JSON\.parse\(/.test(html);
report.priceCountInHtml = (html.match(/\$?\d+\.\d{2}\s*(USD)?\s*\/?\s*(YD|SY|ROLL)?/g)||[]).length;
report.slugMatches = [...new Set((html.match(/hi_res\/[a-z0-9_]+-[a-z0-9_]+\.jpg/gi)||[]).map(s=>s.replace(/hi_res\/|\.jpg/gi,'')))].slice(0,8);
report.slugTotal = (html.match(/hi_res\/[a-z0-9_]+-[a-z0-9_]+\.jpg/gi)||[]).length;
// JSON-ish product fields present?
report.fieldHits = {};
for (const f of ['preferred_color_number','color_number','item_number','itemNumber','price','price_per','unit','pattern_name','color_name','listPrice']) {
report.fieldHits[f] = (html.match(new RegExp('"'+f+'"','g'))||[]).length;
}
// category / manufacturer filter labels
report.filters = await p.evaluate(() => {
const out = { categories: [], manufacturers: [], collections: 0 };
document.querySelectorAll('a[href*="c="], a[href*="m="], a[href*="cl["]').forEach(a=>{
const h=a.getAttribute('href')||''; const t=(a.innerText||'').trim().slice(0,30);
if (/[?&]c=\d/.test(h) && t) out.categories.push(t+' '+h.match(/c=\d+/)[0]);
if (/[?&]m=\d/.test(h) && t) out.manufacturers.push(t+' '+h.match(/m=\d+/)[0]);
if (/cl(\[|%5B)/.test(h)) out.collections++;
});
out.categories=[...new Set(out.categories)]; out.manufacturers=[...new Set(out.manufacturers)];
const cnt = (document.body.innerText.match(/([\d,]+)\s+products/i)||[])[1];
return { ...out, productCount: cnt };
});
console.log(JSON.stringify(report, null, 2));
await b.close();