← back to Japan Enrich
carnegie: add width-backfill revert tool (TK-11016 undo)
a3d377e9b46fd1624d6e90114dfa0a00ec0e2387 · 2026-08-31 09:53:52 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
A carnegie-split/backfill-width-revert.cjs
Diff
commit a3d377e9b46fd1624d6e90114dfa0a00ec0e2387
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Aug 31 09:53:52 2026 -0700
carnegie: add width-backfill revert tool (TK-11016 undo)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
carnegie-split/backfill-width-revert.cjs | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/carnegie-split/backfill-width-revert.cjs b/carnegie-split/backfill-width-revert.cjs
new file mode 100644
index 0000000..3fef669
--- /dev/null
+++ b/carnegie-split/backfill-width-revert.cjs
@@ -0,0 +1,29 @@
+// UNDO for STEP B (TK-11016): deletes the custom.Width / global.Width metafields this
+// backfill CREATED (by their captured metafield_id in the results file). Since every
+// target product had ZERO pre-existing Width metafields (recorded in the restore map),
+// deleting the created ones restores the exact prior state. Products stay DRAFT throughout.
+//
+// Usage: node backfill-width-revert.cjs <results-json> (dry-run)
+// node backfill-width-revert.cjs <results-json> --apply (deletes)
+const fs=require("fs"),os=require("os"),path=require("path"),https=require("https");
+const APPLY=process.argv.includes("--apply");
+const resultsFile=process.argv.find(a=>a.endsWith(".json"));
+if(!resultsFile){console.error("give a results-*.json path");process.exit(1);}
+const env=fs.readFileSync(path.join(os.homedir(),"Projects/secrets-manager/.env"),"utf8");
+const g=k=>{const m=env.match(new RegExp("^"+k+"=(.*)$","m"));return m?m[1].trim().replace(/^["']|["']$/g,""):null};
+const shop="designer-laboratory-sandbox.myshopify.com",tok=g("SHOPIFY_ADMIN_TOKEN")||g("SHOPIFY_ADMIN_API_TOKEN");
+const sleep=ms=>new Promise(r=>setTimeout(r,ms));
+function req(method,p){return new Promise((res)=>{const o={host:shop,path:p,method,headers:{"X-Shopify-Access-Token":tok},timeout:30000};const r=https.request(o,x=>{let d="";x.on("data",c=>d+=c);x.on("end",()=>res({status:x.statusCode,body:d}))});r.on("error",e=>res({status:0,body:String(e)}));r.end()})}
+(async()=>{
+ const results=JSON.parse(fs.readFileSync(resultsFile,"utf8"));
+ const created=results.filter(r=>r.status===201&&r.metafield_id);
+ console.log(`metafields to delete: ${created.length}`);
+ if(!APPLY){console.log("DRY-RUN — pass --apply to delete.");return;}
+ let ok=0,fail=0;
+ for(const r of created){
+ const d=await req("DELETE",`/admin/api/2024-10/products/${r.id}/metafields/${r.metafield_id}.json`);
+ if(d.status===200){ok++;process.stdout.write(".");}else{fail++;process.stdout.write("x");}
+ await sleep(300);
+ }
+ console.log(`\nreverted ${ok}, ${fail} failed. Products remain DRAFT (restored to no-Width state).`);
+})();
← 58e9ec2 carnegie: rollout-draft.cjs writes custom.Width+global.Width
·
back to Japan Enrich
·
carnegie: add GATED activation script for 41 eligible drafts e48de5a →