@turbostarter/cli 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import{Command as Ee}from"commander";import{Command as le}from"commander";import{execa as R}from"execa";import G from"ora";import ce,{join as me}from"path";import k from"picocolors";import ge from"prompts";import{z as Y}from"zod";import I from"prompts";var y={LOCAL:"local",CLOUD:"cloud"},b={STRIPE:"stripe",LEMON_SQUEEZY:"lemon-squeezy"},m={RESEND:"resend",SENDGRID:"sendgrid",POSTMARK:"postmark",PLUNK:"plunk",NODEMAILER:"nodemailer"},v={ROOT:"./",WEB:"./apps/web",MOBILE:"./apps/mobile",EXTENSION:"./apps/extension",DB:"./packages/db"},w={EXAMPLE:".env.example",LOCAL:".env.local"},c={WEB:"web",MOBILE:"mobile",EXTENSION:"extension"},n={db:{url:"DATABASE_URL"},supabase:{key:"SUPABASE_ANON_KEY",url:"SUPABASE_URL"},billing:{provider:"BILLING_PROVIDER",stripe:{secretKey:"STRIPE_SECRET_KEY",webhookSecret:"STRIPE_WEBHOOK_SECRET"},lemonsqueezy:{apiKey:"LEMON_SQUEEZY_API_KEY",signingSecret:"LEMON_SQUEEZY_SIGNING_SECRET",storeId:"LEMON_SQUEEZY_STORE_ID"}},email:{provider:"EMAIL_PROVIDER",resend:{apiKey:"RESEND_API_KEY"},sendgrid:{apiKey:"SENDGRID_API_KEY"},plunk:{apiKey:"PLUNK_API_KEY"},postmark:{apiKey:"POSTMARK_API_KEY"},nodemailer:{user:"NODEMAILER_USER",password:"NODEMAILER_PASSWORD",host:"NODEMAILER_HOST",port:"NODEMAILER_PORT"}}},N={[v.ROOT]:[n.db.url,n.supabase.key,n.supabase.url],[v.WEB]:[n.billing.provider,n.billing.stripe.secretKey,n.billing.stripe.webhookSecret,n.billing.lemonsqueezy.apiKey,n.billing.lemonsqueezy.signingSecret,n.billing.lemonsqueezy.storeId,n.email.provider,n.email.resend.apiKey,n.email.sendgrid.apiKey,n.email.plunk.apiKey,n.email.postmark.apiKey,n.email.nodemailer.user,n.email.nodemailer.password]},C={[c.WEB]:[],[c.MOBILE]:["apps/mobile","packages/ui/mobile","packages/analytics/mobile",".github/workflows/publish-mobile.yml"],[c.EXTENSION]:["apps/extension","packages/analytics/extension",".github/workflows/publish-extension.yml"]},o={name:"TurboStarter",repository:"https://github.com/turbostarter/main.git",env:n};import W from"fs-extra";import V from"lodash";import X from"path";import S from"picocolors";var r={error(e){console.log(S.red(e))},warn(e){console.log(S.yellow(e))},info(e){console.log(S.cyan(e))},success(e){console.log(S.green(e))},log(e){console.log(e)},break(){console.log("")}};function T(e){typeof e=="string"&&(r.error(e),process.exit(1)),e instanceof Error&&(r.error(e.message),process.exit(1)),r.error("Something went wrong. Please try again."),process.exit(1)}var D=()=>{let e=X.join("package.json");return W.readJSONSync(e)},x=e=>e.split("-").map(t=>V.capitalize(t)).join(" "),i=()=>{r.break(),r.error("Operation cancelled."),process.exit(0)};var Q=async()=>I([{type:"select",choices:Object.values(b).map(e=>({title:x(e),value:e})),name:o.env.billing.provider,message:"What do you want to use for billing?"}],{onCancel:i}),Z=async e=>{switch(e){case b.STRIPE:return I([{type:"text",name:o.env.billing.stripe.secretKey,message:"Enter your Stripe secret key"},{type:"text",name:o.env.billing.stripe.webhookSecret,message:"Enter your Stripe webhook secret"}],{onCancel:i});case b.LEMON_SQUEEZY:return I([{type:"text",name:o.env.billing.lemonsqueezy.storeId,message:"Enter your Lemon Squeezy store ID"},{type:"text",name:o.env.billing.lemonsqueezy.apiKey,message:"Enter your Lemon Squeezy API key"},{type:"text",name:o.env.billing.lemonsqueezy.signingSecret,message:"Enter your Lemon Squeezy signing secret"}],{onCancel:i})}},_=async()=>{let e=await Q(),t=await Z(e.BILLING_PROVIDER);return{...e,...t}};import d from"prompts";var J=async()=>d([{type:"select",name:o.env.email.provider,message:"What do you want to use for emails?",choices:Object.values(m).map(e=>({title:x(e),value:e}))}],{onCancel:i}),H=async e=>{switch(e){case m.RESEND:return d([{type:"text",name:o.env.email.resend.apiKey,message:"Enter your Resend API key"}],{onCancel:i});case m.SENDGRID:return d([{type:"text",name:o.env.email.sendgrid.apiKey,message:"Enter your Sendgrid API key"}],{onCancel:i});case m.PLUNK:return d([{type:"text",name:o.env.email.plunk.apiKey,message:"Enter your Plunk API key"}],{onCancel:i});case m.POSTMARK:return d([{type:"text",name:o.env.email.postmark.apiKey,message:"Enter your Postmark API key"}],{onCancel:i});case m.NODEMAILER:return d([{type:"text",name:o.env.email.nodemailer.user,message:"Enter your Nodemailer user"},{type:"text",name:o.env.email.nodemailer.password,message:"Enter your Nodemailer user password"},{type:"text",name:o.env.email.nodemailer.host,message:"Enter your Nodemailer host"},{type:"number",name:o.env.email.nodemailer.port,message:"Enter your Nodemailer port"}],{onCancel:i})}},K=async()=>{let e=await J(),t=await H(e.EMAIL_PROVIDER);return{...e,...t}};import{promises as P}from"fs";import O from"lodash";import ee from"ora";import{join as u}from"path";var B=async e=>{try{await Promise.allSettled(Object.values(v).map(async t=>{let s=u(e,t);await P.copyFile(u(s,w.EXAMPLE),u(s,w.LOCAL))}))}catch{r.error("Failed to prepare environment!"),process.exit(1)}},L=async(e,t,s)=>{if(!s)return;let p=O.keys(O.pickBy(N,l=>O.includes(l,t)));for(let l of p){let g=u(e,l),a=u(g,w.LOCAL),E=await P.readFile(a,"utf8"),A=new RegExp(`^${t}=.*`,"gm");A.test(E)?await P.writeFile(a,E.replace(A,`${t}="${s}"`)):await P.appendFile(a,`
3
- ${t}="${s}"`)}},j=async(e,t)=>{let s=ee("Setting environment variables...").start();try{for(let[p,l]of Object.entries(t))await L(e,p,l);s.succeed("Environment variables successfully set!")}catch{r.error("Failed to set environment variables!"),process.exit(1)}};import M from"prompts";var te=async()=>M([{type:"text",name:o.env.supabase.url,message:"Enter your Supabase project URL"},{type:"text",name:o.env.supabase.key,message:"Enter your Supabase project anononymous key"},{type:"text",name:o.env.db.url,message:"Enter your database URL"}],{onCancel:i}),F=async()=>{let e=await M([{type:"select",name:"type",message:"How do you want to use Supabase?",choices:[{title:"Local (powered by Docker)",value:y.LOCAL,selected:!0},{title:"Cloud",value:y.CLOUD}]}],{onCancel:i});if(e.type===y.CLOUD){let t=await te();return{...e,env:t}}return e};import{execa as ie}from"execa";import ae from"ora";import{execa as f}from"execa";import oe from"ora";import h from"picocolors";var re=async()=>{try{await f("node",["--version"])}catch{r.error(`Node.js is not installed. Please install Node.js and try again.
4
- `),r.info(`To install Node.js, visit: ${h.underline("https://nodejs.org/en/")}`),process.exit(1)}},ne=async()=>{try{await f("pnpm",["--version"])}catch{try{await f("npm",["install","-g","pnpm"])}catch{r.error(`pnpm is not installed. Please install pnpm manually and try again.
5
- `),r.info(`To install pnpm, visit: ${h.underline("https://pnpm.io/installation")}`),process.exit(1)}}},U=async()=>{try{await f("docker",["--version"])}catch{r.error("Docker is not installed. Please install Docker and try again."),r.info(`To install Docker, visit: ${h.underline("https://docs.docker.com/get-docker/")}`),process.exit(1)}},se=async()=>{try{await f("git",["--version"])}catch{r.error("Git is not installed. Please install Git and try again."),r.info(`To install Git, visit: ${h.underline("https://git-scm.com/downloads")}`),process.exit(1)}},q=async()=>{let e=oe(`Checking prerequisites...
6
- `).start();try{await se(),await re(),await ne(),e.succeed(`All prerequisites are satisfied, let's start! \u{1F680}
7
- `)}catch{e.fail("Failed to check prerequisites."),process.exit(1)}};var pe=e=>/anon key:\s([^\s]+)/.exec(e)?.[1],z=async e=>{await U();let t=ae("Starting Supabase...").start();try{let s=await ie("pnpm",["db:setup"],{cwd:e}),p=pe(s.stdout);p&&await L(e,o.env.supabase.key,p),t.succeed("Supabase successfully started!")}catch{t.fail("Failed to start Supabase!"),process.exit(1)}};var ye=Y.object({cwd:Y.string()}),$=new le().name("new").description("create a new TurboStarter project").option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).action(async e=>{try{r.log(`${k.bgYellow(k.black(" TurboStarter "))}
8
- `);let t=ye.parse({cwd:ce.resolve(e.cwd)});await de(t),r.log(`
2
+ import{Command as he}from"commander";import{Command as de}from"commander";import{execa as g}from"execa";import C from"ora";import ye,{join as ue}from"path";import L from"picocolors";import fe from"prompts";import{z as $}from"zod";import A from"prompts";var d={LOCAL:"local",CLOUD:"cloud"},N={S3:"s3"},w={STRIPE:"stripe",LEMON_SQUEEZY:"lemon-squeezy"},y={RESEND:"resend",SENDGRID:"sendgrid",POSTMARK:"postmark",PLUNK:"plunk",NODEMAILER:"nodemailer"},x={ROOT:"./",WEB:"./apps/web",MOBILE:"./apps/mobile",EXTENSION:"./apps/extension",DB:"./packages/db"},h={EXAMPLE:".env.example",LOCAL:".env.local"},m={WEB:"web",MOBILE:"mobile",EXTENSION:"extension"},s={db:{url:"DATABASE_URL"},supabase:{key:"SUPABASE_ANON_KEY",url:"SUPABASE_URL"},billing:{provider:"BILLING_PROVIDER",stripe:{secretKey:"STRIPE_SECRET_KEY",webhookSecret:"STRIPE_WEBHOOK_SECRET"},lemonsqueezy:{apiKey:"LEMON_SQUEEZY_API_KEY",signingSecret:"LEMON_SQUEEZY_SIGNING_SECRET",storeId:"LEMON_SQUEEZY_STORE_ID"}},email:{provider:"EMAIL_PROVIDER",resend:{apiKey:"RESEND_API_KEY"},sendgrid:{apiKey:"SENDGRID_API_KEY"},plunk:{apiKey:"PLUNK_API_KEY"},postmark:{apiKey:"POSTMARK_API_KEY"},nodemailer:{user:"NODEMAILER_USER",password:"NODEMAILER_PASSWORD",host:"NODEMAILER_HOST",port:"NODEMAILER_PORT"}},storage:{provider:"STORAGE_PROVIDER",s3:{region:"S3_REGION",endpoint:"S3_ENDPOINT",accessKeyId:"S3_ACCESS_KEY_ID",secretAccessKey:"S3_SECRET_ACCESS_KEY"}}},_={[x.ROOT]:[s.db.url,s.supabase.key,s.supabase.url],[x.WEB]:[s.billing.provider,s.billing.stripe.secretKey,s.billing.stripe.webhookSecret,s.billing.lemonsqueezy.apiKey,s.billing.lemonsqueezy.signingSecret,s.billing.lemonsqueezy.storeId,s.email.provider,s.email.resend.apiKey,s.email.sendgrid.apiKey,s.email.plunk.apiKey,s.email.postmark.apiKey,s.email.nodemailer.user,s.email.nodemailer.password,s.storage.provider,s.storage.s3.region,s.storage.s3.endpoint,s.storage.s3.accessKeyId,s.storage.s3.secretAccessKey]},K={[m.WEB]:[],[m.MOBILE]:["apps/mobile","packages/ui/mobile","packages/analytics/mobile",".github/workflows/publish-mobile.yml"],[m.EXTENSION]:["apps/extension","packages/analytics/extension",".github/workflows/publish-extension.yml"]},r={name:"TurboStarter",repository:"https://github.com/turbostarter/main.git",env:s};import X from"lodash";import P from"picocolors";var o={error(e){console.log(P.red(e))},warn(e){console.log(P.yellow(e))},info(e){console.log(P.cyan(e))},success(e){console.log(P.green(e))},log(e){console.log(e)},break(){console.log("")}};function D(e){typeof e=="string"&&(o.error(e),process.exit(1)),e instanceof Error&&(o.error(e.message),process.exit(1)),o.error("Something went wrong. Please try again."),process.exit(1)}var f=e=>e.split("-").map(t=>X.capitalize(t)).join(" "),n=()=>{o.break(),o.error("Operation cancelled."),process.exit(0)};var Z=async()=>A([{type:"select",choices:Object.values(w).map(e=>({title:f(e),value:e})),name:r.env.billing.provider,message:"What do you want to use for billing?"}],{onCancel:n}),Q=async e=>{switch(e){case w.STRIPE:return A([{type:"text",name:r.env.billing.stripe.secretKey,message:"Enter your Stripe secret key"},{type:"text",name:r.env.billing.stripe.webhookSecret,message:"Enter your Stripe webhook secret"}],{onCancel:n});case w.LEMON_SQUEEZY:return A([{type:"text",name:r.env.billing.lemonsqueezy.storeId,message:"Enter your Lemon Squeezy store ID"},{type:"text",name:r.env.billing.lemonsqueezy.apiKey,message:"Enter your Lemon Squeezy API key"},{type:"text",name:r.env.billing.lemonsqueezy.signingSecret,message:"Enter your Lemon Squeezy signing secret"}],{onCancel:n})}},T=async()=>{let e=await Z(),t=await Q(e.BILLING_PROVIDER);return{...e,...t}};import v from"prompts";var H=async()=>v([{type:"select",name:r.env.email.provider,message:"What do you want to use for emails?",choices:Object.values(y).map(e=>({title:f(e),value:e}))}],{onCancel:n}),J=async e=>{switch(e){case y.RESEND:return v([{type:"text",name:r.env.email.resend.apiKey,message:"Enter your Resend API key"}],{onCancel:n});case y.SENDGRID:return v([{type:"text",name:r.env.email.sendgrid.apiKey,message:"Enter your Sendgrid API key"}],{onCancel:n});case y.PLUNK:return v([{type:"text",name:r.env.email.plunk.apiKey,message:"Enter your Plunk API key"}],{onCancel:n});case y.POSTMARK:return v([{type:"text",name:r.env.email.postmark.apiKey,message:"Enter your Postmark API key"}],{onCancel:n});case y.NODEMAILER:return v([{type:"text",name:r.env.email.nodemailer.user,message:"Enter your Nodemailer user"},{type:"text",name:r.env.email.nodemailer.password,message:"Enter your Nodemailer user password"},{type:"text",name:r.env.email.nodemailer.host,message:"Enter your Nodemailer host"},{type:"number",name:r.env.email.nodemailer.port,message:"Enter your Nodemailer port"}],{onCancel:n})}},B=async()=>{let e=await H(),t=await J(e.EMAIL_PROVIDER);return{...e,...t}};import{promises as I}from"fs";import R from"lodash";import ee from"ora";import{join as E}from"path";var j=async e=>{try{await Promise.allSettled(Object.values(x).map(async t=>{let i=E(e,t);await I.copyFile(E(i,h.EXAMPLE),E(i,h.LOCAL))}))}catch{o.error("Failed to prepare environment!"),process.exit(1)}},te=async(e,t,i)=>{if(!i)return;let a=R.keys(R.pickBy(_,p=>R.includes(p,t)));for(let p of a){let u=E(e,p),c=E(u,h.LOCAL),l=await I.readFile(c,"utf8"),S=new RegExp(`^${t}=.*`,"gm");S.test(l)?await I.writeFile(c,l.replace(S,`${t}="${i}"`)):await I.appendFile(c,`
3
+ ${t}="${i}"`)}},k=async(e,t)=>{let i=ee("Setting environment variables...").start();try{for(let[a,p]of Object.entries(t))await te(e,a,p);i.succeed("Environment variables successfully set!")}catch{o.error("Failed to set environment variables!"),process.exit(1)}};import M from"prompts";var re=async()=>M([{type:"select",choices:Object.values(N).map(e=>({title:f(e),value:e})),name:r.env.storage.provider,message:"What do you want to use for storage?"}],{onCancel:n}),oe=()=>M([{type:"text",name:r.env.storage.s3.region,message:"Enter your S3 region"},{type:"text",name:r.env.storage.s3.endpoint,message:"Enter your S3 endpoint"},{type:"text",name:r.env.storage.s3.accessKeyId,message:"Enter your S3 access key ID"},{type:"text",name:r.env.storage.s3.secretAccessKey,message:"Enter your S3 secret access key"}],{onCancel:n}),F=async()=>{let e=await re(),t=await oe();return{...e,...t}};import z from"prompts";var se=async()=>z([{type:"text",name:r.env.supabase.url,message:"Enter your Supabase project URL"},{type:"text",name:r.env.supabase.key,message:"Enter your Supabase project anononymous key"},{type:"text",name:r.env.db.url,message:"Enter your database URL"}],{onCancel:n}),G=async()=>{let e=await z([{type:"select",name:"type",message:"How do you want to use Supabase?",choices:[{title:"Local (powered by Docker)",value:d.LOCAL,selected:!0},{title:"Cloud",value:d.CLOUD}]}],{onCancel:n});if(e.type===d.CLOUD){let t=await se();return{...e,env:t}}return e};import{execa as ce}from"execa";import le from"ora";import{execa as b}from"execa";import ie from"ora";import O from"picocolors";var ne=async()=>{try{await b("node",["--version"])}catch{o.error(`Node.js is not installed. Please install Node.js and try again.
4
+ `),o.info(`To install Node.js, visit: ${O.underline("https://nodejs.org/en/")}`),process.exit(1)}},ae=async()=>{try{await b("pnpm",["--version"])}catch{try{await b("npm",["install","-g","pnpm"])}catch{o.error(`pnpm is not installed. Please install pnpm manually and try again.
5
+ `),o.info(`To install pnpm, visit: ${O.underline("https://pnpm.io/installation")}`),process.exit(1)}}},U=async()=>{try{await b("docker",["--version"])}catch{o.error("Docker is not installed. Please install Docker and try again."),o.info(`To install Docker, visit: ${O.underline("https://docs.docker.com/get-docker/")}`),process.exit(1)}},pe=async()=>{try{await b("git",["--version"])}catch{o.error("Git is not installed. Please install Git and try again."),o.info(`To install Git, visit: ${O.underline("https://git-scm.com/downloads")}`),process.exit(1)}},Y=async()=>{let e=ie(`Checking prerequisites...
6
+ `).start();try{await pe(),await ne(),await ae(),e.succeed(`All prerequisites are satisfied, let's start! \u{1F680}
7
+ `)}catch{e.fail("Failed to check prerequisites."),process.exit(1)}};var me=[{variable:r.env.supabase.key,regex:/anon key:\s([^\s]+)/},{variable:r.env.storage.s3.region,regex:/S3 Region:\s([^\s]+)/},{variable:r.env.storage.s3.endpoint,regex:/S3 Storage URL:\s([^\s]+)/},{variable:r.env.storage.s3.accessKeyId,regex:/S3 Access Key:\s([^\s]+)/},{variable:r.env.storage.s3.secretAccessKey,regex:/S3 Secret Key:\s([^\s]+)/}],ge=e=>me.reduce((t,i)=>{let a=i.regex.exec(e);return a?{...t,[i.variable]:a[1]}:t},{}),q=async e=>{await U();let t=le("Starting Supabase...").start();try{let i=await ce("pnpm",["db:setup"],{cwd:e}),a=ge(i.stdout);await k(e,a),t.succeed("Supabase successfully started!")}catch{t.fail("Failed to start Supabase!"),process.exit(1)}};var ve=$.object({cwd:$.string()}),W=new de().name("new").description("create a new TurboStarter project").option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).action(async e=>{try{o.log(`${L.bgYellow(L.black(" TurboStarter "))}
8
+ `);let t=ve.parse({cwd:ye.resolve(e.cwd)});await Ee(t),o.log(`
9
9
  \u{1F389} You can now get started. Open the project and just ship it! \u{1F389}
10
- `),r.info(`Problems? ${k.underline("https://turbostarter.dev/docs")}`)}catch(t){r.break(),T(t)}}),de=async e=>{await q();let t=await ge([{type:"multiselect",name:"apps",message:"What do you want to ship?",instructions:!1,choices:[{title:"Web app",value:c.WEB,selected:!0},{title:"Mobile app",value:c.MOBILE,selected:!1},{title:"Browser extension",value:c.EXTENSION,selected:!1}],hint:`You ${k.bold("must")} ship a web app, to ensure backend services work.`},{type:"text",name:"name",message:"Enter your project name.",validate:E=>E.length>0?!0:"Name is required!"}],{onCancel:i}),s=await F(),p=await _(),l=await K(),g={..."env"in s?s.env:{},...p,...l},a=await ue(e.cwd,t.name,t.apps);await B(a),await j(a,g),await fe(a),s.type===y.LOCAL&&await z(a)},ue=async(e,t,s)=>{let p=G(`Cloning repository into ${t}...`).start(),l=me(e,t),g=Object.values(c).filter(a=>!s.includes(a)).map(a=>C[a]).flat();try{return await R("git",["clone",o.repository,t],{cwd:e}),g.length&&await R("rm",["-rf",...g],{cwd:l}),p.succeed("Repository successfully pulled!"),l}catch{p.fail("Failed to clone TurboStarter! Please try again."),process.exit(1)}},fe=async e=>{let t=G("Installing dependencies...").start();try{await R("pnpm",["install"],{cwd:e}),t.succeed("Dependencies successfully installed!")}catch{t.fail("Failed to install dependencies! Please try again."),process.exit(1)}};process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));function ve(){let e=D(),t=new Ee().name("turbostarter").description("Your TurboStarter assistant for starting new projects, adding plugins and more.").version(e.version??"1.0.0","-v, --version","display the version number");t.addCommand($),t.parse()}ve();
10
+ `),o.info(`Problems? ${L.underline("https://turbostarter.dev/docs")}`)}catch(t){o.break(),D(t)}}),Ee=async e=>{await Y();let t=await fe([{type:"multiselect",name:"apps",message:"What do you want to ship?",instructions:!1,choices:[{title:"Web app",value:m.WEB,selected:!0},{title:"Mobile app",value:m.MOBILE,selected:!1},{title:"Browser extension",value:m.EXTENSION,selected:!1}],hint:`You ${L.bold("must")} ship a web app, to ensure backend services work.`},{type:"text",name:"name",message:"Enter your project name.",validate:S=>S.length>0?!0:"Name is required!"}],{onCancel:n}),i=await G(),a=await T(),p=await B(),u=i.type===d.LOCAL?{}:await F(),c={..."env"in i?i.env:{},...a,...p,...u},l=await be(e.cwd,t.name,t.apps);await Se(l),await j(l),await k(l,c),await xe(l),i.type===d.LOCAL&&await q(l)},be=async(e,t,i)=>{let a=C(`Cloning repository into ${t}...`).start(),p=ue(e,t),u=Object.values(m).filter(c=>!i.includes(c)).map(c=>K[c]).flat();try{return await g("git",["clone",r.repository,t],{cwd:e}),u.length&&await g("rm",["-rf",...u],{cwd:p}),a.succeed("Repository successfully pulled!"),p}catch{a.fail("Failed to clone TurboStarter! Please try again."),process.exit(1)}},Se=async e=>{let t=C("Configuring Git...").start();try{await g("rm",["-rf",".git"],{cwd:e}),await g("git",["init"],{cwd:e}),await g("git",["remote","add","upstream",r.repository],{cwd:e}),await g("git",["add","."],{cwd:e}),await g("git",["commit","-m","Initial commit"],{cwd:e}),t.succeed("Git successfully configured!")}catch{t.fail("Failed to configure Git! Please try again."),process.exit(1)}},xe=async e=>{let t=C("Installing dependencies...").start();try{await g("pnpm",["install"],{cwd:e}),t.succeed("Dependencies successfully installed!")}catch{t.fail("Failed to install dependencies! Please try again."),process.exit(1)}};var V={name:"@turbostarter/cli",version:"1.0.4",main:"index.js",type:"module",exports:"./dist/index.js",publishConfig:{registry:"https://registry.npmjs.org/",access:"public"},bin:{turbostarter:"./dist/index.js"},repository:{url:"https://github.com/turbostarter/cli.git"},homepage:"https://turbostarter.dev",files:["dist"],keywords:["turbostarter","cli","starter kit","template","web","mobile","browser extension"],scripts:{start:"node dist/index.js",dev:"tsup --watch",build:"tsup",typecheck:"tsc --noEmit",prepare:"pnpm run build",lint:"eslint","lint:fix":"eslint --fix",format:'prettier --check "**/*.{ts,tsx,mdx}" --cache',"format:fix":'prettier --write "**/*.{ts,tsx,mdx}" --cache'},author:"Bartosz Zagrodzki",license:"ISC",description:"A CLI for TurboStarter",devDependencies:{"@eslint/compat":"1.2.0","@types/lodash":"4.17.12","@types/node":"22.7.5","@types/prompts":"^2.4.2",eslint:"9.12.0","eslint-plugin-import":"2.31.0","eslint-plugin-unused-imports":"4.1.4",prettier:"3.3.3",tsup:"8.3.0",typescript:"5.5.4","typescript-eslint":"8.9.0"},dependencies:{commander:"12.1.0",execa:"9.4.0",lodash:"4.17.21",ora:"^6.1.2",picocolors:"1.1.0",prompts:"^2.4.2",zod:"3.23.8"},packageManager:"pnpm@9.9.0"};process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));function Pe(){let e=new he().name("turbostarter").description("Your TurboStarter assistant for starting new projects, adding plugins and more.").version(V.version||"1.0.0","-v, --version","display the version number");e.addCommand(W),e.parse()}Pe();
11
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/new/index.ts","../src/commands/new/config/billing.ts","../src/config.ts","../src/utils/index.ts","../src/utils/logger.ts","../src/utils/handle-error.ts","../src/commands/new/config/email.ts","../src/commands/new/config/env.ts","../src/commands/new/config/supabase.ts","../src/commands/new/supabase.ts","../src/commands/new/prerequisites.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\n\nimport { newCommand } from \"~/commands/new\";\nimport { getPackageInfo } from \"~/utils\";\n\nprocess.on(\"SIGINT\", () => process.exit(0));\nprocess.on(\"SIGTERM\", () => process.exit(0));\n\nfunction main() {\n const packageInfo = getPackageInfo();\n\n const program = new Command()\n .name(\"turbostarter\")\n .description(\n \"Your TurboStarter assistant for starting new projects, adding plugins and more.\",\n )\n .version(\n packageInfo.version ?? \"1.0.0\",\n \"-v, --version\",\n \"display the version number\",\n );\n\n program.addCommand(newCommand);\n program.parse();\n}\n\nvoid main();\n","import { Command } from \"commander\";\nimport { execa } from \"execa\";\nimport ora from \"ora\";\nimport path, { join } from \"path\";\nimport color from \"picocolors\";\nimport prompts from \"prompts\";\nimport { z } from \"zod\";\n\nimport { getBillingConfig } from \"~/commands/new/config/billing\";\nimport { getEmailConfig } from \"~/commands/new/config/email\";\nimport {\n prepareEnvironment,\n setEnvironmentVariables,\n} from \"~/commands/new/config/env\";\nimport { getSupabaseConfig } from \"~/commands/new/config/supabase\";\nimport { startSupabase } from \"~/commands/new/supabase\";\nimport { App, appSpecificFiles, config, SupabaseType } from \"~/config\";\nimport { handleError, logger, onCancel } from \"~/utils\";\n\nimport { validatePrerequisites } from \"./prerequisites\";\n\nconst newOptionsSchema = z.object({\n cwd: z.string(),\n});\n\nexport const newCommand = new Command()\n .name(\"new\")\n .description(\"create a new TurboStarter project\")\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .action(async (opts: z.infer<typeof newOptionsSchema>) => {\n try {\n logger.log(`${color.bgYellow(color.black(\" TurboStarter \"))}\\n`);\n\n const options = newOptionsSchema.parse({\n cwd: path.resolve(opts.cwd),\n });\n\n await initializeProject(options);\n\n logger.log(\n `\\nšŸŽ‰ You can now get started. Open the project and just ship it! šŸŽ‰\\n`,\n );\n\n logger.info(\n `Problems? ${color.underline(\"https://turbostarter.dev/docs\")}`,\n );\n } catch (error) {\n logger.break();\n handleError(error);\n }\n });\n\nconst initializeProject = async (options: z.infer<typeof newOptionsSchema>) => {\n await validatePrerequisites();\n\n const global = await prompts(\n [\n {\n type: \"multiselect\",\n name: \"apps\",\n message: `What do you want to ship?`,\n instructions: false,\n choices: [\n { title: \"Web app\", value: App.WEB, selected: true },\n { title: \"Mobile app\", value: App.MOBILE, selected: false },\n {\n title: \"Browser extension\",\n value: App.EXTENSION,\n selected: false,\n },\n ],\n hint: `You ${color.bold(\"must\")} ship a web app, to ensure backend services work.`,\n },\n {\n type: \"text\",\n name: \"name\",\n message: \"Enter your project name.\",\n validate: (value: string) =>\n value.length > 0 ? true : \"Name is required!\",\n },\n ],\n {\n onCancel,\n },\n );\n\n const supabaseConfig = await getSupabaseConfig();\n const billingConfig = await getBillingConfig();\n const emailConfig = await getEmailConfig();\n\n const config = {\n ...(\"env\" in supabaseConfig ? supabaseConfig.env : {}),\n ...billingConfig,\n ...emailConfig,\n };\n\n const projectDir = await cloneRepository(\n options.cwd,\n global.name,\n global.apps,\n );\n await prepareEnvironment(projectDir);\n await setEnvironmentVariables(projectDir, config);\n await installDependencies(projectDir);\n\n if (supabaseConfig.type === SupabaseType.LOCAL) {\n await startSupabase(projectDir);\n }\n};\n\nconst cloneRepository = async (cwd: string, name: string, apps: App[]) => {\n const spinner = ora(`Cloning repository into ${name}...`).start();\n const projectDir = join(cwd, name);\n\n const filesToRemove = Object.values(App)\n .filter((app) => !apps.includes(app))\n .map((app) => appSpecificFiles[app])\n .flat();\n\n try {\n await execa(\"git\", [\"clone\", config.repository, name], { cwd });\n\n if (filesToRemove.length) {\n await execa(\"rm\", [\"-rf\", ...filesToRemove], { cwd: projectDir });\n }\n\n spinner.succeed(\"Repository successfully pulled!\");\n\n return projectDir;\n } catch {\n spinner.fail(\"Failed to clone TurboStarter! Please try again.\");\n process.exit(1);\n }\n};\n\nconst installDependencies = async (cwd: string) => {\n const spinner = ora(`Installing dependencies...`).start();\n\n try {\n await execa(\"pnpm\", [\"install\"], { cwd });\n\n spinner.succeed(\"Dependencies successfully installed!\");\n } catch {\n spinner.fail(\"Failed to install dependencies! Please try again.\");\n process.exit(1);\n }\n};\n","import prompts from \"prompts\";\n\nimport { BillingProvider, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getBillingProvider = async (): Promise<{\n [key in typeof config.env.billing.provider]: BillingProvider;\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n choices: Object.values(BillingProvider).map((provider) => ({\n title: getLabel(provider),\n value: provider,\n })),\n name: config.env.billing.provider,\n message: \"What do you want to use for billing?\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getBillingProviderConfig = async (provider: BillingProvider) => {\n switch (provider) {\n case BillingProvider.STRIPE:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.billing.stripe.secretKey,\n message: \"Enter your Stripe secret key\",\n },\n {\n type: \"text\",\n name: config.env.billing.stripe.webhookSecret,\n message: \"Enter your Stripe webhook secret\",\n },\n ],\n {\n onCancel,\n },\n );\n case BillingProvider.LEMON_SQUEEZY:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.billing.lemonsqueezy.storeId,\n message: \"Enter your Lemon Squeezy store ID\",\n },\n {\n type: \"text\",\n name: config.env.billing.lemonsqueezy.apiKey,\n message: \"Enter your Lemon Squeezy API key\",\n },\n {\n type: \"text\",\n name: config.env.billing.lemonsqueezy.signingSecret,\n message: \"Enter your Lemon Squeezy signing secret\",\n },\n ],\n {\n onCancel,\n },\n );\n }\n};\n\nexport const getBillingConfig = async () => {\n const provider = await getBillingProvider();\n const config = await getBillingProviderConfig(provider.BILLING_PROVIDER);\n\n return { ...provider, ...config };\n};\n","export const SupabaseType = {\n LOCAL: \"local\",\n CLOUD: \"cloud\",\n} as const;\n\nexport const BillingProvider = {\n STRIPE: \"stripe\",\n LEMON_SQUEEZY: \"lemon-squeezy\",\n} as const;\n\nexport const EmailProvider = {\n RESEND: \"resend\",\n SENDGRID: \"sendgrid\",\n POSTMARK: \"postmark\",\n PLUNK: \"plunk\",\n NODEMAILER: \"nodemailer\",\n} as const;\n\nexport const EnvPath = {\n ROOT: \"./\",\n WEB: \"./apps/web\",\n MOBILE: \"./apps/mobile\",\n EXTENSION: \"./apps/extension\",\n DB: \"./packages/db\",\n} as const;\n\nexport const EnvFile = {\n EXAMPLE: \".env.example\",\n LOCAL: \".env.local\",\n} as const;\n\nexport const App = {\n WEB: \"web\",\n MOBILE: \"mobile\",\n EXTENSION: \"extension\",\n} as const;\n\nexport type SupabaseType = (typeof SupabaseType)[keyof typeof SupabaseType];\nexport type BillingProvider =\n (typeof BillingProvider)[keyof typeof BillingProvider];\nexport type EmailProvider = (typeof EmailProvider)[keyof typeof EmailProvider];\nexport type EnvPath = (typeof EnvPath)[keyof typeof EnvPath];\nexport type EnvFile = (typeof EnvFile)[keyof typeof EnvFile];\nexport type App = (typeof App)[keyof typeof App];\n\nconst env = {\n db: {\n url: \"DATABASE_URL\",\n },\n supabase: {\n key: \"SUPABASE_ANON_KEY\",\n url: \"SUPABASE_URL\",\n },\n billing: {\n provider: \"BILLING_PROVIDER\",\n stripe: {\n secretKey: \"STRIPE_SECRET_KEY\",\n webhookSecret: \"STRIPE_WEBHOOK_SECRET\",\n },\n lemonsqueezy: {\n apiKey: \"LEMON_SQUEEZY_API_KEY\",\n signingSecret: \"LEMON_SQUEEZY_SIGNING_SECRET\",\n storeId: \"LEMON_SQUEEZY_STORE_ID\",\n },\n },\n email: {\n provider: \"EMAIL_PROVIDER\",\n resend: {\n apiKey: \"RESEND_API_KEY\",\n },\n sendgrid: {\n apiKey: \"SENDGRID_API_KEY\",\n },\n plunk: {\n apiKey: \"PLUNK_API_KEY\",\n },\n postmark: {\n apiKey: \"POSTMARK_API_KEY\",\n },\n nodemailer: {\n user: \"NODEMAILER_USER\",\n password: \"NODEMAILER_PASSWORD\",\n host: \"NODEMAILER_HOST\",\n port: \"NODEMAILER_PORT\",\n },\n },\n} as const;\n\nexport const envInPaths = {\n [EnvPath.ROOT]: [env.db.url, env.supabase.key, env.supabase.url],\n [EnvPath.WEB]: [\n env.billing.provider,\n env.billing.stripe.secretKey,\n env.billing.stripe.webhookSecret,\n env.billing.lemonsqueezy.apiKey,\n env.billing.lemonsqueezy.signingSecret,\n env.billing.lemonsqueezy.storeId,\n env.email.provider,\n env.email.resend.apiKey,\n env.email.sendgrid.apiKey,\n env.email.plunk.apiKey,\n env.email.postmark.apiKey,\n env.email.nodemailer.user,\n env.email.nodemailer.password,\n ],\n};\n\nexport const appSpecificFiles = {\n [App.WEB]: [],\n [App.MOBILE]: [\n \"apps/mobile\",\n \"packages/ui/mobile\",\n \"packages/analytics/mobile\",\n \".github/workflows/publish-mobile.yml\",\n ],\n [App.EXTENSION]: [\n \"apps/extension\",\n \"packages/analytics/extension\",\n \".github/workflows/publish-extension.yml\",\n ],\n};\n\nexport const config = {\n name: \"TurboStarter\",\n repository: \"https://github.com/turbostarter/main.git\",\n env,\n} as const;\n","import fs from \"fs-extra\";\nimport _ from \"lodash\";\nimport path from \"path\";\n\nimport { logger } from \"~/utils/logger\";\n\nimport type { PackageJson } from \"type-fest\";\n\nexport const getPackageInfo = () => {\n const packageJsonPath = path.join(\"package.json\");\n\n return fs.readJSONSync(packageJsonPath) as PackageJson;\n};\n\nexport const getLabel = (value: string) => {\n return value\n .split(\"-\")\n .map((word) => _.capitalize(word))\n .join(\" \");\n};\n\nexport const onCancel = () => {\n logger.break();\n logger.error(\"Operation cancelled.\");\n process.exit(0);\n};\n\nexport * from \"./handle-error\";\nexport * from \"./logger\";\n","import colors from \"picocolors\";\n\nexport const logger = {\n error(log: string) {\n console.log(colors.red(log));\n },\n warn(log: string) {\n console.log(colors.yellow(log));\n },\n info(log: string) {\n console.log(colors.cyan(log));\n },\n success(log: string) {\n console.log(colors.green(log));\n },\n log(log: string) {\n console.log(log);\n },\n break() {\n console.log(\"\");\n },\n};\n","import { logger } from \"./logger\";\n\nexport function handleError(error: unknown) {\n if (typeof error === \"string\") {\n logger.error(error);\n process.exit(1);\n }\n\n if (error instanceof Error) {\n logger.error(error.message);\n process.exit(1);\n }\n\n logger.error(\"Something went wrong. Please try again.\");\n process.exit(1);\n}\n","import prompts from \"prompts\";\n\nimport { EmailProvider, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getEmailProvider = async (): Promise<{\n [key in typeof config.env.email.provider]: EmailProvider;\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n name: config.env.email.provider,\n message: \"What do you want to use for emails?\",\n choices: Object.values(EmailProvider).map((provider) => ({\n title: getLabel(provider),\n value: provider,\n })),\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getEmailProviderConfig = async (provider: EmailProvider) => {\n switch (provider) {\n case EmailProvider.RESEND:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.email.resend.apiKey,\n message: \"Enter your Resend API key\",\n },\n ],\n {\n onCancel,\n },\n );\n case EmailProvider.SENDGRID:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.email.sendgrid.apiKey,\n message: \"Enter your Sendgrid API key\",\n },\n ],\n {\n onCancel,\n },\n );\n case EmailProvider.PLUNK:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.email.plunk.apiKey,\n message: \"Enter your Plunk API key\",\n },\n ],\n {\n onCancel,\n },\n );\n case EmailProvider.POSTMARK:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.email.postmark.apiKey,\n message: \"Enter your Postmark API key\",\n },\n ],\n {\n onCancel,\n },\n );\n case EmailProvider.NODEMAILER:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.email.nodemailer.user,\n message: \"Enter your Nodemailer user\",\n },\n {\n type: \"text\",\n name: config.env.email.nodemailer.password,\n message: \"Enter your Nodemailer user password\",\n },\n {\n type: \"text\",\n name: config.env.email.nodemailer.host,\n message: \"Enter your Nodemailer host\",\n },\n {\n type: \"number\",\n name: config.env.email.nodemailer.port,\n message: \"Enter your Nodemailer port\",\n },\n ],\n {\n onCancel,\n },\n );\n }\n};\n\nexport const getEmailConfig = async () => {\n const provider = await getEmailProvider();\n const config = await getEmailProviderConfig(provider.EMAIL_PROVIDER);\n\n return { ...provider, ...config };\n};\n","import { promises } from \"fs\";\nimport _ from \"lodash\";\nimport ora from \"ora\";\nimport { join } from \"path\";\n\nimport { EnvFile, envInPaths, EnvPath } from \"~/config\";\nimport { logger } from \"~/utils\";\n\nexport const prepareEnvironment = async (projectDir: string) => {\n try {\n await Promise.allSettled(\n Object.values(EnvPath).map(async (path) => {\n const cwd = join(projectDir, path);\n await promises.copyFile(\n join(cwd, EnvFile.EXAMPLE),\n join(cwd, EnvFile.LOCAL),\n );\n }),\n );\n } catch {\n logger.error(\"Failed to prepare environment!\");\n process.exit(1);\n }\n};\n\nexport const setEnvironmentVariable = async (\n projectDir: string,\n key: string,\n value: string,\n) => {\n if (!value) {\n return;\n }\n\n const paths = _.keys(\n _.pickBy(envInPaths, (values) => _.includes(values, key)),\n );\n\n for (const path of paths) {\n const cwd = join(projectDir, path);\n const envFilePath = join(cwd, EnvFile.LOCAL);\n\n const content = await promises.readFile(envFilePath, \"utf8\");\n\n const regex = new RegExp(`^${key}=.*`, \"gm\");\n\n if (regex.test(content)) {\n await promises.writeFile(\n envFilePath,\n content.replace(regex, `${key}=\"${value}\"`),\n );\n } else {\n await promises.appendFile(envFilePath, `\\n${key}=\"${value}\"`);\n }\n }\n};\n\nexport const setEnvironmentVariables = async (\n projectDir: string,\n variables: Record<string, string>,\n) => {\n const spinner = ora(`Setting environment variables...`).start();\n\n try {\n for (const [key, value] of Object.entries(variables)) {\n await setEnvironmentVariable(projectDir, key, value);\n }\n\n spinner.succeed(\"Environment variables successfully set!\");\n } catch {\n logger.error(\"Failed to set environment variables!\");\n process.exit(1);\n }\n};\n","import prompts from \"prompts\";\n\nimport { config, SupabaseType } from \"~/config\";\nimport { onCancel } from \"~/utils\";\n\nconst getSupabaseCloudConfig = async () => {\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.supabase.url,\n message: \"Enter your Supabase project URL\",\n },\n {\n type: \"text\",\n name: config.env.supabase.key,\n message: \"Enter your Supabase project anononymous key\",\n },\n {\n type: \"text\",\n name: config.env.db.url,\n message: \"Enter your database URL\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nexport const getSupabaseConfig = async () => {\n const response = await prompts(\n [\n {\n type: \"select\",\n name: \"type\",\n message: \"How do you want to use Supabase?\",\n choices: [\n {\n title: \"Local (powered by Docker)\",\n value: SupabaseType.LOCAL,\n selected: true,\n },\n {\n title: `Cloud`,\n value: SupabaseType.CLOUD,\n },\n ],\n },\n ],\n {\n onCancel,\n },\n );\n\n if (response.type === SupabaseType.CLOUD) {\n const supabaseConfig = await getSupabaseCloudConfig();\n\n return { ...response, env: supabaseConfig };\n }\n\n return response;\n};\n","import { execa } from \"execa\";\nimport ora from \"ora\";\n\nimport { setEnvironmentVariable } from \"~/commands/new/config/env\";\nimport { validateDockerInstalled } from \"~/commands/new/prerequisites\";\nimport { config } from \"~/config\";\n\nconst getSupabaseKey = (out: string) => {\n return /anon key:\\s([^\\s]+)/.exec(out)?.[1];\n};\n\nexport const startSupabase = async (cwd: string) => {\n await validateDockerInstalled();\n\n const spinner = ora(`Starting Supabase...`).start();\n\n try {\n const out = await execa(\"pnpm\", [\"db:setup\"], { cwd });\n const key = getSupabaseKey(out.stdout);\n\n if (key) {\n await setEnvironmentVariable(cwd, config.env.supabase.key, key);\n }\n\n spinner.succeed(\"Supabase successfully started!\");\n } catch {\n spinner.fail(\"Failed to start Supabase!\");\n process.exit(1);\n }\n};\n","import { execa } from \"execa\";\nimport ora from \"ora\";\nimport color from \"picocolors\";\n\nimport { logger } from \"~/utils/logger\";\n\nexport const validateNodeInstalled = async () => {\n try {\n await execa(\"node\", [\"--version\"]);\n } catch {\n logger.error(\n \"Node.js is not installed. Please install Node.js and try again.\\n\",\n );\n logger.info(\n `To install Node.js, visit: ${color.underline(\"https://nodejs.org/en/\")}`,\n );\n\n process.exit(1);\n }\n};\n\nexport const validatePnpmInstalled = async () => {\n try {\n await execa(\"pnpm\", [\"--version\"]);\n } catch {\n try {\n await execa(\"npm\", [\"install\", \"-g\", \"pnpm\"]);\n } catch {\n logger.error(\n \"pnpm is not installed. Please install pnpm manually and try again. \\n\",\n );\n logger.info(\n `To install pnpm, visit: ${color.underline(\"https://pnpm.io/installation\")}`,\n );\n\n process.exit(1);\n }\n }\n};\n\nexport const validateDockerInstalled = async () => {\n try {\n await execa(\"docker\", [\"--version\"]);\n } catch {\n logger.error(\n \"Docker is not installed. Please install Docker and try again.\",\n );\n logger.info(\n `To install Docker, visit: ${color.underline(\"https://docs.docker.com/get-docker/\")}`,\n );\n process.exit(1);\n }\n};\n\nconst validateGitInstalled = async () => {\n try {\n await execa(\"git\", [\"--version\"]);\n } catch {\n logger.error(\"Git is not installed. Please install Git and try again.\");\n logger.info(\n `To install Git, visit: ${color.underline(\"https://git-scm.com/downloads\")}`,\n );\n process.exit(1);\n }\n};\n\nexport const validatePrerequisites = async () => {\n const spinner = ora(\"Checking prerequisites... \\n\").start();\n try {\n await validateGitInstalled();\n await validateNodeInstalled();\n await validatePnpmInstalled();\n spinner.succeed(\"All prerequisites are satisfied, let's start! šŸš€\\n\");\n } catch {\n spinner.fail(\"Failed to check prerequisites.\");\n process.exit(1);\n }\n};\n"],"mappings":"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","names":["Command","Command","execa","ora","path","join","color","prompts","z","prompts","SupabaseType","BillingProvider","EmailProvider","EnvPath","EnvFile","App","env","envInPaths","appSpecificFiles","config","fs","_","path","colors","logger","log","handleError","error","logger","getPackageInfo","packageJsonPath","path","fs","getLabel","value","word","_","onCancel","logger","getBillingProvider","prompts","BillingProvider","provider","getLabel","config","onCancel","getBillingProviderConfig","getBillingConfig","prompts","getEmailProvider","prompts","config","EmailProvider","provider","getLabel","onCancel","getEmailProviderConfig","getEmailConfig","promises","_","ora","join","prepareEnvironment","projectDir","EnvPath","path","cwd","join","promises","EnvFile","logger","setEnvironmentVariable","key","value","paths","_","envInPaths","values","envFilePath","content","regex","setEnvironmentVariables","variables","spinner","ora","prompts","getSupabaseCloudConfig","prompts","config","onCancel","getSupabaseConfig","response","SupabaseType","supabaseConfig","execa","ora","execa","ora","color","validateNodeInstalled","execa","logger","color","validatePnpmInstalled","validateDockerInstalled","validateGitInstalled","validatePrerequisites","spinner","ora","getSupabaseKey","out","startSupabase","cwd","validateDockerInstalled","spinner","ora","execa","key","setEnvironmentVariable","config","newOptionsSchema","z","newCommand","Command","opts","logger","color","options","path","initializeProject","error","handleError","validatePrerequisites","global","prompts","App","value","onCancel","supabaseConfig","getSupabaseConfig","billingConfig","getBillingConfig","emailConfig","getEmailConfig","config","projectDir","cloneRepository","prepareEnvironment","setEnvironmentVariables","installDependencies","SupabaseType","startSupabase","cwd","name","apps","spinner","ora","join","filesToRemove","app","appSpecificFiles","execa","main","packageInfo","getPackageInfo","program","Command","newCommand"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/new/index.ts","../src/commands/new/config/billing.ts","../src/config.ts","../src/utils/index.ts","../src/utils/logger.ts","../src/utils/handle-error.ts","../src/commands/new/config/email.ts","../src/commands/new/config/env.ts","../src/commands/new/config/storage.ts","../src/commands/new/config/supabase.ts","../src/commands/new/supabase.ts","../src/commands/new/prerequisites.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\n\nimport { newCommand } from \"~/commands/new\";\n\nimport packageInfo from \"../package.json\";\n\nprocess.on(\"SIGINT\", () => process.exit(0));\nprocess.on(\"SIGTERM\", () => process.exit(0));\n\nfunction main() {\n const program = new Command()\n .name(\"turbostarter\")\n .description(\n \"Your TurboStarter assistant for starting new projects, adding plugins and more.\",\n )\n .version(\n packageInfo.version || \"1.0.0\",\n \"-v, --version\",\n \"display the version number\",\n );\n\n program.addCommand(newCommand);\n program.parse();\n}\n\nvoid main();\n","import { Command } from \"commander\";\nimport { execa } from \"execa\";\nimport ora from \"ora\";\nimport path, { join } from \"path\";\nimport color from \"picocolors\";\nimport prompts from \"prompts\";\nimport { z } from \"zod\";\n\nimport { getBillingConfig } from \"~/commands/new/config/billing\";\nimport { getEmailConfig } from \"~/commands/new/config/email\";\nimport {\n prepareEnvironment,\n setEnvironmentVariables,\n} from \"~/commands/new/config/env\";\nimport { getStorageConfig } from \"~/commands/new/config/storage\";\nimport { getSupabaseConfig } from \"~/commands/new/config/supabase\";\nimport { startSupabase } from \"~/commands/new/supabase\";\nimport { App, appSpecificFiles, config, SupabaseType } from \"~/config\";\nimport { handleError, logger, onCancel } from \"~/utils\";\n\nimport { validatePrerequisites } from \"./prerequisites\";\n\nconst newOptionsSchema = z.object({\n cwd: z.string(),\n});\n\nexport const newCommand = new Command()\n .name(\"new\")\n .description(\"create a new TurboStarter project\")\n .option(\n \"-c, --cwd <cwd>\",\n \"the working directory. defaults to the current directory.\",\n process.cwd(),\n )\n .action(async (opts: z.infer<typeof newOptionsSchema>) => {\n try {\n logger.log(`${color.bgYellow(color.black(\" TurboStarter \"))}\\n`);\n\n const options = newOptionsSchema.parse({\n cwd: path.resolve(opts.cwd),\n });\n\n await initializeProject(options);\n\n logger.log(\n `\\nšŸŽ‰ You can now get started. Open the project and just ship it! šŸŽ‰\\n`,\n );\n\n logger.info(\n `Problems? ${color.underline(\"https://turbostarter.dev/docs\")}`,\n );\n } catch (error) {\n logger.break();\n handleError(error);\n }\n });\n\nconst initializeProject = async (options: z.infer<typeof newOptionsSchema>) => {\n await validatePrerequisites();\n\n const global = await prompts(\n [\n {\n type: \"multiselect\",\n name: \"apps\",\n message: `What do you want to ship?`,\n instructions: false,\n choices: [\n { title: \"Web app\", value: App.WEB, selected: true },\n { title: \"Mobile app\", value: App.MOBILE, selected: false },\n {\n title: \"Browser extension\",\n value: App.EXTENSION,\n selected: false,\n },\n ],\n hint: `You ${color.bold(\"must\")} ship a web app, to ensure backend services work.`,\n },\n {\n type: \"text\",\n name: \"name\",\n message: \"Enter your project name.\",\n validate: (value: string) =>\n value.length > 0 ? true : \"Name is required!\",\n },\n ],\n {\n onCancel,\n },\n );\n\n const supabaseConfig = await getSupabaseConfig();\n const billingConfig = await getBillingConfig();\n const emailConfig = await getEmailConfig();\n const storageConfig =\n supabaseConfig.type === SupabaseType.LOCAL ? {} : await getStorageConfig();\n\n const config = {\n ...(\"env\" in supabaseConfig ? supabaseConfig.env : {}),\n ...billingConfig,\n ...emailConfig,\n ...storageConfig,\n };\n\n const projectDir = await cloneRepository(\n options.cwd,\n global.name,\n global.apps,\n );\n await configureGit(projectDir);\n await prepareEnvironment(projectDir);\n await setEnvironmentVariables(projectDir, config);\n await installDependencies(projectDir);\n\n if (supabaseConfig.type === SupabaseType.LOCAL) {\n await startSupabase(projectDir);\n }\n};\n\nconst cloneRepository = async (cwd: string, name: string, apps: App[]) => {\n const spinner = ora(`Cloning repository into ${name}...`).start();\n const projectDir = join(cwd, name);\n\n const filesToRemove = Object.values(App)\n .filter((app) => !apps.includes(app))\n .map((app) => appSpecificFiles[app])\n .flat();\n\n try {\n await execa(\"git\", [\"clone\", config.repository, name], { cwd });\n\n if (filesToRemove.length) {\n await execa(\"rm\", [\"-rf\", ...filesToRemove], { cwd: projectDir });\n }\n\n spinner.succeed(\"Repository successfully pulled!\");\n\n return projectDir;\n } catch {\n spinner.fail(\"Failed to clone TurboStarter! Please try again.\");\n process.exit(1);\n }\n};\n\nconst configureGit = async (cwd: string) => {\n const spinner = ora(`Configuring Git...`).start();\n\n try {\n await execa(\"rm\", [\"-rf\", \".git\"], { cwd });\n await execa(\"git\", [\"init\"], { cwd });\n await execa(\"git\", [\"remote\", \"add\", \"upstream\", config.repository], {\n cwd,\n });\n await execa(\"git\", [\"add\", \".\"], { cwd });\n await execa(\"git\", [\"commit\", \"-m\", \"Initial commit\"], { cwd });\n\n spinner.succeed(\"Git successfully configured!\");\n } catch {\n spinner.fail(\"Failed to configure Git! Please try again.\");\n process.exit(1);\n }\n};\n\nconst installDependencies = async (cwd: string) => {\n const spinner = ora(`Installing dependencies...`).start();\n\n try {\n await execa(\"pnpm\", [\"install\"], { cwd });\n\n spinner.succeed(\"Dependencies successfully installed!\");\n } catch {\n spinner.fail(\"Failed to install dependencies! Please try again.\");\n process.exit(1);\n }\n};\n","import prompts from \"prompts\";\n\nimport { BillingProvider, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getBillingProvider = async (): Promise<{\n [key in typeof config.env.billing.provider]: BillingProvider;\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n choices: Object.values(BillingProvider).map((provider) => ({\n title: getLabel(provider),\n value: provider,\n })),\n name: config.env.billing.provider,\n message: \"What do you want to use for billing?\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getBillingProviderConfig = async (provider: BillingProvider) => {\n switch (provider) {\n case BillingProvider.STRIPE:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.billing.stripe.secretKey,\n message: \"Enter your Stripe secret key\",\n },\n {\n type: \"text\",\n name: config.env.billing.stripe.webhookSecret,\n message: \"Enter your Stripe webhook secret\",\n },\n ],\n {\n onCancel,\n },\n );\n case BillingProvider.LEMON_SQUEEZY:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.billing.lemonsqueezy.storeId,\n message: \"Enter your Lemon Squeezy store ID\",\n },\n {\n type: \"text\",\n name: config.env.billing.lemonsqueezy.apiKey,\n message: \"Enter your Lemon Squeezy API key\",\n },\n {\n type: \"text\",\n name: config.env.billing.lemonsqueezy.signingSecret,\n message: \"Enter your Lemon Squeezy signing secret\",\n },\n ],\n {\n onCancel,\n },\n );\n }\n};\n\nexport const getBillingConfig = async () => {\n const provider = await getBillingProvider();\n const config = await getBillingProviderConfig(provider.BILLING_PROVIDER);\n\n return { ...provider, ...config };\n};\n","export const SupabaseType = {\n LOCAL: \"local\",\n CLOUD: \"cloud\",\n} as const;\n\nexport const StorageProvider = {\n S3: \"s3\",\n} as const;\n\nexport const BillingProvider = {\n STRIPE: \"stripe\",\n LEMON_SQUEEZY: \"lemon-squeezy\",\n} as const;\n\nexport const EmailProvider = {\n RESEND: \"resend\",\n SENDGRID: \"sendgrid\",\n POSTMARK: \"postmark\",\n PLUNK: \"plunk\",\n NODEMAILER: \"nodemailer\",\n} as const;\n\nexport const EnvPath = {\n ROOT: \"./\",\n WEB: \"./apps/web\",\n MOBILE: \"./apps/mobile\",\n EXTENSION: \"./apps/extension\",\n DB: \"./packages/db\",\n} as const;\n\nexport const EnvFile = {\n EXAMPLE: \".env.example\",\n LOCAL: \".env.local\",\n} as const;\n\nexport const App = {\n WEB: \"web\",\n MOBILE: \"mobile\",\n EXTENSION: \"extension\",\n} as const;\n\nexport type SupabaseType = (typeof SupabaseType)[keyof typeof SupabaseType];\nexport type StorageProvider =\n (typeof StorageProvider)[keyof typeof StorageProvider];\nexport type BillingProvider =\n (typeof BillingProvider)[keyof typeof BillingProvider];\nexport type EmailProvider = (typeof EmailProvider)[keyof typeof EmailProvider];\nexport type EnvPath = (typeof EnvPath)[keyof typeof EnvPath];\nexport type EnvFile = (typeof EnvFile)[keyof typeof EnvFile];\nexport type App = (typeof App)[keyof typeof App];\n\nconst env = {\n db: {\n url: \"DATABASE_URL\",\n },\n supabase: {\n key: \"SUPABASE_ANON_KEY\",\n url: \"SUPABASE_URL\",\n },\n billing: {\n provider: \"BILLING_PROVIDER\",\n stripe: {\n secretKey: \"STRIPE_SECRET_KEY\",\n webhookSecret: \"STRIPE_WEBHOOK_SECRET\",\n },\n lemonsqueezy: {\n apiKey: \"LEMON_SQUEEZY_API_KEY\",\n signingSecret: \"LEMON_SQUEEZY_SIGNING_SECRET\",\n storeId: \"LEMON_SQUEEZY_STORE_ID\",\n },\n },\n email: {\n provider: \"EMAIL_PROVIDER\",\n resend: {\n apiKey: \"RESEND_API_KEY\",\n },\n sendgrid: {\n apiKey: \"SENDGRID_API_KEY\",\n },\n plunk: {\n apiKey: \"PLUNK_API_KEY\",\n },\n postmark: {\n apiKey: \"POSTMARK_API_KEY\",\n },\n nodemailer: {\n user: \"NODEMAILER_USER\",\n password: \"NODEMAILER_PASSWORD\",\n host: \"NODEMAILER_HOST\",\n port: \"NODEMAILER_PORT\",\n },\n },\n storage: {\n provider: \"STORAGE_PROVIDER\",\n s3: {\n region: \"S3_REGION\",\n endpoint: \"S3_ENDPOINT\",\n accessKeyId: \"S3_ACCESS_KEY_ID\",\n secretAccessKey: \"S3_SECRET_ACCESS_KEY\",\n },\n },\n} as const;\n\nexport const envInPaths = {\n [EnvPath.ROOT]: [env.db.url, env.supabase.key, env.supabase.url],\n [EnvPath.WEB]: [\n env.billing.provider,\n env.billing.stripe.secretKey,\n env.billing.stripe.webhookSecret,\n env.billing.lemonsqueezy.apiKey,\n env.billing.lemonsqueezy.signingSecret,\n env.billing.lemonsqueezy.storeId,\n env.email.provider,\n env.email.resend.apiKey,\n env.email.sendgrid.apiKey,\n env.email.plunk.apiKey,\n env.email.postmark.apiKey,\n env.email.nodemailer.user,\n env.email.nodemailer.password,\n env.storage.provider,\n env.storage.s3.region,\n env.storage.s3.endpoint,\n env.storage.s3.accessKeyId,\n env.storage.s3.secretAccessKey,\n ],\n};\n\nexport const appSpecificFiles = {\n [App.WEB]: [],\n [App.MOBILE]: [\n \"apps/mobile\",\n \"packages/ui/mobile\",\n \"packages/analytics/mobile\",\n \".github/workflows/publish-mobile.yml\",\n ],\n [App.EXTENSION]: [\n \"apps/extension\",\n \"packages/analytics/extension\",\n \".github/workflows/publish-extension.yml\",\n ],\n};\n\nexport const config = {\n name: \"TurboStarter\",\n repository: \"https://github.com/turbostarter/main.git\",\n env,\n} as const;\n","import _ from \"lodash\";\n\nimport { logger } from \"~/utils/logger\";\n\nexport const getLabel = (value: string) => {\n return value\n .split(\"-\")\n .map((word) => _.capitalize(word))\n .join(\" \");\n};\n\nexport const onCancel = () => {\n logger.break();\n logger.error(\"Operation cancelled.\");\n process.exit(0);\n};\n\nexport * from \"./handle-error\";\nexport * from \"./logger\";\n","import colors from \"picocolors\";\n\nexport const logger = {\n error(log: string) {\n console.log(colors.red(log));\n },\n warn(log: string) {\n console.log(colors.yellow(log));\n },\n info(log: string) {\n console.log(colors.cyan(log));\n },\n success(log: string) {\n console.log(colors.green(log));\n },\n log(log: string) {\n console.log(log);\n },\n break() {\n console.log(\"\");\n },\n};\n","import { logger } from \"./logger\";\n\nexport function handleError(error: unknown) {\n if (typeof error === \"string\") {\n logger.error(error);\n process.exit(1);\n }\n\n if (error instanceof Error) {\n logger.error(error.message);\n process.exit(1);\n }\n\n logger.error(\"Something went wrong. Please try again.\");\n process.exit(1);\n}\n","import prompts from \"prompts\";\n\nimport { EmailProvider, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getEmailProvider = async (): Promise<{\n [key in typeof config.env.email.provider]: EmailProvider;\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n name: config.env.email.provider,\n message: \"What do you want to use for emails?\",\n choices: Object.values(EmailProvider).map((provider) => ({\n title: getLabel(provider),\n value: provider,\n })),\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getEmailProviderConfig = async (provider: EmailProvider) => {\n switch (provider) {\n case EmailProvider.RESEND:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.email.resend.apiKey,\n message: \"Enter your Resend API key\",\n },\n ],\n {\n onCancel,\n },\n );\n case EmailProvider.SENDGRID:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.email.sendgrid.apiKey,\n message: \"Enter your Sendgrid API key\",\n },\n ],\n {\n onCancel,\n },\n );\n case EmailProvider.PLUNK:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.email.plunk.apiKey,\n message: \"Enter your Plunk API key\",\n },\n ],\n {\n onCancel,\n },\n );\n case EmailProvider.POSTMARK:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.email.postmark.apiKey,\n message: \"Enter your Postmark API key\",\n },\n ],\n {\n onCancel,\n },\n );\n case EmailProvider.NODEMAILER:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.email.nodemailer.user,\n message: \"Enter your Nodemailer user\",\n },\n {\n type: \"text\",\n name: config.env.email.nodemailer.password,\n message: \"Enter your Nodemailer user password\",\n },\n {\n type: \"text\",\n name: config.env.email.nodemailer.host,\n message: \"Enter your Nodemailer host\",\n },\n {\n type: \"number\",\n name: config.env.email.nodemailer.port,\n message: \"Enter your Nodemailer port\",\n },\n ],\n {\n onCancel,\n },\n );\n }\n};\n\nexport const getEmailConfig = async () => {\n const provider = await getEmailProvider();\n const config = await getEmailProviderConfig(provider.EMAIL_PROVIDER);\n\n return { ...provider, ...config };\n};\n","import { promises } from \"fs\";\nimport _ from \"lodash\";\nimport ora from \"ora\";\nimport { join } from \"path\";\n\nimport { EnvFile, envInPaths, EnvPath } from \"~/config\";\nimport { logger } from \"~/utils\";\n\nexport const prepareEnvironment = async (projectDir: string) => {\n try {\n await Promise.allSettled(\n Object.values(EnvPath).map(async (path) => {\n const cwd = join(projectDir, path);\n await promises.copyFile(\n join(cwd, EnvFile.EXAMPLE),\n join(cwd, EnvFile.LOCAL),\n );\n }),\n );\n } catch {\n logger.error(\"Failed to prepare environment!\");\n process.exit(1);\n }\n};\n\nexport const setEnvironmentVariable = async (\n projectDir: string,\n key: string,\n value: string,\n) => {\n if (!value) {\n return;\n }\n\n const paths = _.keys(\n _.pickBy(envInPaths, (values) => _.includes(values, key)),\n );\n\n for (const path of paths) {\n const cwd = join(projectDir, path);\n const envFilePath = join(cwd, EnvFile.LOCAL);\n\n const content = await promises.readFile(envFilePath, \"utf8\");\n\n const regex = new RegExp(`^${key}=.*`, \"gm\");\n\n if (regex.test(content)) {\n await promises.writeFile(\n envFilePath,\n content.replace(regex, `${key}=\"${value}\"`),\n );\n } else {\n await promises.appendFile(envFilePath, `\\n${key}=\"${value}\"`);\n }\n }\n};\n\nexport const setEnvironmentVariables = async (\n projectDir: string,\n variables: Record<string, string>,\n) => {\n const spinner = ora(`Setting environment variables...`).start();\n\n try {\n for (const [key, value] of Object.entries(variables)) {\n await setEnvironmentVariable(projectDir, key, value);\n }\n\n spinner.succeed(\"Environment variables successfully set!\");\n } catch {\n logger.error(\"Failed to set environment variables!\");\n process.exit(1);\n }\n};\n","import prompts from \"prompts\";\n\nimport { config, StorageProvider } from \"~/config\";\nimport { onCancel } from \"~/utils\";\nimport { getLabel } from \"~/utils\";\n\nconst getStorageProvider = async (): Promise<{\n [key in typeof config.env.storage.provider]: StorageProvider;\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n choices: Object.values(StorageProvider).map((provider) => ({\n title: getLabel(provider),\n value: provider,\n })),\n name: config.env.storage.provider,\n message: \"What do you want to use for storage?\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getStorageProviderConfig = () => {\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.storage.s3.region,\n message: \"Enter your S3 region\",\n },\n {\n type: \"text\",\n name: config.env.storage.s3.endpoint,\n message: \"Enter your S3 endpoint\",\n },\n {\n type: \"text\",\n name: config.env.storage.s3.accessKeyId,\n message: \"Enter your S3 access key ID\",\n },\n {\n type: \"text\",\n name: config.env.storage.s3.secretAccessKey,\n message: \"Enter your S3 secret access key\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nexport const getStorageConfig = async () => {\n const provider = await getStorageProvider();\n const config = await getStorageProviderConfig();\n\n return { ...provider, ...config };\n};\n","import prompts from \"prompts\";\n\nimport { config, SupabaseType } from \"~/config\";\nimport { onCancel } from \"~/utils\";\n\nconst getSupabaseCloudConfig = async () => {\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.supabase.url,\n message: \"Enter your Supabase project URL\",\n },\n {\n type: \"text\",\n name: config.env.supabase.key,\n message: \"Enter your Supabase project anononymous key\",\n },\n {\n type: \"text\",\n name: config.env.db.url,\n message: \"Enter your database URL\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nexport const getSupabaseConfig = async () => {\n const response = await prompts(\n [\n {\n type: \"select\",\n name: \"type\",\n message: \"How do you want to use Supabase?\",\n choices: [\n {\n title: \"Local (powered by Docker)\",\n value: SupabaseType.LOCAL,\n selected: true,\n },\n {\n title: `Cloud`,\n value: SupabaseType.CLOUD,\n },\n ],\n },\n ],\n {\n onCancel,\n },\n );\n\n if (response.type === SupabaseType.CLOUD) {\n const supabaseConfig = await getSupabaseCloudConfig();\n\n return { ...response, env: supabaseConfig };\n }\n\n return response;\n};\n","import { execa } from \"execa\";\nimport ora from \"ora\";\n\nimport { setEnvironmentVariables } from \"~/commands/new/config/env\";\nimport { validateDockerInstalled } from \"~/commands/new/prerequisites\";\nimport { config } from \"~/config\";\n\nconst variables = [\n {\n variable: config.env.supabase.key,\n regex: /anon key:\\s([^\\s]+)/,\n },\n {\n variable: config.env.storage.s3.region,\n regex: /S3 Region:\\s([^\\s]+)/,\n },\n {\n variable: config.env.storage.s3.endpoint,\n regex: /S3 Storage URL:\\s([^\\s]+)/,\n },\n {\n variable: config.env.storage.s3.accessKeyId,\n regex: /S3 Access Key:\\s([^\\s]+)/,\n },\n {\n variable: config.env.storage.s3.secretAccessKey,\n regex: /S3 Secret Key:\\s([^\\s]+)/,\n },\n];\n\nconst getVariablesFromOutput = (out: string) => {\n return variables.reduce((acc, variable) => {\n const match = variable.regex.exec(out);\n return match ? { ...acc, [variable.variable]: match[1] } : acc;\n }, {}) as Record<string, string>;\n};\n\nexport const startSupabase = async (cwd: string) => {\n await validateDockerInstalled();\n\n const spinner = ora(`Starting Supabase...`).start();\n\n try {\n const out = await execa(\"pnpm\", [\"db:setup\"], { cwd });\n const variables = getVariablesFromOutput(out.stdout);\n\n await setEnvironmentVariables(cwd, variables);\n\n spinner.succeed(\"Supabase successfully started!\");\n } catch {\n spinner.fail(\"Failed to start Supabase!\");\n process.exit(1);\n }\n};\n","import { execa } from \"execa\";\nimport ora from \"ora\";\nimport color from \"picocolors\";\n\nimport { logger } from \"~/utils/logger\";\n\nexport const validateNodeInstalled = async () => {\n try {\n await execa(\"node\", [\"--version\"]);\n } catch {\n logger.error(\n \"Node.js is not installed. Please install Node.js and try again.\\n\",\n );\n logger.info(\n `To install Node.js, visit: ${color.underline(\"https://nodejs.org/en/\")}`,\n );\n\n process.exit(1);\n }\n};\n\nexport const validatePnpmInstalled = async () => {\n try {\n await execa(\"pnpm\", [\"--version\"]);\n } catch {\n try {\n await execa(\"npm\", [\"install\", \"-g\", \"pnpm\"]);\n } catch {\n logger.error(\n \"pnpm is not installed. Please install pnpm manually and try again. \\n\",\n );\n logger.info(\n `To install pnpm, visit: ${color.underline(\"https://pnpm.io/installation\")}`,\n );\n\n process.exit(1);\n }\n }\n};\n\nexport const validateDockerInstalled = async () => {\n try {\n await execa(\"docker\", [\"--version\"]);\n } catch {\n logger.error(\n \"Docker is not installed. Please install Docker and try again.\",\n );\n logger.info(\n `To install Docker, visit: ${color.underline(\"https://docs.docker.com/get-docker/\")}`,\n );\n process.exit(1);\n }\n};\n\nconst validateGitInstalled = async () => {\n try {\n await execa(\"git\", [\"--version\"]);\n } catch {\n logger.error(\"Git is not installed. Please install Git and try again.\");\n logger.info(\n `To install Git, visit: ${color.underline(\"https://git-scm.com/downloads\")}`,\n );\n process.exit(1);\n }\n};\n\nexport const validatePrerequisites = async () => {\n const spinner = ora(\"Checking prerequisites... \\n\").start();\n try {\n await validateGitInstalled();\n await validateNodeInstalled();\n await validatePnpmInstalled();\n spinner.succeed(\"All prerequisites are satisfied, let's start! šŸš€\\n\");\n } catch {\n spinner.fail(\"Failed to check prerequisites.\");\n process.exit(1);\n }\n};\n","{\n \"name\": \"@turbostarter/cli\",\n \"version\": \"1.0.4\",\n \"main\": \"index.js\",\n \"type\": \"module\",\n \"exports\": \"./dist/index.js\",\n \"publishConfig\": {\n \"registry\": \"https://registry.npmjs.org/\",\n \"access\": \"public\"\n },\n \"bin\": {\n \"turbostarter\": \"./dist/index.js\"\n },\n \"repository\": {\n \"url\": \"https://github.com/turbostarter/cli.git\"\n },\n \"homepage\": \"https://turbostarter.dev\",\n \"files\": [\n \"dist\"\n ],\n \"keywords\": [\n \"turbostarter\",\n \"cli\",\n \"starter kit\",\n \"template\",\n \"web\",\n \"mobile\",\n \"browser extension\"\n ],\n \"scripts\": {\n \"start\": \"node dist/index.js\",\n \"dev\": \"tsup --watch\",\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"prepare\": \"pnpm run build\",\n \"lint\": \"eslint\",\n \"lint:fix\": \"eslint --fix\",\n \"format\": \"prettier --check \\\"**/*.{ts,tsx,mdx}\\\" --cache\",\n \"format:fix\": \"prettier --write \\\"**/*.{ts,tsx,mdx}\\\" --cache\"\n },\n \"author\": \"Bartosz Zagrodzki\",\n \"license\": \"ISC\",\n \"description\": \"A CLI for TurboStarter\",\n \"devDependencies\": {\n \"@eslint/compat\": \"1.2.0\",\n \"@types/lodash\": \"4.17.12\",\n \"@types/node\": \"22.7.5\",\n \"@types/prompts\": \"^2.4.2\",\n \"eslint\": \"9.12.0\",\n \"eslint-plugin-import\": \"2.31.0\",\n \"eslint-plugin-unused-imports\": \"4.1.4\",\n \"prettier\": \"3.3.3\",\n \"tsup\": \"8.3.0\",\n \"typescript\": \"5.5.4\",\n \"typescript-eslint\": \"8.9.0\"\n },\n \"dependencies\": {\n \"commander\": \"12.1.0\",\n \"execa\": \"9.4.0\",\n \"lodash\": \"4.17.21\",\n \"ora\": \"^6.1.2\",\n \"picocolors\": \"1.1.0\",\n \"prompts\": \"^2.4.2\",\n \"zod\": \"3.23.8\"\n },\n \"packageManager\": \"pnpm@9.9.0\"\n}\n"],"mappings":"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","names":["Command","Command","execa","ora","path","join","color","prompts","z","prompts","SupabaseType","StorageProvider","BillingProvider","EmailProvider","EnvPath","EnvFile","App","env","envInPaths","appSpecificFiles","config","_","colors","logger","log","handleError","error","logger","getLabel","value","word","_","onCancel","logger","getBillingProvider","prompts","BillingProvider","provider","getLabel","config","onCancel","getBillingProviderConfig","getBillingConfig","prompts","getEmailProvider","prompts","config","EmailProvider","provider","getLabel","onCancel","getEmailProviderConfig","getEmailConfig","promises","_","ora","join","prepareEnvironment","projectDir","EnvPath","path","cwd","join","promises","EnvFile","logger","setEnvironmentVariable","key","value","paths","_","envInPaths","values","envFilePath","content","regex","setEnvironmentVariables","variables","spinner","ora","prompts","getStorageProvider","prompts","StorageProvider","provider","getLabel","config","onCancel","getStorageProviderConfig","getStorageConfig","prompts","getSupabaseCloudConfig","prompts","config","onCancel","getSupabaseConfig","response","SupabaseType","supabaseConfig","execa","ora","execa","ora","color","validateNodeInstalled","execa","logger","color","validatePnpmInstalled","validateDockerInstalled","validateGitInstalled","validatePrerequisites","spinner","ora","variables","config","getVariablesFromOutput","out","acc","variable","match","startSupabase","cwd","validateDockerInstalled","spinner","ora","execa","setEnvironmentVariables","newOptionsSchema","z","newCommand","Command","opts","logger","color","options","path","initializeProject","error","handleError","validatePrerequisites","global","prompts","App","value","onCancel","supabaseConfig","getSupabaseConfig","billingConfig","getBillingConfig","emailConfig","getEmailConfig","storageConfig","SupabaseType","getStorageConfig","config","projectDir","cloneRepository","configureGit","prepareEnvironment","setEnvironmentVariables","installDependencies","startSupabase","cwd","name","apps","spinner","ora","join","filesToRemove","app","appSpecificFiles","execa","package_default","main","program","Command","package_default","newCommand"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@turbostarter/cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "exports": "./dist/index.js",
@@ -32,7 +32,6 @@
32
32
  "description": "A CLI for TurboStarter",
33
33
  "devDependencies": {
34
34
  "@eslint/compat": "1.2.0",
35
- "@types/fs-extra": "^11.0.1",
36
35
  "@types/lodash": "4.17.12",
37
36
  "@types/node": "22.7.5",
38
37
  "@types/prompts": "^2.4.2",
@@ -41,14 +40,12 @@
41
40
  "eslint-plugin-unused-imports": "4.1.4",
42
41
  "prettier": "3.3.3",
43
42
  "tsup": "8.3.0",
44
- "type-fest": "^3.8.0",
45
43
  "typescript": "5.5.4",
46
44
  "typescript-eslint": "8.9.0"
47
45
  },
48
46
  "dependencies": {
49
47
  "commander": "12.1.0",
50
48
  "execa": "9.4.0",
51
- "fs-extra": "^11.1.0",
52
49
  "lodash": "4.17.21",
53
50
  "ora": "^6.1.2",
54
51
  "picocolors": "1.1.0",