← back to Koroseal Goodrich Audit
TK-10347: TAK-ED01-04 cropped cream weave applied live (Steve ruling=crop); ticket complete
367765775b0b774e9c0bcecfbc7965e74321c2b1 · 2026-08-08 07:56:40 -0700 · Steve Abrams
Files touched
A tk10347/TAKUMI_TAK-ED01-04_CREAM_cropped.jpgA tk10347/apply_ed0104.mjs
Diff
commit 367765775b0b774e9c0bcecfbc7965e74321c2b1
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Aug 8 07:56:40 2026 -0700
TK-10347: TAK-ED01-04 cropped cream weave applied live (Steve ruling=crop); ticket complete
---
tk10347/TAKUMI_TAK-ED01-04_CREAM_cropped.jpg | Bin 0 -> 336229 bytes
tk10347/apply_ed0104.mjs | 50 +++++++++++++++++++++++++++
2 files changed, 50 insertions(+)
diff --git a/tk10347/TAKUMI_TAK-ED01-04_CREAM_cropped.jpg b/tk10347/TAKUMI_TAK-ED01-04_CREAM_cropped.jpg
new file mode 100644
index 0000000..ec12a86
Binary files /dev/null and b/tk10347/TAKUMI_TAK-ED01-04_CREAM_cropped.jpg differ
diff --git a/tk10347/apply_ed0104.mjs b/tk10347/apply_ed0104.mjs
new file mode 100644
index 0000000..61a557e
--- /dev/null
+++ b/tk10347/apply_ed0104.mjs
@@ -0,0 +1,50 @@
+#!/usr/bin/env node
+// TK-10347 — TAK-ED01-04: upload cropped cream weave (Steve ruled crop), feature, remove wrong ED01-01.
+import fs from 'node:fs';
+const ENV = fs.readFileSync(process.env.HOME + '/Projects/secrets-manager/.env','utf8');
+const TOKEN = (ENV.match(/^SHOPIFY_ADMIN_TOKEN=(.+)$/m)||[])[1]?.trim().replace(/^["']|["']$/g,'');
+const STORE='designer-laboratory-sandbox.myshopify.com', API='2024-10';
+const URL=`https://${STORE}/admin/api/${API}/graphql.json`;
+const PID='gid://shopify/Product/7519950602291';
+const WRONG='gid://shopify/MediaImage/24773828804659';
+const FILE='/tmp/korpg/verify/TAKUMI_TAK-ED01-04_CREAM_cropped.jpg';
+const FNAME='TAKUMI_TAK-ED01-04_CREAM_cropped.jpg';
+const APPLY=process.argv.includes('--apply');
+const sleep=ms=>new Promise(r=>setTimeout(r,ms));
+async function gql(query,variables){
+ const r=await fetch(URL,{method:'POST',headers:{'X-Shopify-Access-Token':TOKEN,'Content-Type':'application/json'},body:JSON.stringify({query,variables})});
+ const j=await r.json(); if(j.errors) throw new Error(JSON.stringify(j.errors)); return j.data;
+}
+async function run(){
+ const bytes=fs.statSync(FILE).size;
+ console.log('APPLY',APPLY,'file',bytes,'bytes');
+ if(!APPLY){ console.log('DRY: staged upload + createMedia + reorder0 + delete',WRONG); return; }
+ // 1. staged upload target
+ const su=await gql(`mutation($input:[StagedUploadInput!]!){ stagedUploadsCreate(input:$input){ stagedTargets{ url resourceUrl parameters{ name value } } userErrors{ message } } }`,
+ {input:[{filename:FNAME, mimeType:'image/jpeg', resource:'IMAGE', httpMethod:'POST', fileSize:String(bytes)}]});
+ if(su.stagedUploadsCreate.userErrors.length) throw new Error('staged: '+JSON.stringify(su.stagedUploadsCreate.userErrors));
+ const t=su.stagedUploadsCreate.stagedTargets[0];
+ // 2. POST file to staged target
+ const fd=new FormData();
+ for(const p of t.parameters) fd.append(p.name,p.value);
+ fd.append('file', new Blob([fs.readFileSync(FILE)],{type:'image/jpeg'}), FNAME);
+ const up=await fetch(t.url,{method:'POST',body:fd});
+ if(!(up.status>=200&&up.status<300)) throw new Error('upload status '+up.status+' '+(await up.text()).slice(0,200));
+ console.log('uploaded to staged target', up.status, 'resourceUrl', t.resourceUrl);
+ // 3. create media from resourceUrl
+ const cm=await gql(`mutation($pid:ID!,$m:[CreateMediaInput!]!){ productCreateMedia(productId:$pid,media:$m){ media{ ... on MediaImage{ id status } } mediaUserErrors{ message } } }`,
+ {pid:PID, m:[{originalSource:t.resourceUrl, mediaContentType:'IMAGE', alt:'Dapper Paper Weave Cream TAK-ED01-04'}]});
+ if(cm.productCreateMedia.mediaUserErrors.length) throw new Error('createMedia: '+JSON.stringify(cm.productCreateMedia.mediaUserErrors));
+ const newId=cm.productCreateMedia.media[0].id; console.log('created',newId);
+ for(let i=0;i<30;i++){ const p=await gql(`query($id:ID!){ node(id:$id){ ... on MediaImage{ status image{ url } } } }`,{id:newId});
+ if(p.node.status==='READY'){ console.log('READY',(p.node.image?.url||'').slice(-70)); break; }
+ if(p.node.status==='FAILED') throw new Error('media FAILED'); await sleep(2000); }
+ // 4. feature + delete wrong
+ await gql(`mutation($id:ID!,$moves:[MoveInput!]!){ productReorderMedia(id:$id,moves:$moves){ mediaUserErrors{ message } } }`,{id:PID,moves:[{id:newId,newPosition:'0'}]});
+ console.log('reordered ->0'); await sleep(2500);
+ const dd=await gql(`mutation($pid:ID!,$ids:[ID!]!){ productDeleteMedia(productId:$pid,mediaIds:$ids){ deletedMediaIds mediaUserErrors{ message } } }`,{pid:PID,ids:[WRONG]});
+ console.log('deleted wrong', dd.productDeleteMedia.deletedMediaIds);
+ const fm=await gql(`query($id:ID!){ product(id:$id){ featuredMedia{ ... on MediaImage{ image{ url } } } media(first:5){ edges{ node{ id } } } } }`,{id:PID});
+ console.log('NOW featured', fm.product.featuredMedia.image.url, '| imgs', fm.product.media.edges.length);
+}
+run().catch(e=>{console.error('ERROR',e.message);process.exit(1);});
← 09a9d53 TK-10347: applied 6 approved Koroseal cross-link image swaps
·
back to Koroseal Goodrich Audit
·
TK-10369: Koroseal fleet cross-link scan candidates (22 file 6dc5b68 →