create-pylon
Version:
CLI for creating a Pylon
17 lines (13 loc) • 6.54 kB
JavaScript
import{Option as $,program as F}from"commander";import y from"consola";import{input as Y,select as C,confirm as N}from"@inquirer/prompts";import o from"path";import m from"chalk";import*as t from"fs";import*as O from"@getcronit/pylon-telemetry";import{fileURLToPath as H}from"url";import{dirname as X}from"path";import{spawnSync as Q}from"child_process";import*as h from"node:fs";import*as w from"node:path";import v from"node:process";import{execSync as T}from"node:child_process";import M from"consola";function j(e){try{return T(`${e} --version`,{stdio:"ignore"}),!0}catch(r){return console.error(r),!1}}function B(){return typeof Bun<"u"&&j("bun")}function W(){return v.env.npm_execpath?.includes("npm")??!1}function L(){return v.env.npm_execpath?.includes("yarn")??!1}function J(){return typeof Deno<"u"&&j("deno")}function U(){return v.env.npm_execpath?.includes("pnpm")??!1}function V(e){return h.existsSync(w.join(e,"bun.lockb"))?"bun":h.existsSync(w.join(e,"package-lock.json"))?"npm":h.existsSync(w.join(e,"yarn.lock"))?"yarn":h.existsSync(w.join(e,"deno.json"))||h.existsSync(w.join(e,"deno.lock"))?"deno":h.existsSync(w.join(e,"pnpm-lock.yaml"))?"pnpm":null}function E({preferredPm:e,cwd:r=v.cwd()}){if(e&&j(e))return e;if(B())return"bun";if(W())return"npm";if(U())return"pnpm";if(J())return"deno";if(L())return"yarn";let n=V(r);if(n){if(M.info(`Detected package manager by lock file: ${n}`),j(n))return n;M.warn(`Lock file detected, but ${n} is not installed.`)}return"unknown"}function D(e){switch(e){case"bun":return"bun";case"npm":return"npm run";case"yarn":return"yarn";case"pnpm":return"pnpm run";case"deno":return"deno task";default:throw new Error("Unknown package manager")}}var q=H(import.meta.url),x=X(q),A=JSON.parse(t.readFileSync(o.join(x,"..","package.json"),"utf-8")).version;function z(e){try{t.mkdirSync(e,{recursive:!0})}catch(r){if(r instanceof Error&&"code"in r&&r.code==="EEXIST")return;throw r}}var P=[{key:"bun",name:"Bun.js",website:"https://bunjs.dev",templates:["default","pages"]},{key:"node",name:"Node.js",website:"https://nodejs.org",templates:["default"]},{key:"cf-workers",name:"Cloudflare Workers",website:"https://workers.cloudflare.com",templates:["default"]},{key:"deno",name:"Deno",website:"https://deno.land",templates:["default"]}],I=[{key:"default",name:"Default",description:"Default template"},{key:"database",name:"Database (Prisma)",description:"Template with Prisma ORM"},{key:"pages",name:"Fullstack (Pages)",description:"Build fullstack applications with pages and layouts."}],G=(e,r)=>{let n=e;return Object.entries(r).forEach(([a,k])=>{n=n.replaceAll(a,k)}),n},_=e=>{let r=n=>{let a=[];return t.readdirSync(n).forEach(S=>{let p=o.join(n,S);t.statSync(p).isDirectory()&&a.push(...r(p)),t.statSync(p).isFile()&&a.push(p)}),a};return r(e).map(n=>n.replace(e,"."))},K=async e=>{let{runtime:r,template:n,target:a}=e,k=P.find(({key:i})=>i===r)?.name,S=I.find(({key:i})=>i===n)?.name;if(!k)throw new Error(`Invalid runtime: ${r}`);if(!S)throw new Error(`Invalid template: ${n}`);let p=o.join(x,"..","templates","shared");if(!t.existsSync(p))throw new Error(`Shared templates not found: ${p}`);let s=o.join(x,"..","templates",r,n);if(!t.existsSync(s))throw new Error(`Template not found: ${s}`);let u=o.join(process.cwd(),a);y.start(`Creating pylon in ${u}`);let d=i=>G(i,{__PYLON_NAME__:e.name});_(p).forEach(i=>{let f=o.join(p,i),c=o.join(u,i),g=o.dirname(c);if(r==="cf-workers"&&f.includes(".github/workflows/publish.yaml"))return;t.existsSync(g)||t.mkdirSync(g,{recursive:!0}),c.endsWith(".example")&&(c=c.replace(".example",""));let b=d(t.readFileSync(f,"utf-8"));t.writeFileSync(c,b)}),_(s).forEach(i=>{let f=o.join(s,i),c=o.join(u,i),g=o.dirname(c);t.existsSync(g)||t.mkdirSync(g,{recursive:!0}),c.endsWith(".example")&&(c=c.replace(".example",""));let b=d(t.readFileSync(f,"utf-8"));t.writeFileSync(c,b)}),y.success("Pylon created")},Z=async e=>{let r=o.resolve(e.target),n=e.packageManager,a="";switch(n){case"yarn":a="yarn";break;case"npm":a="npm install";break;case"pnpm":a="pnpm install";break;case"bun":a="bun install";break;case"deno":a="deno install";break;default:throw new Error(`Invalid package manager: ${n}`)}if(y.start(`Installing dependencies using ${n}`),Q(a,{cwd:r,shell:!0,stdio:"inherit"}).status!==0)throw new Error("Failed to install dependencies");y.success("Dependencies installed")};F.name("create-pylon").version(A).arguments("[target]").addOption(new $("-i, --install","Install dependencies")).addOption(new $("-r, --runtime <runtime>","Runtime").choices(P.map(({key:e})=>e))).addOption(new $("-t, --template <template>","Template")).addOption(new $("-pm, --package-manager <packageManager>","Package manager")).action(ne);var ee=e=>{if(e==="bun")return"bun";if(e==="deno")return"deno"};async function ne(e,r,n){try{y.log(`${n.name()} version ${n.version()}`);let{install:a,runtime:k,template:S,packageManager:p}=r,s="";e?(s=e,y.success(`Using target directory \u2026 ${s}`)):s=await Y({message:"Target directory",default:"my-pylon"});let u="";s==="."?u=o.basename(process.cwd()):u=o.basename(s);let d=k||await C({message:"Which runtime would you like to use?",choices:P.map(l=>({name:`${l.name} (${l.website})`,value:l.key})),default:0});if(!d)throw new Error("No runtime selected");let i=P.find(({key:l})=>l===d);if(!i)throw new Error(`Invalid runtime selected: ${d}`);let f=S||await C({message:"Which template would you like to use?",choices:I.filter(l=>i.templates?.includes(l.key)).map(l=>({name:l.name,value:l.key})),default:0});if(!f)throw new Error("No template selected");t.existsSync(s)?t.readdirSync(s).length>0&&(await N({message:"Directory not empty. Continue?",default:!1})||process.exit(1)):z(s);let c=a||await N({message:"Would you like to install dependencies?"});await K({name:u,runtime:d,template:f,target:s});let g=E({preferredPm:ee(i.key),cwd:s});c&&await Z({target:s,packageManager:g});let b=D(g),R=`
\u{1F389} ${m.green.bold("Pylon created successfully.")}
\u{1F4BB} ${m.cyan.bold("Continue Developing")}
${m.yellow("Change directories:")} cd ${m.blue(s)}
${m.yellow("Start dev server:")} ${b} dev
${m.yellow("Deploy:")} ${b} deploy
\u{1F4D6} ${m.cyan.bold("Explore Documentation")}
${m.underline.blue("https://pylon.cronit.io/docs")}
\u{1F4AC} ${m.cyan.bold("Join our Community")}
${m.underline.blue("https://discord.gg/cbJjkVrnHe")}
`;await O.sendCreateEvent({name:u,pylonCreateVersion:A,runtime:d,template:f}),y.box(R)}catch(a){y.error(a)}}F.parse();
//# sourceMappingURL=index.js.map