← back to Newmor Onboard

scripts/preflight.mjs

44 lines

import fs from 'node:fs';
import assert from 'node:assert/strict';
import { ROOT, gql, request, fields, complete, read, save } from './shopify.mjs';
const plan = read('data/newmor-showroom-plan-2026-09-08.json');
if(!process.argv.includes('--saved')&&fs.existsSync(`${ROOT}/data/live-2026-09-09/shopify-before.json`))throw Error('Captured launch baseline already exists. Use --saved for offline checks; never overwrite rollback evidence with current live state.');
const products=process.argv.includes('--saved')?read('data/live-2026-09-09/shopify-before.json').products:[];
let after=null;
if (!products.length) do {
  const d=await gql(`query($after:String){products(first:15,after:$after,query:"vendor:'Newmor Wallcoverings'"){nodes{${fields}}pageInfo{hasNextPage endCursor}}}`,{after});
  products.push(...d.products.nodes.map(complete));
  after=d.products.pageInfo.hasNextPage?d.products.pageInfo.endCursor:null;
  console.log(`Read ${products.length} Newmor products`);
} while(after);
assert(products.every(p=>p.vendor==='Newmor Wallcoverings'));
const counts=products.reduce((a,p)=>(a[p.status]=(a[p.status]||0)+1,a),{});
const ids=new Set(products.map(p=>p.id));
assert.equal(products.length,542); assert.equal(ids.size,542);
assert.deepEqual(counts,{ARCHIVED:237,DRAFT:305});
if (!process.argv.includes('--saved')) save('data/live-2026-09-09/shopify-before.json',{fetched_at:new Date().toISOString(),products});
const byid=new Map(products.map(p=>[p.id,p]));
for (const c of plan.candidates) {
  const p=byid.get(c.id); assert(p); assert.equal(p.status,'DRAFT');
  assert.equal(p.resourcePublications.nodes.filter(x=>x.isPublished).length,0);
  assert.equal(p.handle,c.handle);
  assert(p.variants.nodes.every(v=>/sample/i.test(v.title)),`Unexpected merchandise variant ${p.id}`);
}
const missingImages=plan.candidates.filter(c=>!byid.get(c.id).images.nodes.length).map(c=>({id:c.id,code:c.manufacturer_code,pattern:c.pattern}));
save('data/live-2026-09-09/image-gaps.json',missingImages);
console.log(`Image gaps requiring resolution before publication: ${missingImages.length}`);
if(process.argv.includes('--saved')){console.log('Saved prelaunch baseline checked; live assets and original backups were not overwritten.');process.exit(0);}
const themes=(await request('themes.json')).themes;
const main=themes.find(t=>t.role==='main'); assert(main);
const publications=await gql('{publications(first:50){nodes{id name}pageInfo{hasNextPage}}}');
assert(!publications.publications.pageInfo.hasNextPage);
save('data/live-2026-09-09/theme-and-publications.json',{fetched_at:new Date().toISOString(),themes,publications:publications.publications.nodes,main});
const assets=(await request(`themes/${main.id}/assets.json`)).assets;
save('data/live-2026-09-09/theme-asset-index.json',assets);
const keys=assets.map(a=>a.key).filter(k=>/\.(liquid|js|json)$/.test(k)&& /product|price|quote|showroom|cart|search|theme\.liquid|grid|collection|contact/.test(k) && !/\.min\./.test(k));
for(const key of keys){
 const a=(await request(`themes/${main.id}/assets.json?asset[key]=${encodeURIComponent(key)}`)).asset;
 if(typeof a.value==='string') {const p=`${ROOT}/data/live-2026-09-09/theme/${key}`;fs.mkdirSync(p.substring(0,p.lastIndexOf('/')),{recursive:true});fs.writeFileSync(p,a.value);}
}
console.log(JSON.stringify({counts,main_theme:main.id,theme_assets_saved:keys.length,publications:publications.publications.nodes}));