@shopify/cli
Version:
A CLI tool to build for the Shopify platform
11 lines (10 loc) • 12.9 kB
JavaScript
import{a as xe}from"../../../chunk-JCL2RRU6.js";import{Ba as Le,E as Pe,J as ve,M as Ae,O as ke,_ as Ce,aa as Te,g as we,ya as Re}from"../../../chunk-54CAKCYR.js";import{T as N,X as Ie,k as be}from"../../../chunk-7ESSIN27.js";import{a as ye}from"../../../chunk-ZTMSBSYD.js";import{b as ge}from"../../../chunk-E3EMHAJB.js";import{b as he}from"../../../chunk-6WL4GA2M.js";import{a as de,c as ue}from"../../../chunk-TYZXGSHO.js";import"../../../chunk-GZS44BUW.js";import"../../../chunk-K2WUCOQJ.js";import"../../../chunk-7QIOUDCX.js";import"../../../chunk-7MUKLZOL.js";import"../../../chunk-VBUZWRUL.js";import"../../../chunk-DCPBRWVC.js";import"../../../chunk-KR6QDE7D.js";import"../../../chunk-UXVZ2P63.js";import"../../../chunk-QSTEVZFQ.js";import"../../../chunk-5Y7GIF2W.js";import"../../../chunk-EKXY5COY.js";import"../../../chunk-4DCQNGUV.js";import"../../../chunk-QBSKKQBN.js";import"../../../chunk-FQWB2F75.js";import"../../../chunk-XONFGLJQ.js";import"../../../chunk-4LNCYIS3.js";import{B as ie,D as re,E as oe,f as T,g as ee,i as te,p as ae}from"../../../chunk-L2MGAEV3.js";import"../../../chunk-PRKBO42R.js";import"../../../chunk-ZSBA6VIC.js";import{a as z}from"../../../chunk-F2QU6WWX.js";import"../../../chunk-XULPJ6UG.js";import{b as fe}from"../../../chunk-XR6GMMEU.js";import"../../../chunk-3TNEIDOD.js";import{b as Q}from"../../../chunk-MHWV5RQV.js";import"../../../chunk-XOTA6JTZ.js";import"../../../chunk-MOA33ZFO.js";import"../../../chunk-JUVAGMIH.js";import{D as ce,f as ne,u as se,v as le,z as S}from"../../../chunk-6G6TMKXF.js";import"../../../chunk-P6XE4MH5.js";import"../../../chunk-KLMDWDT2.js";import"../../../chunk-5CH3B62S.js";import"../../../chunk-QUTQDXSL.js";import{d as pe}from"../../../chunk-WSDN25F5.js";import{d as m}from"../../../chunk-M56NDIMD.js";import"../../../chunk-PD5ZHJWI.js";import{r as je}from"../../../chunk-LDGAHMS7.js";import"../../../chunk-ZR76GGZ6.js";import"../../../chunk-EENHXSWU.js";import"../../../chunk-FUOIGXI4.js";import"../../../chunk-6M3ZYNGO.js";import"../../../chunk-QYR5VPQA.js";import"../../../chunk-OBEWZXOQ.js";import{$ as U,$a as Z,Ab as X,Bb as J,Ca as k,Gb as g,Hb as R,Ib as w,Ja as B,Oa as K,Ta as I,Ua as C,Va as W,Wa as q,ka as H,ma as Y,sa as F,ua as O,wa as V}from"../../../chunk-N5PQPIBF.js";import"../../../chunk-CERXUPGC.js";import"../../../chunk-T4M5CWAO.js";import"../../../chunk-PRVQAHWI.js";import{e as me}from"../../../chunk-YTNDFQJT.js";import"../../../chunk-ULQG3XQS.js";import{d as s,e as A,f as D,p as j,q as E}from"../../../chunk-IU2ZQ6TE.js";import"../../../chunk-PIBY5DDZ.js";import{e as De,g as u}from"../../../chunk-VPRTJUIN.js";u();u();var b={reactRouter:{url:"https://github.com/Shopify/shopify-app-template-react-router",label:"Build a React Router app (recommended)",visible:!0,branches:{prompt:"For your React Router template, which language do you want?",options:{javascript:{branch:"javascript-cli",label:"JavaScript"},typescript:{branch:"main-cli",label:"TypeScript"}}}},remix:{url:"https://github.com/Shopify/shopify-app-template-remix",label:"Build a Remix app",visible:!1,branches:{prompt:"For your Remix template, which language do you want?",options:{javascript:{branch:"javascript",label:"JavaScript"},typescript:{branch:"main",label:"TypeScript"}}}},none:{url:"https://github.com/Shopify/shopify-app-template-extension-only",label:"Build an extension-only app",visible:!0},node:{url:"https://github.com/Shopify/shopify-app-template-node",visible:!1},ruby:{url:"https://github.com/Shopify/shopify-app-template-ruby",visible:!1}},_=Object.keys(b),L=_.filter(e=>b[e].visible),Ee=["reactRouter","none"],Ue=async e=>{let t=e.template,a=e.flavor,o={template:b.reactRouter.url};t??=await S({choices:Ee.map(r=>({label:b[r].label||r,value:r})),message:"Get started building your app:",defaultValue:_.find(r=>b[r].url===o.template)});let i={...e,template:t,templateType:x(t)?t:"custom",globalCLIResult:{install:!1,alreadyInstalled:!1}},n,p;if(i.templateType!=="custom"){let r=b[i.templateType];n=r.url,r.branches&&(a?p=r.branches.options[a]?.branch:p=await S({message:r.branches.prompt||"Choose a flavor:",choices:Object.entries(r.branches.options).map(([f,c])=>({value:c.branch,label:c.label}))}))}return p&&(n=`${n}#${p}`),i.template=n||i.template||o.template,i.globalCLIResult=await J(),i},Fe=Ue;function x(e){return _.includes(e)}u();u();import{platform as He}from"os";async function Oe({packageJSON:e,local:t,useGlobalCLI:a}){if(e.dependencies=e.dependencies??{},a?delete e.dependencies["@shopify/cli"]:e.dependencies["@shopify/cli"]=z,delete e.dependencies["@shopify/app"],t){let o=await Ye("cli");e.dependencies["@shopify/cli"]=o;let i={"@shopify/cli":o};e.overrides=e.overrides?{...e.overrides,...i}:i,e.resolutions=e.resolutions?{...e.resolutions,...i}:i}return e}async function Ye(e){return`file:${await Z(`packages/${e}`,{type:"directory",cwd:j(import.meta.url)})}`}async function Se({from:e,packageManager:t}){let a=He()==="win32"&&t==="yarn"?["--network-concurrency","1"]:[];return ae({directory:A(e),packageManager:t,args:a})}u();async function G(e,t){let o=(await q([s(e,"**",".git"),s(e,"**",".github"),s(e,"**",".gitmodules"),s(e,"**",".cli-liquid-bypass"),s(e,"LICENSE*"),s(e,"**","frontend/LICENSE*"),s(e,"package.json.cli2")],{dot:!0,onlyFiles:!1,onlyDirectories:!1,ignore:["**/node_modules/**"]})).map(p=>k(p,{force:!0})),i=new Set(ee[t]),n=T.filter(p=>!i.has(p)).map(p=>{let r=s(e,p);if(C(r))return B(r)});return Promise.all([...o,...n])}async function Ve(e){let t=e.packageManager,a=U(e.name),o=s(e.directory,a),i=ge(e.template);await Ne(o,a),await Be(o),se({body:["Initializing project with",{command:t},`
Use the`,{command:"--package-manager"},"flag to select a different package manager."]}),await H(async r=>{let f=s(r,"download"),c=i.filePath?s(f,i.filePath):f,d=s(r,"app"),v=i.branch?`${i.baseURL}#${i.branch}`:i.baseURL;await V(f);let y=[{title:`Downloading template from ${v}`,task:async()=>{await ue({repoUrl:v,destination:f,shallow:!0})}}];y.push({title:"Parsing liquid",task:async()=>{await he(c,d,{dependency_manager:t,app_name:e.name})}},{title:"Updating package.json",task:async()=>{let l=(await ie(d)).content;l.name=a,l.author=await ne()??"",l.private=!0;let P=["extensions/*"].concat(Ke(d));switch(t){case"npm":case"yarn":case"bun":l.workspaces=P;break;case"pnpm":{await We(d,P),await F(s(d,".npmrc"),`auto-install-peers=true
`);break}case"homebrew":case"unknown":throw new te}await Oe({packageJSON:l,local:e.local,directory:d,useGlobalCLI:e.useGlobalCLI}),await re(d,l)}}),e.postCloneActions.removeLockfilesFromGitignore&&y.push({title:"Removing lockfiles from .gitignore",task:async()=>{let l=s(d,".gitignore");if(await I(l)){let P=await Y(l);T.forEach($e=>{let ze=new RegExp(`^${$e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}$`,"gm");P=P.replace(ze,"")}),await O(l,P.trim())}}}),await me()&&y.push({title:"[Shopifolks-only] Configuring the project's NPM registry",task:async()=>{let l=s(d,".npmrc");await F(l,`@shopify:registry=https://registry.npmjs.org
`)}});let $=!1;y.push({title:"Preparing project directory",task:async()=>{await Ne(o,a),$=!0,await K(d,o)}}),y.push({title:`Installing dependencies with ${t}`,task:async()=>{await Se({from:o,packageManager:t})}},{title:"Cleaning up",task:async()=>{await G(o,t)}},{title:"Initializing a Git repository...",task:async()=>{await de(o)}});try{await ce(y)}catch(l){throw $&&await k(o).catch(()=>{}),l}});let n;if(e.selectedAppOrNameResult.result==="new"){let r=await Pe(o,e.name),f=e.selectedAppOrNameResult.org;n=await e.developerPlatformClient.createApp(f,r)}else n=e.selectedAppOrNameResult.app;await Re({directory:o,apiKey:n.apiKey,appId:n.id,organizationId:n.organizationId,configName:"shopify.app.toml",developerPlatformClient:e.developerPlatformClient,isNewApp:!0},!1);let p=await Le({directory:o,clientId:void 0,forceRelink:!1,userProvidedConfigName:void 0});return le({headline:[{userInput:a},"is ready for you to build!"],nextSteps:[["Run",{command:`cd ${a}`}],["For extensions, run",{command:R(t,"shopify app generate extension")}],["To see your app, run",{command:R(t,"shopify app dev")}]],reference:[{link:{label:"Shopify docs",url:"https://shopify.dev"}},[{link:{label:"Shopify Dev MCP,",url:"https://shopify.dev/docs/apps/build/devmcp"}},"connect your AI assistant to development resources"],["For an overview of commands, run",{command:R(t,"shopify app","--help")}]]}),{app:p.app}}async function Ne(e,t){if(await I(e))throw new m(`
A directory with this name (${t}) already exists.
Choose a new name for your app.`)}async function Be(e){let t=new Q({projectName:"shopify-cli-app"}),a=A(e);t.delete(a)}function Ke(e){return["web","web/frontend"].filter(t=>C(s(e,t)))}async function We(e,t){let a=s(e,"pnpm-workspace.yaml");if(await I(a))return;let o=t.map(i=>` - '${i}'`).join(`
`);await O(a,`packages:
${o}`)}var _e=Ve;u();function Ge(e){if(!e)return;let t=ye(e);if(t&&t.origin!=="https://github.com")throw new m("Only GitHub repository references are supported, e.g., https://github.com/Shopify/<repository>/[subpath]#[branch]");if(!t&&!x(e))throw new m(w`Only ${L.map(a=>w`${g.yellow(a)}`.value).join(", ")} template aliases are supported, please provide a valid URL`)}function Me(e,t){if(!e){if(t)throw new m(w`The ${g.yellow("--flavor")} flag requires the ${g.yellow("--template")} flag to be set`);return}if(!t)return;if(!x(e))throw new m(w`The ${g.yellow("--flavor")} flag is not supported for custom templates`);let a=b[e];if(!a.branches)throw new m(w`The ${g.yellow(e)} template does not support flavors`);if(!a.branches.options[t])throw new m(w`Invalid option for ${g.yellow("--flavor")}\nThe ${g.yellow("--flavor")} flag for ${g.yellow(e)} accepts only ${Object.keys(a.branches.options).map(o=>w`${g.yellow(o)}`.value).join(", ")}`)}var h=De(je(),1);var M=class e extends xe{static{this.summary="Create a new app project"}static{this.flags={...fe,name:h.Flags.string({char:"n",env:"SHOPIFY_FLAG_NAME",hidden:!1,description:"The name for the new app. When provided, skips the app selection prompt and creates a new app with this name."}),path:h.Flags.string({char:"p",env:"SHOPIFY_FLAG_PATH",parse:async t=>D(t),default:async()=>E(),hidden:!1}),template:h.Flags.string({description:`The app template. Accepts one of the following:
- <${L.join("|")}>
- Any GitHub repo with optional branch and subpath, e.g., https://github.com/Shopify/<repository>/[subpath]#[branch]`,env:"SHOPIFY_FLAG_TEMPLATE"}),flavor:h.Flags.string({description:"Which flavor of the given template to use.",env:"SHOPIFY_FLAG_TEMPLATE_FLAVOR"}),"package-manager":h.Flags.string({char:"d",env:"SHOPIFY_FLAG_PACKAGE_MANAGER",hidden:!1,options:["npm","yarn","pnpm","bun"]}),local:h.Flags.boolean({char:"l",env:"SHOPIFY_FLAG_LOCAL",default:!1,hidden:!0}),"client-id":h.Flags.string({hidden:!1,description:"The Client ID of your app. Use this to automatically link your new project to an existing app. Using this flag avoids the app selection prompt.",env:"SHOPIFY_FLAG_CLIENT_ID",exclusive:["config"]}),"organization-id":h.Flags.string({hidden:!1,description:"The organization ID. Your organization ID can be found in your Dev Dashboard URL: https://dev.shopify.com/dashboard/<organization-id>",env:"SHOPIFY_FLAG_ORGANIZATION_ID",exclusive:["client-id"]})}}async run(){let{flags:t}=await this.parse(e);if(Ge(t.template),Me(t.template,t.flavor),t.name!==void 0&&t.name.trim()==="")throw new m("The --name flag can't be empty","Provide a valid app name, for example: --name my-app");let a=oe(t["package-manager"]),o=t.name??await qe(t.path),i=N();await i.session();let n=await Fe({template:t.template,flavor:t.flavor}),p,r;if(t["client-id"]){let c=await Ce({apiKey:t["client-id"]});r=c.title,i=c.developerPlatformClient??i,p={result:"existing",app:c}}else{let c;t["organization-id"]?c=await Ie(t["organization-id"],i):c=await Te(),i=N({organization:c});let{organization:d,apps:v,hasMorePages:y}=await i.orgAndApps(c.id);p=await Ze(t.name!==void 0,o,v,y,d,i),r=p.result==="new"?p.name:p.app.title}n.globalCLIResult.install&&await X(a),await pe(()=>({cmd_create_app_template:n.templateType,cmd_create_app_template_url:n.template}));let{app:f}=await _e({name:r,selectedAppOrNameResult:p,packageManager:a,template:n.template,local:t.local,directory:t.path,useGlobalCLI:n.globalCLIResult.alreadyInstalled||n.globalCLIResult.install,developerPlatformClient:i,postCloneActions:{removeLockfilesFromGitignore:n.templateType!=="custom"}});return{app:f}}};async function qe(e){for(let t=0;t<3;t++){let a=await W({suffix:"app",directory:e});if(be(a))return a}return""}async function Ze(e,t,a,o,i,n){let p=a.length===0||e;if(p||(p=await ke()),p)return{result:"new",name:e?t:await Ae(t),org:i};{let r=await ve(we(n,i.id),a,o);if(!r)throw new m("Unable to select an app: the selection prompt was interrupted.");let f=await n.appFromIdentifiers(r.apiKey);if(!f)throw new m(`App with id ${r.id} not found`);return{result:"existing",app:f}}}export{M as default};