1#!/usr/bin/env node2var ve=Object.defineProperty;var c=(e,t)=>ve(e,"name",{value:t,configurable:!0});import{execFile as De}from"child_process";import{existsSync as qe,mkdtempSync as Ge,readFileSync as Je,realpathSync as Ne,writeFileSync as M}
58}`,Oe=["templates/index.json","config/settings_data.json","sections/collection-list.liquid","locales/en.default.schema.json"];var ze=Ke(De),Xe="shopify-onboarding-merchant",Ze="1.16.0",_="mock.shop",et="Online Store",A=250,tt=64*1024*1024,V="shopify",nt=2481,ot=15,st=c(e=>new Promise(t=>setTimeout(t,e)),"sleep");function rt(e){let t=e.trim().toLowerCase();t=t.replace(/^[a-z]+:\/\//,"").split(/[/?#]/)[0],(t===""||t==="default")&&(t=_);let n;if(t===_||t===`hydrogen.${_}`)n="";else if(t.endsWith(`.hydrogen.${_}`))n=t.slice(0,-`.hydrogen.${_}`.length);else if(t.endsWith(`.${_}`))n=t.slice(0,-`.${_}`.length);else if(!t.includes("."))n=t;else throw new Error(`"${e}" is not a mock.shop store. Pass a subdomain like "candles" or a host like candles.mock.shop.`);if(n&&!/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(n))throw new Error(`"${e}" is not a valid mock.shop subdomain.`);let o=n?`${n}.${_}`:_,s=n?`${n}.hydrogen.${_}`:`hydrogen.${_}`;return{subdomain:n,apiUrl:`https://${o}/api`,previewUrl:`https://${s}`,label:o}}c(rt,"resolveSource");var it=`
59query Products($after: String) {
60 shop { name }
61 products(first: ${A}, after: $after) {
62 pageInfo { hasNextPage endCursor }
63 nodes {
64 handle title descriptionHtml vendor productType tags
93}`;async function j(e,t,n,o){let s=await e(t,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":`shopify-ai-toolkit/${Xe} ${Ze}`},body:JSON.stringify({query:n,variables:o})}),i=await s.text();if(!s.ok)throw new Error(`${t} answered ${s.status}: ${i.slice(0,300)}`);let l=JSON.parse(i);if(l.errors?.length)throw new Error(`${t} returned GraphQL errors: ${l.errors.map(r=>r.message).join("; ")}`);return l.data}c(j,"storefrontQuery");async function ct(e,t=fetch){let n=[],o="",s=null;do{let l=await j(t,e,it,{after:s});o=l.shop?.name??o;for(let r of l.products.nodes){if(r.images.pageInfo.hasNextPage||r.variants.pageInfo.hasNextPage)throw new Error(`Product ${r.handle} has more than ${A} images or variants; this importer does not page inside a product.`);n.push({handle:r.handle,title:r.title,descriptionHtml:r.descriptionHtml??"",vendor:r.vendor??"",productType:r.productType??"",tags:r.tags??[],options:r.options??[],images:r.images.nodes,variants:r.variants.nodes})}s=l.products.pageInfo.hasNextPage?l.products.pageInfo.endCursor:null}while(s);let i=[];s=null;do{let l=await j(t,e,lt,{after:s});for(let r of l.collections.nodes){let u=r.products.nodes.map(h=>h.handle),f=r.products.pageInfo;for(;f.hasNextPage;){let h=await j(t,e,at,{handle:r.handle,after:f.endCursor});u.push(...h.collection.products.nodes.map(T=>T.handle)),f=h.collection.products.pageInfo}i.push({handle:r.handle,title:r.title,descriptionHtml:r.descriptionHtml??"",image:r.image??null,productHandles:u})}s=l.collections.pageInfo.hasNextPage?l.collections.pageInfo.endCursor:null}while(s);return{shopName:o,products:n,collections:i}}c(ct,"fetchCatalog");async function ut(e,t=fetch){return re(await j(t,e,se,{}))}c(ut,"fetchExtras");var we=`mutation ImportProduct($identifier: ProductSetIdentifiers, $input: ProductSetInput!) {
110`}c(Ce,"toJsonl");function yt(e){let t=e.indexOf("{");if(t<0)throw new Error(`Shopify CLI returned no JSON: ${e.slice(0,200)}`);let n=JSON.parse(e.slice(t));if(n.errors?.length)throw new Error(`Admin API errors: ${n.errors.map(o=>o.message??JSON.stringify(o)).join("; ")}`);return n.data??n.result?.data??n}c(yt,"unwrapData");function bt(e){async function t(n){e(`$ ${V} ${n.map(o=>/\s/.test(o)?JSON.stringify(o):o).join(" ")}`);try{let{stdout:o}=await ze(V,n,{maxBuffer:tt,env:{...process.env,SHOPIFY_FLAG_NO_COLOR:"1"}});return o}catch(o){let s=[o.stdout,o.stderr].filter(Boolean).join(`
111`);throw new Error(`\`${V} ${n.slice(0,3).join(" ")}\` failed: ${s.trim()||o.message}`)}}return c(t,"run"),{async execute(n,o,s,i=!1){let l=["store","execute","--store",n,"--json","--query",o];return s&&l.push("--variables",JSON.stringify(s)),i&&l.push("--allow-mutations"),yt(await t(l))},async bulk(n,o,s,i){if(await t(["store","bulk","execute","--store",n,"--query-file",o,"--variable-file",s,"--allow-mutations","--watch","--output-file",i]),!qe(i))throw new Error("bulk operation wrote no results file; it likely failed before running (see the CLI output above)");return Je(i,"utf-8")}}}c(bt,"makeCliRunner");function O(e,t){let n=e?.[t];if(n?.userErrors?.length)throw new Error(`${t}: ${n.userErrors.map(o=>`${(o.field??[]).join(".")||"input"}: ${o.message}`).join("; ")}`);return n}c(O,"payloadOf");async function It(e){let{log:t}=e,{store:n}=e,o=rt(e.source),s=Ge(w(Ye(),"mock-shop-import-"));t(`Reading ${o.label} catalog\u2026`);let i=await ct(o.apiUrl,e.fetchImpl),l=await ut(o.apiUrl,e.fetchImpl);t(` ${i.products.length} products, ${i.collections.length} collections, ${l.pages.length} pages, ${l.blogs.length} blogs from "${i.shopName}"`);let r={source:{...o,shopName:i.shopName},store:n,storeName:null,collections:{total:i.collections.length,created:0,reused:0},products:{total:i.products.length,imported:0,failed:[]},published:{attempted:0,failed:0,publicationId:null},files:{hero:null,logo:null,ready:!1},content:{pages:{created:0,reused:0},blogs:{created:0,reused:0},articles:{created:0,reused:0},menus:[],note:null},theme:{id:null,name:null,heroImageSet:!1,headingSet:!1,logoSet:!1,collectionListAdded:!1,featuredCollections:[],upserted:[],note:null}},u=bt(t),f=new Map,h=null,T=i.collections.map((a,g)=>`c${g}: collections(first: 1, query: ${JSON.stringify(`handle:${a.handle}`)}) { nodes { id handle } }`).join(`
112`),x=await u.execute(n,`query Lookup { publications(first: 25) { nodes { id name catalog { title } } } ${T} }`);i.collections.forEach((a,g)=>{let m=x[`c${g}`]?.nodes?.find(y=>y.handle===a.handle);m&&f.set(a.handle,m.id)}),h=ht(x.publications?.nodes??[])?.id??null,r.published.publicationId=h,h||t(" warning: no Online Store publication found; products will be imported but not published");for(let a of i.collections){if(f.has(a.handle)){r.collections.reused+=1;continue}let g=await u.execute(n,pt,{input:mt(a)},!0),m=O(g,"collectionCreate");f.set(a.handle,m.collection.id),r.collections.created+=1}t(` collections: ${r.collections.created} created, ${r.collections.reused} already present`);let H=new Map;for(let a of i.collections){let g=f.get(a.handle);if(g)for(let m of a.productHandles)H.set(m,[...H.get(m)??[],g])}let L=i.products.map(a=>gt(a,H.get(a.handle)??[])),W=w(s,"product_set.graphql"),K=w(s,"products.jsonl"),Re=w(s,"products.results.jsonl");M(W,we),M(K,Ce(L)),t(`Importing ${L.length} products\u2026`);let ke=await u.bulk(n,W,K,Re),z=Ae(ke,"productSet"),X=z.succeeded.map(a=>a.id).filter(a=>!!a);for(let a of z.failed){let g=L[a.line];if(g){t(` retrying ${g.identifier.handle}: ${a.errors.join("; ")}`);try{let m=await u.execute(n,we,g,!0),y=O(m,"productSet");y?.product?.id&&X.push(y.product.id)}catch(m){r.products.failed.push({handle:g.identifier.handle,errors:[m.message]})}}}if(r.products.imported=L.length-r.products.failed.length,t(` ${r.products.imported}/${L.length} products imported`),h){let a=[...X,...f.values()],g=ft(a,h),m=w(s,"publish.graphql"),y=w(s,"publish.jsonl"),I=w(s,"publish.results.jsonl");M(m,dt),M(y,Ce(g)),t(`Publishing ${a.length} products and collections to the Online Store\u2026`);let d=await u.bulk(n,m,y,I),b=Ae(d,"publishablePublish");r.published={attempted:a.length,failed:b.failed.length,publicationId:h},b.failed.length&&t(` ${b.failed.length} publish operations failed; rerun to converge`)}let P=ie({brand:l.brand,collectionImageUrls:i.collections.map(a=>a.image?.url),productImageUrls:i.products.map(a=>a.images[0]?.url)}),N=[];if(P){let a=J(le,P.url);r.files.hero={filename:a,source:P.source},N.push({originalSource:P.url,filename:a,contentType:"IMAGE",duplicateResolutionMode:"REPLACE",alt:l.brand.coverImageAlt??`${i.shopName} hero image`})}if(l.brand.logoUrl){let a=J(ae,l.brand.logoUrl);r.files.logo={filename:a},N.push({originalSource:l.brand.logoUrl,filename:a,contentType:"IMAGE",duplicateResolutionMode:"REPLACE",alt:`${i.shopName} logo`})}if(N.length){t(`Uploading brand assets: ${N.map(m=>m.filename).join(", ")}\u2026`),O(await u.execute(n,ge,{files:N},!0),"fileCreate");let a=N.map(m=>`filename:${m.filename}`).join(" OR "),g=!1;for(let m=0;m<ot;m++){let I=(await u.execute(n,me,{query:a})).files?.nodes??[];if(I.length>=N.length&&I.every(d=>d.fileStatus==="READY")){r.files.ready=!0;break}if(I.some(d=>d.fileStatus==="FAILED")){g=!0;break}await st(2e3)}g?(r.files.hero=null,r.files.logo=null,t(" brand asset upload failed; hero and logo will not be wired")):t(r.files.ready?" brand assets ready":" brand assets still processing; the theme will pick them up shortly")}try{let a=new Map,g=new Map;if(l.pages.length){let I=new Map(((await u.execute(n,fe)).pages?.nodes??[]).map(d=>[d.handle,d.id]));for(let d of l.pages){if(I.has(d.handle)){g.set(d.handle,I.get(d.handle)),r.content.pages.reused+=1;continue}let b=O(await u.execute(n,he,{page:{title:d.title,handle:d.handle,body:d.body,isPublished:!0}},!0),"pageCreate");g.set(d.handle,b.page.id),r.content.pages.created+=1}}if(l.blogs.length){let I=(await u.execute(n,ye)).blogs?.nodes??[];for(let d of l.blogs){let b=I.find(p=>p.handle===d.handle),$,C=new Set((b?.articles?.nodes??[]).map(p=>p.handle));b?($=b.id,r.content.blogs.reused+=1):($=O(await u.execute(n,be,{blog:{title:d.title,handle:d.handle}},!0),"blogCreate").blog.id,r.content.blogs.created+=1),a.set(d.handle,$);for(let p of d.articles){if(C.has(p.handle)){r.content.articles.reused+=1;continue}let E={blogId:$,title:p.title,handle:p.handle,body:p.contentHtml,isPublished:!0,author:{name:p.author??i.shopName}};p.excerpt&&(E.summary=p.excerpt),p.publishedAt&&(E.publishDate=p.publishedAt),p.imageUrl&&(E.image={url:p.imageUrl,altText:p.imageAlt??p.title}),O(await u.execute(n,Ie,{article:E},!0),"articleCreate"),r.content.articles.created+=1}}}(r.content.pages.created||r.content.blogs.created)&&t(` content: ${r.content.pages.created} pages, ${r.content.blogs.created} blogs, ${r.content.articles.created} articles created`);let m={collectionIdByHandle:f,blogIdByHandle:a,pageIdByHandle:g},y=[];if(l.menus.main?.items.length&&y.push(["main-menu",l.menus.main]),l.menus.footer?.items.length&&y.push(["footer",l.menus.footer]),y.length){let I=(await u.execute(n,Se)).menus?.nodes??[];for(let[d,b]of y){let $=b.items.map(E=>Q(E,m)),C=b.title||(d==="footer"?"Footer menu":"Main menu"),p=I.find(E=>E.handle===d);p?O(await u.execute(n,Ee,{id:p.id,title:C,handle:d,items:$},!0),"menuUpdate"):O(await u.execute(n,_e,{title:C,handle:d,items:$},!0),"menuCreate"),r.content.menus.push(d)}t(` menus: ${r.content.menus.join(", ")}`)}}catch(a){r.content.note=a.message,t(` content copy stopped: ${a.message}`)}try{let g=((await u.execute(n,xe)).themes?.nodes??[]).find(S=>S.role==="MAIN");if(!g)throw new Error("no live theme found");if(g.themeStoreId!==nt&&!/horizon/i.test(g.name??""))throw new Error(`live theme "${g.name}" is not Horizon; homepage left untouched`);let m=g.id,y=g.name;r.theme.id=m,r.theme.name=y;let I=(await u.execute(n,$e,{id:m,filenames:Oe})).theme?.files?.nodes??[],d=new Map(I.map(S=>[S.filename,S.body?.content??""])),b=d.get("templates/index.json"),$=d.get("config/settings_data.json");if(!b)throw new Error(`theme "${y}" has no templates/index.json; skipping wiring`);let C=d.get("locales/en.default.schema.json")?U(d.get("locales/en.default.schema.json")):{},p=de(U(b),{heroRef:r.files.hero?Y(r.files.hero.filename):null,slogan:l.brand.slogan,collectionHandles:[...i.collections].sort((S,k)=>+!!k.image-+!!S.image).map(S=>S.handle),collectionListLiquid:d.get("sections/collection-list.liquid")??null,locale:C}),E=v(p.index);if(E.length)throw new Error(`unresolved translation keys in settings: ${E.join(", ")}`);let R=[];if((p.heroImageSet||p.headingSet||p.collectionListAdded)&&R.push({filename:"templates/index.json",body:{type:"TEXT",value:JSON.stringify(p.index,null,2)}}),$&&r.files.logo){let S=pe(U($),Y(r.files.logo.filename));S.logoSet&&(r.theme.logoSet=!0,R.push({filename:"config/settings_data.json",body:{type:"TEXT",value:JSON.stringify(S.settings,null,2)}}))}if(R.length){t(`Wiring theme "${y}": ${R.map(k=>k.filename).join(", ")}\u2026`);let S=O(await u.execute(n,Te,{themeId:m,files:R},!0),"themeFilesUpsert");r.theme.upserted=(S.upsertedThemeFiles??[]).map(k=>k.filename)}r.theme.heroImageSet=p.heroImageSet,r.theme.headingSet=p.headingSet,r.theme.collectionListAdded=p.collectionListAdded,r.theme.featuredCollections=p.featuredHandles,p.heroSectionId||(r.theme.note="no hero section in templates/index.json; hero and heading not set")}catch(a){r.theme.note=a.message,t(` theme wiring skipped: ${a.message}`)}let Pe=await u.execute(n,"query StoreName { shop { name } }");return r.storeName=Pe.shop?.name??null,r}c(It,"importCatalog");function St(e){let t=[`Copied "${e.source.shopName}" (${e.source.label}) into ${e.store}:`,` products: ${e.products.imported} of ${e.products.total} imported${e.products.failed.length?`, ${e.products.failed.length} failed`:""}`,` collections: ${e.collections.created} created, ${e.collections.reused} reused (${e.collections.total} total)`,e.published.publicationId?` published to Online Store: ${e.published.attempted-e.published.failed} of ${e.published.attempted}`:" not published: no Online Store publication found"],n=[e.files.hero?`hero (${e.files.hero.source} image)`:null,e.files.logo?"logo":null].filter(Boolean);t.push(n.length?` brand assets: ${n.join(", ")}${e.files.ready?"":" (still processing)"}`:" brand assets: none available from the reference store");let o=e.content,s=[o.pages.created+o.pages.reused?`${o.pages.created+o.pages.reused} pages`:null,o.blogs.created+o.blogs.reused?`${o.blogs.created+o.blogs.reused} blogs`:null,o.articles.created+o.articles.reused?`${o.articles.created+o.articles.reused} articles`:null,o.menus.length?`menus: ${o.menus.join(", ")}`:null].filter(Boolean);t.push(` content: ${s.length?s.join(", "):"nothing to copy"}${o.note?` (stopped: ${o.note})`:""}`);let i=e.theme,l=[i.heroImageSet?"hero image":null,i.headingSet?"hero heading":null,i.collectionListAdded?`featured collections (${i.featuredCollections.join(", ")})`:null,i.logoSet?"logo":null].filter(Boolean);t.push(i.id?` theme: "${i.name}"${l.length?`, wired ${l.join(", ")}`:", nothing to wire"}${i.note?` (${i.note})`:""}`:` theme: not wired${i.note?` (${i.note})`:""}`),e.storeName&&t.push(e.storeName===e.source.shopName?` store name: "${e.storeName}"`:` store name: "${e.storeName}" (reference is "${e.source.shopName}"; a store's name is set when it is created and this import does not change it)`);for(let r of e.products.failed)t.push(` FAILED ${r.handle}: ${r.errors.join("; ")}`);return(e.products.failed.length||e.published.failed)&&t.push(" Rerun the same command to converge; existing handles are updated, not duplicated."),t.join(`
113`)}c(St,"summarize");var Le={store:{type:"string",valueName:"domain",description:"Target store domain, e.g. my-store.myshopify.com"},source:{type:"string",valueName:"store",description:"mock.shop reference store: subdomain, host, or preview URL (e.g. candles)"},json:{type:"boolean",description:"Print the full report as JSON"},...ne},Et=oe(["scripts/import_mock_shop_catalog.mjs --store <domain> --source <store> [options]"],Le);async function _t(){let{values:e}=We({options:Z(Le),allowPositionals:!1});e.help&&(console.log(Et),process.exit(0)),(!e.store||!e.source)&&(console.error("Usage: scripts/import_mock_shop_catalog.mjs --store <domain> --source <store> (run with --help for details)"),process.exit(1));let t=await It({store:e.store,source:e.source,log:c(n=>console.error(n),"log")});console.log(e.json?JSON.stringify(t,null,2):St(t)),process.exit(t.products.failed.length||t.published.failed?2:0)}c(_t,"main");var xt=(()=>{try{if(!process.argv[1])return!1;let e=Ne(Ve(import.meta.url)),t=Ne(Qe(process.argv[1]));return e===t}catch{return!1}})();xt&&_t().catch(e=>{console.error(e instanceof Error?e.message:String(e)),process.exit(1)});export{pt as COLLECTION_CREATE_MUTATION,_ as MOCK_SHOP_APEX,et as ONLINE_STORE_PUBLICATION_NAME,we as PRODUCT_SET_MUTATION,dt as PUBLISH_MUTATION,ft as buildPublishVariables,ct as fetchCatalog,ut as fetchExtras,ht as findOnlineStorePublication,It as importCatalog,Ae as parseBulkResults,rt as resolveSource,St as summarize,mt as toCollectionCreateInput,Ce as toJsonl,gt as toProductSetVariables};