← back to Newmor Onboard

scripts/apply-theme.mjs

36 lines

import fs from 'node:fs';
import assert from 'node:assert/strict';
import {hash,transition} from './asset-transition.mjs';
import {ROOT,request,read,save} from './shopify.mjs';
const plan=read('data/live-2026-09-09/theme-change-plan.json');
const apply=process.argv.includes('--approved');const rollback=process.argv.includes('--rollback');
const themes=(await request('themes.json')).themes;
assert.equal(themes.find(t=>t.role==='main').id,plan.theme_id,'Active theme changed');
const receipts=[];
for(const c of plan.changes){
 const path=`themes/${plan.theme_id}/assets.json`;
 const assetURL=()=>path+`?asset[key]=${encodeURIComponent(c.key)}&_tk10670=${Date.now()}`;
 const current=(await request(assetURL())).asset.value;
 const wanted=fs.readFileSync(`${ROOT}/${rollback?'data/live-2026-09-09/theme':'theme-work'}/${c.key}`,'utf8');
 const sourceHash=rollback?c.after_sha256:(c.previous_after_sha256&&hash(current)===c.previous_after_sha256?c.previous_after_sha256:c.before_sha256);
 const targetHash=rollback?c.before_sha256:c.after_sha256;
 const result=await transition({current,wanted,sourceHash,targetHash,apply,
   write:async value=>{
     save('data/live-2026-09-09/theme-apply-journal.json',{started_at:new Date().toISOString(),rollback,receipts,next_asset:c.key});
     await request(path,'PUT',{asset:{key:c.key,value}});
   },
   readback:async()=> {
     let value;
     for(let attempt=0;attempt<5;attempt++){
       value=(await request(assetURL())).asset.value;
       if(hash(value)===targetHash)return value;
       await new Promise(r=>setTimeout(r,1000));
     }
     return value;
   }
 });
 receipts.push({key:c.key,at:new Date().toISOString(),sha256:targetHash,result});
 if(apply)save('data/live-2026-09-09/theme-apply-journal.json',{rollback,receipts});
 console.log(`${result}: ${c.key}`);
}