← back to Dw Daily Catchup 20260909
scripts/unpublish-exact-google.js
17 lines
'use strict';
const fs=require('node:fs'),path=require('node:path'),os=require('node:os'),assert=require('node:assert/strict');
const args=process.argv.slice(2); const apply=args.includes('--apply'); const limit=Number(args.find(x=>x.startsWith('--limit='))?.split('=')[1]||63);
assert.ok(apply && Number.isSafeInteger(limit) && limit>=1 && limit<=63, 'use --apply --limit=1..63');
const csv=path.resolve('verification/tk11326/google-channel-exceptions.csv');
const rows=fs.readFileSync(csv,'utf8').trim().split(/\r?\n/).slice(1).map(x=>{const [id,title,vendor]=x.split(',');return{id,title,vendor};});
assert.equal(rows.length,63); const selected=rows.slice(0,limit);
const env=fs.readFileSync(path.join(os.homedir(),'Projects/secrets-manager/.env'),'utf8'); const token=env.match(/^SHOPIFY_ADMIN_TOKEN=(.*)$/m)[1].trim().replace(/^['"]|['"]$/g,'');
const store='designer-laboratory-sandbox.myshopify.com', pub='gid://shopify/Publication/29646651457';
async function gql(query,variables){const r=await fetch(`https://${store}/admin/api/2026-07/graphql.json`,{method:'POST',headers:{'Content-Type':'application/json','X-Shopify-Access-Token':token},body:JSON.stringify({query,variables}),signal:AbortSignal.timeout(30000)});return{status:r.status,json:await r.json()};}
async function read(id){const r=await gql(`query($id:ID!){product(id:$id){id title status onG:publishedOnPublication(publicationId:"${pub}") onOS:publishedOnPublication(publicationId:"gid://shopify/Publication/22208643184")}}`,{id});assert.equal(r.status,200);assert.equal(r.json.errors,undefined);return r.json.data.product;}
async function main(){const before=[];for(let i=0;i<selected.length;i++){const x=selected[i],p=await read(x.id);assert.equal(p.id,x.id);assert.equal(p.status,'ACTIVE');assert.equal(p.onOS,true);assert.ok(p.onG===true || (i===0 && p.onG===false));before.push(p);}
const journal=path.resolve(`verification/tk11326/google-unpublish-${new Date().toISOString().replace(/[:.]/g,'-')}.jsonl`);let ok=0;for(let i=0;i<selected.length;i++){const x=selected[i];if(before[i].onG===false){fs.appendFileSync(journal,JSON.stringify({id:x.id,title:x.title,vendor:x.vendor,publication:pub,action:'already-unpublished',ok:true,ts:new Date().toISOString()})+'\n');continue;}const r=await gql(`mutation($id:ID!,$pid:ID!){publishableUnpublish(id:$id,input:{publicationId:$pid}){userErrors{field message}}}`,{id:x.id,pid:pub});const ue=r.json?.data?.publishableUnpublish?.userErrors||[];assert.equal(r.status,200);assert.equal(r.json.errors,undefined);assert.equal(ue.length,0,JSON.stringify(ue));fs.appendFileSync(journal,JSON.stringify({id:x.id,title:x.title,vendor:x.vendor,publication:pub,action:'unpublish',ok:true,ts:new Date().toISOString()})+'\n');ok++;await new Promise(r=>setTimeout(r,300));}
const after=[];for(const x of selected){const p=await read(x.id);assert.equal(p.status,'ACTIVE');assert.equal(p.onG,false);assert.equal(p.onOS,true);after.push(p);}
const evidence={timestamp:new Date().toISOString(),selected:selected.length,ok,journal,before,after,assertions:'ACTIVE preserved; Online Store preserved; Google false after independent reread'};fs.writeFileSync(path.resolve(`verification/tk11326/google-unpublish-verified-${selected.length}.json`),JSON.stringify(evidence,null,2)+'\n');console.log(JSON.stringify({verdict:'PASS',selected:selected.length,ok,journal}));}
main().catch(e=>{console.error(e.stack);process.exitCode=1;});