@turbostarter/cli 1.0.7 → 1.2.0
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 +15 -8
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as Ae}from"commander";import{Command as be}from"commander";import{execa as y}from"execa";import L from"ora";import we,{join as Se}from"path";import R from"picocolors";import xe from"prompts";import{z as V}from"zod";import O from"prompts";var f={LOCAL:"local",CLOUD:"cloud"},A={DB:"db"},h={S3:"s3"},d={STRIPE:"stripe",LEMON_SQUEEZY:"lemon-squeezy",POLAR:"polar"},l={RESEND:"resend",SENDGRID:"sendgrid",POSTMARK:"postmark",PLUNK:"plunk",NODEMAILER:"nodemailer"},x={ROOT:"./",WEB:"./apps/web",MOBILE:"./apps/mobile",EXTENSION:"./apps/extension"},P={EXAMPLE:".env.example",LOCAL:".env.local"},u={WEB:"web",MOBILE:"mobile",EXTENSION:"extension"},c={db:{url:"DATABASE_URL"},billing:{[d.STRIPE]:{secretKey:"STRIPE_SECRET_KEY",webhookSecret:"STRIPE_WEBHOOK_SECRET"},[d.LEMON_SQUEEZY]:{apiKey:"LEMON_SQUEEZY_API_KEY",signingSecret:"LEMON_SQUEEZY_SIGNING_SECRET",storeId:"LEMON_SQUEEZY_STORE_ID"},[d.POLAR]:{accessToken:"POLAR_ACCESS_TOKEN",webhookSecret:"POLAR_WEBHOOK_SECRET",organizationSlug:"POLAR_ORGANIZATION_SLUG"}},email:{[l.RESEND]:{apiKey:"RESEND_API_KEY"},[l.SENDGRID]:{apiKey:"SENDGRID_API_KEY"},[l.PLUNK]:{apiKey:"PLUNK_API_KEY"},[l.POSTMARK]:{apiKey:"POSTMARK_API_KEY"},[l.NODEMAILER]:{user:"NODEMAILER_USER",password:"NODEMAILER_PASSWORD",host:"NODEMAILER_HOST",port:"NODEMAILER_PORT"}},storage:{[h.S3]:{region:"S3_REGION",bucket:"S3_BUCKET",endpoint:"S3_ENDPOINT",accessKeyId:"S3_ACCESS_KEY_ID",secretAccessKey:"S3_SECRET_ACCESS_KEY"}}},D={[x.ROOT]:[c.db.url],[x.WEB]:[c.billing.stripe.secretKey,c.billing.stripe.webhookSecret,c.billing["lemon-squeezy"].apiKey,c.billing["lemon-squeezy"].signingSecret,c.billing["lemon-squeezy"].storeId,c.billing.polar.accessToken,c.billing.polar.webhookSecret,c.billing.polar.organizationSlug,c.email.resend.apiKey,c.email.sendgrid.apiKey,c.email.plunk.apiKey,c.email.postmark.apiKey,c.email.nodemailer.user,c.email.nodemailer.password,c.storage.s3.accessKeyId,c.storage.s3.secretAccessKey]},_={[u.WEB]:[],[u.MOBILE]:["apps/mobile","packages/ui/mobile","packages/analytics/mobile",".github/workflows/publish-mobile.yml"],[u.EXTENSION]:["apps/extension","packages/analytics/extension",".github/workflows/publish-extension.yml"]},N={billing:{files:["packages/billing/src/providers/index.ts","packages/billing/src/providers/env.ts"],pattern:new RegExp(`(${Object.values(d).join("|")})`,"gi")},email:{files:["packages/email/src/providers/index.ts","packages/email/src/providers/env.ts"],pattern:new RegExp(`(${Object.values(l).join("|")})`,"gi")},storage:{files:["packages/storage/src/providers/index.ts","packages/storage/src/providers/env.ts"],pattern:new RegExp(`(${Object.values(h).join("|")})`,"gi")}},K={[A.DB]:"@turbostarter/db"},r={name:"TurboStarter",repository:"https://github.com/turbostarter/main.git",env:c};import re from"lodash";import k from"picocolors";var i={error(e){console.log(k.red(e))},warn(e){console.log(k.yellow(e))},info(e){console.log(k.cyan(e))},success(e){console.log(k.green(e))},log(e){console.log(e)},break(){console.log("")}};function j(e){typeof e=="string"&&(i.error(e),process.exit(1)),e instanceof Error&&(i.error(e.message),process.exit(1)),i.error("Something went wrong. Please try again."),process.exit(1)}var v=e=>e.split("-").map(t=>re.capitalize(t)).join(" "),s=()=>{i.break(),i.error("Operation cancelled."),process.exit(0)};var oe=async()=>O([{type:"select",choices:Object.values(d).map(e=>({title:v(e),value:e})),name:"provider",message:"What do you want to use for billing?"}],{onCancel:s}),ie=async e=>{switch(e){case d.STRIPE:return O([{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:s});case d.LEMON_SQUEEZY:return O([{type:"text",name:r.env.billing["lemon-squeezy"].storeId,message:"Enter your Lemon Squeezy store ID"},{type:"text",name:r.env.billing["lemon-squeezy"].apiKey,message:"Enter your Lemon Squeezy API key"},{type:"text",name:r.env.billing["lemon-squeezy"].signingSecret,message:"Enter your Lemon Squeezy signing secret"}],{onCancel:s});case d.POLAR:return O([{type:"text",name:r.env.billing.polar.accessToken,message:"Enter your Polar access token"},{type:"text",name:r.env.billing.polar.webhookSecret,message:"Enter your Polar webhook secret"},{type:"text",name:r.env.billing.polar.organizationSlug,message:"Enter your Polar organization slug"}],{onCancel:s})}},B=async()=>{let{provider:e}=await oe(),t=await ie(e);return{provider:e,env:t}};import F from"prompts";var se=async()=>F([{type:"text",name:r.env.db.url,message:"Enter your database URL"}],{onCancel:s}),M=async()=>{let e=await F([{type:"select",name:"type",message:"How do you want to use database?",choices:[{title:"Local (powered by Docker)",value:f.LOCAL,selected:!0},{title:"Cloud",value:f.CLOUD}]}],{onCancel:s});if(e.type===f.CLOUD){let t=await se();return{...e,env:t}}return e};import E from"prompts";var ne=async()=>E([{type:"select",name:"provider",message:"What do you want to use for emails?",choices:Object.values(l).map(e=>({title:v(e),value:e}))}],{onCancel:s}),ae=async e=>{switch(e){case l.RESEND:return E([{type:"text",name:r.env.email.resend.apiKey,message:"Enter your Resend API key"}],{onCancel:s});case l.SENDGRID:return E([{type:"text",name:r.env.email.sendgrid.apiKey,message:"Enter your Sendgrid API key"}],{onCancel:s});case l.PLUNK:return E([{type:"text",name:r.env.email.plunk.apiKey,message:"Enter your Plunk API key"}],{onCancel:s});case l.POSTMARK:return E([{type:"text",name:r.env.email.postmark.apiKey,message:"Enter your Postmark API key"}],{onCancel:s});case l.NODEMAILER:return E([{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:s})}},z=async()=>{let{provider:e}=await ne(),t=await ae(e);return{provider:e,env:t}};import{promises as I}from"fs";import T from"lodash";import ce from"ora";import{join as w}from"path";var G=async e=>{try{await Promise.allSettled(Object.values(x).map(async t=>{let o=w(e,t);await I.copyFile(w(o,P.EXAMPLE),w(o,P.LOCAL))}))}catch{i.error("Failed to prepare environment!"),process.exit(1)}},pe=async(e,t,o)=>{if(!o)return;let n=T.keys(T.pickBy(D,a=>T.includes(a,t)));for(let a of n){let m=w(e,a),p=w(m,P.LOCAL),g=await I.readFile(p,"utf8"),b=new RegExp(`^${t}=.*`,"gm");b.test(g)?await I.writeFile(p,g.replace(b,`${t}="${o}"`)):await I.appendFile(p,`
|
|
3
|
-
${
|
|
4
|
-
`),
|
|
5
|
-
`),
|
|
6
|
-
`).start();try{await
|
|
7
|
-
`)}catch{
|
|
8
|
-
`);let
|
|
2
|
+
import{Command as pt}from"commander";import{Command as Ze}from"commander";import{execa as v}from"execa";import W from"ora";import Qe,{join as ve}from"path";import P from"picocolors";import fe from"prompts";import{z as ue}from"zod";var h={LOCAL:"local",CLOUD:"cloud"},R={DB:"db"},L={S3:"s3"},u={STRIPE:"stripe",LEMON_SQUEEZY:"lemon-squeezy",POLAR:"polar"},y={RESEND:"resend",SENDGRID:"sendgrid",POSTMARK:"postmark",PLUNK:"plunk",NODEMAILER:"nodemailer"},I={ROOT:"./",WEB:"./apps/web",MOBILE:"./apps/mobile",EXTENSION:"./apps/extension"},B={EXAMPLE:".env.example",LOCAL:".env.local"},e={WEB:"web",MOBILE:"mobile",EXTENSION:"extension"},c={[e.WEB]:{GOOGLE_ANALYTICS:"google-analytics",MIXPANEL:"mixpanel",OPEN_PANEL:"open-panel",PLAUSIBLE:"plausible",POSTHOG:"posthog",UMAMI:"umami",VEMETRIC:"vemetric",VERCEL:"vercel"},[e.MOBILE]:{GOOGLE_ANALYTICS:"google-analytics",MIXPANEL:"mixpanel",POSTHOG:"posthog"},[e.EXTENSION]:{GOOGLE_ANALYTICS:"google-analytics",POSTHOG:"posthog"}},m={[e.WEB]:{SENTRY:"sentry",POSTHOG:"posthog"},[e.MOBILE]:{SENTRY:"sentry",POSTHOG:"posthog"},[e.EXTENSION]:{SENTRY:"sentry",POSTHOG:"posthog"}},r={db:{url:"DATABASE_URL"},billing:{[u.STRIPE]:{secretKey:"STRIPE_SECRET_KEY",webhookSecret:"STRIPE_WEBHOOK_SECRET"},[u.LEMON_SQUEEZY]:{apiKey:"LEMON_SQUEEZY_API_KEY",signingSecret:"LEMON_SQUEEZY_SIGNING_SECRET",storeId:"LEMON_SQUEEZY_STORE_ID"},[u.POLAR]:{accessToken:"POLAR_ACCESS_TOKEN",webhookSecret:"POLAR_WEBHOOK_SECRET",organizationSlug:"POLAR_ORGANIZATION_SLUG"}},email:{[y.RESEND]:{apiKey:"RESEND_API_KEY"},[y.SENDGRID]:{apiKey:"SENDGRID_API_KEY"},[y.PLUNK]:{apiKey:"PLUNK_API_KEY"},[y.POSTMARK]:{apiKey:"POSTMARK_API_KEY"},[y.NODEMAILER]:{user:"NODEMAILER_USER",password:"NODEMAILER_PASSWORD",host:"NODEMAILER_HOST",port:"NODEMAILER_PORT"}},storage:{[L.S3]:{region:"S3_REGION",bucket:"S3_BUCKET",endpoint:"S3_ENDPOINT",accessKeyId:"S3_ACCESS_KEY_ID",secretAccessKey:"S3_SECRET_ACCESS_KEY"}},analytics:{[e.WEB]:{[c[e.WEB].GOOGLE_ANALYTICS]:{measurementId:"NEXT_PUBLIC_GOOGLE_ANALYTICS_MEASUREMENT_ID",secret:"GOOGLE_ANALYTICS_SECRET"},[c[e.WEB].MIXPANEL]:{token:"NEXT_PUBLIC_MIXPANEL_TOKEN"},[c[e.WEB].OPEN_PANEL]:{clientId:"NEXT_PUBLIC_OPEN_PANEL_CLIENT_ID",secret:"OPEN_PANEL_SECRET"},[c[e.WEB].PLAUSIBLE]:{domain:"NEXT_PUBLIC_PLAUSIBLE_DOMAIN",host:"NEXT_PUBLIC_PLAUSIBLE_HOST"},[c[e.WEB].POSTHOG]:{key:"NEXT_PUBLIC_POSTHOG_KEY",host:"NEXT_PUBLIC_POSTHOG_HOST"},[c[e.WEB].UMAMI]:{host:"NEXT_PUBLIC_UMAMI_HOST",websiteId:"NEXT_PUBLIC_UMAMI_WEBSITE_ID",apiHost:"UMAMI_API_HOST",apiKey:"UMAMI_API_KEY"},[c[e.WEB].VEMETRIC]:{token:"NEXT_PUBLIC_VEMETRIC_PROJECT_TOKEN"},[c[e.WEB].VERCEL]:{}},[e.MOBILE]:{[c[e.MOBILE].GOOGLE_ANALYTICS]:{},[c[e.MOBILE].MIXPANEL]:{token:"EXPO_PUBLIC_MIXPANEL_TOKEN"},[c[e.MOBILE].POSTHOG]:{key:"EXPO_PUBLIC_POSTHOG_KEY",host:"EXPO_PUBLIC_POSTHOG_HOST"}},[e.EXTENSION]:{[c[e.EXTENSION].GOOGLE_ANALYTICS]:{measurementId:"VITE_GOOGLE_ANALYTICS_MEASUREMENT_ID",secret:"VITE_GOOGLE_ANALYTICS_SECRET"},[c[e.EXTENSION].POSTHOG]:{key:"VITE_POSTHOG_KEY",host:"VITE_POSTHOG_HOST"}}},monitoring:{[e.WEB]:{[m[e.WEB].SENTRY]:{dsn:"NEXT_PUBLIC_SENTRY_DSN"},[m[e.WEB].POSTHOG]:{key:"NEXT_PUBLIC_POSTHOG_KEY",host:"NEXT_PUBLIC_POSTHOG_HOST"}},[e.MOBILE]:{[m[e.MOBILE].SENTRY]:{dsn:"EXPO_PUBLIC_SENTRY_DSN"},[m[e.MOBILE].POSTHOG]:{key:"EXPO_PUBLIC_POSTHOG_KEY",host:"EXPO_PUBLIC_POSTHOG_HOST"}},[e.EXTENSION]:{[m[e.EXTENSION].SENTRY]:{dsn:"VITE_SENTRY_DSN"},[m[e.EXTENSION].POSTHOG]:{key:"VITE_POSTHOG_KEY",host:"VITE_POSTHOG_HOST"}}}},Y={[I.ROOT]:[r.db.url],[I.WEB]:[r.billing.stripe.secretKey,r.billing.stripe.webhookSecret,r.billing["lemon-squeezy"].apiKey,r.billing["lemon-squeezy"].signingSecret,r.billing["lemon-squeezy"].storeId,r.billing.polar.accessToken,r.billing.polar.webhookSecret,r.billing.polar.organizationSlug,r.email.resend.apiKey,r.email.sendgrid.apiKey,r.email.plunk.apiKey,r.email.postmark.apiKey,r.email.nodemailer.user,r.email.nodemailer.password,r.storage.s3.accessKeyId,r.storage.s3.secretAccessKey,r.analytics[e.WEB]["google-analytics"].measurementId,r.analytics[e.WEB]["google-analytics"].secret,r.analytics[e.WEB].mixpanel.token,r.analytics[e.WEB]["open-panel"].clientId,r.analytics[e.WEB]["open-panel"].secret,r.analytics[e.WEB].plausible.domain,r.analytics[e.WEB].plausible.host,r.analytics[e.WEB].posthog.key,r.analytics[e.WEB].posthog.host,r.analytics[e.WEB].umami.host,r.analytics[e.WEB].umami.websiteId,r.analytics[e.WEB].umami.apiHost,r.analytics[e.WEB].umami.apiKey,r.analytics[e.WEB].vemetric.token,r.monitoring[e.WEB].sentry.dsn,r.monitoring[e.WEB].posthog.key,r.monitoring[e.WEB].posthog.host],[I.MOBILE]:[r.analytics[e.MOBILE].mixpanel.token,r.analytics[e.MOBILE].posthog.key,r.analytics[e.MOBILE].posthog.host,r.monitoring[e.MOBILE].sentry.dsn],[I.EXTENSION]:[r.analytics[e.EXTENSION]["google-analytics"].measurementId,r.analytics[e.EXTENSION]["google-analytics"].secret,r.analytics[e.EXTENSION].posthog.key,r.analytics[e.EXTENSION].posthog.host,r.monitoring[e.EXTENSION].sentry.dsn]},F={[e.WEB]:[],[e.MOBILE]:["apps/mobile","packages/ui/mobile","packages/analytics/mobile","packages/monitoring/mobile",".github/workflows/publish-mobile.yml"],[e.EXTENSION]:["apps/extension","packages/analytics/extension","packages/monitoring/extension",".github/workflows/publish-extension.yml"]},d={billing:{files:["packages/billing/src/providers/index.ts","packages/billing/src/providers/env.ts"],pattern:new RegExp(`(${Object.values(u).join("|")})`,"gi")},email:{files:["packages/email/src/providers/index.ts","packages/email/src/providers/env.ts"],pattern:new RegExp(`(${Object.values(y).join("|")})`,"gi")},storage:{files:["packages/storage/src/providers/index.ts","packages/storage/src/providers/env.ts"],pattern:new RegExp(`(${Object.values(L).join("|")})`,"gi")},analytics:{[e.WEB]:{files:["packages/analytics/web/src/providers/index.tsx","packages/analytics/web/src/providers/server.ts","packages/analytics/web/src/providers/env.ts"],pattern:new RegExp(`(${Object.values(c[e.WEB]).join("|")})`,"gi")},[e.MOBILE]:{files:["packages/analytics/mobile/src/providers/index.ts"],pattern:new RegExp(`(${Object.values(c[e.MOBILE]).join("|")})`,"gi")},[e.EXTENSION]:{files:["packages/analytics/extension/src/providers/index.ts"],pattern:new RegExp(`(${Object.values(c[e.EXTENSION]).join("|")})`,"gi")}},monitoring:{[e.WEB]:{files:["packages/monitoring/web/src/providers/index.ts"],pattern:new RegExp(`(${Object.values(m[e.WEB]).join("|")})`,"gi")},[e.MOBILE]:{files:["packages/monitoring/mobile/src/providers/index.ts"],pattern:new RegExp(`(${Object.values(m[e.MOBILE]).join("|")})`,"gi")},[e.EXTENSION]:{files:["packages/monitoring/extension/src/providers/index.ts"],pattern:new RegExp(`(${Object.values(m[e.EXTENSION]).join("|")})`,"gi")}}},$={[R.DB]:"@turbostarter/db"},n={name:"TurboStarter",repository:"https://github.com/turbostarter/core.git",env:r};import G from"prompts";import Ie from"lodash";import _ from"picocolors";var l={error(t){console.log(_.red(t))},warn(t){console.log(_.yellow(t))},info(t){console.log(_.cyan(t))},success(t){console.log(_.green(t))},log(t){console.log(t)},break(){console.log("")}};function z(t){typeof t=="string"&&(l.error(t),process.exit(1)),t instanceof Error&&(l.error(t.message),process.exit(1)),l.error("Something went wrong. Please try again."),process.exit(1)}var g=t=>t.split("-").map(o=>Ie.capitalize(o)).join(" "),i=()=>{l.break(),l.error("Operation cancelled."),process.exit(0)};var he=async()=>G([{type:"select",choices:Object.values(c[e.EXTENSION]).map(t=>({title:g(t),value:t})),name:"provider",message:"What do you want to use for extension analytics?"}],{onCancel:i}),be=async t=>{switch(t){case c[e.EXTENSION].GOOGLE_ANALYTICS:return G([{type:"text",name:n.env.analytics[e.EXTENSION]["google-analytics"].measurementId,message:"Enter your Google Analytics measurement ID"},{type:"text",name:n.env.analytics[e.EXTENSION]["google-analytics"].secret,message:"Enter your Google Analytics secret"}],{onCancel:i});case c[e.EXTENSION].POSTHOG:return G([{type:"text",name:n.env.analytics[e.EXTENSION].posthog.key,message:"Enter your PostHog key"},{type:"text",name:n.env.analytics[e.EXTENSION].posthog.host,message:"Enter your PostHog host",initial:"https://us.posthog.com"}],{onCancel:i})}},V=async()=>{let{provider:t}=await he(),o=await be(t);return{provider:t,env:o}};import X from"prompts";var Ne=async()=>X([{type:"select",choices:Object.values(c[e.MOBILE]).map(t=>({title:g(t),value:t})),name:"provider",message:"What do you want to use for mobile analytics?"}],{onCancel:i}),xe=async t=>{switch(t){case c[e.MOBILE].GOOGLE_ANALYTICS:return l.info("Check how to configure Google Analytics for mobile at https://www.turbostarter.dev/docs/mobile/analytics/configuration#google-analytics"),{};case c[e.MOBILE].MIXPANEL:return X([{type:"text",name:n.env.analytics[e.MOBILE].mixpanel.token,message:"Enter your Mixpanel token"}],{onCancel:i});case c[e.MOBILE].POSTHOG:return X([{type:"text",name:n.env.analytics[e.MOBILE].posthog.key,message:"Enter your PostHog key"},{type:"text",name:n.env.analytics[e.MOBILE].posthog.host,message:"Enter your PostHog host",initial:"https://us.posthog.com"}],{onCancel:i})}},q=async()=>{let{provider:t}=await Ne(),o=await xe(t);return{provider:t,env:o}};import O from"prompts";var Te=async()=>O([{type:"select",choices:Object.values(c[e.WEB]).map(t=>({title:g(t),value:t})),name:"provider",message:"What do you want to use for web analytics?"}],{onCancel:i}),we=async t=>{switch(t){case c[e.WEB].GOOGLE_ANALYTICS:return O([{type:"text",name:n.env.analytics[e.WEB]["google-analytics"].measurementId,message:"Enter your Google Analytics measurement ID"},{type:"text",name:n.env.analytics[e.WEB]["google-analytics"].secret,message:"Enter your Google Analytics secret"}],{onCancel:i});case c[e.WEB].MIXPANEL:return O([{type:"text",name:n.env.analytics[e.WEB].mixpanel.token,message:"Enter your Mixpanel token"}],{onCancel:i});case c[e.WEB].OPEN_PANEL:return O([{type:"text",name:n.env.analytics[e.WEB]["open-panel"].clientId,message:"Enter your OpenPanel client ID"},{type:"text",name:n.env.analytics[e.WEB]["open-panel"].secret,message:"Enter your OpenPanel secret"}],{onCancel:i});case c[e.WEB].PLAUSIBLE:return O([{type:"text",name:n.env.analytics[e.WEB].plausible.domain,message:"Enter your Plausible domain"},{type:"text",name:n.env.analytics[e.WEB].plausible.host,message:"Enter your Plausible host",initial:"https://plausible.io"}],{onCancel:i});case c[e.WEB].POSTHOG:return O([{type:"text",name:n.env.analytics[e.WEB].posthog.key,message:"Enter your PostHog key"},{type:"text",name:n.env.analytics[e.WEB].posthog.host,message:"Enter your PostHog host",initial:"https://us.posthog.com"}],{onCancel:i});case c[e.WEB].UMAMI:return O([{type:"text",name:n.env.analytics[e.WEB].umami.host,message:"Enter your Umami host",initial:"https://cloud.umami.is"},{type:"text",name:n.env.analytics[e.WEB].umami.websiteId,message:"Enter your Umami website ID"},{type:"text",name:n.env.analytics[e.WEB].umami.apiHost,message:"Enter your Umami API host",initial:"https://api-gateway.umami.dev"},{type:"text",name:n.env.analytics[e.WEB].umami.apiKey,message:"Enter your Umami API key"}],{onCancel:i});case c[e.WEB].VEMETRIC:return O([{type:"text",name:n.env.analytics[e.WEB].vemetric.token,message:"Enter your Vemetric project token"}],{onCancel:i});case c[e.WEB].VERCEL:return{}}},Z=async()=>{let{provider:t}=await Te(),o=await we(t);return{provider:t,env:o}};var Q=async t=>{let o={},s={};if(t.includes(e.WEB)){let{provider:a,env:p}=await Z();o[e.WEB]=a,Object.assign(s,p)}if(t.includes(e.MOBILE)){let{provider:a,env:p}=await q();o[e.MOBILE]=a,Object.assign(s,p)}if(t.includes(e.EXTENSION)){let{provider:a,env:p}=await V();o[e.EXTENSION]=a,Object.assign(s,p)}return{providers:o,env:s}};import M from"prompts";var Ae=async()=>M([{type:"select",choices:Object.values(u).map(t=>({title:g(t),value:t})),name:"provider",message:"What do you want to use for billing?"}],{onCancel:i}),Le=async t=>{switch(t){case u.STRIPE:return M([{type:"text",name:n.env.billing.stripe.secretKey,message:"Enter your Stripe secret key"},{type:"text",name:n.env.billing.stripe.webhookSecret,message:"Enter your Stripe webhook secret"}],{onCancel:i});case u.LEMON_SQUEEZY:return M([{type:"text",name:n.env.billing["lemon-squeezy"].storeId,message:"Enter your Lemon Squeezy store ID"},{type:"text",name:n.env.billing["lemon-squeezy"].apiKey,message:"Enter your Lemon Squeezy API key"},{type:"text",name:n.env.billing["lemon-squeezy"].signingSecret,message:"Enter your Lemon Squeezy signing secret"}],{onCancel:i});case u.POLAR:return M([{type:"text",name:n.env.billing.polar.accessToken,message:"Enter your Polar access token"},{type:"text",name:n.env.billing.polar.webhookSecret,message:"Enter your Polar webhook secret"},{type:"text",name:n.env.billing.polar.organizationSlug,message:"Enter your Polar organization slug"}],{onCancel:i})}},J=async()=>{let{provider:t}=await Ae(),o=await Le(t);return{provider:t,env:o}};import ee from"prompts";var Be=async()=>ee([{type:"text",name:n.env.db.url,message:"Enter your database URL"}],{onCancel:i}),te=async()=>{let t=await ee([{type:"select",name:"type",message:"How do you want to use database?",choices:[{title:"Local (powered by Docker)",value:h.LOCAL,selected:!0},{title:"Cloud",value:h.CLOUD}]}],{onCancel:i});if(t.type===h.CLOUD){let o=await Be();return{...t,env:o}}return t};import b from"prompts";var _e=async()=>b([{type:"select",name:"provider",message:"What do you want to use for emails?",choices:Object.values(y).map(t=>({title:g(t),value:t}))}],{onCancel:i}),Me=async t=>{switch(t){case y.RESEND:return b([{type:"text",name:n.env.email.resend.apiKey,message:"Enter your Resend API key"}],{onCancel:i});case y.SENDGRID:return b([{type:"text",name:n.env.email.sendgrid.apiKey,message:"Enter your Sendgrid API key"}],{onCancel:i});case y.PLUNK:return b([{type:"text",name:n.env.email.plunk.apiKey,message:"Enter your Plunk API key"}],{onCancel:i});case y.POSTMARK:return b([{type:"text",name:n.env.email.postmark.apiKey,message:"Enter your Postmark API key"}],{onCancel:i});case y.NODEMAILER:return b([{type:"text",name:n.env.email.nodemailer.user,message:"Enter your Nodemailer user"},{type:"text",name:n.env.email.nodemailer.password,message:"Enter your Nodemailer user password"},{type:"text",name:n.env.email.nodemailer.host,message:"Enter your Nodemailer host"},{type:"number",name:n.env.email.nodemailer.port,message:"Enter your Nodemailer port"}],{onCancel:i})}},oe=async()=>{let{provider:t}=await _e(),o=await Me(t);return{provider:t,env:o}};import{promises as C}from"fs";import j from"lodash";import Ce from"ora";import{join as w}from"path";var ne=async t=>{try{await Promise.allSettled(Object.values(I).map(async o=>{let s=w(t,o);await C.copyFile(w(s,B.EXAMPLE),w(s,B.LOCAL))}))}catch{l.error("Failed to prepare environment!"),process.exit(1)}},ke=async(t,o,s)=>{if(!s)return;let a=j.keys(j.pickBy(Y,p=>j.includes(p,o)));for(let p of a){let f=w(t,p),E=w(f,B.LOCAL),x=await C.readFile(E,"utf8"),T=new RegExp(`^${o}=.*`,"gm");T.test(x)?await C.writeFile(E,x.replace(T,`${o}="${s}"`)):await C.appendFile(E,`
|
|
3
|
+
${o}="${s}"`)}},ie=async(t,o)=>{let s=Ce("Setting environment variables...").start();try{for(let[a,p]of Object.entries(o))await ke(t,a,p);s.succeed("Environment variables successfully set!")}catch{l.error("Failed to set environment variables!"),process.exit(1)}};import K from"prompts";var We=async()=>K([{type:"select",choices:Object.values(m[e.EXTENSION]).map(t=>({title:g(t),value:t})),name:"provider",message:"What do you want to use for extension monitoring?"}],{onCancel:i}),Re=async t=>{switch(t){case m[e.EXTENSION].SENTRY:return K([{type:"text",name:n.env.monitoring[e.EXTENSION].sentry.dsn,message:"Enter your Sentry DSN"}],{onCancel:i});case m[e.EXTENSION].POSTHOG:return K([{type:"text",name:n.env.monitoring[e.EXTENSION].posthog.key,message:"Enter your PostHog key"},{type:"text",name:n.env.monitoring[e.EXTENSION].posthog.host,message:"Enter your PostHog host",initial:"https://us.posthog.com"}],{onCancel:i})}},re=async()=>{let{provider:t}=await We(),o=await Re(t);return{provider:t,env:o}};import D from"prompts";var Ge=async()=>D([{type:"select",choices:Object.values(m[e.MOBILE]).map(t=>({title:g(t),value:t})),name:"provider",message:"What do you want to use for mobile monitoring?"}],{onCancel:i}),Xe=async t=>{switch(t){case m[e.MOBILE].SENTRY:return D([{type:"text",name:n.env.monitoring[e.MOBILE].sentry.dsn,message:"Enter your Sentry DSN"}],{onCancel:i});case m[e.MOBILE].POSTHOG:return D([{type:"text",name:n.env.monitoring[e.MOBILE].posthog.key,message:"Enter your PostHog key"},{type:"text",name:n.env.monitoring[e.MOBILE].posthog.host,message:"Enter your PostHog host",initial:"https://us.posthog.com"}],{onCancel:i})}},se=async()=>{let{provider:t}=await Ge(),o=await Xe(t);return{provider:t,env:o}};import H from"prompts";var je=async()=>H([{type:"select",choices:Object.values(m[e.WEB]).map(t=>({title:g(t),value:t})),name:"provider",message:"What do you want to use for web monitoring?"}],{onCancel:i}),Ke=async t=>{switch(t){case m[e.WEB].SENTRY:return H([{type:"text",name:n.env.monitoring[e.WEB].sentry.dsn,message:"Enter your Sentry DSN"}],{onCancel:i});case m[e.WEB].POSTHOG:return H([{type:"text",name:n.env.monitoring[e.WEB].posthog.key,message:"Enter your PostHog key"},{type:"text",name:n.env.monitoring[e.WEB].posthog.host,message:"Enter your PostHog host",initial:"https://us.posthog.com"}],{onCancel:i})}},ae=async()=>{let{provider:t}=await je(),o=await Ke(t);return{provider:t,env:o}};var ce=async t=>{let o={},s={};if(t.includes(e.WEB)){let{provider:a,env:p}=await ae();o[e.WEB]=a,Object.assign(s,p)}if(t.includes(e.MOBILE)){let{provider:a,env:p}=await se();o[e.MOBILE]=a,Object.assign(s,p)}if(t.includes(e.EXTENSION)){let{provider:a,env:p}=await re();o[e.EXTENSION]=a,Object.assign(s,p)}return{providers:o,env:s}};import pe from"prompts";var De=async()=>pe([{type:"select",choices:Object.values(L).map(t=>({title:g(t),value:t})),name:"provider",message:"What do you want to use for storage?"}],{onCancel:i}),He=()=>pe([{type:"text",name:n.env.storage.s3.region,message:"Enter your S3 region",initial:"us-east-1"},{type:"text",name:n.env.storage.s3.endpoint,message:"Enter your S3 endpoint",initial:"https://s3.amazonaws.com"},{type:"text",name:n.env.storage.s3.bucket,message:"Enter your default S3 bucket name"},{type:"text",name:n.env.storage.s3.accessKeyId,message:"Enter your S3 access key ID"},{type:"text",name:n.env.storage.s3.secretAccessKey,message:"Enter your S3 secret access key"}],{onCancel:i}),le=async()=>{let{provider:t}=await De(),o=await He();return{provider:t,env:o}};import{execa as Ee}from"execa";import ze from"ora";import{execa as A}from"execa";import Ue from"ora";import k from"picocolors";var Ye=async()=>{try{await A("node",["--version"])}catch{l.error(`Node.js is not installed. Please install Node.js and try again.
|
|
4
|
+
`),l.info(`To install Node.js, visit: ${k.underline("https://nodejs.org/en/")}`),process.exit(1)}},Fe=async()=>{try{await A("pnpm",["--version"])}catch{try{await A("npm",["install","-g","pnpm"])}catch{l.error(`pnpm is not installed. Please install pnpm manually and try again.
|
|
5
|
+
`),l.info(`To install pnpm, visit: ${k.underline("https://pnpm.io/installation")}`),process.exit(1)}}},me=async()=>{try{await A("docker",["--version"])}catch{l.error("Docker is not installed. Please install Docker and try again."),l.info(`To install Docker, visit: ${k.underline("https://docs.docker.com/get-docker/")}`),process.exit(1)}},$e=async()=>{try{await A("git",["--version"])}catch{l.error("Git is not installed. Please install Git and try again."),l.info(`To install Git, visit: ${k.underline("https://git-scm.com/downloads")}`),process.exit(1)}},ge=async()=>{let t=Ue(`Checking prerequisites...
|
|
6
|
+
`).start();try{await $e(),await Ye(),await Fe(),t.succeed(`All prerequisites are satisfied, let's start! \u{1F680}
|
|
7
|
+
`)}catch{t.fail("Failed to check prerequisites."),process.exit(1)}};var ye=async(t,o)=>{await me();let s=ze("Starting Docker services...").start();try{await Ee("pnpm",["services:start","--",...o],{cwd:t}),await Ee("pnpm",["with-env","pnpm","turbo","setup",o.map(a=>`--filter=${$[a]}`).join(" ")],{cwd:t}),s.succeed("Services successfully started!")}catch(a){console.error(a),s.fail("Failed to start services!"),process.exit(1)}};import{promises as de}from"fs";import{join as Ve}from"path";var qe=async({cwd:t,path:o,pattern:s,value:a})=>{let p=Ve(t,o),E=(await de.readFile(p,"utf8")).replace(s,a);await de.writeFile(p,E)},N=async({cwd:t,paths:o,pattern:s,value:a})=>{await Promise.all(o.map(async p=>{await qe({cwd:t,path:p,pattern:s,value:a})}))};var Je=ue.object({cwd:ue.string()}),Oe=new Ze().name("new").description("create a new TurboStarter project").option("-c, --cwd <cwd>","the working directory. defaults to the current directory.",process.cwd()).action(async t=>{try{l.log(`${P.bgRedBright(P.white(" TurboStarter "))}
|
|
8
|
+
`);let o=Je.parse({cwd:Qe.resolve(t.cwd)}),{name:s}=await et(o);l.log(`
|
|
9
9
|
\u{1F389} You can now get started. Open the project and just ship it! \u{1F389}
|
|
10
|
-
`),
|
|
10
|
+
`),l.log(`> cd ${s}
|
|
11
|
+
> pnpm dev
|
|
12
|
+
`),l.info(`Problems? ${P.underline("https://turbostarter.dev/docs")}`)}catch(o){l.break(),z(o)}}),et=async t=>{await ge();let o=await tt(),s=await ot();l.info(`
|
|
13
|
+
Let's configure it!
|
|
14
|
+
You can skip any step by pressing ${P.bold("enter")}.
|
|
15
|
+
`);let a=await te(),p=await J(),f=await oe(),E=await le(),x=await Q(s),T=await ce(s),Se={..."env"in a?a.env:{},...p.env,...f.env,...E.env,...x.env,...T.env};l.log(`
|
|
16
|
+
Creating a new TurboStarter project in ${P.greenBright(ve(t.cwd,o))}.
|
|
17
|
+
`);let S=await it(t.cwd,o,s);await ne(S),await at(S,{billing:p.provider,email:f.provider,storage:E.provider,analytics:x.providers,monitoring:T.providers}),await ie(S,Se),await rt(S),await st(S);let U=[...a.type===h.LOCAL?[R.DB]:[]];return U.length>0&&await ye(S,U),{name:o,apps:s}},tt=async()=>{let t=await fe({type:"text",name:"name",message:"Enter your project name.",validate:o=>o.length>0?!0:"Name is required!"},{onCancel:i});return String(t.name)},ot=async()=>{for(;;){let o=(await fe({type:"multiselect",name:"apps",message:"What do you want to ship?",instructions:!1,choices:[{title:"Web app",value:e.WEB,selected:!0},{title:"Mobile app",value:e.MOBILE,selected:!1},{title:"Browser extension",value:e.EXTENSION,selected:!1}],hint:`You ${P.bold("must")} ship a web app, to ensure backend services work.`},{onCancel:i})).apps;if(o.includes(e.WEB))return o;l.error(`You ${P.bold("must")} ship a web app, to ensure backend services work.`)}},nt=async t=>{try{return await v("ssh",["-T","git@github.com"],{timeout:5e3}),t.replace("https://github.com/","git@github.com:")}catch{return t}},it=async(t,o,s)=>{let a=W(`Cloning repository into ${o}...`).start(),p=ve(t,o),f=Object.values(e).filter(E=>!s.includes(E)).map(E=>F[E]).flat();try{let E=await nt(n.repository);return await v("git",["clone","-b","main","--single-branch",E,o],{cwd:t}),f.length&&await v("rm",["-rf",...f],{cwd:p}),a.succeed("Repository successfully pulled!"),p}catch{a.fail("Failed to clone TurboStarter! Please try again."),process.exit(1)}},rt=async t=>{let o=W("Configuring Git...").start();try{await v("rm",["-rf",".git"],{cwd:t}),await v("git",["init"],{cwd:t}),await v("git",["remote","add","upstream",n.repository],{cwd:t}),await v("git",["add","."],{cwd:t}),await v("git",["commit","-m","Initial commit"],{cwd:t}),o.succeed("Git successfully configured!")}catch{o.fail("Failed to configure Git! Please try again."),process.exit(1)}},st=async t=>{let o=W("Installing dependencies...").start();try{await v("pnpm",["install"],{cwd:t}),o.succeed("Dependencies successfully installed!")}catch{o.fail("Failed to install dependencies! Please try again."),process.exit(1)}},at=async(t,o)=>{let s=W("Updating providers files...").start();try{o.billing&&await N({cwd:t,paths:d.billing.files,pattern:d.billing.pattern,value:o.billing}),o.email&&await N({cwd:t,paths:d.email.files,pattern:d.email.pattern,value:o.email}),o.storage&&await N({cwd:t,paths:d.storage.files,pattern:d.storage.pattern,value:o.storage}),o.analytics&&Object.keys(o.analytics).length>0&&await Promise.all(Object.entries(o.analytics).map(([a,p])=>N({cwd:t,paths:d.analytics[a].files,pattern:d.analytics[a].pattern,value:p}))),o.monitoring&&Object.keys(o.monitoring).length>0&&await Promise.all(Object.entries(o.monitoring).map(([a,p])=>N({cwd:t,paths:d.monitoring[a].files,pattern:d.monitoring[a].pattern,value:p}))),s.succeed("Providers files successfully updated!")}catch{s.fail("Failed to update providers files! Please try again."),process.exit(1)}};var Pe={name:"@turbostarter/cli",version:"1.2.0",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",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:"Your TurboStarter assistant for starting new projects, adding plugins and more.",devDependencies:{"@changesets/changelog-github":"^0.5.1","@changesets/cli":"^2.29.2","@eslint/compat":"1.4.0","@types/lodash":"4.17.12","@types/node":"22.7.5","@types/prompts":"^2.4.2",eslint:"9.37.0","eslint-plugin-import":"2.31.0","eslint-plugin-unused-imports":"4.1.4",prettier:"3.3.3",tsup:"8.3.0",typescript:"5.9.2","typescript-eslint":"8.46.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@10.18.2"};process.on("SIGINT",()=>process.exit(0));process.on("SIGTERM",()=>process.exit(0));function lt(){let t=new pt().name("turbostarter").description("Your TurboStarter assistant for starting new projects, adding plugins and more.").version(Pe.version||"1.0.0","-v, --version","display the version number");t.addCommand(Oe),t.parse()}lt();
|
|
11
18
|
//# 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/db.ts","../src/commands/new/config/email.ts","../src/commands/new/config/env.ts","../src/commands/new/config/storage.ts","../src/commands/new/services.ts","../src/commands/new/prerequisites.ts","../src/utils/file.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 { getDatabaseConfig } from \"~/commands/new/config/db\";\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 { startServices } from \"~/commands/new/services\";\nimport {\n App,\n appSpecificFiles,\n config,\n providerConfigFiles,\n Service,\n ServiceType,\n} from \"~/config\";\nimport { handleError, logger, onCancel } from \"~/utils\";\nimport { replaceInFiles } from \"~/utils/file\";\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 dbConfig = await getDatabaseConfig();\n const billingConfig = await getBillingConfig();\n const emailConfig = await getEmailConfig();\n const storageConfig = await getStorageConfig();\n\n const env = {\n ...(\"env\" in dbConfig ? dbConfig.env : {}),\n ...billingConfig.env,\n ...emailConfig.env,\n ...storageConfig.env,\n };\n\n const projectDir = await cloneRepository(\n options.cwd,\n global.name,\n global.apps,\n );\n await prepareEnvironment(projectDir);\n await updateProvidersFiles(projectDir, {\n billing: billingConfig.provider,\n email: emailConfig.provider,\n storage: storageConfig.provider,\n });\n await setEnvironmentVariables(projectDir, env);\n await configureGit(projectDir);\n await installDependencies(projectDir);\n\n const localServices = [\n ...(dbConfig.type === ServiceType.LOCAL ? [Service.DB] : []),\n ];\n\n if (localServices.length > 0) {\n await startServices(projectDir, localServices);\n }\n};\n\nconst getRepositoryUrl = async (httpsUrl: string): Promise<string> => {\n try {\n await execa(\"ssh\", [\"-T\", \"git@github.com\"], { timeout: 5000 });\n return httpsUrl.replace(\"https://github.com/\", \"git@github.com:\");\n } catch {\n return httpsUrl;\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 const url = await getRepositoryUrl(config.repository);\n await execa(\"git\", [\"clone\", \"-b\", \"main\", \"--single-branch\", url, name], {\n cwd,\n });\n\n if (filesToRemove.length) {\n await execa(\"rm\", [\"-rf\", ...filesToRemove], { cwd: projectDir });\n }\n\n spinner.succeed(\"Repository successfully pulled!\");\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\nconst updateProvidersFiles = async (\n cwd: string,\n providers: Record<keyof typeof providerConfigFiles, string>,\n) => {\n const spinner = ora(`Updating providers files...`).start();\n\n try {\n await Promise.all(\n Object.entries(providers).map(([key, value]) => {\n const provider = key as keyof typeof providerConfigFiles;\n return replaceInFiles({\n cwd,\n paths: providerConfigFiles[provider].files,\n pattern: providerConfigFiles[provider].pattern,\n value,\n });\n }),\n );\n\n spinner.succeed(\"Providers files successfully updated!\");\n } catch {\n spinner.fail(\"Failed to update providers files! 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 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: \"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[\"lemon-squeezy\"].storeId,\n message: \"Enter your Lemon Squeezy store ID\",\n },\n {\n type: \"text\",\n name: config.env.billing[\"lemon-squeezy\"].apiKey,\n message: \"Enter your Lemon Squeezy API key\",\n },\n {\n type: \"text\",\n name: config.env.billing[\"lemon-squeezy\"].signingSecret,\n message: \"Enter your Lemon Squeezy signing secret\",\n },\n ],\n {\n onCancel,\n },\n );\n case BillingProvider.POLAR:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.billing.polar.accessToken,\n message: \"Enter your Polar access token\",\n },\n {\n type: \"text\",\n name: config.env.billing.polar.webhookSecret,\n message: \"Enter your Polar webhook secret\",\n },\n {\n type: \"text\",\n name: config.env.billing.polar.organizationSlug,\n message: \"Enter your Polar organization slug\",\n },\n ],\n {\n onCancel,\n },\n );\n }\n};\n\nexport const getBillingConfig = async () => {\n const { provider } = await getBillingProvider();\n const env = await getBillingProviderConfig(provider);\n\n return { provider, env };\n};\n","export const ServiceType = {\n LOCAL: \"local\",\n CLOUD: \"cloud\",\n} as const;\n\nexport const Service = {\n DB: \"db\",\n};\n\nexport const StorageProvider = {\n S3: \"s3\",\n} as const;\n\nexport const BillingProvider = {\n STRIPE: \"stripe\",\n LEMON_SQUEEZY: \"lemon-squeezy\",\n POLAR: \"polar\",\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} 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 ServiceType = (typeof ServiceType)[keyof typeof ServiceType];\nexport type Service = (typeof Service)[keyof typeof Service];\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 billing: {\n [BillingProvider.STRIPE]: {\n secretKey: \"STRIPE_SECRET_KEY\",\n webhookSecret: \"STRIPE_WEBHOOK_SECRET\",\n },\n [BillingProvider.LEMON_SQUEEZY]: {\n apiKey: \"LEMON_SQUEEZY_API_KEY\",\n signingSecret: \"LEMON_SQUEEZY_SIGNING_SECRET\",\n storeId: \"LEMON_SQUEEZY_STORE_ID\",\n },\n [BillingProvider.POLAR]: {\n accessToken: \"POLAR_ACCESS_TOKEN\",\n webhookSecret: \"POLAR_WEBHOOK_SECRET\",\n organizationSlug: \"POLAR_ORGANIZATION_SLUG\",\n },\n },\n email: {\n [EmailProvider.RESEND]: {\n apiKey: \"RESEND_API_KEY\",\n },\n [EmailProvider.SENDGRID]: {\n apiKey: \"SENDGRID_API_KEY\",\n },\n [EmailProvider.PLUNK]: {\n apiKey: \"PLUNK_API_KEY\",\n },\n [EmailProvider.POSTMARK]: {\n apiKey: \"POSTMARK_API_KEY\",\n },\n [EmailProvider.NODEMAILER]: {\n user: \"NODEMAILER_USER\",\n password: \"NODEMAILER_PASSWORD\",\n host: \"NODEMAILER_HOST\",\n port: \"NODEMAILER_PORT\",\n },\n },\n storage: {\n [StorageProvider.S3]: {\n region: \"S3_REGION\",\n bucket: \"S3_BUCKET\",\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],\n [EnvPath.WEB]: [\n env.billing.stripe.secretKey,\n env.billing.stripe.webhookSecret,\n env.billing[\"lemon-squeezy\"].apiKey,\n env.billing[\"lemon-squeezy\"].signingSecret,\n env.billing[\"lemon-squeezy\"].storeId,\n env.billing.polar.accessToken,\n env.billing.polar.webhookSecret,\n env.billing.polar.organizationSlug,\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.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 providerConfigFiles = {\n billing: {\n files: [\n \"packages/billing/src/providers/index.ts\",\n \"packages/billing/src/providers/env.ts\",\n ],\n pattern: new RegExp(`(${Object.values(BillingProvider).join(\"|\")})`, \"gi\"),\n },\n email: {\n files: [\n \"packages/email/src/providers/index.ts\",\n \"packages/email/src/providers/env.ts\",\n ],\n pattern: new RegExp(`(${Object.values(EmailProvider).join(\"|\")})`, \"gi\"),\n },\n storage: {\n files: [\n \"packages/storage/src/providers/index.ts\",\n \"packages/storage/src/providers/env.ts\",\n ],\n pattern: new RegExp(`(${Object.values(StorageProvider).join(\"|\")})`, \"gi\"),\n },\n};\n\nexport const servicesPackages: Record<Service, string> = {\n [Service.DB]: \"@turbostarter/db\",\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 { config, ServiceType } from \"~/config\";\nimport { onCancel } from \"~/utils\";\n\nconst getDatabaseCloudConfig = async () => {\n return prompts(\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 getDatabaseConfig = async () => {\n const response = await prompts(\n [\n {\n type: \"select\",\n name: \"type\",\n message: \"How do you want to use database?\",\n choices: [\n {\n title: \"Local (powered by Docker)\",\n value: ServiceType.LOCAL,\n selected: true,\n },\n {\n title: `Cloud`,\n value: ServiceType.CLOUD,\n },\n ],\n },\n ],\n {\n onCancel,\n },\n );\n\n if (response.type === ServiceType.CLOUD) {\n const dbConfig = await getDatabaseCloudConfig();\n\n return { ...response, env: dbConfig };\n }\n\n return response;\n};\n","import prompts from \"prompts\";\n\nimport { EmailProvider, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getEmailProvider = async (): Promise<{\n provider: EmailProvider;\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n name: \"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 env = await getEmailProviderConfig(provider);\n\n return { provider, env };\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 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: \"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 initial: \"us-east-1\",\n },\n {\n type: \"text\",\n name: config.env.storage.s3.endpoint,\n message: \"Enter your S3 endpoint\",\n initial: \"https://s3.amazonaws.com\",\n },\n {\n type: \"text\",\n name: config.env.storage.s3.bucket,\n message: \"Enter your default S3 bucket name\",\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 env = await getStorageProviderConfig();\n\n return { provider, env };\n};\n","import { execa } from \"execa\";\nimport ora from \"ora\";\n\nimport { validateDockerInstalled } from \"~/commands/new/prerequisites\";\nimport { servicesPackages } from \"~/config\";\n\nimport type { Service } from \"~/config\";\n\nexport const startServices = async (cwd: string, services: Service[]) => {\n await validateDockerInstalled();\n\n const spinner = ora(`Starting Docker services...`).start();\n\n try {\n await execa(\"pnpm\", [\"services:start\", \"--\", ...services], { cwd });\n await execa(\n \"pnpm\",\n [\n \"with-env\",\n \"pnpm\",\n \"turbo\",\n \"setup\",\n services\n .map((service) => `--filter=${servicesPackages[service]}`)\n .join(\" \"),\n ],\n { cwd },\n );\n\n spinner.succeed(\"Services successfully started!\");\n } catch (error) {\n console.error(error);\n spinner.fail(\"Failed to start services!\");\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","import { promises } from \"fs\";\nimport { join } from \"path\";\n\nexport const replaceInFile = async ({\n cwd,\n path,\n pattern,\n value,\n}: {\n cwd: string;\n path: string;\n pattern: RegExp | string;\n value: string;\n}) => {\n const fullPath = join(cwd, path);\n const content = await promises.readFile(fullPath, \"utf8\");\n const newContent = content.replace(pattern, value);\n await promises.writeFile(fullPath, newContent);\n};\n\nexport const replaceInFiles = async ({\n cwd,\n paths,\n pattern,\n value,\n}: {\n cwd: string;\n paths: string[];\n pattern: RegExp | string;\n value: string;\n}) => {\n await Promise.all(\n paths.map(async (path) => {\n await replaceInFile({ cwd, path, pattern, value });\n }),\n );\n};\n","{\n \"name\": \"@turbostarter/cli\",\n \"version\": \"1.0.7\",\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 \"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\": \"Your TurboStarter assistant for starting new projects, adding plugins and more.\",\n \"devDependencies\": {\n \"@changesets/changelog-github\": \"^0.5.1\",\n \"@changesets/cli\": \"^2.29.2\",\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","ServiceType","Service","StorageProvider","BillingProvider","EmailProvider","EnvPath","EnvFile","App","env","envInPaths","appSpecificFiles","providerConfigFiles","servicesPackages","config","_","colors","logger","log","handleError","error","logger","getLabel","value","word","_","onCancel","logger","getBillingProvider","prompts","BillingProvider","provider","getLabel","onCancel","getBillingProviderConfig","config","getBillingConfig","env","prompts","getDatabaseCloudConfig","prompts","config","onCancel","getDatabaseConfig","response","ServiceType","dbConfig","prompts","getEmailProvider","prompts","EmailProvider","provider","getLabel","onCancel","getEmailProviderConfig","config","getEmailConfig","env","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","onCancel","getStorageProviderConfig","config","getStorageConfig","env","execa","ora","execa","ora","color","validateNodeInstalled","execa","logger","color","validatePnpmInstalled","validateDockerInstalled","validateGitInstalled","validatePrerequisites","spinner","ora","startServices","cwd","services","validateDockerInstalled","spinner","ora","execa","service","servicesPackages","error","promises","join","replaceInFile","cwd","path","pattern","value","fullPath","newContent","replaceInFiles","paths","newOptionsSchema","z","newCommand","Command","opts","logger","color","options","path","initializeProject","error","handleError","validatePrerequisites","global","prompts","App","value","onCancel","dbConfig","getDatabaseConfig","billingConfig","getBillingConfig","emailConfig","getEmailConfig","storageConfig","getStorageConfig","env","projectDir","cloneRepository","prepareEnvironment","updateProvidersFiles","setEnvironmentVariables","configureGit","installDependencies","localServices","ServiceType","Service","startServices","getRepositoryUrl","httpsUrl","execa","cwd","name","apps","spinner","ora","join","filesToRemove","app","appSpecificFiles","url","config","providers","key","provider","replaceInFiles","providerConfigFiles","package_default","main","program","Command","package_default","newCommand"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/new/index.ts","../src/config.ts","../src/commands/new/config/analytics/extension.ts","../src/utils/index.ts","../src/utils/logger.ts","../src/utils/handle-error.ts","../src/commands/new/config/analytics/mobile.ts","../src/commands/new/config/analytics/web.ts","../src/commands/new/config/analytics/index.ts","../src/commands/new/config/billing.ts","../src/commands/new/config/db.ts","../src/commands/new/config/email.ts","../src/commands/new/config/env.ts","../src/commands/new/config/monitoring/extension.ts","../src/commands/new/config/monitoring/mobile.ts","../src/commands/new/config/monitoring/web.ts","../src/commands/new/config/monitoring/index.ts","../src/commands/new/config/storage.ts","../src/commands/new/services.ts","../src/commands/new/prerequisites.ts","../src/utils/file.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 { getAnalyticsConfig } from \"~/commands/new/config/analytics\";\nimport { getBillingConfig } from \"~/commands/new/config/billing\";\nimport { getDatabaseConfig } from \"~/commands/new/config/db\";\nimport { getEmailConfig } from \"~/commands/new/config/email\";\nimport {\n prepareEnvironment,\n setEnvironmentVariables,\n} from \"~/commands/new/config/env\";\nimport { getMonitoringConfig } from \"~/commands/new/config/monitoring\";\nimport { getStorageConfig } from \"~/commands/new/config/storage\";\nimport { startServices } from \"~/commands/new/services\";\nimport {\n App,\n appSpecificFiles,\n config,\n providerConfigFiles,\n Service,\n ServiceType,\n} from \"~/config\";\nimport { handleError, logger, onCancel } from \"~/utils\";\nimport { replaceInFiles } from \"~/utils/file\";\n\nimport { validatePrerequisites } from \"./prerequisites\";\n\nimport type {\n AnalyticsProvider,\n BillingProvider,\n EmailProvider,\n MonitoringProvider,\n StorageProvider,\n} from \"~/config\";\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.bgRedBright(color.white(\" TurboStarter \"))}\\n`);\n\n const options = newOptionsSchema.parse({\n cwd: path.resolve(opts.cwd),\n });\n\n const { name } = await initializeProject(options);\n\n logger.log(\n `\\n🎉 You can now get started. Open the project and just ship it! 🎉\\n`,\n );\n logger.log(`> cd ${name}\\n> pnpm dev\\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 name = await getName();\n const apps = await getApps();\n\n logger.info(\n `\\nLet's configure it!\\nYou can skip any step by pressing ${color.bold(\"enter\")}.\\n`,\n );\n\n const dbConfig = await getDatabaseConfig();\n const billingConfig = await getBillingConfig();\n const emailConfig = await getEmailConfig();\n const storageConfig = await getStorageConfig();\n const analyticsConfig = await getAnalyticsConfig(apps);\n const monitoringConfig = await getMonitoringConfig(apps);\n\n const env = {\n ...(\"env\" in dbConfig ? dbConfig.env : {}),\n ...billingConfig.env,\n ...emailConfig.env,\n ...storageConfig.env,\n ...analyticsConfig.env,\n ...monitoringConfig.env,\n };\n\n logger.log(\n `\\nCreating a new TurboStarter project in ${color.greenBright(join(options.cwd, name))}. \\n`,\n );\n\n const projectDir = await cloneRepository(options.cwd, name, apps);\n await prepareEnvironment(projectDir);\n await updateProvidersFiles(projectDir, {\n billing: billingConfig.provider,\n email: emailConfig.provider,\n storage: storageConfig.provider,\n analytics: analyticsConfig.providers,\n monitoring: monitoringConfig.providers,\n });\n await setEnvironmentVariables(projectDir, env);\n await configureGit(projectDir);\n await installDependencies(projectDir);\n\n const localServices = [\n ...(dbConfig.type === ServiceType.LOCAL ? [Service.DB] : []),\n ];\n\n if (localServices.length > 0) {\n await startServices(projectDir, localServices);\n }\n\n return { name, apps };\n};\n\nconst getName = async () => {\n const result = await prompts(\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 onCancel,\n },\n );\n\n return String(result.name);\n};\n\nconst getApps = async () => {\n while (true) {\n const result = await prompts(\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 onCancel,\n },\n );\n\n const apps = result.apps as App[];\n\n if (apps.includes(App.WEB)) {\n return apps;\n } else {\n logger.error(\n `You ${color.bold(\"must\")} ship a web app, to ensure backend services work.`,\n );\n }\n }\n};\n\nconst getRepositoryUrl = async (httpsUrl: string): Promise<string> => {\n try {\n await execa(\"ssh\", [\"-T\", \"git@github.com\"], { timeout: 5000 });\n return httpsUrl.replace(\"https://github.com/\", \"git@github.com:\");\n } catch {\n return httpsUrl;\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 const url = await getRepositoryUrl(config.repository);\n await execa(\"git\", [\"clone\", \"-b\", \"main\", \"--single-branch\", url, name], {\n cwd,\n });\n\n if (filesToRemove.length) {\n await execa(\"rm\", [\"-rf\", ...filesToRemove], { cwd: projectDir });\n }\n\n spinner.succeed(\"Repository successfully pulled!\");\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\nconst updateProvidersFiles = async (\n cwd: string,\n providers: {\n billing?: BillingProvider;\n email?: EmailProvider;\n storage?: StorageProvider;\n analytics?: Partial<AnalyticsProvider>;\n monitoring?: Partial<MonitoringProvider>;\n },\n) => {\n const spinner = ora(`Updating providers files...`).start();\n\n try {\n if (providers.billing) {\n await replaceInFiles({\n cwd,\n paths: providerConfigFiles.billing.files,\n pattern: providerConfigFiles.billing.pattern,\n value: providers.billing,\n });\n }\n if (providers.email) {\n await replaceInFiles({\n cwd,\n paths: providerConfigFiles.email.files,\n pattern: providerConfigFiles.email.pattern,\n value: providers.email,\n });\n }\n if (providers.storage) {\n await replaceInFiles({\n cwd,\n paths: providerConfigFiles.storage.files,\n pattern: providerConfigFiles.storage.pattern,\n value: providers.storage,\n });\n }\n if (providers.analytics && Object.keys(providers.analytics).length > 0) {\n await Promise.all(\n Object.entries(providers.analytics).map(([key, value]) =>\n replaceInFiles({\n cwd,\n paths: providerConfigFiles.analytics[key as App].files,\n pattern: providerConfigFiles.analytics[key as App].pattern,\n value,\n }),\n ),\n );\n }\n if (providers.monitoring && Object.keys(providers.monitoring).length > 0) {\n await Promise.all(\n Object.entries(providers.monitoring).map(([key, value]) =>\n replaceInFiles({\n cwd,\n paths: providerConfigFiles.monitoring[key as App].files,\n pattern: providerConfigFiles.monitoring[key as App].pattern,\n value,\n }),\n ),\n );\n }\n\n spinner.succeed(\"Providers files successfully updated!\");\n } catch {\n spinner.fail(\"Failed to update providers files! Please try again.\");\n process.exit(1);\n }\n};\n","export const ServiceType = {\n LOCAL: \"local\",\n CLOUD: \"cloud\",\n} as const;\n\nexport const Service = {\n DB: \"db\",\n};\n\nexport const StorageProvider = {\n S3: \"s3\",\n} as const;\n\nexport const BillingProvider = {\n STRIPE: \"stripe\",\n LEMON_SQUEEZY: \"lemon-squeezy\",\n POLAR: \"polar\",\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} 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 const AnalyticsProvider = {\n [App.WEB]: {\n GOOGLE_ANALYTICS: \"google-analytics\",\n MIXPANEL: \"mixpanel\",\n OPEN_PANEL: \"open-panel\",\n PLAUSIBLE: \"plausible\",\n POSTHOG: \"posthog\",\n UMAMI: \"umami\",\n VEMETRIC: \"vemetric\",\n VERCEL: \"vercel\",\n },\n [App.MOBILE]: {\n GOOGLE_ANALYTICS: \"google-analytics\",\n MIXPANEL: \"mixpanel\",\n POSTHOG: \"posthog\",\n },\n [App.EXTENSION]: {\n GOOGLE_ANALYTICS: \"google-analytics\",\n POSTHOG: \"posthog\",\n },\n} as const;\n\nexport const MonitoringProvider = {\n [App.WEB]: {\n SENTRY: \"sentry\",\n POSTHOG: \"posthog\",\n },\n [App.MOBILE]: {\n SENTRY: \"sentry\",\n POSTHOG: \"posthog\",\n },\n [App.EXTENSION]: {\n SENTRY: \"sentry\",\n POSTHOG: \"posthog\",\n },\n} as const;\n\nexport type ServiceType = (typeof ServiceType)[keyof typeof ServiceType];\nexport type Service = (typeof Service)[keyof typeof Service];\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];\nexport type AnalyticsProvider = {\n [K in App]: (typeof AnalyticsProvider)[K][keyof (typeof AnalyticsProvider)[K]];\n};\nexport type MonitoringProvider = {\n [K in App]: (typeof MonitoringProvider)[K][keyof (typeof MonitoringProvider)[K]];\n};\n\nconst env = {\n db: {\n url: \"DATABASE_URL\",\n },\n billing: {\n [BillingProvider.STRIPE]: {\n secretKey: \"STRIPE_SECRET_KEY\",\n webhookSecret: \"STRIPE_WEBHOOK_SECRET\",\n },\n [BillingProvider.LEMON_SQUEEZY]: {\n apiKey: \"LEMON_SQUEEZY_API_KEY\",\n signingSecret: \"LEMON_SQUEEZY_SIGNING_SECRET\",\n storeId: \"LEMON_SQUEEZY_STORE_ID\",\n },\n [BillingProvider.POLAR]: {\n accessToken: \"POLAR_ACCESS_TOKEN\",\n webhookSecret: \"POLAR_WEBHOOK_SECRET\",\n organizationSlug: \"POLAR_ORGANIZATION_SLUG\",\n },\n },\n email: {\n [EmailProvider.RESEND]: {\n apiKey: \"RESEND_API_KEY\",\n },\n [EmailProvider.SENDGRID]: {\n apiKey: \"SENDGRID_API_KEY\",\n },\n [EmailProvider.PLUNK]: {\n apiKey: \"PLUNK_API_KEY\",\n },\n [EmailProvider.POSTMARK]: {\n apiKey: \"POSTMARK_API_KEY\",\n },\n [EmailProvider.NODEMAILER]: {\n user: \"NODEMAILER_USER\",\n password: \"NODEMAILER_PASSWORD\",\n host: \"NODEMAILER_HOST\",\n port: \"NODEMAILER_PORT\",\n },\n },\n storage: {\n [StorageProvider.S3]: {\n region: \"S3_REGION\",\n bucket: \"S3_BUCKET\",\n endpoint: \"S3_ENDPOINT\",\n accessKeyId: \"S3_ACCESS_KEY_ID\",\n secretAccessKey: \"S3_SECRET_ACCESS_KEY\",\n },\n },\n analytics: {\n [App.WEB]: {\n [AnalyticsProvider[App.WEB].GOOGLE_ANALYTICS]: {\n measurementId: \"NEXT_PUBLIC_GOOGLE_ANALYTICS_MEASUREMENT_ID\",\n secret: \"GOOGLE_ANALYTICS_SECRET\",\n },\n [AnalyticsProvider[App.WEB].MIXPANEL]: {\n token: \"NEXT_PUBLIC_MIXPANEL_TOKEN\",\n },\n [AnalyticsProvider[App.WEB].OPEN_PANEL]: {\n clientId: \"NEXT_PUBLIC_OPEN_PANEL_CLIENT_ID\",\n secret: \"OPEN_PANEL_SECRET\",\n },\n [AnalyticsProvider[App.WEB].PLAUSIBLE]: {\n domain: \"NEXT_PUBLIC_PLAUSIBLE_DOMAIN\",\n host: \"NEXT_PUBLIC_PLAUSIBLE_HOST\",\n },\n [AnalyticsProvider[App.WEB].POSTHOG]: {\n key: \"NEXT_PUBLIC_POSTHOG_KEY\",\n host: \"NEXT_PUBLIC_POSTHOG_HOST\",\n },\n [AnalyticsProvider[App.WEB].UMAMI]: {\n host: \"NEXT_PUBLIC_UMAMI_HOST\",\n websiteId: \"NEXT_PUBLIC_UMAMI_WEBSITE_ID\",\n apiHost: \"UMAMI_API_HOST\",\n apiKey: \"UMAMI_API_KEY\",\n },\n [AnalyticsProvider[App.WEB].VEMETRIC]: {\n token: \"NEXT_PUBLIC_VEMETRIC_PROJECT_TOKEN\",\n },\n [AnalyticsProvider[App.WEB].VERCEL]: {},\n },\n [App.MOBILE]: {\n [AnalyticsProvider[App.MOBILE].GOOGLE_ANALYTICS]: {},\n [AnalyticsProvider[App.MOBILE].MIXPANEL]: {\n token: \"EXPO_PUBLIC_MIXPANEL_TOKEN\",\n },\n [AnalyticsProvider[App.MOBILE].POSTHOG]: {\n key: \"EXPO_PUBLIC_POSTHOG_KEY\",\n host: \"EXPO_PUBLIC_POSTHOG_HOST\",\n },\n },\n [App.EXTENSION]: {\n [AnalyticsProvider[App.EXTENSION].GOOGLE_ANALYTICS]: {\n measurementId: \"VITE_GOOGLE_ANALYTICS_MEASUREMENT_ID\",\n secret: \"VITE_GOOGLE_ANALYTICS_SECRET\",\n },\n [AnalyticsProvider[App.EXTENSION].POSTHOG]: {\n key: \"VITE_POSTHOG_KEY\",\n host: \"VITE_POSTHOG_HOST\",\n },\n },\n },\n monitoring: {\n [App.WEB]: {\n [MonitoringProvider[App.WEB].SENTRY]: {\n dsn: \"NEXT_PUBLIC_SENTRY_DSN\",\n },\n [MonitoringProvider[App.WEB].POSTHOG]: {\n key: \"NEXT_PUBLIC_POSTHOG_KEY\",\n host: \"NEXT_PUBLIC_POSTHOG_HOST\",\n },\n },\n [App.MOBILE]: {\n [MonitoringProvider[App.MOBILE].SENTRY]: {\n dsn: \"EXPO_PUBLIC_SENTRY_DSN\",\n },\n [MonitoringProvider[App.MOBILE].POSTHOG]: {\n key: \"EXPO_PUBLIC_POSTHOG_KEY\",\n host: \"EXPO_PUBLIC_POSTHOG_HOST\",\n },\n },\n [App.EXTENSION]: {\n [MonitoringProvider[App.EXTENSION].SENTRY]: {\n dsn: \"VITE_SENTRY_DSN\",\n },\n [MonitoringProvider[App.EXTENSION].POSTHOG]: {\n key: \"VITE_POSTHOG_KEY\",\n host: \"VITE_POSTHOG_HOST\",\n },\n },\n },\n} as const;\n\nexport const envInPaths = {\n [EnvPath.ROOT]: [env.db.url],\n [EnvPath.WEB]: [\n env.billing.stripe.secretKey,\n env.billing.stripe.webhookSecret,\n env.billing[\"lemon-squeezy\"].apiKey,\n env.billing[\"lemon-squeezy\"].signingSecret,\n env.billing[\"lemon-squeezy\"].storeId,\n env.billing.polar.accessToken,\n env.billing.polar.webhookSecret,\n env.billing.polar.organizationSlug,\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.s3.accessKeyId,\n env.storage.s3.secretAccessKey,\n env.analytics[App.WEB][\"google-analytics\"].measurementId,\n env.analytics[App.WEB][\"google-analytics\"].secret,\n env.analytics[App.WEB].mixpanel.token,\n env.analytics[App.WEB][\"open-panel\"].clientId,\n env.analytics[App.WEB][\"open-panel\"].secret,\n env.analytics[App.WEB].plausible.domain,\n env.analytics[App.WEB].plausible.host,\n env.analytics[App.WEB].posthog.key,\n env.analytics[App.WEB].posthog.host,\n env.analytics[App.WEB].umami.host,\n env.analytics[App.WEB].umami.websiteId,\n env.analytics[App.WEB].umami.apiHost,\n env.analytics[App.WEB].umami.apiKey,\n env.analytics[App.WEB].vemetric.token,\n env.monitoring[App.WEB].sentry.dsn,\n env.monitoring[App.WEB].posthog.key,\n env.monitoring[App.WEB].posthog.host,\n ],\n [EnvPath.MOBILE]: [\n env.analytics[App.MOBILE].mixpanel.token,\n env.analytics[App.MOBILE].posthog.key,\n env.analytics[App.MOBILE].posthog.host,\n env.monitoring[App.MOBILE].sentry.dsn,\n ],\n [EnvPath.EXTENSION]: [\n env.analytics[App.EXTENSION][\"google-analytics\"].measurementId,\n env.analytics[App.EXTENSION][\"google-analytics\"].secret,\n env.analytics[App.EXTENSION].posthog.key,\n env.analytics[App.EXTENSION].posthog.host,\n env.monitoring[App.EXTENSION].sentry.dsn,\n ],\n};\n\nexport const appSpecificFiles = {\n [App.WEB]: [],\n [App.MOBILE]: [\n \"apps/mobile\",\n \"packages/ui/mobile\",\n \"packages/analytics/mobile\",\n \"packages/monitoring/mobile\",\n \".github/workflows/publish-mobile.yml\",\n ],\n [App.EXTENSION]: [\n \"apps/extension\",\n \"packages/analytics/extension\",\n \"packages/monitoring/extension\",\n \".github/workflows/publish-extension.yml\",\n ],\n};\n\nexport const providerConfigFiles = {\n billing: {\n files: [\n \"packages/billing/src/providers/index.ts\",\n \"packages/billing/src/providers/env.ts\",\n ],\n pattern: new RegExp(`(${Object.values(BillingProvider).join(\"|\")})`, \"gi\"),\n },\n email: {\n files: [\n \"packages/email/src/providers/index.ts\",\n \"packages/email/src/providers/env.ts\",\n ],\n pattern: new RegExp(`(${Object.values(EmailProvider).join(\"|\")})`, \"gi\"),\n },\n storage: {\n files: [\n \"packages/storage/src/providers/index.ts\",\n \"packages/storage/src/providers/env.ts\",\n ],\n pattern: new RegExp(`(${Object.values(StorageProvider).join(\"|\")})`, \"gi\"),\n },\n analytics: {\n [App.WEB]: {\n files: [\n \"packages/analytics/web/src/providers/index.tsx\",\n \"packages/analytics/web/src/providers/server.ts\",\n \"packages/analytics/web/src/providers/env.ts\",\n ],\n pattern: new RegExp(\n `(${Object.values(AnalyticsProvider[App.WEB]).join(\"|\")})`,\n \"gi\",\n ),\n },\n [App.MOBILE]: {\n files: [\"packages/analytics/mobile/src/providers/index.ts\"],\n pattern: new RegExp(\n `(${Object.values(AnalyticsProvider[App.MOBILE]).join(\"|\")})`,\n \"gi\",\n ),\n },\n [App.EXTENSION]: {\n files: [\"packages/analytics/extension/src/providers/index.ts\"],\n pattern: new RegExp(\n `(${Object.values(AnalyticsProvider[App.EXTENSION]).join(\"|\")})`,\n \"gi\",\n ),\n },\n },\n monitoring: {\n [App.WEB]: {\n files: [\"packages/monitoring/web/src/providers/index.ts\"],\n pattern: new RegExp(\n `(${Object.values(MonitoringProvider[App.WEB]).join(\"|\")})`,\n \"gi\",\n ),\n },\n [App.MOBILE]: {\n files: [\"packages/monitoring/mobile/src/providers/index.ts\"],\n pattern: new RegExp(\n `(${Object.values(MonitoringProvider[App.MOBILE]).join(\"|\")})`,\n \"gi\",\n ),\n },\n [App.EXTENSION]: {\n files: [\"packages/monitoring/extension/src/providers/index.ts\"],\n pattern: new RegExp(\n `(${Object.values(MonitoringProvider[App.EXTENSION]).join(\"|\")})`,\n \"gi\",\n ),\n },\n },\n};\n\nexport const servicesPackages: Record<Service, string> = {\n [Service.DB]: \"@turbostarter/db\",\n};\n\nexport const config = {\n name: \"TurboStarter\",\n repository: \"https://github.com/turbostarter/core.git\",\n env,\n} as const;\n","import prompts from \"prompts\";\n\nimport { AnalyticsProvider, App, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getAnalyticsExtensionProvider = async (): Promise<{\n provider: AnalyticsProvider[typeof App.EXTENSION];\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n choices: Object.values(AnalyticsProvider[App.EXTENSION]).map(\n (provider) => ({\n title: getLabel(provider),\n value: provider,\n }),\n ),\n name: \"provider\",\n message: \"What do you want to use for extension analytics?\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getAnalyticsExtensionProviderConfig = async (\n provider: AnalyticsProvider[typeof App.EXTENSION],\n) => {\n switch (provider) {\n case AnalyticsProvider[App.EXTENSION].GOOGLE_ANALYTICS:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.EXTENSION][\"google-analytics\"]\n .measurementId,\n message: \"Enter your Google Analytics measurement ID\",\n },\n {\n type: \"text\",\n name: config.env.analytics[App.EXTENSION][\"google-analytics\"]\n .secret,\n message: \"Enter your Google Analytics secret\",\n },\n ],\n { onCancel },\n );\n case AnalyticsProvider[App.EXTENSION].POSTHOG:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.EXTENSION].posthog.key,\n message: \"Enter your PostHog key\",\n },\n {\n type: \"text\",\n name: config.env.analytics[App.EXTENSION].posthog.host,\n message: \"Enter your PostHog host\",\n initial: \"https://us.posthog.com\",\n },\n ],\n { onCancel },\n );\n }\n};\n\nexport const getAnalyticsExtensionConfig = async () => {\n const { provider } = await getAnalyticsExtensionProvider();\n const env = await getAnalyticsExtensionProviderConfig(provider);\n\n return { provider, env };\n};\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 { AnalyticsProvider, App, config } from \"~/config\";\nimport { getLabel, logger, onCancel } from \"~/utils\";\n\nconst getAnalyticsMobileProvider = async (): Promise<{\n provider: AnalyticsProvider[typeof App.MOBILE];\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n choices: Object.values(AnalyticsProvider[App.MOBILE]).map(\n (provider) => ({\n title: getLabel(provider),\n value: provider,\n }),\n ),\n name: \"provider\",\n message: \"What do you want to use for mobile analytics?\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getAnalyticsMobileProviderConfig = async (\n provider: AnalyticsProvider[typeof App.MOBILE],\n) => {\n switch (provider) {\n case AnalyticsProvider[App.MOBILE].GOOGLE_ANALYTICS:\n logger.info(\n \"Check how to configure Google Analytics for mobile at https://www.turbostarter.dev/docs/mobile/analytics/configuration#google-analytics\",\n );\n return {};\n case AnalyticsProvider[App.MOBILE].MIXPANEL:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.MOBILE].mixpanel.token,\n message: \"Enter your Mixpanel token\",\n },\n ],\n { onCancel },\n );\n case AnalyticsProvider[App.MOBILE].POSTHOG:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.MOBILE].posthog.key,\n message: \"Enter your PostHog key\",\n },\n {\n type: \"text\",\n name: config.env.analytics[App.MOBILE].posthog.host,\n message: \"Enter your PostHog host\",\n initial: \"https://us.posthog.com\",\n },\n ],\n { onCancel },\n );\n }\n};\n\nexport const getAnalyticsMobileConfig = async () => {\n const { provider } = await getAnalyticsMobileProvider();\n const env = await getAnalyticsMobileProviderConfig(provider);\n\n return { provider, env };\n};\n","import prompts from \"prompts\";\n\nimport { AnalyticsProvider, App, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getAnalyticsWebProvider = async (): Promise<{\n provider: AnalyticsProvider[typeof App.WEB];\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n choices: Object.values(AnalyticsProvider[App.WEB]).map((provider) => ({\n title: getLabel(provider),\n value: provider,\n })),\n name: \"provider\",\n message: \"What do you want to use for web analytics?\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getAnalyticsWebProviderConfig = async (\n provider: AnalyticsProvider[typeof App.WEB],\n) => {\n switch (provider) {\n case AnalyticsProvider[App.WEB].GOOGLE_ANALYTICS:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.WEB][\"google-analytics\"]\n .measurementId,\n message: \"Enter your Google Analytics measurement ID\",\n },\n {\n type: \"text\",\n name: config.env.analytics[App.WEB][\"google-analytics\"].secret,\n message: \"Enter your Google Analytics secret\",\n },\n ],\n { onCancel },\n );\n case AnalyticsProvider[App.WEB].MIXPANEL:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.WEB].mixpanel.token,\n message: \"Enter your Mixpanel token\",\n },\n ],\n { onCancel },\n );\n case AnalyticsProvider[App.WEB].OPEN_PANEL:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.WEB][\"open-panel\"].clientId,\n message: \"Enter your OpenPanel client ID\",\n },\n {\n type: \"text\",\n name: config.env.analytics[App.WEB][\"open-panel\"].secret,\n message: \"Enter your OpenPanel secret\",\n },\n ],\n { onCancel },\n );\n case AnalyticsProvider[App.WEB].PLAUSIBLE:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.WEB].plausible.domain,\n message: \"Enter your Plausible domain\",\n },\n {\n type: \"text\",\n name: config.env.analytics[App.WEB].plausible.host,\n message: \"Enter your Plausible host\",\n initial: \"https://plausible.io\",\n },\n ],\n { onCancel },\n );\n case AnalyticsProvider[App.WEB].POSTHOG:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.WEB].posthog.key,\n message: \"Enter your PostHog key\",\n },\n {\n type: \"text\",\n name: config.env.analytics[App.WEB].posthog.host,\n message: \"Enter your PostHog host\",\n initial: \"https://us.posthog.com\",\n },\n ],\n { onCancel },\n );\n case AnalyticsProvider[App.WEB].UMAMI:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.WEB].umami.host,\n message: \"Enter your Umami host\",\n initial: \"https://cloud.umami.is\",\n },\n {\n type: \"text\",\n name: config.env.analytics[App.WEB].umami.websiteId,\n message: \"Enter your Umami website ID\",\n },\n {\n type: \"text\",\n name: config.env.analytics[App.WEB].umami.apiHost,\n message: \"Enter your Umami API host\",\n initial: \"https://api-gateway.umami.dev\",\n },\n {\n type: \"text\",\n name: config.env.analytics[App.WEB].umami.apiKey,\n message: \"Enter your Umami API key\",\n },\n ],\n { onCancel },\n );\n case AnalyticsProvider[App.WEB].VEMETRIC:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.analytics[App.WEB].vemetric.token,\n message: \"Enter your Vemetric project token\",\n },\n ],\n { onCancel },\n );\n case AnalyticsProvider[App.WEB].VERCEL:\n return {};\n }\n};\n\nexport const getAnalyticsWebConfig = async () => {\n const { provider } = await getAnalyticsWebProvider();\n const env = await getAnalyticsWebProviderConfig(provider);\n\n return { provider, env };\n};\n","import { App } from \"~/config\";\n\nimport { getAnalyticsExtensionConfig } from \"./extension\";\nimport { getAnalyticsMobileConfig } from \"./mobile\";\nimport { getAnalyticsWebConfig } from \"./web\";\n\nimport type { AnalyticsProvider } from \"~/config\";\n\nexport const getAnalyticsConfig = async (apps: App[]) => {\n const providers: Partial<AnalyticsProvider> = {};\n const env: Record<string, string> = {};\n\n if (apps.includes(App.WEB)) {\n const { provider, env: webEnv } = await getAnalyticsWebConfig();\n providers[App.WEB] = provider;\n Object.assign(env, webEnv);\n }\n\n if (apps.includes(App.MOBILE)) {\n const { provider, env: mobileEnv } = await getAnalyticsMobileConfig();\n providers[App.MOBILE] = provider;\n Object.assign(env, mobileEnv);\n }\n\n if (apps.includes(App.EXTENSION)) {\n const { provider, env: extensionEnv } = await getAnalyticsExtensionConfig();\n providers[App.EXTENSION] = provider;\n Object.assign(env, extensionEnv);\n }\n\n return { providers, env };\n};\n","import prompts from \"prompts\";\n\nimport { BillingProvider, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getBillingProvider = async (): Promise<{\n 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: \"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[\"lemon-squeezy\"].storeId,\n message: \"Enter your Lemon Squeezy store ID\",\n },\n {\n type: \"text\",\n name: config.env.billing[\"lemon-squeezy\"].apiKey,\n message: \"Enter your Lemon Squeezy API key\",\n },\n {\n type: \"text\",\n name: config.env.billing[\"lemon-squeezy\"].signingSecret,\n message: \"Enter your Lemon Squeezy signing secret\",\n },\n ],\n {\n onCancel,\n },\n );\n case BillingProvider.POLAR:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.billing.polar.accessToken,\n message: \"Enter your Polar access token\",\n },\n {\n type: \"text\",\n name: config.env.billing.polar.webhookSecret,\n message: \"Enter your Polar webhook secret\",\n },\n {\n type: \"text\",\n name: config.env.billing.polar.organizationSlug,\n message: \"Enter your Polar organization slug\",\n },\n ],\n {\n onCancel,\n },\n );\n }\n};\n\nexport const getBillingConfig = async () => {\n const { provider } = await getBillingProvider();\n const env = await getBillingProviderConfig(provider);\n\n return { provider, env };\n};\n","import prompts from \"prompts\";\n\nimport { config, ServiceType } from \"~/config\";\nimport { onCancel } from \"~/utils\";\n\nconst getDatabaseCloudConfig = async () => {\n return prompts(\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 getDatabaseConfig = async () => {\n const response = await prompts(\n [\n {\n type: \"select\",\n name: \"type\",\n message: \"How do you want to use database?\",\n choices: [\n {\n title: \"Local (powered by Docker)\",\n value: ServiceType.LOCAL,\n selected: true,\n },\n {\n title: `Cloud`,\n value: ServiceType.CLOUD,\n },\n ],\n },\n ],\n {\n onCancel,\n },\n );\n\n if (response.type === ServiceType.CLOUD) {\n const dbConfig = await getDatabaseCloudConfig();\n\n return { ...response, env: dbConfig };\n }\n\n return response;\n};\n","import prompts from \"prompts\";\n\nimport { EmailProvider, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getEmailProvider = async (): Promise<{\n provider: EmailProvider;\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n name: \"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 env = await getEmailProviderConfig(provider);\n\n return { provider, env };\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 { MonitoringProvider, App, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getMonitoringExtensionProvider = async (): Promise<{\n provider: MonitoringProvider[typeof App.EXTENSION];\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n choices: Object.values(MonitoringProvider[App.EXTENSION]).map(\n (provider) => ({\n title: getLabel(provider),\n value: provider,\n }),\n ),\n name: \"provider\",\n message: \"What do you want to use for extension monitoring?\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getMonitoringExtensionProviderConfig = async (\n provider: MonitoringProvider[typeof App.EXTENSION],\n) => {\n switch (provider) {\n case MonitoringProvider[App.EXTENSION].SENTRY:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.monitoring[App.EXTENSION].sentry.dsn,\n message: \"Enter your Sentry DSN\",\n },\n ],\n { onCancel },\n );\n case MonitoringProvider[App.EXTENSION].POSTHOG:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.monitoring[App.EXTENSION].posthog.key,\n message: \"Enter your PostHog key\",\n },\n {\n type: \"text\",\n name: config.env.monitoring[App.EXTENSION].posthog.host,\n message: \"Enter your PostHog host\",\n initial: \"https://us.posthog.com\",\n },\n ],\n { onCancel },\n );\n }\n};\n\nexport const getMonitoringExtensionConfig = async () => {\n const { provider } = await getMonitoringExtensionProvider();\n const env = await getMonitoringExtensionProviderConfig(provider);\n\n return { provider, env };\n};\n","import prompts from \"prompts\";\n\nimport { MonitoringProvider, App, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getMonitoringMobileProvider = async (): Promise<{\n provider: MonitoringProvider[typeof App.MOBILE];\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n choices: Object.values(MonitoringProvider[App.MOBILE]).map(\n (provider) => ({\n title: getLabel(provider),\n value: provider,\n }),\n ),\n name: \"provider\",\n message: \"What do you want to use for mobile monitoring?\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getMonitoringMobileProviderConfig = async (\n provider: MonitoringProvider[typeof App.MOBILE],\n) => {\n switch (provider) {\n case MonitoringProvider[App.MOBILE].SENTRY:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.monitoring[App.MOBILE].sentry.dsn,\n message: \"Enter your Sentry DSN\",\n },\n ],\n { onCancel },\n );\n case MonitoringProvider[App.MOBILE].POSTHOG:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.monitoring[App.MOBILE].posthog.key,\n message: \"Enter your PostHog key\",\n },\n {\n type: \"text\",\n name: config.env.monitoring[App.MOBILE].posthog.host,\n message: \"Enter your PostHog host\",\n initial: \"https://us.posthog.com\",\n },\n ],\n { onCancel },\n );\n }\n};\n\nexport const getMonitoringMobileConfig = async () => {\n const { provider } = await getMonitoringMobileProvider();\n const env = await getMonitoringMobileProviderConfig(provider);\n\n return { provider, env };\n};\n","import prompts from \"prompts\";\n\nimport { MonitoringProvider, App, config } from \"~/config\";\nimport { getLabel, onCancel } from \"~/utils\";\n\nconst getMonitoringWebProvider = async (): Promise<{\n provider: MonitoringProvider[typeof App.WEB];\n}> => {\n return prompts(\n [\n {\n type: \"select\",\n choices: Object.values(MonitoringProvider[App.WEB]).map((provider) => ({\n title: getLabel(provider),\n value: provider,\n })),\n name: \"provider\",\n message: \"What do you want to use for web monitoring?\",\n },\n ],\n {\n onCancel,\n },\n );\n};\n\nconst getMonitoringWebProviderConfig = async (\n provider: MonitoringProvider[typeof App.WEB],\n) => {\n switch (provider) {\n case MonitoringProvider[App.WEB].SENTRY:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.monitoring[App.WEB].sentry.dsn,\n message: \"Enter your Sentry DSN\",\n },\n ],\n { onCancel },\n );\n case MonitoringProvider[App.WEB].POSTHOG:\n return prompts(\n [\n {\n type: \"text\",\n name: config.env.monitoring[App.WEB].posthog.key,\n message: \"Enter your PostHog key\",\n },\n {\n type: \"text\",\n name: config.env.monitoring[App.WEB].posthog.host,\n message: \"Enter your PostHog host\",\n initial: \"https://us.posthog.com\",\n },\n ],\n { onCancel },\n );\n }\n};\n\nexport const getMonitoringWebConfig = async () => {\n const { provider } = await getMonitoringWebProvider();\n const env = await getMonitoringWebProviderConfig(provider);\n\n return { provider, env };\n};\n","import { App } from \"~/config\";\n\nimport { getMonitoringExtensionConfig } from \"./extension\";\nimport { getMonitoringMobileConfig } from \"./mobile\";\nimport { getMonitoringWebConfig } from \"./web\";\n\nimport type { MonitoringProvider } from \"~/config\";\n\nexport const getMonitoringConfig = async (apps: App[]) => {\n const providers: Partial<MonitoringProvider> = {};\n const env: Record<string, string> = {};\n\n if (apps.includes(App.WEB)) {\n const { provider, env: webEnv } = await getMonitoringWebConfig();\n providers[App.WEB] = provider;\n Object.assign(env, webEnv);\n }\n\n if (apps.includes(App.MOBILE)) {\n const { provider, env: mobileEnv } = await getMonitoringMobileConfig();\n providers[App.MOBILE] = provider;\n Object.assign(env, mobileEnv);\n }\n\n if (apps.includes(App.EXTENSION)) {\n const { provider, env: extensionEnv } =\n await getMonitoringExtensionConfig();\n providers[App.EXTENSION] = provider;\n Object.assign(env, extensionEnv);\n }\n\n return { providers, env };\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 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: \"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 initial: \"us-east-1\",\n },\n {\n type: \"text\",\n name: config.env.storage.s3.endpoint,\n message: \"Enter your S3 endpoint\",\n initial: \"https://s3.amazonaws.com\",\n },\n {\n type: \"text\",\n name: config.env.storage.s3.bucket,\n message: \"Enter your default S3 bucket name\",\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 env = await getStorageProviderConfig();\n\n return { provider, env };\n};\n","import { execa } from \"execa\";\nimport ora from \"ora\";\n\nimport { validateDockerInstalled } from \"~/commands/new/prerequisites\";\nimport { servicesPackages } from \"~/config\";\n\nimport type { Service } from \"~/config\";\n\nexport const startServices = async (cwd: string, services: Service[]) => {\n await validateDockerInstalled();\n\n const spinner = ora(`Starting Docker services...`).start();\n\n try {\n await execa(\"pnpm\", [\"services:start\", \"--\", ...services], { cwd });\n await execa(\n \"pnpm\",\n [\n \"with-env\",\n \"pnpm\",\n \"turbo\",\n \"setup\",\n services\n .map((service) => `--filter=${servicesPackages[service]}`)\n .join(\" \"),\n ],\n { cwd },\n );\n\n spinner.succeed(\"Services successfully started!\");\n } catch (error) {\n console.error(error);\n spinner.fail(\"Failed to start services!\");\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","import { promises } from \"fs\";\nimport { join } from \"path\";\n\nexport const replaceInFile = async ({\n cwd,\n path,\n pattern,\n value,\n}: {\n cwd: string;\n path: string;\n pattern: RegExp | string;\n value: string;\n}) => {\n const fullPath = join(cwd, path);\n const content = await promises.readFile(fullPath, \"utf8\");\n const newContent = content.replace(pattern, value);\n await promises.writeFile(fullPath, newContent);\n};\n\nexport const replaceInFiles = async ({\n cwd,\n paths,\n pattern,\n value,\n}: {\n cwd: string;\n paths: string[];\n pattern: RegExp | string;\n value: string;\n}) => {\n await Promise.all(\n paths.map(async (path) => {\n await replaceInFile({ cwd, path, pattern, value });\n }),\n );\n};\n","{\n \"name\": \"@turbostarter/cli\",\n \"version\": \"1.2.0\",\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 \"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\": \"Your TurboStarter assistant for starting new projects, adding plugins and more.\",\n \"devDependencies\": {\n \"@changesets/changelog-github\": \"^0.5.1\",\n \"@changesets/cli\": \"^2.29.2\",\n \"@eslint/compat\": \"1.4.0\",\n \"@types/lodash\": \"4.17.12\",\n \"@types/node\": \"22.7.5\",\n \"@types/prompts\": \"^2.4.2\",\n \"eslint\": \"9.37.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.9.2\",\n \"typescript-eslint\": \"8.46.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@10.18.2\"\n}\n"],"mappings":"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","names":["Command","Command","execa","ora","path","join","color","prompts","z","ServiceType","Service","StorageProvider","BillingProvider","EmailProvider","EnvPath","EnvFile","App","AnalyticsProvider","MonitoringProvider","env","envInPaths","appSpecificFiles","providerConfigFiles","servicesPackages","config","prompts","_","colors","logger","log","handleError","error","logger","getLabel","value","word","_","onCancel","logger","getAnalyticsExtensionProvider","prompts","AnalyticsProvider","App","provider","getLabel","onCancel","getAnalyticsExtensionProviderConfig","config","getAnalyticsExtensionConfig","env","prompts","getAnalyticsMobileProvider","prompts","AnalyticsProvider","App","provider","getLabel","onCancel","getAnalyticsMobileProviderConfig","logger","config","getAnalyticsMobileConfig","env","prompts","getAnalyticsWebProvider","prompts","AnalyticsProvider","App","provider","getLabel","onCancel","getAnalyticsWebProviderConfig","config","getAnalyticsWebConfig","env","getAnalyticsConfig","apps","providers","env","App","provider","webEnv","getAnalyticsWebConfig","mobileEnv","getAnalyticsMobileConfig","extensionEnv","getAnalyticsExtensionConfig","prompts","getBillingProvider","prompts","BillingProvider","provider","getLabel","onCancel","getBillingProviderConfig","config","getBillingConfig","env","prompts","getDatabaseCloudConfig","prompts","config","onCancel","getDatabaseConfig","response","ServiceType","dbConfig","prompts","getEmailProvider","prompts","EmailProvider","provider","getLabel","onCancel","getEmailProviderConfig","config","getEmailConfig","env","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","getMonitoringExtensionProvider","prompts","MonitoringProvider","App","provider","getLabel","onCancel","getMonitoringExtensionProviderConfig","config","getMonitoringExtensionConfig","env","prompts","getMonitoringMobileProvider","prompts","MonitoringProvider","App","provider","getLabel","onCancel","getMonitoringMobileProviderConfig","config","getMonitoringMobileConfig","env","prompts","getMonitoringWebProvider","prompts","MonitoringProvider","App","provider","getLabel","onCancel","getMonitoringWebProviderConfig","config","getMonitoringWebConfig","env","getMonitoringConfig","apps","providers","env","App","provider","webEnv","getMonitoringWebConfig","mobileEnv","getMonitoringMobileConfig","extensionEnv","getMonitoringExtensionConfig","prompts","getStorageProvider","prompts","StorageProvider","provider","getLabel","onCancel","getStorageProviderConfig","config","getStorageConfig","env","execa","ora","execa","ora","color","validateNodeInstalled","execa","logger","color","validatePnpmInstalled","validateDockerInstalled","validateGitInstalled","validatePrerequisites","spinner","ora","startServices","cwd","services","validateDockerInstalled","spinner","ora","execa","service","servicesPackages","error","promises","join","replaceInFile","cwd","path","pattern","value","fullPath","newContent","replaceInFiles","paths","newOptionsSchema","z","newCommand","Command","opts","logger","color","options","path","name","initializeProject","error","handleError","validatePrerequisites","getName","apps","getApps","dbConfig","getDatabaseConfig","billingConfig","getBillingConfig","emailConfig","getEmailConfig","storageConfig","getStorageConfig","analyticsConfig","getAnalyticsConfig","monitoringConfig","getMonitoringConfig","env","join","projectDir","cloneRepository","prepareEnvironment","updateProvidersFiles","setEnvironmentVariables","configureGit","installDependencies","localServices","ServiceType","Service","startServices","result","prompts","value","onCancel","App","getRepositoryUrl","httpsUrl","execa","cwd","spinner","ora","filesToRemove","app","appSpecificFiles","url","config","providers","replaceInFiles","providerConfigFiles","key","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
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./dist/index.js",
|
|
@@ -33,17 +33,17 @@
|
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@changesets/changelog-github": "^0.5.1",
|
|
35
35
|
"@changesets/cli": "^2.29.2",
|
|
36
|
-
"@eslint/compat": "1.
|
|
36
|
+
"@eslint/compat": "1.4.0",
|
|
37
37
|
"@types/lodash": "4.17.12",
|
|
38
38
|
"@types/node": "22.7.5",
|
|
39
39
|
"@types/prompts": "^2.4.2",
|
|
40
|
-
"eslint": "9.
|
|
40
|
+
"eslint": "9.37.0",
|
|
41
41
|
"eslint-plugin-import": "2.31.0",
|
|
42
42
|
"eslint-plugin-unused-imports": "4.1.4",
|
|
43
43
|
"prettier": "3.3.3",
|
|
44
44
|
"tsup": "8.3.0",
|
|
45
|
-
"typescript": "5.
|
|
46
|
-
"typescript-eslint": "8.
|
|
45
|
+
"typescript": "5.9.2",
|
|
46
|
+
"typescript-eslint": "8.46.0"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"commander": "12.1.0",
|