← back to Designer Wallcoverings
mailers/upload-cdn.js
11 lines
const fs=require('fs'),path=require('path');
const DOMAIN='designer-laboratory-sandbox.myshopify.com',API='2024-10';
const TOKEN=process.env.SHOPIFY_DRAFT_TOKEN;
if(!TOKEN){console.error('Missing SHOPIFY_DRAFT_TOKEN');process.exit(1);}
async function gql(query,variables){const r=await fetch(`https://${DOMAIN}/admin/api/${API}/graphql.json`,{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 staged(fn,mime,sz){const q=`mutation($input:[StagedUploadInput!]!){stagedUploadsCreate(input:$input){stagedTargets{url resourceUrl parameters{name value}}userErrors{message}}}`;const d=await gql(q,{input:[{resource:'FILE',filename:fn,mimeType:mime,httpMethod:'POST',fileSize:String(sz)}]});const ue=d.stagedUploadsCreate.userErrors;if(ue&&ue.length)throw new Error(JSON.stringify(ue));return d.stagedUploadsCreate.stagedTargets[0];}
async function put(t,buf,mime){const fd=new FormData();for(const p of t.parameters)fd.append(p.name,p.value);fd.append('file',new Blob([buf],{type:mime}));const r=await fetch(t.url,{method:'POST',body:fd});if(!(r.status>=200&&r.status<300))throw new Error('PUT '+r.status+' '+(await r.text()).slice(0,200));}
async function create(src,fn,alt){const q=`mutation($files:[FileCreateInput!]!){fileCreate(files:$files){files{id fileStatus ... on MediaImage{image{url}}}userErrors{message}}}`;const d=await gql(q,{files:[{originalSource:src,contentType:'IMAGE',alt,filename:fn}]});const ue=d.fileCreate.userErrors;if(ue&&ue.length)throw new Error(JSON.stringify(ue));return d.fileCreate.files[0];}
async function poll(id){const q=`query($id:ID!){node(id:$id){... on MediaImage{fileStatus image{url}}}}`;for(let i=0;i<30;i++){const d=await gql(q,{id});const n=d.node;if(n&&n.fileStatus==='READY'&&n.image&&n.image.url)return n.image.url;if(n&&n.fileStatus==='FAILED')throw new Error('FAILED');await new Promise(r=>setTimeout(r,2000));}throw new Error('timeout');}
(async()=>{const out={};for(const spec of process.argv.slice(2)){const [fp,mime,alt]=spec.split('::');const buf=fs.readFileSync(fp);const fn=path.basename(fp);const t=await staged(fn,mime,buf.length);await put(t,buf,mime);const c=await create(t.resourceUrl,fn,alt||fn);out[fn]=await poll(c.id);console.error(fn,'->',out[fn]);}console.log('RESULT '+JSON.stringify(out));})().catch(e=>{console.error('FATAL',e.message);process.exit(1);});