create-better-t-stack 2.2.3 → 2.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,135 +1,131 @@
1
1
  #!/usr/bin/env node
2
- import tn from"node:path";import{cancel as rn,intro as an,log as U,outro as sn}from"@clack/prompts";import{consola as D}from"consola";import cr from"fs-extra";import _ from"picocolors";import nn from"yargs";import{hideBin as on}from"yargs/helpers";import _e from"node:path";import{fileURLToPath as wr}from"node:url";var re=()=>{let e=process.env.npm_config_user_agent;return e?.startsWith("pnpm")?"pnpm":e?.startsWith("bun")?"bun":"npm"};var yr=wr(import.meta.url),vr=_e.dirname(yr),k=_e.join(vr,"../"),P={projectName:"my-better-t-app",frontend:["tanstack-router"],database:"sqlite",orm:"drizzle",auth:!0,addons:[],examples:[],git:!0,packageManager:re(),install:!0,dbSetup:"none",backend:"hono",runtime:"bun",api:"trpc"},we={"better-auth":"^1.2.7","@better-auth/expo":"^1.2.7","drizzle-orm":"^0.38.4","drizzle-kit":"^0.30.5","@libsql/client":"^0.14.0",pg:"^8.14.1","@types/pg":"^8.11.11",mysql2:"^3.14.0","@prisma/client":"^6.6.0",prisma:"^6.6.0","vite-plugin-pwa":"^0.21.2","@vite-pwa/assets-generator":"^0.2.6","@tauri-apps/cli":"^2.4.0","@biomejs/biome":"1.9.4",husky:"^9.1.7","lint-staged":"^15.5.0","@hono/node-server":"^1.14.0",tsx:"^4.19.2","@types/node":"^22.13.11","@types/bun":"^1.2.6","@elysiajs/node":"^1.2.6","@elysiajs/cors":"^1.2.0","@elysiajs/trpc":"^1.1.0",elysia:"^1.2.25","@hono/trpc-server":"^0.3.4",hono:"^4.7.6",cors:"^2.8.5",express:"^5.1.0","@types/express":"^5.0.1","@types/cors":"^2.8.17",turbo:"^2.4.2",ai:"^4.2.8","@ai-sdk/google":"^1.2.3","@ai-sdk/vue":"^1.2.8","@ai-sdk/svelte":"^2.1.9","@prisma/extension-accelerate":"^1.3.0","@orpc/server":"^1.1.0","@orpc/client":"^1.1.0","@orpc/react-query":"^1.1.0","@orpc/vue-query":"^1.1.0","@orpc/svelte-query":"^1.1.0","@trpc/tanstack-react-query":"^11.0.0","@trpc/server":"^11.0.0","@trpc/client":"^11.0.0"};import za from"node:path";import{cancel as qa,log as Va}from"@clack/prompts";import Ga from"fs-extra";import Ja from"picocolors";import W from"node:path";import N from"fs-extra";import Pr from"node:path";import We from"fs-extra";var v=async e=>{let{dependencies:t=[],devDependencies:r=[],projectDir:a}=e,s=Pr.join(a,"package.json"),n=await We.readJson(s);n.dependencies||(n.dependencies={}),n.devDependencies||(n.devDependencies={});for(let o of t){let i=we[o];i?n.dependencies[o]=i:console.warn(`Warning: Dependency ${o} not found in version map.`)}for(let o of r){let i=we[o];i?n.devDependencies[o]=i:console.warn(`Warning: Dev dependency ${o} not found in version map.`)}await We.writeJson(s,n,{spaces:2})};import ze from"node:path";import{spinner as jr}from"@clack/prompts";import kr from"consola";import{execa as xr}from"execa";import qe from"picocolors";function R(e,t){switch(e){case"pnpm":return`pnpm dlx ${t}`;case"bun":return`bunx ${t}`;default:return`npx ${t}`}}async function Ve(e){let{projectName:t,packageManager:r}=e,a=ze.resolve(process.cwd(),t),s=jr();try{s.start("Setting up Starlight docs...");let i=`create-astro@latest ${["docs","--template","starlight","--no-install","--add","tailwind","--no-git","--skip-houston"].join(" ")}`,c=R(r,i);await xr(c,{cwd:ze.join(a,"apps"),env:{CI:"true"},shell:!0}),s.stop("Starlight docs setup successfully!")}catch(n){s.stop(qe.red("Failed to set up Starlight docs")),n instanceof Error&&kr.error(qe.red(n.message))}}import H from"node:path";import{spinner as Sr}from"@clack/prompts";import{consola as Dr}from"consola";import{execa as Ar}from"execa";import ae from"fs-extra";import Ge from"picocolors";async function Je(e){let{projectName:t,packageManager:r,frontend:a}=e,s=H.resolve(process.cwd(),t),n=Sr(),o=H.join(s,"apps/web");if(await ae.pathExists(o))try{n.start("Setting up Tauri desktop app support..."),await v({devDependencies:["@tauri-apps/cli"],projectDir:o});let i=H.join(o,"package.json");if(await ae.pathExists(i)){let A=await ae.readJson(i);A.scripts={...A.scripts,tauri:"tauri","desktop:dev":"tauri dev","desktop:build":"tauri build"},await ae.writeJson(i,A,{spaces:2})}let c=a.includes("tanstack-router"),p=a.includes("react-router"),b=a.includes("nuxt"),m=a.includes("svelte"),w=p||m?"http://localhost:5173":"http://localhost:3001",u=b?"../.output/public":m?"../build":"../dist",S=`@tauri-apps/cli@latest ${["init",`--app-name=${H.basename(s)}`,`--window-title=${H.basename(s)}`,`--frontend-dist=${u}`,`--dev-url=${w}`,`--before-dev-command="${r} run dev"`,`--before-build-command="${r} run build"`].join(" ")}`,$=R(r,S);await Ar($,{cwd:o,env:{CI:"true"},shell:!0}),n.stop("Tauri desktop app support configured successfully!")}catch(i){n.stop(Ge.red("Failed to set up Tauri")),i instanceof Error&&Dr.error(Ge.red(i.message))}}async function Qe(e){let{projectName:t,addons:r,frontend:a}=e,s=W.resolve(process.cwd(),t),n=a.includes("react-router")||a.includes("tanstack-router"),o=a.includes("nuxt"),i=a.includes("svelte");r.includes("turborepo")&&await v({devDependencies:["turbo"],projectDir:s}),r.includes("pwa")&&n&&await Tr(s,a),r.includes("tauri")&&(n||o||i)&&await Je(e),r.includes("biome")&&await Er(s),r.includes("husky")&&await Cr(s),r.includes("starlight")&&await Ve(e)}function $r(e,t){return t.some(r=>["react-router","tanstack-router","nuxt","svelte"].includes(r))?W.join(e,"apps/web"):W.join(e,"apps/web")}async function Er(e){await v({devDependencies:["@biomejs/biome"],projectDir:e});let t=W.join(e,"package.json");if(await N.pathExists(t)){let r=await N.readJson(t);r.scripts={...r.scripts,check:"biome check --write ."},await N.writeJson(t,r,{spaces:2})}}async function Cr(e){await v({devDependencies:["husky","lint-staged"],projectDir:e});let t=W.join(e,"package.json");if(await N.pathExists(t)){let r=await N.readJson(t);r.scripts={...r.scripts,prepare:"husky"},r["lint-staged"]={"*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}":["biome check --write ."]},await N.writeJson(t,r,{spaces:2})}}async function Tr(e,t){if(!t.some(n=>["react-router","tanstack-router"].includes(n)))return;let a=$r(e,t);if(!await N.pathExists(a))return;await v({dependencies:["vite-plugin-pwa"],devDependencies:["@vite-pwa/assets-generator"],projectDir:a});let s=W.join(a,"package.json");if(await N.pathExists(s)){let n=await N.readJson(s);n.scripts={...n.scripts,"generate-pwa-assets":"pwa-assets-generator"},await N.writeJson(s,n,{spaces:2})}}import*as z from"node:path";import He from"fs-extra";async function Ye(e){let{api:t,projectName:r,frontend:a}=e,s=z.resolve(process.cwd(),r),n=z.join(s,"apps/web"),o=z.join(s,"apps/server"),i=await He.pathExists(n),c=a.some(m=>["tanstack-router","react-router","tanstack-start","next"].includes(m)),p=a.includes("nuxt"),b=a.includes("svelte");if(t==="orpc"?await v({dependencies:["@orpc/server","@orpc/client"],projectDir:o}):t==="trpc"&&(await v({dependencies:["@trpc/server","@trpc/client"],projectDir:o}),e.backend==="hono"?await v({dependencies:["@hono/trpc-server"],projectDir:o}):e.backend==="elysia"&&await v({dependencies:["@elysiajs/trpc"],projectDir:o})),i&&(c?t==="orpc"?await v({dependencies:["@orpc/react-query","@orpc/client","@orpc/server"],projectDir:n}):t==="trpc"&&await v({dependencies:["@trpc/tanstack-react-query","@trpc/client","@trpc/server"],projectDir:n}):p?t==="orpc"&&await v({dependencies:["@orpc/vue-query","@orpc/client","@orpc/server"],projectDir:n}):b&&t==="orpc"&&await v({dependencies:["@orpc/svelte-query","@orpc/client","@orpc/server"],projectDir:n})),a.includes("native")){let m=z.join(s,"apps/native");await He.pathExists(m)&&(t==="trpc"?await v({dependencies:["@trpc/tanstack-react-query","@trpc/client","@trpc/server"],projectDir:m}):t==="orpc"&&await v({dependencies:["@orpc/react-query","@orpc/client","@orpc/server"],projectDir:m}))}}import se from"node:path";import Ke from"consola";import Xe from"fs-extra";import Ze from"picocolors";async function et(e){let{projectName:t,auth:r,frontend:a}=e;if(!r)return;let s=se.resolve(process.cwd(),t),n=se.join(s,"apps/server"),o=se.join(s,"apps/web"),i=se.join(s,"apps/native"),c=await Xe.pathExists(o),p=await Xe.pathExists(i);try{await v({dependencies:["better-auth"],projectDir:n}),a.some(m=>["react-router","tanstack-router","tanstack-start","next","nuxt","svelte"].includes(m))&&c&&await v({dependencies:["better-auth"],projectDir:o}),a.includes("native")&&p&&(await v({dependencies:["better-auth","@better-auth/expo"],projectDir:i}),await v({dependencies:["@better-auth/expo"],projectDir:n}))}catch(b){Ke.error(Ze.red("Failed to configure authentication dependencies")),b instanceof Error&&Ke.error(Ze.red(b.message))}}function tt(e=32){let t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",r="",a=t.length;for(let s=0;s<e;s++)r+=t.charAt(Math.floor(Math.random()*a));return r}import rt from"node:path";async function at(e){let{projectName:t,backend:r,runtime:a,api:s}=e,n=rt.resolve(process.cwd(),t),o=r,i=rt.join(n,"apps/server"),c=[],p=[];o==="hono"?(c.push("hono"),s==="trpc"&&c.push("@hono/trpc-server"),a==="node"&&(c.push("@hono/node-server"),p.push("tsx","@types/node"))):o==="elysia"?(c.push("elysia","@elysiajs/cors"),s==="trpc"&&c.push("@elysiajs/trpc"),a==="node"&&(c.push("@elysiajs/node"),p.push("tsx","@types/node"))):o==="express"&&(c.push("express","cors"),p.push("@types/express","@types/cors"),a==="node"&&p.push("tsx","@types/node")),a==="bun"&&p.push("@types/bun"),await v({dependencies:c,devDependencies:p,projectDir:i})}import Rr from"node:path";import Nr from"consola";import Fr from"fs-extra";async function st(e,t){let r=Rr.join(e,"README.md"),a=Br(t);try{await Fr.writeFile(r,a)}catch(s){Nr.error("Failed to create README.md file:",s)}}function Br(e){let{projectName:t,packageManager:r,database:a,auth:s,addons:n=[],orm:o="drizzle",runtime:i="bun",frontend:c=["tanstack-router"],backend:p="hono"}=e,b=c.includes("react-router"),m=c.includes("tanstack-router"),w=c.includes("native"),u=c.includes("next"),d=c.includes("tanstack-start"),y=c.includes("svelte"),S=c.includes("nuxt"),$=r==="npm"?"npm run":r,A="3001";return(b||y)&&(A="5173"),`# ${t}
2
+ import*as e from"node:path";import t from"node:path";import{cancel as n,confirm as r,group as i,intro as a,isCancel as o,log as s,multiselect as c,outro as l,password as u,select as d,spinner as f,text as p}from"@clack/prompts";import m,{consola as h}from"consola";import g from"fs-extra";import _ from"picocolors";import v from"yargs";import{hideBin as y}from"yargs/helpers";import{fileURLToPath as b}from"node:url";import{$ as x,execa as S}from"execa";import C from"node:os";import{globby as w}from"globby";import T from"handlebars";import E from"gradient-string";const D=()=>{let e=process.env.npm_config_user_agent;return e?.startsWith(`pnpm`)?`pnpm`:e?.startsWith(`bun`)?`bun`:`npm`},O=b(import.meta.url),k=t.dirname(O),A=t.join(k,`../`),j={projectName:`my-better-t-app`,frontend:[`tanstack-router`],database:`sqlite`,orm:`drizzle`,auth:!0,addons:[],examples:[],git:!0,packageManager:D(),install:!0,dbSetup:`none`,backend:`hono`,runtime:`bun`,api:`trpc`},M={"better-auth":`^1.2.7`,"@better-auth/expo":`^1.2.7`,"drizzle-orm":`^0.38.4`,"drizzle-kit":`^0.30.5`,"@libsql/client":`^0.14.0`,pg:`^8.14.1`,"@types/pg":`^8.11.11`,mysql2:`^3.14.0`,"@prisma/client":`^6.6.0`,prisma:`^6.6.0`,"vite-plugin-pwa":`^0.21.2`,"@vite-pwa/assets-generator":`^0.2.6`,"@tauri-apps/cli":`^2.4.0`,"@biomejs/biome":`1.9.4`,husky:`^9.1.7`,"lint-staged":`^15.5.0`,"@hono/node-server":`^1.14.0`,tsx:`^4.19.2`,"@types/node":`^22.13.11`,"@types/bun":`^1.2.6`,"@elysiajs/node":`^1.2.6`,"@elysiajs/cors":`^1.2.0`,"@elysiajs/trpc":`^1.1.0`,elysia:`^1.2.25`,"@hono/trpc-server":`^0.3.4`,hono:`^4.7.6`,cors:`^2.8.5`,express:`^5.1.0`,"@types/express":`^5.0.1`,"@types/cors":`^2.8.17`,turbo:`^2.4.2`,ai:`^4.2.8`,"@ai-sdk/google":`^1.2.3`,"@ai-sdk/vue":`^1.2.8`,"@ai-sdk/svelte":`^2.1.9`,"@prisma/extension-accelerate":`^1.3.0`,"@orpc/server":`^1.1.0`,"@orpc/client":`^1.1.0`,"@orpc/react-query":`^1.1.0`,"@orpc/vue-query":`^1.1.0`,"@orpc/svelte-query":`^1.1.0`,"@trpc/tanstack-react-query":`^11.0.0`,"@trpc/server":`^11.0.0`,"@trpc/client":`^11.0.0`},N=async e=>{let{dependencies:n=[],devDependencies:r=[],projectDir:i}=e,a=t.join(i,`package.json`),o=await g.readJson(a);o.dependencies||={},o.devDependencies||={};for(let e of n){let t=M[e];t?o.dependencies[e]=t:console.warn(`Warning: Dependency ${e} not found in version map.`)}for(let e of r){let t=M[e];t?o.devDependencies[e]=t:console.warn(`Warning: Dev dependency ${e} not found in version map.`)}await g.writeJson(a,o,{spaces:2})};function P(e,t){switch(e){case`pnpm`:return`pnpm dlx ${t}`;case`bun`:return`bunx ${t}`;default:return`npx ${t}`}}async function ee(e){let{projectName:n,packageManager:r}=e,i=t.resolve(process.cwd(),n),a=f();try{a.start(`Setting up Starlight docs...`);let e=[`docs`,`--template`,`starlight`,`--no-install`,`--add`,`tailwind`,`--no-git`,`--skip-houston`],n=e.join(` `),o=`create-astro@latest ${n}`,s=P(r,o);await S(s,{cwd:t.join(i,`apps`),env:{CI:`true`},shell:!0}),a.stop(`Starlight docs setup successfully!`)}catch(e){a.stop(_.red(`Failed to set up Starlight docs`)),e instanceof Error&&m.error(_.red(e.message))}}async function te(e){let{projectName:n,packageManager:r,frontend:i}=e,a=t.resolve(process.cwd(),n),o=f(),s=t.join(a,`apps/web`);if(await g.pathExists(s))try{o.start(`Setting up Tauri desktop app support...`),await N({devDependencies:[`@tauri-apps/cli`],projectDir:s});let e=t.join(s,`package.json`);if(await g.pathExists(e)){let t=await g.readJson(e);t.scripts={...t.scripts,tauri:`tauri`,"desktop:dev":`tauri dev`,"desktop:build":`tauri build`},await g.writeJson(e,t,{spaces:2})}let n=i.includes(`tanstack-router`),c=i.includes(`react-router`),l=i.includes(`nuxt`),u=i.includes(`svelte`),d=c||u?`http://localhost:5173`:`http://localhost:3001`,f=l?`../.output/public`:u?`../build`:`../dist`,p=[`init`,`--app-name=${t.basename(a)}`,`--window-title=${t.basename(a)}`,`--frontend-dist=${f}`,`--dev-url=${d}`,`--before-dev-command=\"${r} run dev\"`,`--before-build-command=\"${r} run build\"`],m=p.join(` `),h=`@tauri-apps/cli@latest ${m}`,_=P(r,h);await S(_,{cwd:s,env:{CI:`true`},shell:!0}),o.stop(`Tauri desktop app support configured successfully!`)}catch(e){o.stop(_.red(`Failed to set up Tauri`)),e instanceof Error&&h.error(_.red(e.message))}}async function ne(e){let{projectName:n,addons:r,frontend:i}=e,a=t.resolve(process.cwd(),n),o=i.includes(`react-router`)||i.includes(`tanstack-router`),s=i.includes(`nuxt`),c=i.includes(`svelte`);r.includes(`turborepo`)&&await N({devDependencies:[`turbo`],projectDir:a}),r.includes(`pwa`)&&o&&await oe(a,i),r.includes(`tauri`)&&(o||s||c)&&await te(e),r.includes(`biome`)&&await ie(a),r.includes(`husky`)&&await ae(a),r.includes(`starlight`)&&await ee(e)}function re(e,n){return n.some(e=>[`react-router`,`tanstack-router`,`nuxt`,`svelte`].includes(e)),t.join(e,`apps/web`)}async function ie(e){await N({devDependencies:[`@biomejs/biome`],projectDir:e});let n=t.join(e,`package.json`);if(await g.pathExists(n)){let e=await g.readJson(n);e.scripts={...e.scripts,check:`biome check --write .`},await g.writeJson(n,e,{spaces:2})}}async function ae(e){await N({devDependencies:[`husky`,`lint-staged`],projectDir:e});let n=t.join(e,`package.json`);if(await g.pathExists(n)){let e=await g.readJson(n);e.scripts={...e.scripts,prepare:`husky`},e[`lint-staged`]={"*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}":[`biome check --write .`]},await g.writeJson(n,e,{spaces:2})}}async function oe(e,n){let r=n.some(e=>[`react-router`,`tanstack-router`].includes(e));if(!r)return;let i=re(e,n);if(!await g.pathExists(i))return;await N({dependencies:[`vite-plugin-pwa`],devDependencies:[`@vite-pwa/assets-generator`],projectDir:i});let a=t.join(i,`package.json`);if(await g.pathExists(a)){let e=await g.readJson(a);e.scripts={...e.scripts,"generate-pwa-assets":`pwa-assets-generator`},await g.writeJson(a,e,{spaces:2})}}async function se(t){let{api:n,projectName:r,frontend:i}=t,a=e.resolve(process.cwd(),r),o=e.join(a,`apps/web`),s=e.join(a,`apps/server`),c=await g.pathExists(o),l=i.some(e=>[`tanstack-router`,`react-router`,`tanstack-start`,`next`].includes(e)),u=i.includes(`nuxt`),d=i.includes(`svelte`);if(n===`orpc`?await N({dependencies:[`@orpc/server`,`@orpc/client`],projectDir:s}):n===`trpc`&&(await N({dependencies:[`@trpc/server`,`@trpc/client`],projectDir:s}),t.backend===`hono`?await N({dependencies:[`@hono/trpc-server`],projectDir:s}):t.backend===`elysia`&&await N({dependencies:[`@elysiajs/trpc`],projectDir:s})),c&&(l?n===`orpc`?await N({dependencies:[`@orpc/react-query`,`@orpc/client`,`@orpc/server`],projectDir:o}):n===`trpc`&&await N({dependencies:[`@trpc/tanstack-react-query`,`@trpc/client`,`@trpc/server`],projectDir:o}):u?n===`orpc`&&await N({dependencies:[`@orpc/vue-query`,`@orpc/client`,`@orpc/server`],projectDir:o}):d&&n===`orpc`&&await N({dependencies:[`@orpc/svelte-query`,`@orpc/client`,`@orpc/server`],projectDir:o})),i.includes(`native`)){let t=e.join(a,`apps/native`);await g.pathExists(t)&&(n===`trpc`?await N({dependencies:[`@trpc/tanstack-react-query`,`@trpc/client`,`@trpc/server`],projectDir:t}):n===`orpc`&&await N({dependencies:[`@orpc/react-query`,`@orpc/client`,`@orpc/server`],projectDir:t}))}}async function ce(e){let{projectName:n,auth:r,frontend:i}=e;if(!r)return;let a=t.resolve(process.cwd(),n),o=t.join(a,`apps/server`),s=t.join(a,`apps/web`),c=t.join(a,`apps/native`),l=await g.pathExists(s),u=await g.pathExists(c);try{await N({dependencies:[`better-auth`],projectDir:o});let e=i.some(e=>[`react-router`,`tanstack-router`,`tanstack-start`,`next`,`nuxt`,`svelte`].includes(e));e&&l&&await N({dependencies:[`better-auth`],projectDir:s}),i.includes(`native`)&&u&&(await N({dependencies:[`better-auth`,`@better-auth/expo`],projectDir:c}),await N({dependencies:[`@better-auth/expo`],projectDir:o}))}catch(e){m.error(_.red(`Failed to configure authentication dependencies`)),e instanceof Error&&m.error(_.red(e.message))}}function le(e=32){let t=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`,n=``,r=t.length;for(let i=0;i<e;i++)n+=t.charAt(Math.floor(Math.random()*r));return n}async function ue(e){let{projectName:n,backend:r,runtime:i,api:a}=e,o=t.resolve(process.cwd(),n),s=r,c=t.join(o,`apps/server`),l=[],u=[];s===`hono`?(l.push(`hono`),a===`trpc`&&l.push(`@hono/trpc-server`),i===`node`&&(l.push(`@hono/node-server`),u.push(`tsx`,`@types/node`))):s===`elysia`?(l.push(`elysia`,`@elysiajs/cors`),a===`trpc`&&l.push(`@elysiajs/trpc`),i===`node`&&(l.push(`@elysiajs/node`),u.push(`tsx`,`@types/node`))):s===`express`&&(l.push(`express`,`cors`),u.push(`@types/express`,`@types/cors`),i===`node`&&u.push(`tsx`,`@types/node`)),i===`bun`&&u.push(`@types/bun`),await N({dependencies:l,devDependencies:u,projectDir:c})}async function de(e,n){let r=t.join(e,`README.md`),i=fe(n);try{await g.writeFile(r,i)}catch(e){m.error(`Failed to create README.md file:`,e)}}function fe(e){let{projectName:t,packageManager:n,database:r,auth:i,addons:a=[],orm:o=`drizzle`,runtime:s=`bun`,frontend:c=[`tanstack-router`],backend:l=`hono`}=e,u=c.includes(`react-router`),d=c.includes(`tanstack-router`),f=c.includes(`native`),p=c.includes(`next`),m=c.includes(`tanstack-start`),h=c.includes(`svelte`),g=c.includes(`nuxt`),_=n===`npm`?`npm run`:n,v=`3001`;return(u||h)&&(v=`5173`),`# ${t}
3
3
 
4
- This project was created with [Better-T-Stack](https://github.com/AmanVarshney01/create-better-t-stack), a modern TypeScript stack that combines React, ${m?"TanStack Router":b?"React Router":u?"Next.js":d?"TanStack Start":y?"SvelteKit":S?"Nuxt":""}, ${p[0].toUpperCase()+p.slice(1)}, tRPC, and more.
4
+ This project was created with [Better-T-Stack](https://github.com/AmanVarshney01/create-better-t-stack), a modern TypeScript stack that combines React, ${d?`TanStack Router`:u?`React Router`:p?`Next.js`:m?`TanStack Start`:h?`SvelteKit`:g?`Nuxt`:``}, ${l[0].toUpperCase()+l.slice(1)}, tRPC, and more.
5
5
 
6
6
  ## Features
7
7
 
8
- ${Ir(a,s,n,o,i,c,p)}
8
+ ${pe(r,i,a,o,s,c,l)}
9
9
 
10
10
  ## Getting Started
11
11
 
12
12
  First, install the dependencies:
13
13
 
14
14
  \`\`\`bash
15
- ${r} install
15
+ ${n} install
16
16
  \`\`\`
17
17
 
18
- ${Lr(a,s,$,o)}
18
+ ${me(r,i,_,o)}
19
19
 
20
20
  Then, run the development server:
21
21
 
22
22
  \`\`\`bash
23
- ${$} dev
23
+ ${_} dev
24
24
  \`\`\`
25
25
 
26
- ${m||b||u||d||y||S?`Open [http://localhost:${A}](http://localhost:${A}) in your browser to see the web application.`:""}
27
- ${w?`Use the Expo Go app to run the mobile application.
28
- `:""}
26
+ ${d||u||p||m||h||g?`Open [http://localhost:${v}](http://localhost:${v}) in your browser to see the web application.`:``}
27
+ ${f?`Use the Expo Go app to run the mobile application.
28
+ `:``}
29
29
  The API is running at [http://localhost:3000](http://localhost:3000).
30
30
 
31
- ${n.includes("pwa")&&b?`
31
+ ${a.includes(`pwa`)&&u?`
32
32
  ## PWA Support with React Router v7
33
33
 
34
34
  There is a known compatibility issue between VitePWA and React Router v7.
35
35
  See: https://github.com/vite-pwa/vite-plugin-pwa/issues/809
36
- `:""}
36
+ `:``}
37
37
 
38
38
  ## Project Structure
39
39
 
40
40
  \`\`\`
41
41
  ${t}/
42
- \u251C\u2500\u2500 apps/
43
- ${m||b||u||d||y||S?`\u2502 \u251C\u2500\u2500 web/ # Frontend application (${m?"React + TanStack Router":b?"React + React Router":u?"Next.js":d?"React + TanStack Start":y?"SvelteKit":S?"Nuxt":""})
44
- `:""}${w?`\u2502 \u251C\u2500\u2500 native/ # Mobile application (React Native, Expo)
45
- `:""}${n.includes("starlight")?`\u2502 \u251C\u2500\u2500 docs/ # Documentation site (Astro Starlight)
46
- `:""}\u2502 \u2514\u2500\u2500 server/ # Backend API (${p[0].toUpperCase()+p.slice(1)}, tRPC)
42
+ ├── apps/
43
+ ${d||u||p||m||h||g?`│ ├── web/ # Frontend application (${d?`React + TanStack Router`:u?`React + React Router`:p?`Next.js`:m?`React + TanStack Start`:h?`SvelteKit`:g?`Nuxt`:``})\n`:``}${f?`│ ├── native/ # Mobile application (React Native, Expo)
44
+ `:``}${a.includes(`starlight`)?`│ ├── docs/ # Documentation site (Astro Starlight)
45
+ `:``} └── server/ # Backend API (${l[0].toUpperCase()+l.slice(1)}, tRPC)
47
46
  \`\`\`
48
47
 
49
48
  ## Available Scripts
50
49
 
51
- ${Mr($,a,o,s,w,n,p)}
52
- `}function Ir(e,t,r,a,s,n,o){let i=n.includes("tanstack-router"),c=n.includes("react-router"),p=n.includes("native"),b=n.includes("next"),m=n.includes("tanstack-start"),w=n.includes("svelte"),u=n.includes("nuxt"),d=["- **TypeScript** - For type safety and improved developer experience"];i?d.push("- **TanStack Router** - File-based routing with full type safety"):c?d.push("- **React Router** - Declarative routing for React"):b?d.push("- **Next.js** - Full-stack React framework"):m?d.push("- **TanStack Start** - SSR framework with TanStack Router"):w?d.push("- **SvelteKit** - Web framework for building Svelte apps"):u&&d.push("- **Nuxt** - The Intuitive Vue Framework"),p&&(d.push("- **React Native** - Build mobile apps using React"),d.push("- **Expo** - Tools for React Native development")),d.push("- **TailwindCSS** - Utility-first CSS for rapid UI development","- **shadcn/ui** - Reusable UI components"),o==="hono"?d.push("- **Hono** - Lightweight, performant server framework"):o==="express"?d.push("- **Express** - Fast, unopinionated web framework"):o==="elysia"?d.push("- **Elysia** - Type-safe, high-performance framework"):o==="next"&&d.push("- **Next.js** - Full-stack React framework"),d.push("- **tRPC** - End-to-end type-safe APIs",`- **${s==="bun"?"Bun":"Node.js"}** - Runtime environment`),e!=="none"&&d.push(`- **${a==="drizzle"?"Drizzle":"Prisma"}** - TypeScript-first ORM`,`- **${e==="sqlite"?"SQLite/Turso":e==="postgres"?"PostgreSQL":e==="mysql"?"MySQL":"MongoDB"}** - Database engine`),t&&d.push("- **Authentication** - Email & password authentication with Better Auth");for(let y of r)y==="pwa"?d.push("- **PWA** - Progressive Web App support"):y==="tauri"?d.push("- **Tauri** - Build native desktop applications"):y==="biome"?d.push("- **Biome** - Linting and formatting"):y==="husky"?d.push("- **Husky** - Git hooks for code quality"):y==="starlight"&&d.push("- **Starlight** - Documentation site with Astro");return d.join(`
53
- `)}function Lr(e,t,r,a){if(e==="none")return"";let s=`## Database Setup
50
+ ${he(_,r,o,i,f,a,l)}
51
+ `}function pe(e,t,n,r,i,a,o){let s=a.includes(`tanstack-router`),c=a.includes(`react-router`),l=a.includes(`native`),u=a.includes(`next`),d=a.includes(`tanstack-start`),f=a.includes(`svelte`),p=a.includes(`nuxt`),m=[`- **TypeScript** - For type safety and improved developer experience`];s?m.push(`- **TanStack Router** - File-based routing with full type safety`):c?m.push(`- **React Router** - Declarative routing for React`):u?m.push(`- **Next.js** - Full-stack React framework`):d?m.push(`- **TanStack Start** - SSR framework with TanStack Router`):f?m.push(`- **SvelteKit** - Web framework for building Svelte apps`):p&&m.push(`- **Nuxt** - The Intuitive Vue Framework`),l&&(m.push(`- **React Native** - Build mobile apps using React`),m.push(`- **Expo** - Tools for React Native development`)),m.push(`- **TailwindCSS** - Utility-first CSS for rapid UI development`,`- **shadcn/ui** - Reusable UI components`),o===`hono`?m.push(`- **Hono** - Lightweight, performant server framework`):o===`express`?m.push(`- **Express** - Fast, unopinionated web framework`):o===`elysia`?m.push(`- **Elysia** - Type-safe, high-performance framework`):o===`next`&&m.push(`- **Next.js** - Full-stack React framework`),m.push(`- **tRPC** - End-to-end type-safe APIs`,`- **${i===`bun`?`Bun`:`Node.js`}** - Runtime environment`),e!==`none`&&m.push(`- **${r===`drizzle`?`Drizzle`:`Prisma`}** - TypeScript-first ORM`,`- **${e===`sqlite`?`SQLite/Turso`:e===`postgres`?`PostgreSQL`:e===`mysql`?`MySQL`:`MongoDB`}** - Database engine`),t&&m.push(`- **Authentication** - Email & password authentication with Better Auth`);for(let e of n)e===`pwa`?m.push(`- **PWA** - Progressive Web App support`):e===`tauri`?m.push(`- **Tauri** - Build native desktop applications`):e===`biome`?m.push(`- **Biome** - Linting and formatting`):e===`husky`?m.push(`- **Husky** - Git hooks for code quality`):e===`starlight`&&m.push(`- **Starlight** - Documentation site with Astro`);return m.join(`
52
+ `)}function me(e,t,n,r){if(e===`none`)return``;let i=`## Database Setup
54
53
 
55
- `;return e==="sqlite"?s+=`This project uses SQLite${a==="drizzle"?" with Drizzle ORM":" with Prisma"}.
54
+ `;return e===`sqlite`?i+=`This project uses SQLite${r===`drizzle`?` with Drizzle ORM`:` with Prisma`}.
56
55
 
57
56
  1. Start the local SQLite database:
58
57
  \`\`\`bash
59
- cd apps/server && ${r} db:local
58
+ cd apps/server && ${n} db:local
60
59
  \`\`\`
61
60
 
62
61
  2. Update your \`.env\` file in the \`apps/server\` directory with the appropriate connection details if needed.
63
- `:e==="postgres"?s+=`This project uses PostgreSQL${a==="drizzle"?" with Drizzle ORM":" with Prisma"}.
62
+ `:e===`postgres`?i+=`This project uses PostgreSQL${r===`drizzle`?` with Drizzle ORM`:` with Prisma`}.
64
63
 
65
64
  1. Make sure you have a PostgreSQL database set up.
66
65
  2. Update your \`apps/server/.env\` file with your PostgreSQL connection details.
67
- `:e==="mysql"?s+=`This project uses MySQL${a==="drizzle"?" with Drizzle ORM":" with Prisma"}.
66
+ `:e===`mysql`?i+=`This project uses MySQL${r===`drizzle`?` with Drizzle ORM`:` with Prisma`}.
68
67
 
69
68
  1. Make sure you have a MySQL database set up.
70
69
  2. Update your \`apps/server/.env\` file with your MySQL connection details.
71
- `:e==="mongodb"&&(s+=`This project uses MongoDB with Prisma ORM.
70
+ `:e===`mongodb`&&(i+=`This project uses MongoDB with Prisma ORM.
72
71
 
73
72
  1. Make sure you have MongoDB set up.
74
73
  2. Update your \`apps/server/.env\` file with your MongoDB connection URI.
75
- `),s+=`
76
- 3. ${a==="prisma"?`Generate the Prisma client and push the schema:
74
+ `),i+=`
75
+ 3. ${r===`prisma`?`Generate the Prisma client and push the schema:
77
76
  \`\`\`bash
78
- ${r} db:push
77
+ ${n} db:push
79
78
  \`\`\``:`Apply the schema to your database:
80
79
  \`\`\`bash
81
- ${r} db:push
80
+ ${n} db:push
82
81
  \`\`\``}
83
- `,s}function Mr(e,t,r,a,s,n,o){let i=`- \`${e} dev\`: Start all applications in development mode
82
+ `,i}function he(e,t,n,r,i,a,o){let s=`- \`${e} dev\`: Start all applications in development mode
84
83
  - \`${e} build\`: Build all applications
85
84
  - \`${e} dev:web\`: Start only the web application
86
85
  - \`${e} dev:server\`: Start only the server
87
- - \`${e} check-types\`: Check TypeScript types across all apps`;return s&&(i+=`
88
- - \`${e} dev:native\`: Start the React Native/Expo development server`),t!=="none"&&(i+=`
86
+ - \`${e} check-types\`: Check TypeScript types across all apps`;return i&&(s+=`
87
+ - \`${e} dev:native\`: Start the React Native/Expo development server`),t!==`none`&&(s+=`
89
88
  - \`${e} db:push\`: Push schema changes to database
90
- - \`${e} db:studio\`: Open database studio UI`,t==="sqlite"&&r==="drizzle"&&(i+=`
91
- - \`cd apps/server && ${e} db:local\`: Start the local SQLite database`)),n.includes("biome")&&(i+=`
92
- - \`${e} check\`: Run Biome formatting and linting`),n.includes("pwa")&&(i+=`
93
- - \`cd apps/web && ${e} generate-pwa-assets\`: Generate PWA assets`),n.includes("tauri")&&(i+=`
89
+ - \`${e} db:studio\`: Open database studio UI`,t===`sqlite`&&n===`drizzle`&&(s+=`
90
+ - \`cd apps/server && ${e} db:local\`: Start the local SQLite database`)),a.includes(`biome`)&&(s+=`
91
+ - \`${e} check\`: Run Biome formatting and linting`),a.includes(`pwa`)&&(s+=`
92
+ - \`cd apps/web && ${e} generate-pwa-assets\`: Generate PWA assets`),a.includes(`tauri`)&&(s+=`
94
93
  - \`cd apps/web && ${e} desktop:dev\`: Start Tauri desktop app in development
95
- - \`cd apps/web && ${e} desktop:build\`: Build Tauri desktop app`),n.includes("starlight")&&(i+=`
94
+ - \`cd apps/web && ${e} desktop:build\`: Build Tauri desktop app`),a.includes(`starlight`)&&(s+=`
96
95
  - \`cd apps/docs && ${e} dev\`: Start documentation site
97
- - \`cd apps/docs && ${e} build\`: Build documentation site`),i}import Ce from"node:path";import{spinner as ba}from"@clack/prompts";import wa from"consola";import ya from"fs-extra";import ht from"picocolors";import oe from"node:path";import{cancel as Or,isCancel as Ur,log as q,spinner as it,text as _r}from"@clack/prompts";import ie from"consola";import{execa as Wr}from"execa";import Y from"fs-extra";import E from"picocolors";import{execa as nt}from"execa";async function ne(e){try{return process.platform==="win32"?(await nt("where",[e])).exitCode===0:(await nt("which",[e])).exitCode===0}catch{return!1}}async function zr(){let e=it();e.start("Checking for MongoDB Atlas CLI");try{let t=await ne("atlas");return e.stop(t?"MongoDB Atlas CLI found":E.yellow("MongoDB Atlas CLI not found")),t}catch{return e.stop(E.red("Error checking for MongoDB Atlas CLI")),!1}}async function qr(e){try{if(!await zr())return ie.error(E.red("MongoDB Atlas CLI not found.")),q.info(E.yellow("Please install it from: https://www.mongodb.com/docs/atlas/cli/current/install-atlas-cli/")),null;q.info(E.blue("Running MongoDB Atlas setup...")),await Wr("atlas",["deployments","setup"],{cwd:e,stdio:"inherit"}),q.info(E.green("Atlas setup complete!"));let r=await _r({message:"Enter your MongoDB connection string:",placeholder:"mongodb+srv://username:password@cluster.mongodb.net/database",validate(a){if(!a)return"Please enter a connection string";if(!a.startsWith("mongodb"))return"URL should start with mongodb:// or mongodb+srv://"}});return Ur(r)?(Or("MongoDB setup cancelled"),null):{connectionString:r}}catch(t){return t instanceof Error&&ie.error(E.red(t.message)),null}}async function ye(e,t){try{let r=oe.join(e,"apps/server",".env");await Y.ensureDir(oe.dirname(r));let a="";await Y.pathExists(r)&&(a=await Y.readFile(r,"utf8"));let s=t?`DATABASE_URL="${t.connectionString}"`:'DATABASE_URL="mongodb://localhost:27017/mydb"';a.includes("DATABASE_URL=")?a=a.replace(/DATABASE_URL=.*(\r?\n|$)/,`${s}$1`):a+=`
98
- ${s}`,await Y.writeFile(r,a.trim())}catch{ie.error("Failed to update environment configuration")}}function ot(){q.info(`
99
- ${E.green("MongoDB Atlas Manual Setup Instructions:")}
96
+ - \`cd apps/docs && ${e} build\`: Build documentation site`),s}async function F(e){try{let t=process.platform===`win32`;if(t){let t=await S(`where`,[e]);return t.exitCode===0}let n=await S(`which`,[e]);return n.exitCode===0}catch{return!1}}async function ge(){let e=f();e.start(`Checking for MongoDB Atlas CLI`);try{let t=await F(`atlas`);return e.stop(t?`MongoDB Atlas CLI found`:_.yellow(`MongoDB Atlas CLI not found`)),t}catch{return e.stop(_.red(`Error checking for MongoDB Atlas CLI`)),!1}}async function _e(e){try{let t=await ge();if(!t)return m.error(_.red(`MongoDB Atlas CLI not found.`)),s.info(_.yellow(`Please install it from: https://www.mongodb.com/docs/atlas/cli/current/install-atlas-cli/`)),null;s.info(_.blue(`Running MongoDB Atlas setup...`)),await S(`atlas`,[`deployments`,`setup`],{cwd:e,stdio:`inherit`}),s.info(_.green(`Atlas setup complete!`));let r=await p({message:`Enter your MongoDB connection string:`,placeholder:`mongodb+srv://username:password@cluster.mongodb.net/database`,validate(e){if(!e)return`Please enter a connection string`;if(!e.startsWith(`mongodb`))return`URL should start with mongodb:// or mongodb+srv://`}});return o(r)?(n(`MongoDB setup cancelled`),null):{connectionString:r}}catch(e){return e instanceof Error&&m.error(_.red(e.message)),null}}async function I(e,n){try{let r=t.join(e,`apps/server`,`.env`);await g.ensureDir(t.dirname(r));let i=``;await g.pathExists(r)&&(i=await g.readFile(r,`utf8`));let a=n?`DATABASE_URL="${n.connectionString}"`:`DATABASE_URL="mongodb://localhost:27017/mydb"`;i.includes(`DATABASE_URL=`)?i=i.replace(/DATABASE_URL=.*(\r?\n|$)/,`${a}$1`):i+=`\n${a}`,await g.writeFile(r,i.trim())}catch{m.error(`Failed to update environment configuration`)}}function L(){s.info(`
97
+ ${_.green(`MongoDB Atlas Manual Setup Instructions:`)}
100
98
 
101
99
  1. Install Atlas CLI:
102
- ${E.blue("https://www.mongodb.com/docs/atlas/cli/stable/install-atlas-cli/")}
100
+ ${_.blue(`https://www.mongodb.com/docs/atlas/cli/stable/install-atlas-cli/`)}
103
101
 
104
102
  2. Run the following command and follow the prompts:
105
- ${E.blue("atlas deployments setup")}
103
+ ${_.blue(`atlas deployments setup`)}
106
104
 
107
105
  3. Get your connection string from the Atlas dashboard:
108
- Format: ${E.dim("mongodb+srv://USERNAME:PASSWORD@CLUSTER.mongodb.net/DATABASE_NAME")}
106
+ Format: ${_.dim(`mongodb+srv://USERNAME:PASSWORD@CLUSTER.mongodb.net/DATABASE_NAME`)}
109
107
 
110
108
  4. Add the connection string to your .env file:
111
- ${E.dim('DATABASE_URL="your_connection_string"')}
112
- `)}async function ct(e){let{projectName:t}=e,r=oe.resolve(process.cwd(),t),a=it();a.start("Setting up MongoDB Atlas");let s=oe.join(r,"apps/server");try{await Y.ensureDir(s),a.stop("Starting MongoDB Atlas setup");let n=await qr(s);n?(await ye(r,n),q.success(E.green("MongoDB Atlas setup complete! Connection saved to .env file."))):(q.warn(E.yellow("Falling back to local MongoDB configuration")),await ye(r),ot())}catch(n){a.stop(E.red("MongoDB Atlas setup failed")),ie.error(E.red(`Error during MongoDB Atlas setup: ${n instanceof Error?n.message:String(n)}`));try{await ye(r),ot()}catch{}}}import L from"node:path";import{cancel as Vr,isCancel as Gr,log as K,password as Jr,spinner as Pe}from"@clack/prompts";import{consola as je}from"consola";import{execa as Qr}from"execa";import F from"fs-extra";import V from"picocolors";async function Hr(e,t){let r=Pe();try{r.start("Initializing Prisma PostgreSQL");let a=L.join(e,"prisma");await F.ensureDir(a),r.stop("Initializing Prisma. Follow the prompts below:");let s=R(t,"prisma init --db");await Qr(s,{cwd:e,stdio:"inherit",shell:!0}),K.info(V.yellow(`Please copy the Prisma Postgres URL from the output above.
113
- It looks like: prisma+postgres://accelerate.prisma-data.net/?api_key=...`));let n=await Jr({message:"Paste your Prisma Postgres database URL:",validate(o){if(!o)return"Please enter a database URL";if(!o.startsWith("prisma+postgres://"))return"URL should start with prisma+postgres://"}});return Gr(n)?(Vr("Database setup cancelled"),null):{databaseUrl:n}}catch(a){return r.stop(V.red("Failed to initialize Prisma PostgreSQL")),a instanceof Error&&je.error(a.message),null}}async function ve(e,t){try{let r=L.join(e,"apps/server",".env");await F.ensureDir(L.dirname(r));let a="";await F.pathExists(r)&&(a=await F.readFile(r,"utf8"));let s=t?`DATABASE_URL="${t.databaseUrl}"`:'DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"';a.includes("DATABASE_URL=")?a=a.replace(/DATABASE_URL=.*(\r?\n|$)/,`${s}$1`):a+=`
114
- ${s}`,await F.writeFile(r,a.trim())}catch{je.error("Failed to update environment configuration")}}function pt(){K.info(`Manual Prisma PostgreSQL Setup Instructions:
109
+ ${_.dim(`DATABASE_URL="your_connection_string"`)}
110
+ `)}async function ve(e){let{projectName:n}=e,r=t.resolve(process.cwd(),n),i=f();i.start(`Setting up MongoDB Atlas`);let a=t.join(r,`apps/server`);try{await g.ensureDir(a),i.stop(`Starting MongoDB Atlas setup`);let e=await _e(a);e?(await I(r,e),s.success(_.green(`MongoDB Atlas setup complete! Connection saved to .env file.`))):(s.warn(_.yellow(`Falling back to local MongoDB configuration`)),await I(r),L())}catch(e){i.stop(_.red(`MongoDB Atlas setup failed`)),m.error(_.red(`Error during MongoDB Atlas setup: ${e instanceof Error?e.message:String(e)}`));try{await I(r),L()}catch{}}}async function ye(e,r){let i=f();try{i.start(`Initializing Prisma PostgreSQL`);let a=t.join(e,`prisma`);await g.ensureDir(a),i.stop(`Initializing Prisma. Follow the prompts below:`);let c=P(r,`prisma init --db`);await S(c,{cwd:e,stdio:`inherit`,shell:!0}),s.info(_.yellow(`Please copy the Prisma Postgres URL from the output above.
111
+ It looks like: prisma+postgres://accelerate.prisma-data.net/?api_key=...`));let l=await u({message:`Paste your Prisma Postgres database URL:`,validate(e){if(!e)return`Please enter a database URL`;if(!e.startsWith(`prisma+postgres://`))return`URL should start with prisma+postgres://`}});return o(l)?(n(`Database setup cancelled`),null):{databaseUrl:l}}catch(e){return i.stop(_.red(`Failed to initialize Prisma PostgreSQL`)),e instanceof Error&&h.error(e.message),null}}async function R(e,n){try{let r=t.join(e,`apps/server`,`.env`);await g.ensureDir(t.dirname(r));let i=``;await g.pathExists(r)&&(i=await g.readFile(r,`utf8`));let a=n?`DATABASE_URL="${n.databaseUrl}"`:`DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"`;i.includes(`DATABASE_URL=`)?i=i.replace(/DATABASE_URL=.*(\r?\n|$)/,`${a}$1`):i+=`\n${a}`,await g.writeFile(r,i.trim())}catch{h.error(`Failed to update environment configuration`)}}function z(){s.info(`Manual Prisma PostgreSQL Setup Instructions:
115
112
 
116
113
  1. Visit https://console.prisma.io and create an account
117
114
  2. Create a new PostgreSQL database from the dashboard
118
115
  3. Get your database URL
119
116
  4. Add the database URL to the .env file in apps/server/.env
120
117
 
121
- DATABASE_URL="your_database_url"`)}async function Yr(e){try{await v({dependencies:["@prisma/extension-accelerate"],projectDir:e});let t=L.join(e,"prisma/index.ts");await F.writeFile(t,`
118
+ DATABASE_URL="your_database_url"`)}async function be(e){try{await N({dependencies:[`@prisma/extension-accelerate`],projectDir:e});let n=t.join(e,`prisma/index.ts`),r=`
122
119
  import { PrismaClient } from "./generated/client";
123
120
  import { withAccelerate } from "@prisma/extension-accelerate";
124
121
 
125
122
  const prisma = new PrismaClient().$extends(withAccelerate());
126
123
 
127
124
  export default prisma;
128
- `.trim());let a=L.join(e,"src/db/index.ts");if(await F.pathExists(a)){let s=await F.readFile(a,"utf8");s.includes("@prisma/extension-accelerate")||(s=`import { withAccelerate } from "@prisma/extension-accelerate";
129
- ${s}`,s=s.replace("export const db = new PrismaClient();","export const db = new PrismaClient().$extends(withAccelerate());"),await F.writeFile(a,s))}return!0}catch{return K.warn(V.yellow("Could not add Prisma Accelerate extension automatically")),!1}}async function lt(e){let{projectName:t,packageManager:r}=e,a=L.resolve(process.cwd(),t),s=L.join(a,"apps/server"),n=Pe();n.start("Setting up Prisma PostgreSQL");try{await F.ensureDir(s),n.stop("Starting Prisma setup");let o=await Hr(s,r);if(o)await ve(a,o),await Yr(s),K.success(V.green("Prisma PostgreSQL database configured successfully!"));else{let i=Pe();i.start("Setting up fallback configuration"),await ve(a),i.stop("Manual setup required"),pt()}}catch(o){n.stop(V.red("Prisma PostgreSQL setup failed")),je.error(V.red(`Error during Prisma PostgreSQL setup: ${o instanceof Error?o.message:String(o)}`));try{await ve(a),pt()}catch{}K.info("Setup completed with manual configuration required.")}}import Kr from"node:os";import pe from"node:path";import{cancel as xe,confirm as Xr,isCancel as Se,log as G,select as Zr,spinner as J,text as ea}from"@clack/prompts";import ta from"consola";import{$ as B}from"execa";import dt from"fs-extra";import C from"picocolors";async function ra(){return ne("turso")}async function aa(){try{return!(await B`turso auth whoami`).stdout.includes("You are not logged in")}catch{return!1}}async function sa(){let e=J();try{return e.start("Logging in to Turso..."),await B`turso auth login`,e.stop("Logged in to Turso successfully!"),!0}catch{e.stop(C.red("Failed to log in to Turso"))}}async function na(e){let t=J();try{if(t.start("Installing Turso CLI..."),e)await B`brew install tursodatabase/tap/turso`;else{let{stdout:r}=await B`curl -sSfL https://get.tur.so/install.sh`;await B`bash -c '${r}'`}return t.stop("Turso CLI installed successfully!"),!0}catch(r){if(r instanceof Error&&r.message.includes("User force closed"))throw t.stop("Turso CLI installation cancelled"),G.warn(C.yellow("Turso CLI installation cancelled by user")),new Error("Installation cancelled");t.stop(C.red("Failed to install Turso CLI"))}}async function oa(){let e=J();try{e.start("Fetching Turso groups...");let{stdout:t}=await B`turso group list`,r=t.trim().split(`
130
- `);if(r.length<=1)return e.stop("No Turso groups found"),[];let a=r.slice(1).map(s=>{let[n,o,i,c]=s.trim().split(/\s{2,}/);return{name:n,locations:o,version:i,status:c}});return e.stop(`Found ${a.length} Turso groups`),a}catch(t){return e.stop(C.red("Error fetching Turso groups")),console.error("Error fetching Turso groups:",t),[]}}async function ia(){let e=await oa();if(e.length===0)return null;if(e.length===1)return G.info(`Using the only available group: ${C.blue(e[0].name)}`),e[0].name;let t=e.map(a=>({value:a.name,label:`${a.name} (${a.locations})`})),r=await Zr({message:"Select a Turso database group:",options:t});return Se(r)&&(xe(C.red("Operation cancelled")),process.exit(0)),r}async function ca(e,t){let r=J();try{r.start(`Creating Turso database "${e}"${t?` in group "${t}"`:""}...`),t?await B`turso db create ${e} --group ${t}`:await B`turso db create ${e}`,r.stop(`Created database "${e}"`)}catch(a){if(r.stop(C.red(`Failed to create database "${e}"`)),a instanceof Error&&a.message.includes("already exists"))throw new Error("DATABASE_EXISTS")}r.start("Retrieving database connection details...");try{let{stdout:a}=await B`turso db show ${e} --url`,{stdout:s}=await B`turso db tokens create ${e}`;return r.stop("Retrieved database connection details"),{dbUrl:a.trim(),authToken:s.trim()}}catch{r.stop(C.red("Failed to retrieve database connection details"))}}async function ce(e,t){let r=pe.join(e,"apps/server",".env"),a=t?`DATABASE_URL="${t.dbUrl}"
131
- DATABASE_AUTH_TOKEN="${t.authToken}"`:`DATABASE_URL=
132
- DATABASE_AUTH_TOKEN=`;await dt.ensureDir(pe.dirname(r)),await dt.writeFile(r,a)}function ke(){G.info(`Manual Turso Setup Instructions:
125
+ `;await g.writeFile(n,r.trim());let i=t.join(e,`src/db/index.ts`);if(await g.pathExists(i)){let e=await g.readFile(i,`utf8`);e.includes(`@prisma/extension-accelerate`)||(e=`import { withAccelerate } from "@prisma/extension-accelerate";\n${e}`,e=e.replace(`export const db = new PrismaClient();`,`export const db = new PrismaClient().$extends(withAccelerate());`),await g.writeFile(i,e))}return!0}catch{return s.warn(_.yellow(`Could not add Prisma Accelerate extension automatically`)),!1}}async function xe(e){let{projectName:n,packageManager:r}=e,i=t.resolve(process.cwd(),n),a=t.join(i,`apps/server`),o=f();o.start(`Setting up Prisma PostgreSQL`);try{await g.ensureDir(a),o.stop(`Starting Prisma setup`);let e=await ye(a,r);if(e)await R(i,e),await be(a),s.success(_.green(`Prisma PostgreSQL database configured successfully!`));else{let e=f();e.start(`Setting up fallback configuration`),await R(i),e.stop(`Manual setup required`),z()}}catch(e){o.stop(_.red(`Prisma PostgreSQL setup failed`)),h.error(_.red(`Error during Prisma PostgreSQL setup: ${e instanceof Error?e.message:String(e)}`));try{await R(i),z()}catch{}s.info(`Setup completed with manual configuration required.`)}}async function Se(){return F(`turso`)}async function Ce(){try{let e=await x`turso auth whoami`;return!e.stdout.includes(`You are not logged in`)}catch{return!1}}async function we(){let e=f();try{return e.start(`Logging in to Turso...`),await x`turso auth login`,e.stop(`Logged in to Turso successfully!`),!0}catch{e.stop(_.red(`Failed to log in to Turso`))}}async function Te(e){let t=f();try{if(t.start(`Installing Turso CLI...`),e)await x`brew install tursodatabase/tap/turso`;else{let{stdout:e}=await x`curl -sSfL https://get.tur.so/install.sh`;await x`bash -c '${e}'`}return t.stop(`Turso CLI installed successfully!`),!0}catch(e){if(e instanceof Error&&e.message.includes(`User force closed`))throw t.stop(`Turso CLI installation cancelled`),s.warn(_.yellow(`Turso CLI installation cancelled by user`)),Error(`Installation cancelled`);t.stop(_.red(`Failed to install Turso CLI`))}}async function Ee(){let e=f();try{e.start(`Fetching Turso groups...`);let{stdout:t}=await x`turso group list`,n=t.trim().split(`
126
+ `);if(n.length<=1)return e.stop(`No Turso groups found`),[];let r=n.slice(1).map(e=>{let[t,n,r,i]=e.trim().split(/\s{2,}/);return{name:t,locations:n,version:r,status:i}});return e.stop(`Found ${r.length} Turso groups`),r}catch(t){return e.stop(_.red(`Error fetching Turso groups`)),console.error(`Error fetching Turso groups:`,t),[]}}async function De(){let e=await Ee();if(e.length===0)return null;if(e.length===1)return s.info(`Using the only available group: ${_.blue(e[0].name)}`),e[0].name;let t=e.map(e=>({value:e.name,label:`${e.name} (${e.locations})`})),r=await d({message:`Select a Turso database group:`,options:t});return o(r)&&(n(_.red(`Operation cancelled`)),process.exit(0)),r}async function Oe(e,t){let n=f();try{n.start(`Creating Turso database "${e}"${t?` in group "${t}"`:``}...`),t?await x`turso db create ${e} --group ${t}`:await x`turso db create ${e}`,n.stop(`Created database "${e}"`)}catch(t){if(n.stop(_.red(`Failed to create database "${e}"`)),t instanceof Error&&t.message.includes(`already exists`))throw Error(`DATABASE_EXISTS`)}n.start(`Retrieving database connection details...`);try{let{stdout:t}=await x`turso db show ${e} --url`,{stdout:r}=await x`turso db tokens create ${e}`;return n.stop(`Retrieved database connection details`),{dbUrl:t.trim(),authToken:r.trim()}}catch{n.stop(_.red(`Failed to retrieve database connection details`))}}async function B(e,n){let r=t.join(e,`apps/server`,`.env`),i=n?`DATABASE_URL="${n.dbUrl}"
127
+ DATABASE_AUTH_TOKEN="${n.authToken}"`:`DATABASE_URL=
128
+ DATABASE_AUTH_TOKEN=`;await g.ensureDir(t.dirname(r)),await g.writeFile(r,i)}function V(){s.info(`Manual Turso Setup Instructions:
133
129
 
134
130
  1. Visit https://turso.tech and create an account
135
131
  2. Create a new database from the dashboard
@@ -137,85 +133,43 @@ DATABASE_AUTH_TOKEN=`;await dt.ensureDir(pe.dirname(r)),await dt.writeFile(r,a)}
137
133
  4. Add these credentials to the .env file in apps/server/.env
138
134
 
139
135
  DATABASE_URL=your_database_url
140
- DATABASE_AUTH_TOKEN=your_auth_token`)}async function ut(e){let{projectName:t,orm:r}=e,a=pe.resolve(process.cwd(),t),s=r==="drizzle",n=J();n.start("Setting up Turso database");try{let o=Kr.platform(),i=o==="darwin",c=o==="linux";if(o==="win32"){n.stop(C.yellow("Turso setup not supported on Windows")),G.warn(C.yellow("Automatic Turso setup is not supported on Windows.")),await ce(a),ke();return}if(n.stop("Checking Turso CLI"),!await ra()){let S=await Xr({message:"Would you like to install Turso CLI?",initialValue:!0});if(Se(S)&&(xe(C.red("Operation cancelled")),process.exit(0)),!S){await ce(a),ke();return}await na(i)}await aa()||await sa();let w=await ia(),u=!1,d="",y=pe.basename(a);for(;!u;){let S=await ea({message:"Enter a name for your database:",defaultValue:y,initialValue:y,placeholder:y});Se(S)&&(xe(C.red("Operation cancelled")),process.exit(0)),d=S;try{let $=await ca(d,w),A=J();A.start("Writing configuration to .env file"),await ce(a,$),A.stop("Turso database configured successfully!"),u=!0}catch($){$ instanceof Error&&$.message==="DATABASE_EXISTS"&&(G.warn(C.yellow(`Database "${C.red(d)}" already exists`)),y=`${d}-${Math.floor(Math.random()*1e3)}`)}}}catch(o){n.stop(C.red("Failed to set up Turso database")),ta.error(C.red(`Error during Turso setup: ${o instanceof Error?o.message:String(o)}`)),await ce(a),ke(),G.success("Setup completed with manual configuration required.")}}import X from"node:path";import{cancel as pa,isCancel as la,log as $e,spinner as De,text as da}from"@clack/prompts";import{consola as le}from"consola";import{execa as ua}from"execa";import Ae from"fs-extra";import M from"picocolors";async function Ee(e,t,r){let a=De();try{let s=R(e,t);a&&a.start(r);let n=await ua(s,{shell:!0});return a&&a.stop(r),n}catch(s){throw a&&a.stop(M.red(`Failed: ${r}`)),s}}async function ma(e){try{let r=await Ee(e,"neonctl projects list");return!r.stdout.includes("not authenticated")&&!r.stdout.includes("error")}catch{return!1}}async function fa(e){try{return await Ee(e,"neonctl auth","Authenticating with Neon..."),$e.success("Authenticated with Neon successfully!"),!0}catch{le.error(M.red("Failed to authenticate with Neon"))}}async function ha(e,t){try{let r=`neonctl projects create --name "${e}" --output json`,{stdout:a}=await Ee(t,r,`Creating Neon project "${e}"...`),s=JSON.parse(a);if(s.project&&s.connection_uris&&s.connection_uris.length>0){let n=s.project.id,o=s.connection_uris[0].connection_uri,i=s.connection_uris[0].connection_parameters;return{connectionString:o,projectId:n,dbName:i.database,roleName:i.role}}return le.error(M.red("Failed to extract connection information from response")),null}catch{le.error(M.red("Failed to create Neon project"))}}async function mt(e,t){let r=X.join(e,"apps/server",".env"),a=t?`DATABASE_URL="${t.connectionString}"`:'DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"';return await Ae.ensureDir(X.dirname(r)),await Ae.writeFile(r,a),!0}function ga(){$e.info(`Manual Neon PostgreSQL Setup Instructions:
136
+ DATABASE_AUTH_TOKEN=your_auth_token`)}async function ke(e){let{projectName:i,orm:a}=e,c=t.resolve(process.cwd(),i),l=a===`drizzle`,u=f();u.start(`Setting up Turso database`);try{let e=C.platform(),i=e===`darwin`,a=e===`linux`,l=e===`win32`;if(l){u.stop(_.yellow(`Turso setup not supported on Windows`)),s.warn(_.yellow(`Automatic Turso setup is not supported on Windows.`)),await B(c),V();return}u.stop(`Checking Turso CLI`);let d=await Se();if(!d){let e=await r({message:`Would you like to install Turso CLI?`,initialValue:!0});if(o(e)&&(n(_.red(`Operation cancelled`)),process.exit(0)),!e){await B(c),V();return}await Te(i)}let m=await Ce();m||await we();let h=await De(),g=!1,v=``,y=t.basename(c);for(;!g;){let e=await p({message:`Enter a name for your database:`,defaultValue:y,initialValue:y,placeholder:y});o(e)&&(n(_.red(`Operation cancelled`)),process.exit(0)),v=e;try{let e=await Oe(v,h),t=f();t.start(`Writing configuration to .env file`),await B(c,e),t.stop(`Turso database configured successfully!`),g=!0}catch(e){e instanceof Error&&e.message===`DATABASE_EXISTS`&&(s.warn(_.yellow(`Database "${_.red(v)}" already exists`)),y=`${v}-${Math.floor(Math.random()*1e3)}`)}}}catch(e){u.stop(_.red(`Failed to set up Turso database`)),m.error(_.red(`Error during Turso setup: ${e instanceof Error?e.message:String(e)}`)),await B(c),V(),s.success(`Setup completed with manual configuration required.`)}}async function H(e,t,n){let r=f();try{let i=P(e,t);r&&r.start(n);let a=await S(i,{shell:!0});return r&&r.stop(n),a}catch(e){throw r&&r.stop(_.red(`Failed: ${n}`)),e}}async function Ae(e){try{let t=`neonctl projects list`,n=await H(e,t);return!n.stdout.includes(`not authenticated`)&&!n.stdout.includes(`error`)}catch{return!1}}async function je(e){try{return await H(e,`neonctl auth`,`Authenticating with Neon...`),s.success(`Authenticated with Neon successfully!`),!0}catch{h.error(_.red(`Failed to authenticate with Neon`))}}async function Me(e,t){try{let n=`neonctl projects create --name "${e}" --output json`,{stdout:r}=await H(t,n,`Creating Neon project "${e}"...`),i=JSON.parse(r);if(i.project&&i.connection_uris&&i.connection_uris.length>0){let e=i.project.id,t=i.connection_uris[0].connection_uri,n=i.connection_uris[0].connection_parameters;return{connectionString:t,projectId:e,dbName:n.database,roleName:n.role}}return h.error(_.red(`Failed to extract connection information from response`)),null}catch{h.error(_.red(`Failed to create Neon project`))}}async function U(e,n){let r=t.join(e,`apps/server`,`.env`),i=n?`DATABASE_URL="${n.connectionString}"`:`DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"`;return await g.ensureDir(t.dirname(r)),await g.writeFile(r,i),!0}function Ne(){s.info(`Manual Neon PostgreSQL Setup Instructions:
141
137
 
142
138
  1. Visit https://neon.tech and create an account
143
139
  2. Create a new project from the dashboard
144
140
  3. Get your connection string
145
141
  4. Add the database URL to the .env file in apps/server/.env
146
142
 
147
- DATABASE_URL="your_connection_string"`)}async function ft(e){let{projectName:t,packageManager:r}=e,a=X.resolve(process.cwd(),t),s=De();s.start("Setting up Neon PostgreSQL");try{let n=await ma(r);s.stop("Setting up Neon PostgreSQL"),n||($e.info("Please authenticate with Neon to continue:"),await fa(r));let o=X.basename(a),i=await da({message:"Enter a name for your Neon project:",defaultValue:o,initialValue:o});la(i)&&(pa(M.red("Operation cancelled")),process.exit(0));let c=await ha(i,r);if(!c)throw new Error("Failed to create project - couldn't get connection information");let p=De();p.start("Configuring database connection"),await Ae.ensureDir(X.join(a,"apps/server")),await mt(a,c),p.stop("Neon database configured successfully!")}catch(n){s.stop(M.red("Neon PostgreSQL setup failed")),n instanceof Error&&le.error(M.red(n.message)),await mt(a),ga()}}async function gt(e){let{projectName:t,database:r,orm:a,dbSetup:s}=e,n=Ce.resolve(process.cwd(),t),o=ba(),i=Ce.join(n,"apps/server");if(r==="none"){await ya.remove(Ce.join(i,"src/db"));return}try{a==="prisma"?await v({dependencies:["@prisma/client"],devDependencies:["prisma"],projectDir:i}):a==="drizzle"&&(r==="sqlite"?await v({dependencies:["drizzle-orm","@libsql/client"],devDependencies:["drizzle-kit"],projectDir:i}):r==="postgres"?await v({dependencies:["drizzle-orm","pg"],devDependencies:["drizzle-kit","@types/pg"],projectDir:i}):r==="mysql"&&await v({dependencies:["drizzle-orm","mysql2"],devDependencies:["drizzle-kit"],projectDir:i})),r==="sqlite"&&s==="turso"?await ut(e):r==="postgres"?a==="prisma"&&s==="prisma-postgres"?await lt(e):s==="neon"&&await ft(e):r==="mongodb"&&s==="mongodb-atlas"&&await ct(e)}catch(c){o.stop(ht.red("Failed to set up database")),c instanceof Error&&wa.error(ht.red(c.message))}}import I from"node:path";import de from"fs-extra";async function Te(e,t){await de.ensureDir(I.dirname(e));let r="";await de.pathExists(e)&&(r=await de.readFile(e,"utf8"));let a=!1;for(let{key:s,value:n,condition:o}of t)if(o){let i=new RegExp(`^${s}=.*$`,"m");i.test(r)?n&&(r=r.replace(i,`${s}=${n}`),a=!0):(r+=`
148
- ${s}=${n}`,a=!0)}a&&await de.writeFile(e,r.trim())}async function bt(e){let{projectName:t}=e,r=I.resolve(process.cwd(),t),a=e,s=I.join(r,"apps/server"),n=I.join(s,".env"),o=a.frontend.includes("react-router"),i=a.frontend.includes("tanstack-router"),c=a.frontend.includes("tanstack-start"),p=a.frontend.includes("next"),b=a.frontend.includes("nuxt"),m=a.frontend.includes("svelte"),w=o||i||c||p||b||m,u="http://localhost:3001";o||m?u="http://localhost:5173":(i||c||p||b)&&(u="http://localhost:3001");let d="",y=a.dbSetup==="turso"||a.dbSetup==="prisma-postgres"||a.dbSetup==="mongodb-atlas"||a.dbSetup==="neon";y||(a.database==="postgres"?d="postgresql://postgres:postgres@localhost:5432/mydb?schema=public":a.database==="mysql"?d="mysql://root:password@localhost:3306/mydb":a.database==="mongodb"?d="mongodb://localhost:27017/mydatabase":a.database==="sqlite"&&(d="file:./local.db"));let S=[{key:"CORS_ORIGIN",value:u,condition:!0},{key:"BETTER_AUTH_SECRET",value:tt(),condition:!!a.auth},{key:"BETTER_AUTH_URL",value:"http://localhost:3000",condition:!!a.auth},{key:"DATABASE_URL",value:d,condition:a.database!=="none"&&d!==""&&!y},{key:"GOOGLE_GENERATIVE_AI_API_KEY",value:"",condition:a.examples?.includes("ai")||!1}];if(await Te(n,S),w){let $=I.join(r,"apps/web"),A="VITE_SERVER_URL";p?A="NEXT_PUBLIC_SERVER_URL":b?A="NUXT_PUBLIC_SERVER_URL":m&&(A="PUBLIC_SERVER_URL");let be=[{key:A,value:"http://localhost:3000",condition:!0}];await Te(I.join($,".env"),be)}if(a.frontend.includes("native")){let $=I.join(r,"apps/native"),A=[{key:"EXPO_PUBLIC_SERVER_URL",value:"http://localhost:3000",condition:!0}];await Te(I.join($,".env"),A)}}import Re from"node:path";import va from"fs-extra";async function wt(e){let{projectName:t,examples:r,frontend:a}=e,s=Re.resolve(process.cwd(),t);if(r.includes("ai")){let n=Re.join(s,"apps/web"),o=Re.join(s,"apps/server"),i=await va.pathExists(n),c=a.includes("nuxt"),p=a.includes("svelte");if(i){let b=["ai"];c?b.push("@ai-sdk/vue"):p&&b.push("@ai-sdk/svelte"),await v({dependencies:b,projectDir:n})}await v({dependencies:["ai","@ai-sdk/google"],projectDir:o})}}import{log as Pa,spinner as yt}from"@clack/prompts";import ja from"consola";import{$ as vt}from"execa";import ue from"picocolors";async function Pt({projectDir:e,packageManager:t,addons:r=[]}){let a=yt();try{a.start(`Running ${t} install...`),await vt({cwd:e,stderr:"inherit"})`${t} install`,a.stop("Dependencies installed successfully"),(r.includes("biome")||r.includes("husky"))&&await ka(e,t)}catch(s){a.stop(ue.red("Failed to install dependencies")),s instanceof Error&&ja.error(ue.red(`Installation error: ${s.message}`))}}async function ka(e,t){let r=yt();try{r.start("Running Biome format check..."),await vt({cwd:e,stderr:"inherit"})`${t} biome check --write .`,r.stop("Biome check completed successfully")}catch{r.stop(ue.yellow("Biome check encountered issues")),Pa.warn(ue.yellow("Some files may need manual formatting"))}}import{consola as xa}from"consola";import j from"picocolors";function jt(e){let{database:t,projectName:r,packageManager:a,depsInstalled:s,orm:n,addons:o,runtime:i,frontend:c}=e,p=a==="npm"?"npm run":a,b=`cd ${r}`,m=o?.includes("husky")||o?.includes("biome"),w=t!=="none"?Aa(t,n,p,i):"",u=o?.includes("tauri")?$a(p):"",d=m?Da(p):"",y=c?.includes("native")?Sa():"",S=o?.includes("pwa")&&(c?.includes("react-router")||c?.includes("tanstack-router"))?Ea():"",$=o?.includes("starlight")?Ca(p):"",A=c?.some(br=>["tanstack-router","react-router","next","tanstack-start","nuxt","svelte"].includes(br)),be=c?.includes("native"),Ie=a==="bun"&&be&&A?Ra():"",Le=t!=="none"&&n==="none"?Ta():"",lr=c?.includes("tanstack-router"),dr=c?.includes("tanstack-start"),Me=c?.includes("react-router"),ur=c?.includes("nuxt"),Oe=c?.includes("svelte"),Ue=lr||Me||dr||ur||Oe,mr=c?.includes("native"),fr=Ue||mr,hr=Me||Oe?"5173":"3001",gr=R(a,"taze -r");xa.box(`${j.bold("Next steps")}
149
- ${j.cyan("1.")} ${b}
150
- ${s?"":`${j.cyan("2.")} ${a} install
151
- `}${j.cyan(s?"2.":"3.")} ${p} dev
152
-
153
- ${j.bold("Your project will be available at:")}
154
- ${fr?`${Ue?`${j.cyan("\u2022")} Frontend: http://localhost:${hr}
155
- `:""}`:`${j.yellow("NOTE:")} You are creating a backend-only app (no frontend selected)
156
- `}${j.cyan("\u2022")} Backend: http://localhost:3000
157
- ${o?.includes("starlight")?`${j.cyan("\u2022")} Docs: http://localhost:4321
158
- `:""}${y?`
159
- ${y.trim()}`:""}${w?`
160
- ${w.trim()}`:""}${u?`
161
- ${u.trim()}`:""}${d?`
162
- ${d.trim()}`:""}${S?`
163
- ${S.trim()}`:""}${$?`
164
- ${$.trim()}`:""}${Le?`
165
- ${Le.trim()}`:""}${Ie?`
166
- ${Ie.trim()}`:""}
167
-
168
- ${j.bold(`Update all dependencies:
169
- `)}${j.cyan(gr)}
170
-
171
- ${j.bold("Like Better-T Stack?")} Please consider giving us a star on GitHub:
172
- ${j.cyan("https://github.com/AmanVarshney01/create-better-t-stack")}`)}function Sa(){return`${j.yellow("NOTE:")} For Expo connectivity issues, update apps/native/.env
173
- with your local IP:
174
- EXPO_PUBLIC_SERVER_URL=http://192.168.0.103:3000
175
- `}function Da(e){return`${j.bold("Linting and formatting:")}
176
- ${j.cyan("\u2022")} Format and lint fix: ${`${e} check`}
177
-
178
- `}function Aa(e,t,r,a){let s=[];return t==="prisma"?(e==="sqlite"&&s.push(`${j.yellow("NOTE:")} Turso support with Prisma is in Early Access and requires additional setup.`,"Learn more at: https://www.prisma.io/docs/orm/overview/databases/turso"),a==="bun"&&s.push(`${j.yellow("NOTE:")} Prisma with Bun may require additional configuration. If you encounter errors,
179
- follow the guidance provided in the error messages`),s.push(`${j.cyan("\u2022")} Apply schema: ${`${r} db:push`}`),s.push(`${j.cyan("\u2022")} Database UI: ${`${r} db:studio`}`)):t==="drizzle"&&(s.push(`${j.cyan("\u2022")} Apply schema: ${`${r} db:push`}`),s.push(`${j.cyan("\u2022")} Database UI: ${`${r} db:studio`}`)),s.length?`${j.bold("Database commands:")}
180
- ${s.join(`
181
- `)}
182
-
183
- `:""}function $a(e){return`
184
- ${j.bold("Desktop app with Tauri:")}
185
- ${j.cyan("\u2022")} Start desktop app: ${`cd apps/web && ${e} desktop:dev`}
186
- ${j.cyan("\u2022")} Build desktop app: ${`cd apps/web && ${e} desktop:build`}
187
- ${j.yellow("NOTE:")} Tauri requires Rust and platform-specific dependencies.
188
- See: https://v2.tauri.app/start/prerequisites/
189
-
190
- `}function Ea(){return`${j.bold("PWA with React Router v7:")}
191
- ${j.yellow("NOTE:")} There is a known compatibility issue between VitePWA and React Router v7.
192
- See: https://github.com/vite-pwa/vite-plugin-pwa/issues/809
193
- `}function Ca(e){return`${j.bold("Documentation with Starlight:")}
194
- ${j.cyan("\u2022")} Start docs site: ${`cd apps/docs && ${e} dev`}
195
- ${j.cyan("\u2022")} Build docs site: ${`cd apps/docs && ${e} build`}
196
- `}function Ta(){return`
197
- ${j.yellow("WARNING:")} Database selected without an ORM. Features requiring database access (e.g., examples, auth) need manual setup.
198
- `}function Ra(){return`
199
- ${j.yellow("WARNING:")} 'bun' might cause issues with web + native apps in a monorepo. Use 'pnpm' if problems arise.
200
- `}import xt from"node:path";import{log as Na}from"@clack/prompts";import{$ as kt,execa as Fa}from"execa";import Q from"fs-extra";import Ba from"picocolors";async function St(e,t){await Ia(e,t),await La(e,t)}async function Ia(e,t){let r=xt.join(e,"package.json");if(await Q.pathExists(r)){let a=await Q.readJson(r);a.name=t.projectName;let s={dev:"turbo dev",build:"turbo build","check-types":"turbo check-types","dev:native":"turbo -F native dev","dev:web":"turbo -F web dev","dev:server":"turbo -F server dev","db:push":"turbo -F server db:push","db:studio":"turbo -F server db:studio"},n={dev:"pnpm -r dev",build:"pnpm -r build","check-types":"pnpm -r check-types","dev:native":"pnpm --filter native dev","dev:web":"pnpm --filter web dev","dev:server":"pnpm --filter server dev","db:push":"pnpm --filter server db:push","db:studio":"pnpm --filter server db:studio"},o={dev:"npm run dev --workspaces",build:"npm run build --workspaces","check-types":"npm run check-types --workspaces","dev:native":"npm run dev --workspace native","dev:web":"npm run dev --workspace web","dev:server":"npm run dev --workspace server","db:push":"npm run db:push --workspace server","db:studio":"npm run db:studio --workspace server"},i={dev:"bun run --filter '*' dev",build:"bun run --filter '*' build","check-types":"bun run --filter '*' check-types","dev:native":"bun run --filter native dev","dev:web":"bun run --filter web dev","dev:server":"bun run --filter server dev","db:push":"bun run --filter server db:push","db:studio":"bun run --filter server db:studio"};t.addons.includes("turborepo")?a.scripts=s:t.packageManager==="pnpm"?a.scripts=n:t.packageManager==="npm"?a.scripts=o:t.packageManager==="bun"?a.scripts=i:a.scripts={};let{stdout:c}=await Fa(t.packageManager,["-v"],{cwd:e});a.packageManager=`${t.packageManager}@${c.trim()}`,await Q.writeJson(r,a,{spaces:2})}}async function La(e,t){let r=xt.join(e,"apps/server/package.json");if(await Q.pathExists(r)){let a=await Q.readJson(r);t.database!=="none"&&(t.database==="sqlite"&&t.orm==="drizzle"&&(a.scripts["db:local"]="turso dev --db-file local.db"),t.orm==="prisma"?(a.scripts["db:push"]="prisma db push --schema ./prisma/schema",a.scripts["db:studio"]="prisma studio"):t.orm==="drizzle"&&(a.scripts["db:push"]="drizzle-kit push",a.scripts["db:studio"]="drizzle-kit studio")),await Q.writeJson(r,a,{spaces:2})}}async function Dt(e,t){if(!t)return;if((await kt({cwd:e,reject:!1,stderr:"pipe"})`git --version`).exitCode!==0){Na.warn(Ba.yellow("Git is not installed"));return}let a=await kt({cwd:e,reject:!1,stderr:"pipe"})`git init`;if(a.exitCode!==0)throw new Error(`Git initialization failed: ${a.stderr}`)}import me from"node:path";import fe from"fs-extra";async function At(e){let{projectName:t,runtime:r,backend:a}=e,s=me.resolve(process.cwd(),t);if(a==="next")return;let n=me.join(s,"apps/server");r==="bun"?await Ma(n,a):r==="node"&&await Oa(n,a)}async function Ma(e,t){let r=me.join(e,"package.json"),a=await fe.readJson(r);a.scripts={...a.scripts,dev:"bun run --hot src/index.ts",start:"bun run dist/src/index.js"},await fe.writeJson(r,a,{spaces:2}),await v({devDependencies:["@types/bun"],projectDir:e})}async function Oa(e,t){let r=me.join(e,"package.json"),a=await fe.readJson(r);a.scripts={...a.scripts,dev:"tsx watch src/index.ts",start:"node dist/src/index.js"},await fe.writeJson(r,a,{spaces:2}),await v({devDependencies:["tsx","@types/node"],projectDir:e}),t==="hono"?await v({dependencies:["@hono/node-server"],projectDir:e}):t==="elysia"&&await v({dependencies:["@elysiajs/node"],projectDir:e})}import l from"node:path";import Z from"consola";import f from"fs-extra";import{globby as Wa}from"globby";import ee from"picocolors";import Ua from"node:path";import _a from"consola";import Ne from"fs-extra";import he from"handlebars";async function Fe(e,t,r){try{let a=await Ne.readFile(e,"utf-8"),n=he.compile(a)(r);await Ne.ensureDir(Ua.dirname(t)),await Ne.writeFile(t,n)}catch(a){throw _a.error(`Error processing template ${e}:`,a),new Error(`Failed to process template ${e}`)}}he.registerHelper("or",(e,t)=>e||t);he.registerHelper("eq",(e,t)=>e===t);he.registerHelper("includes",(e,t)=>Array.isArray(e)&&e.includes(t));async function x(e,t,r,a,s=!0){let n=await Wa(e,{cwd:t,dot:!0,onlyFiles:!0,absolute:!1});for(let o of n){let i=l.join(t,o),c=o;o.endsWith(".hbs")&&(c=o.slice(0,-4)),l.basename(o)==="_gitignore"&&(c=l.join(l.dirname(o),".gitignore")),l.basename(o)==="_npmrc"&&(c=l.join(l.dirname(o),".npmrc"));let p=l.join(r,c);await f.ensureDir(l.dirname(p)),!(!s&&await f.pathExists(p))&&(i.endsWith(".hbs")?await Fe(i,p,a):await f.copy(i,p,{overwrite:!0}))}}async function $t(e,t){let r=l.join(k,"templates/base");await x(["**/*"],r,e,t)}async function Et(e,t){let r=t.frontend.some(o=>["tanstack-router","react-router","tanstack-start","next"].includes(o)),a=t.frontend.includes("nuxt"),s=t.frontend.includes("svelte"),n=t.frontend.includes("native");if(r||a||s){let o=l.join(e,"apps/web");if(await f.ensureDir(o),r){let i=l.join(k,"templates/frontend/react/web-base");await f.pathExists(i)&&await x("**/*",i,o,t);let c=t.frontend.find(p=>["tanstack-router","react-router","tanstack-start","next"].includes(p));if(c){let p=l.join(k,`templates/frontend/react/${c}`);await f.pathExists(p)&&await x("**/*",p,o,t);let b=l.join(k,`templates/api/${t.api}/web/react/base`);await f.pathExists(b)&&await x("**/*",b,o,t)}}else if(a){let i=l.join(k,"templates/frontend/nuxt");await f.pathExists(i)&&await x("**/*",i,o,t);let c=l.join(k,`templates/api/${t.api}/web/nuxt`);await f.pathExists(c)&&await x("**/*",c,o,t)}else if(s){let i=l.join(k,"templates/frontend/svelte");if(await f.pathExists(i)&&await x("**/*",i,o,t),t.api==="orpc"){let c=l.join(k,`templates/api/${t.api}/web/svelte`);await f.pathExists(c)&&await x("**/*",c,o,t)}}}if(n){let o=l.join(e,"apps/native");await f.ensureDir(o);let i=l.join(k,"templates/frontend/native");if(await f.pathExists(i)&&await x("**/*",i,o,t),t.api==="trpc"){let c=l.join(k,`templates/api/${t.api}/native`);await f.pathExists(c)&&await x("**/*",c,o,t)}else if(t.api==="orpc"){let c=l.join(k,`templates/api/${t.api}/native`);await f.pathExists(c)&&await x("**/*",c,o,t)}}}async function Ct(e,t){if(t.backend==="none")return;let r=l.join(e,"apps/server");await f.ensureDir(r);let a=l.join(k,"templates/backend/server-base");await f.pathExists(a)?await x("**/*",a,r,t):Z.warn(ee.yellow(`Warning: server-base template not found at ${a}`));let s=l.join(k,`templates/backend/${t.backend}`);await f.pathExists(s)?await x("**/*",s,r,t):Z.warn(ee.yellow(`Warning: Backend template directory not found, skipping: ${s}`));let n=l.join(k,`templates/api/${t.api}/server/base`);await f.pathExists(n)&&await x("**/*",n,r,t);let o=l.join(k,`templates/api/${t.api}/server/${t.backend}`);await f.pathExists(o)&&await x("**/*",o,r,t)}async function Tt(e,t){if(t.orm==="none"||t.database==="none")return;let r=l.join(e,"apps/server");await f.ensureDir(r);let a=l.join(k,`templates/db/${t.orm}/${t.database}`);await f.pathExists(a)?await x("**/*",a,r,t):Z.warn(ee.yellow(`Warning: Database/ORM template directory not found, skipping: ${a}`))}async function Rt(e,t){if(!t.auth)return;let r=l.join(e,"apps/server"),a=l.join(e,"apps/web"),s=l.join(e,"apps/native"),n=await f.pathExists(r),o=await f.pathExists(a),i=await f.pathExists(s),c=t.frontend.some(w=>["tanstack-router","react-router","tanstack-start","next"].includes(w)),p=t.frontend.includes("nuxt"),b=t.frontend.includes("svelte"),m=t.frontend.includes("native");if(n){let w=l.join(k,"templates/auth/server/base");if(await f.pathExists(w)&&await x("**/*",w,r,t),t.backend==="next"){let u=l.join(k,"templates/auth/server/next");await f.pathExists(u)&&await x("**/*",u,r,t)}if(t.orm!=="none"&&t.database!=="none"){let u=t.orm,d=t.database,y="";u==="drizzle"?y=l.join(k,`templates/auth/server/db/drizzle/${d}`):u==="prisma"&&(y=l.join(k,`templates/auth/server/db/prisma/${d}`)),y&&await f.pathExists(y)?await x("**/*",y,r,t):Z.warn(ee.yellow(`Warning: Auth template for ${u}/${d} not found at ${y}`))}}if((c||p||b)&&o){if(c){let w=l.join(k,"templates/auth/web/react/base");await f.pathExists(w)&&await x("**/*",w,a,t);let u=t.frontend.find(d=>["tanstack-router","react-router","tanstack-start","next"].includes(d));if(u){let d=l.join(k,`templates/auth/web/react/${u}`);await f.pathExists(d)&&await x("**/*",d,a,t)}}else if(p){let w=l.join(k,"templates/auth/web/nuxt");await f.pathExists(w)&&await x("**/*",w,a,t)}else if(b&&t.api==="orpc"){let w=l.join(k,"templates/auth/web/svelte");await f.pathExists(w)&&await x("**/*",w,a,t)}}if(m&&i){let w=l.join(k,"templates/auth/native");await f.pathExists(w)?await x("**/*",w,s,t):Z.warn(ee.yellow(`Warning: Auth native template not found at ${w}`))}}async function Nt(e,t){if(!(!t.addons||t.addons.length===0))for(let r of t.addons){if(r==="none")continue;let a=l.join(k,`templates/addons/${r}`),s=e;r==="pwa"&&(a=l.join(k,"templates/addons/pwa/apps/web"),s=l.join(e,"apps/web"),!await f.pathExists(s))||await f.pathExists(a)&&await x("**/*",a,s,t)}}async function Ft(e,t){if(!t.examples||t.examples.length===0)return;let r=l.join(e,"apps/server"),a=l.join(e,"apps/web"),s=await f.pathExists(r),n=await f.pathExists(a),o=t.frontend.some(p=>["tanstack-router","react-router","tanstack-start","next"].includes(p)),i=t.frontend.includes("nuxt"),c=t.frontend.includes("svelte");for(let p of t.examples){if(p==="none")continue;let b=l.join(k,`templates/examples/${p}`);if(s){let m=l.join(b,"server");if(await f.pathExists(m)&&t.orm!=="none"){let w=l.join(m,t.orm,"base");if(await f.pathExists(w)&&await x("**/*",w,r,t,!1),t.database!=="none"){let u=l.join(m,t.orm,t.database);await f.pathExists(u)&&await x("**/*",u,r,t,!1)}}}if(o&&n){let m=l.join(b,"web/react");if(await f.pathExists(m)){let w=t.frontend.find(u=>["next","react-router","tanstack-router","tanstack-start"].includes(u));if(w){let u=l.join(m,w);await f.pathExists(u)&&await x("**/*",u,a,t,!1)}}}else if(i&&n){if(t.api==="orpc"){let m=l.join(b,"web/nuxt");await f.pathExists(m)&&await x("**/*",m,a,t,!1)}}else if(c&&n&&t.api==="orpc"){let m=l.join(b,"web/svelte");await f.pathExists(m)&&await x("**/*",m,a,t,!1)}}}async function Bt(e,t){let r=l.join(k,"templates/extras");if(t.packageManager==="pnpm"){let a=l.join(r,"pnpm-workspace.yaml"),s=l.join(e,"pnpm-workspace.yaml");await f.pathExists(a)&&await f.copy(a,s)}if(t.packageManager==="pnpm"&&(t.frontend.includes("native")||t.frontend.includes("nuxt"))){let a=l.join(r,"_npmrc.hbs"),s=l.join(e,".npmrc");await f.pathExists(a)&&await Fe(a,s,t)}}async function It(e){let t=za.resolve(process.cwd(),e.projectName);try{return await Ga.ensureDir(t),await $t(t,e),await Et(t,e),await Ct(t,e),await at(e),await Tt(t,e),await gt(e),await Rt(t,e),await et(e),await Nt(t,e),e.addons.length>0&&e.addons[0]!=="none"&&await Qe(e),await Ft(t,e),await Bt(t,e),e.examples.length>0&&e.examples[0]!=="none"&&await wt(e),await Ye(e),await At(e),await bt(e),await St(t,e),await st(t,e),await Dt(t,e.git),Va.success("Project template successfully scaffolded!"),e.install&&await Pt({projectDir:t,packageManager:e.packageManager,addons:e.addons}),jt({...e,depsInstalled:e.install}),t}catch(r){r instanceof Error&&(qa(Ja.red(`Error during project creation: ${r.message}`)),console.error(r.stack),process.exit(1))}}import{cancel as Ys,group as Ks}from"@clack/prompts";import Xs from"picocolors";import{cancel as Qa,isCancel as Ha,multiselect as Ya}from"@clack/prompts";import Ka from"picocolors";async function Lt(e,t){if(e!==void 0)return e;let r=t?.includes("react-router")||t?.includes("tanstack-router"),a=t?.includes("react-router")||t?.includes("tanstack-router")||t?.includes("nuxt")||t?.includes("svelte"),n=[{value:"turborepo",label:"Turborepo (Recommended)",hint:"Optimize builds for monorepos"},{value:"starlight",label:"Starlight",hint:"Add Astro Starlight documentation site"},{value:"biome",label:"Biome",hint:"Add Biome for linting and formatting"},{value:"husky",label:"Husky",hint:"Add Git hooks with Husky, lint-staged (requires Biome)"},{value:"pwa",label:"PWA (Progressive Web App)",hint:"Make your app installable and work offline"},{value:"tauri",label:"Tauri Desktop App",hint:"Build native desktop apps from your web frontend"}].filter(c=>c.value==="pwa"?r:c.value==="tauri"?a:!0),o=P.addons.filter(c=>n.some(p=>p.value===c)),i=await Ya({message:"Select addons",options:n,initialValues:o,required:!1});return Ha(i)&&(Qa(Ka.red("Operation cancelled")),process.exit(0)),i.includes("husky")&&!i.includes("biome")&&i.push("biome"),i}import{cancel as Xa,isCancel as Za,select as es}from"@clack/prompts";import ts from"picocolors";async function Mt(e,t){if(e)return e;let r=t?.includes("nuxt"),a=t?.includes("svelte"),s=[{value:"trpc",label:"tRPC",hint:"End-to-end typesafe APIs made easy"},{value:"orpc",label:"oRPC",hint:"End-to-end type-safe APIs that adhere to OpenAPI standards"}];(r||a)&&(s=[{value:"orpc",label:"oRPC",hint:`End-to-end type-safe APIs (Required for ${r?"Nuxt":"Svelte"} frontend)`}]);let n=await es({message:"Select API type",options:s,initialValue:r||a?"orpc":P.api});return Za(n)&&(Xa(ts.red("Operation cancelled")),process.exit(0)),(r||a)&&n!=="orpc"?"orpc":n}import{cancel as rs,confirm as as,isCancel as ss}from"@clack/prompts";import ns from"picocolors";async function Ot(e,t){if(!t)return!1;if(e!==void 0)return e;let r=await as({message:"Add authentication with Better-Auth?",initialValue:P.auth});return ss(r)&&(rs(ns.red("Operation cancelled")),process.exit(0)),r}import{cancel as os,isCancel as is,select as cs}from"@clack/prompts";import ps from"picocolors";async function Ut(e){if(e!==void 0)return e;let t=await cs({message:"Select backend framework",options:[{value:"hono",label:"Hono",hint:"Lightweight, ultrafast web framework"},{value:"next",label:"Next.js",hint:"Full-stack framework with API routes"},{value:"express",label:"Express",hint:"Fast, unopinionated, minimalist web framework for Node.js"},{value:"elysia",label:"Elysia",hint:"Ergonomic web framework for building backend servers"}],initialValue:P.backend});return is(t)&&(os(ps.red("Operation cancelled")),process.exit(0)),t}import{cancel as ls,isCancel as ds,select as us}from"@clack/prompts";import ms from"picocolors";async function _t(e){if(e!==void 0)return e;let t=await us({message:"Select database",options:[{value:"none",label:"None",hint:"No database setup"},{value:"sqlite",label:"SQLite",hint:"lightweight, server-less, embedded relational database"},{value:"postgres",label:"PostgreSQL",hint:"powerful, open source object-relational database system"},{value:"mysql",label:"MySQL",hint:"popular open-source relational database system"},{value:"mongodb",label:"MongoDB",hint:"open-source NoSQL database that stores data in JSON-like documents called BSON"}],initialValue:P.database});return ds(t)&&(ls(ms.red("Operation cancelled")),process.exit(0)),t}import{cancel as fs,isCancel as hs,select as gs}from"@clack/prompts";import bs from"picocolors";async function Wt(e,t,r){if(t!==void 0)return t;if(e==="sqlite"&&r==="prisma")return"none";let a=[];if(e==="sqlite")a=[{value:"turso",label:"Turso",hint:"SQLite for Production. Powered by libSQL"},{value:"none",label:"None",hint:"Manual setup"}];else if(e==="postgres")a=[{value:"neon",label:"Neon Postgres",hint:"Serverless Postgres with branching capability"},...r==="prisma"?[{value:"prisma-postgres",label:"Prisma Postgres",hint:"Instant Postgres for Global Applications"}]:[],{value:"none",label:"None",hint:"Manual setup"}];else if(e==="mongodb")a=[{value:"mongodb-atlas",label:"MongoDB Atlas",hint:"The most effective way to deploy MongoDB"},{value:"none",label:"None",hint:"Manual setup"}];else return"none";let s=await gs({message:`Select ${e} setup option`,options:a,initialValue:"none"});return hs(s)&&(fs(bs.red("Operation cancelled")),process.exit(0)),s}import{cancel as ws,isCancel as ys,multiselect as vs}from"@clack/prompts";import Ps from"picocolors";async function zt(e,t,r,a){if(e!==void 0)return e;if(t==="none")return[];if(!(r?.includes("react-router")||r?.includes("tanstack-router")||r?.includes("tanstack-start")||r?.includes("next")||r?.includes("nuxt")||r?.includes("svelte")))return[];let n=[],o=[{value:"todo",label:"Todo App",hint:"A simple CRUD example app"}];return a!=="elysia"&&o.push({value:"ai",label:"AI Chat",hint:"A simple AI chat interface using AI SDK"}),n=await vs({message:"Include examples",options:o,required:!1,initialValues:P.examples}),ys(n)&&(ws(Ps.red("Operation cancelled")),process.exit(0)),n}import{cancel as qt,isCancel as Vt,multiselect as js,select as ks}from"@clack/prompts";import Gt from"picocolors";async function Jt(e){if(e!==void 0)return e;let t=await js({message:"Select platforms to develop for",options:[{value:"web",label:"Web",hint:"React, Vue or Svelte Web Application"},{value:"native",label:"Native",hint:"Create a React Native/Expo app"}],required:!1,initialValues:P.frontend.some(a=>a==="tanstack-router"||a==="react-router"||a==="tanstack-start"||a==="next"||a==="nuxt"||a==="svelte")?["web"]:[]});Vt(t)&&(qt(Gt.red("Operation cancelled")),process.exit(0));let r=[];if(t.includes("web")){let a=await ks({message:"Choose frontend framework",options:[{value:"tanstack-router",label:"TanStack Router",hint:"Modern and scalable routing for React Applications"},{value:"react-router",label:"React Router",hint:"A user\u2011obsessed, standards\u2011focused, multi\u2011strategy router"},{value:"next",label:"Next.js",hint:"The React Framework for the Web"},{value:"nuxt",label:"Nuxt",hint:"The Progressive Web Framework for Vue.js"},{value:"svelte",label:"Svelte",hint:"web development for the rest of us"},{value:"tanstack-start",label:"TanStack Start (beta)",hint:"SSR, Server Functions, API Routes and more with TanStack Router"}],initialValue:P.frontend.find(s=>s==="tanstack-router"||s==="react-router"||s==="tanstack-start"||s==="next"||s==="nuxt"||s==="svelte")||"tanstack-router"});Vt(a)&&(qt(Gt.red("Operation cancelled")),process.exit(0)),r.push(a)}return t.includes("native")&&r.push("native"),r}import{cancel as xs,confirm as Ss,isCancel as Ds}from"@clack/prompts";import As from"picocolors";async function Qt(e){if(e!==void 0)return e;let t=await Ss({message:"Initialize git repository?",initialValue:P.git});return Ds(t)&&(xs(As.red("Operation cancelled")),process.exit(0)),t}import{cancel as $s,confirm as Es,isCancel as Cs}from"@clack/prompts";import Ts from"picocolors";async function Ht(e){if(e!==void 0)return e;let t=await Es({message:"Install dependencies?",initialValue:P.install});return Cs(t)&&($s(Ts.red("Operation cancelled")),process.exit(0)),t}import{cancel as Rs,isCancel as Ns,log as Fs,select as Bs}from"@clack/prompts";import Is from"picocolors";async function Yt(e,t,r){if(!t)return"none";if(e!==void 0)return e;if(r==="mongodb")return Fs.info("Only Prisma is supported with MongoDB."),"prisma";let a=await Bs({message:"Select ORM",options:[{value:"drizzle",label:"Drizzle",hint:"lightweight and performant TypeScript ORM"},{value:"prisma",label:"Prisma",hint:"Powerful, feature-rich ORM"}],initialValue:P.orm});return Ns(a)&&(Rs(Is.red("Operation cancelled")),process.exit(0)),a}import{cancel as Ls,isCancel as Ms,select as Os}from"@clack/prompts";import Us from"picocolors";async function Kt(e){if(e!==void 0)return e;let t=re(),r=await Os({message:"Choose package manager",options:[{value:"npm",label:"npm",hint:"Node Package Manager"},{value:"pnpm",label:"pnpm",hint:"Fast, disk space efficient package manager"},{value:"bun",label:"bun",hint:"All-in-one JavaScript runtime & toolkit"}],initialValue:t});return Ms(r)&&(Ls(Us.red("Operation cancelled")),process.exit(0)),r}import te from"node:path";import{cancel as _s,isCancel as Ws,text as zs}from"@clack/prompts";import O from"fs-extra";import qs from"picocolors";var Vs=["<",">",":",'"',"|","?","*"],Xt=255;function Zt(e){if(e!=="."){if(!e)return"Project name cannot be empty";if(e.length>Xt)return`Project name must be less than ${Xt} characters`;if(Vs.some(t=>e.includes(t)))return"Project name contains invalid characters";if(e.startsWith(".")||e.startsWith("-"))return"Project name cannot start with a dot or dash";if(e.toLowerCase()==="node_modules")return"Project name is reserved"}}async function ge(e){if(e)if(e==="."){let n=process.cwd();if(O.readdirSync(n).length===0)return e}else{let n=te.basename(e);if(!Zt(n)){let i=te.resolve(process.cwd(),e);if(!O.pathExistsSync(i)||O.readdirSync(i).length===0)return e}}let t=!1,r="",a=P.projectName,s=1;for(;O.pathExistsSync(te.resolve(process.cwd(),a));)a=`${P.projectName}-${s}`,s++;for(;!t;){let n=await zs({message:"Enter your project name or path (relative to current directory)",placeholder:a,initialValue:e,defaultValue:a,validate:o=>{let i=o.trim()||a;if(i==="."){if(O.readdirSync(process.cwd()).length>0)return"Current directory is not empty. Please choose a different directory.";t=!0;return}let c=te.resolve(process.cwd(),i),p=te.basename(c),b=Zt(p);if(b)return b;if(!c.startsWith(process.cwd()))return"Project path must be within current directory";if(O.pathExistsSync(c)&&O.readdirSync(c).length>0)return`Directory "${i}" already exists and is not empty. Please choose a different name or path.`;t=!0}});Ws(n)&&(_s(qs.red("Operation cancelled.")),process.exit(0)),r=n||a}return r}import{cancel as Gs,isCancel as Js,select as Qs}from"@clack/prompts";import Hs from"picocolors";async function er(e,t){if(e!==void 0)return e;if(t==="next")return"node";let r=await Qs({message:"Select runtime",options:[{value:"bun",label:"Bun",hint:"Fast all-in-one JavaScript runtime"},{value:"node",label:"Node.js",hint:"Traditional Node.js runtime"}],initialValue:P.runtime});return Js(r)&&(Gs(Hs.red("Operation cancelled")),process.exit(0)),r}async function tr(e){let t=await Ks({projectName:async()=>ge(e.projectName),frontend:()=>Jt(e.frontend),backend:()=>Ut(e.backend),runtime:({results:r})=>er(e.runtime,r.backend),database:()=>_t(e.database),orm:({results:r})=>Yt(e.orm,r.database!=="none",r.database),api:({results:r})=>Mt(e.api,r.frontend),auth:({results:r})=>Ot(e.auth,r.database!=="none"),addons:({results:r})=>Lt(e.addons,r.frontend),examples:({results:r})=>zt(e.examples,r.database,r.frontend,r.backend),dbSetup:({results:r})=>Wt(r.database??"none",e.dbSetup,r.orm),git:()=>Qt(e.git),packageManager:()=>Kt(e.packageManager),install:()=>Ht(e.install)},{onCancel:()=>{Ys(Xs.red("Operation cancelled")),process.exit(0)}});return{projectName:t.projectName,frontend:t.frontend,database:t.database,orm:t.orm,auth:t.auth,addons:t.addons,examples:t.examples,git:t.git,packageManager:t.packageManager,install:t.install,dbSetup:t.dbSetup,backend:t.backend,runtime:t.runtime,api:t.api}}import T from"picocolors";function Be(e){let t=[];if(e.projectName&&t.push(`${T.blue("Project Name:")} ${e.projectName}`),e.frontend!==void 0){let r=Array.isArray(e.frontend)?e.frontend:[e.frontend],a=r.length>0&&r[0]!==void 0&&r[0]!==""?r.join(", "):"none";t.push(`${T.blue("Frontend:")} ${a}`)}if(e.backend!==void 0&&t.push(`${T.blue("Backend Framework:")} ${String(e.backend)}`),e.runtime!==void 0&&t.push(`${T.blue("Runtime:")} ${String(e.runtime)}`),e.api!==void 0&&t.push(`${T.blue("API:")} ${String(e.api)}`),e.database!==void 0&&t.push(`${T.blue("Database:")} ${String(e.database)}`),e.orm!==void 0&&t.push(`${T.blue("ORM:")} ${String(e.orm)}`),e.auth!==void 0){let r=typeof e.auth=="boolean"?e.auth?"Yes":"No":String(e.auth);t.push(`${T.blue("Authentication:")} ${r}`)}if(e.addons!==void 0){let r=Array.isArray(e.addons)?e.addons:[e.addons],a=r.length>0&&r[0]!==void 0?r.join(", "):"none";t.push(`${T.blue("Addons:")} ${a}`)}if(e.examples!==void 0){let r=Array.isArray(e.examples)?e.examples:[e.examples],a=r.length>0&&r[0]!==void 0?r.join(", "):"none";t.push(`${T.blue("Examples:")} ${a}`)}if(e.git!==void 0){let r=typeof e.git=="boolean"?e.git?"Yes":"No":String(e.git);t.push(`${T.blue("Git Init:")} ${r}`)}if(e.packageManager!==void 0&&t.push(`${T.blue("Package Manager:")} ${String(e.packageManager)}`),e.install!==void 0){let r=typeof e.install=="boolean"?e.install?"Yes":"No":String(e.install);t.push(`${T.blue("Install Dependencies:")} ${r}`)}return e.dbSetup!==void 0&&t.push(`${T.blue("Database Setup:")} ${String(e.dbSetup)}`),t.length===0?T.yellow("No configuration selected."):t.join(`
201
- `)}function rr(e){let t=[];e.database==="none"?t.push("--database none"):(t.push(`--database ${e.database}`),e.orm&&t.push(`--orm ${e.orm}`),e.dbSetup&&t.push(`--db-setup ${e.dbSetup}`)),e.api&&t.push(`--api ${e.api}`),t.push(e.auth?"--auth":"--no-auth"),t.push(e.git?"--git":"--no-git"),t.push(e.install?"--install":"--no-install"),e.runtime&&t.push(`--runtime ${e.runtime}`),e.backend&&t.push(`--backend ${e.backend}`),e.frontend&&e.frontend.length>0&&t.push(`--frontend ${e.frontend.join(" ")}`),e.addons&&e.addons.length>0?t.push(`--addons ${e.addons.join(" ")}`):t.push("--addons none"),e.examples&&e.examples.length>0?t.push(`--examples ${e.examples.join(" ")}`):t.push("--examples none"),e.packageManager&&t.push(`--package-manager ${e.packageManager}`);let r="",a=e.packageManager;a==="npm"?r="npx create-better-t-stack@latest":a==="pnpm"?r="pnpm create better-t-stack@latest":a==="bun"&&(r="bun create better-t-stack@latest");let s=e.projectName?` ${e.projectName}`:"";return`${r}${s} ${t.join(" ")}`}import Zs from"node:path";import en from"fs-extra";var ar=()=>{let e=Zs.join(k,"package.json");return en.readJSONSync(e).version??"1.0.0"};import sr from"gradient-string";var nr=`
202
- \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557
203
- \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
204
- \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
205
- \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
206
- \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551
207
- \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
208
-
209
- \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557
210
- \u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u255D
211
- \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2554\u255D
212
- \u2588\u2588\u2551 \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2588\u2588\u2557
213
- \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2557
214
- \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
215
- `,or={pink:"#F5C2E7",mauve:"#CBA6F7",red:"#F38BA8",maroon:"#E78284",peach:"#FAB387",yellow:"#F9E2AF",green:"#A6E3A1",teal:"#94E2D5",sky:"#89DCEB",sapphire:"#74C7EC",lavender:"#B4BEFE"},ir=()=>{let e=process.stdout.columns||80,t=nr.split(`
216
- `),r=Math.max(...t.map(a=>a.length));e<r?console.log(sr(Object.values(or)).multiline(`
217
- \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
218
- \u2551 Better T-Stack \u2551
219
- \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
220
- `)):console.log(sr(Object.values(or)).multiline(nr))};var pr=()=>process.exit(0);process.on("SIGINT",pr);process.on("SIGTERM",pr);async function cn(){let e=Date.now();try{let r=await nn(on(process.argv)).scriptName("create-better-t-stack").usage("$0 [project-directory] [options]","Create a new Better-T Stack project").positional("project-directory",{describe:"Project name/directory",type:"string"}).option("yes",{alias:"y",type:"boolean",describe:"Use default configuration and skip prompts",default:!1}).option("database",{type:"string",describe:"Database type",choices:["none","sqlite","postgres","mysql","mongodb"]}).option("orm",{type:"string",describe:"ORM type",choices:["drizzle","prisma","none"]}).option("auth",{type:"boolean",describe:"Include authentication (use --no-auth to exclude)"}).option("frontend",{type:"array",string:!0,describe:"Frontend types",choices:["tanstack-router","react-router","tanstack-start","next","nuxt","native","svelte","none"]}).option("addons",{type:"array",string:!0,describe:"Additional addons",choices:["pwa","tauri","starlight","biome","husky","turborepo","none"]}).option("examples",{type:"array",string:!0,describe:"Examples to include",choices:["todo","ai","none"]}).option("git",{type:"boolean",describe:"Initialize git repository (use --no-git to skip)"}).option("package-manager",{alias:"pm",type:"string",describe:"Package manager",choices:["npm","pnpm","bun"]}).option("install",{type:"boolean",describe:"Install dependencies (use --no-install to skip)"}).option("db-setup",{type:"string",describe:"Database setup",choices:["turso","neon","prisma-postgres","mongodb-atlas","none"]}).option("backend",{type:"string",describe:"Backend framework",choices:["hono","express","next","elysia"]}).option("runtime",{type:"string",describe:"Runtime",choices:["bun","node"]}).option("api",{type:"string",describe:"API type",choices:["trpc","orpc"]}).completion().recommendCommands().version(ar()).alias("version","v").help().alias("help","h").strict().wrap(null).parse(),a=r.projectDirectory;ir();let s=pn(r,a);an(_.magenta("Creating a new Better-T-Stack project")),!r.yes&&Object.keys(s).length>0&&(U.info(_.yellow("Using these pre-selected options:")),U.message(Be(s)),U.message(""));let n;r.yes?(n={...P,projectName:a??P.projectName,...s},n.database==="none"&&(n.orm="none",n.auth=!1,n.dbSetup="none",n.examples=n.examples.filter(c=>c!=="todo")),U.info(_.yellow("Using these default/flag options:")),U.message(Be(n)),U.message("")):n=await tr(s);let o=tn.resolve(process.cwd(),n.projectName);if(cr.pathExistsSync(o)&&cr.readdirSync(o).length>0){let c=await ge();n.projectName=c}await It(n),U.success(_.blue(`You can reproduce this setup with the following command:
221
- ${rr(n)}`));let i=((Date.now()-e)/1e3).toFixed(2);sn(_.magenta(`Project created successfully in ${_.bold(i)} seconds!`))}catch(t){t instanceof Error?(t.name==="YError"?rn(_.red(`Invalid arguments: ${t.message}`)):(D.error(`An unexpected error occurred: ${t.message}`),D.error(t.stack)),process.exit(1)):(D.error("An unexpected error occurred."),console.error(t),process.exit(1))}}function pn(e,t){let r={};if(e.database&&(r.database=e.database),e.orm&&(r.orm=e.orm),e.auth!==void 0&&(r.auth=e.auth),e.git!==void 0&&(r.git=e.git),e.install!==void 0&&(r.install=e.install),e.backend&&(r.backend=e.backend),e.runtime&&(r.runtime=e.runtime),e.frontend&&e.frontend.length>0)if(e.frontend.includes("none"))e.frontend.length>1&&(D.fatal("Cannot combine 'none' with other frontend options."),process.exit(1)),r.frontend=[];else{let u=e.frontend.filter(y=>y!=="none");u.filter(y=>y==="tanstack-router"||y==="react-router"||y==="tanstack-start"||y==="next"||y==="nuxt"||y==="svelte").length>1&&(D.fatal("Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router, next, nuxt, svelte"),process.exit(1)),r.frontend=u}e.api&&(r.api=e.api),e.addons&&e.addons.length>0&&(e.addons.includes("none")?(e.addons.length>1&&(D.fatal("Cannot combine 'none' with other addons."),process.exit(1)),r.addons=[]):r.addons=e.addons.filter(u=>u!=="none")),e.examples&&e.examples.length>0&&(e.examples.includes("none")?(e.examples.length>1&&(D.fatal("Cannot combine 'none' with other examples."),process.exit(1)),r.examples=[]):r.examples=e.examples.filter(u=>u!=="none")),e.packageManager&&(r.packageManager=e.packageManager),t&&(r.projectName=t),e.dbSetup&&(r.dbSetup=e.dbSetup);let a=r.database??(e.yes?P.database:void 0),s=r.orm??(e.yes?P.orm:void 0),n=r.auth??(e.yes?P.auth:void 0),o=r.dbSetup??(e.yes?P.dbSetup:void 0),i=r.examples??(e.yes?P.examples:void 0),c=r.frontend??(e.yes?P.frontend:void 0),p=r.api??(e.yes?P.api:void 0),b=r.backend??(e.yes?P.backend:void 0);if(a==="none"&&(s&&s!=="none"&&(D.fatal(`Cannot use ORM '--orm ${s}' when database is 'none'.`),process.exit(1)),r.orm="none",n===!0&&(D.fatal("Authentication requires a database. Cannot use --auth when database is 'none'."),process.exit(1)),r.auth=!1,o&&o!=="none"&&(D.fatal(`Database setup '--db-setup ${o}' requires a database. Cannot use when database is 'none'.`),process.exit(1)),r.dbSetup="none",i?.includes("todo")&&(D.fatal("The 'todo' example requires a database. Cannot use --examples todo when database is 'none'."),process.exit(1)),r.examples&&(r.examples=r.examples.filter(u=>u!=="todo"))),a==="mongodb"&&s==="drizzle"&&(D.fatal("MongoDB is only available with Prisma. Cannot use --database mongodb with --orm drizzle"),process.exit(1)),r.dbSetup&&r.dbSetup!=="none"){let u=r.dbSetup;u==="turso"?(a&&a!=="sqlite"&&(D.fatal(`Turso setup requires SQLite. Cannot use --db-setup turso with --database ${a}`),process.exit(1)),s==="prisma"&&(D.fatal("Turso setup is not compatible with Prisma. Cannot use --db-setup turso with --orm prisma"),process.exit(1)),r.database="sqlite",r.orm="drizzle"):u==="prisma-postgres"?(a&&a!=="postgres"&&(D.fatal(`Prisma PostgreSQL setup requires PostgreSQL. Cannot use --db-setup prisma-postgres with --database ${a}.`),process.exit(1)),s&&s!=="prisma"&&s!=="none"&&(D.fatal(`Prisma PostgreSQL setup requires Prisma ORM. Cannot use --db-setup prisma-postgres with --orm ${s}.`),process.exit(1)),r.database="postgres",r.orm="prisma"):u==="mongodb-atlas"?(a&&a!=="mongodb"&&(D.fatal(`MongoDB Atlas setup requires MongoDB. Cannot use --db-setup mongodb-atlas with --database ${a}.`),process.exit(1)),s&&s!=="prisma"&&s!=="none"&&(D.fatal(`MongoDB Atlas setup requires Prisma ORM. Cannot use --db-setup mongodb-atlas with --orm ${s}.`),process.exit(1)),r.database="mongodb",r.orm="prisma"):u==="neon"&&(a&&a!=="postgres"&&(D.fatal(`Neon PostgreSQL setup requires PostgreSQL. Cannot use --db-setup neon with --database ${a}.`),process.exit(1)),r.database="postgres")}let m=c?.includes("nuxt"),w=c?.includes("svelte");if((m||w)&&p==="trpc"&&(D.fatal(`tRPC API is not supported with '${m?"nuxt":"svelte"}' frontend. Please use --api orpc or remove '${m?"nuxt":"svelte"}' from --frontend.`),process.exit(1)),(m||w)&&p!=="orpc"&&(!e.api||e.yes&&e.api!=="trpc")&&(r.api="orpc"),r.addons&&r.addons.length>0){let u=["pwa","tauri"],d=r.addons.some(S=>u.includes(S)),y=c?.some(S=>S==="tanstack-router"||S==="react-router"||S==="nuxt"&&r.addons?.includes("tauri")&&!r.addons?.includes("pwa")||S==="svelte"&&r.addons?.includes("tauri")&&!r.addons?.includes("pwa"));if(d&&!y){let S="";r.addons.includes("pwa")&&m?S="PWA addon is not compatible with Nuxt.":(r.addons.includes("pwa")||r.addons.includes("tauri"))&&(S="PWA and Tauri addons require tanstack-router, react-router, or Nuxt/Svelte (Tauri only)."),D.fatal(`${S} Cannot use these addons with your frontend selection.`),process.exit(1)}r.addons.includes("husky")&&!r.addons.includes("biome")&&D.warn("Husky addon is recommended to be used with Biome for lint-staged configuration."),r.addons=[...new Set(r.addons)]}if(r.examples&&r.examples.length>0){r.examples.includes("ai")&&b==="elysia"&&(D.fatal("The 'ai' example is not compatible with the Elysia backend."),process.exit(1));let u=c?.some(d=>["tanstack-router","react-router","tanstack-start","next","nuxt","svelte"].includes(d));r.examples.length>0&&!u&&(D.fatal("Examples require a web frontend (tanstack-router, react-router, tanstack-start, next, nuxt, or svelte)."),process.exit(1))}return r}cn().catch(e=>{D.error("Aborting installation due to unexpected error..."),e instanceof Error?D.error(e.message):console.error(e),process.exit(1)});
143
+ DATABASE_URL="your_connection_string"`)}async function Pe(e){let{projectName:r,packageManager:i}=e,a=t.resolve(process.cwd(),r),c=f();c.start(`Setting up Neon PostgreSQL`);try{let e=await Ae(i);c.stop(`Setting up Neon PostgreSQL`),e||(s.info(`Please authenticate with Neon to continue:`),await je(i));let r=t.basename(a),l=await p({message:`Enter a name for your Neon project:`,defaultValue:r,initialValue:r});o(l)&&(n(_.red(`Operation cancelled`)),process.exit(0));let u=await Me(l,i);if(!u)throw Error(`Failed to create project - couldn't get connection information`);let d=f();d.start(`Configuring database connection`),await g.ensureDir(t.join(a,`apps/server`)),await U(a,u),d.stop(`Neon database configured successfully!`)}catch(e){c.stop(_.red(`Neon PostgreSQL setup failed`)),e instanceof Error&&h.error(_.red(e.message)),await U(a),Ne()}}async function Fe(e){let{projectName:n,database:r,orm:i,dbSetup:a}=e,o=t.resolve(process.cwd(),n),s=f(),c=t.join(o,`apps/server`);if(r===`none`){await g.remove(t.join(c,`src/db`));return}try{i===`prisma`?await N({dependencies:[`@prisma/client`],devDependencies:[`prisma`],projectDir:c}):i===`drizzle`&&(r===`sqlite`?await N({dependencies:[`drizzle-orm`,`@libsql/client`],devDependencies:[`drizzle-kit`],projectDir:c}):r===`postgres`?await N({dependencies:[`drizzle-orm`,`pg`],devDependencies:[`drizzle-kit`,`@types/pg`],projectDir:c}):r===`mysql`&&await N({dependencies:[`drizzle-orm`,`mysql2`],devDependencies:[`drizzle-kit`],projectDir:c})),r===`sqlite`&&a===`turso`?await ke(e):r===`postgres`?i===`prisma`&&a===`prisma-postgres`?await xe(e):a===`neon`&&await Pe(e):r===`mongodb`&&a===`mongodb-atlas`&&await ve(e)}catch(e){s.stop(_.red(`Failed to set up database`)),e instanceof Error&&m.error(_.red(e.message))}}async function W(e,n){await g.ensureDir(t.dirname(e));let r=``;await g.pathExists(e)&&(r=await g.readFile(e,`utf8`));let i=!1;for(let{key:e,value:t,condition:a}of n)if(a){let n=RegExp(`^${e}=.*$`,`m`);n.test(r)?t&&(r=r.replace(n,`${e}=${t}`),i=!0):(r+=`\n${e}=${t}`,i=!0)}i&&await g.writeFile(e,r.trim())}async function Ie(e){let{projectName:n}=e,r=t.resolve(process.cwd(),n),i=e,a=t.join(r,`apps/server`),o=t.join(a,`.env`),s=i.frontend.includes(`react-router`),c=i.frontend.includes(`tanstack-router`),l=i.frontend.includes(`tanstack-start`),u=i.frontend.includes(`next`),d=i.frontend.includes(`nuxt`),f=i.frontend.includes(`svelte`),p=s||c||l||u||d||f,m=`http://localhost:3001`;s||f?m=`http://localhost:5173`:(c||l||u||d)&&(m=`http://localhost:3001`);let h=``,g=i.dbSetup===`turso`||i.dbSetup===`prisma-postgres`||i.dbSetup===`mongodb-atlas`||i.dbSetup===`neon`;g||(i.database===`postgres`?h=`postgresql://postgres:postgres@localhost:5432/mydb?schema=public`:i.database===`mysql`?h=`mysql://root:password@localhost:3306/mydb`:i.database===`mongodb`?h=`mongodb://localhost:27017/mydatabase`:i.database===`sqlite`&&(h=`file:./local.db`));let _=[{key:`CORS_ORIGIN`,value:m,condition:!0},{key:`BETTER_AUTH_SECRET`,value:le(),condition:!!i.auth},{key:`BETTER_AUTH_URL`,value:`http://localhost:3000`,condition:!!i.auth},{key:`DATABASE_URL`,value:h,condition:i.database!==`none`&&h!==``&&!g},{key:`GOOGLE_GENERATIVE_AI_API_KEY`,value:``,condition:i.examples?.includes(`ai`)||!1}];if(await W(o,_),p){let e=t.join(r,`apps/web`),n=`VITE_SERVER_URL`;u?n=`NEXT_PUBLIC_SERVER_URL`:d?n=`NUXT_PUBLIC_SERVER_URL`:f&&(n=`PUBLIC_SERVER_URL`);let i=[{key:n,value:`http://localhost:3000`,condition:!0}];await W(t.join(e,`.env`),i)}if(i.frontend.includes(`native`)){let e=t.join(r,`apps/native`),n=[{key:`EXPO_PUBLIC_SERVER_URL`,value:`http://localhost:3000`,condition:!0}];await W(t.join(e,`.env`),n)}}async function Le(e){let{projectName:n,examples:r,frontend:i}=e,a=t.resolve(process.cwd(),n);if(r.includes(`ai`)){let e=t.join(a,`apps/web`),n=t.join(a,`apps/server`),r=await g.pathExists(e),o=i.includes(`nuxt`),s=i.includes(`svelte`);if(r){let t=[`ai`];o?t.push(`@ai-sdk/vue`):s&&t.push(`@ai-sdk/svelte`),await N({dependencies:t,projectDir:e})}await N({dependencies:[`ai`,`@ai-sdk/google`],projectDir:n})}}async function Re({projectDir:e,packageManager:t,addons:n=[]}){let r=f();try{r.start(`Running ${t} install...`),await x({cwd:e,stderr:`inherit`})`${t} install`,r.stop(`Dependencies installed successfully`),(n.includes(`biome`)||n.includes(`husky`))&&await ze(e,t)}catch(e){r.stop(_.red(`Failed to install dependencies`)),e instanceof Error&&m.error(_.red(`Installation error: ${e.message}`))}}async function ze(e,t){let n=f();try{n.start(`Running Biome format check...`),await x({cwd:e,stderr:`inherit`})`${t} biome check --write .`,n.stop(`Biome check completed successfully`)}catch{n.stop(_.yellow(`Biome check encountered issues`)),s.warn(_.yellow(`Some files may need manual formatting`))}}function Be(e){let{database:t,projectName:n,packageManager:r,depsInstalled:i,orm:a,addons:o,runtime:s,frontend:c}=e,l=r===`npm`?`npm run`:r,u=`cd ${n}`,d=o?.includes(`husky`)||o?.includes(`biome`),f=t===`none`?``:Ue(t,a,l,s),p=o?.includes(`tauri`)?We(l):``,m=d?He(l):``,g=c?.includes(`native`)?Ve():``,v=o?.includes(`pwa`)&&(c?.includes(`react-router`)||c?.includes(`tanstack-router`))?Ge():``,y=o?.includes(`starlight`)?Ke(l):``,b=c?.some(e=>[`tanstack-router`,`react-router`,`next`,`tanstack-start`,`nuxt`,`svelte`].includes(e)),x=c?.includes(`native`),S=r===`bun`&&x&&b?Je():``,C=t!==`none`&&a===`none`?qe():``,w=c?.includes(`tanstack-router`),T=c?.includes(`tanstack-start`),E=c?.includes(`react-router`),D=c?.includes(`nuxt`),O=c?.includes(`svelte`),k=w||E||T||D||O,A=c?.includes(`native`),j=k||A,M=E||O?`5173`:`3001`,N=P(r,`taze -r`);h.box(`${_.bold(`Next steps`)}\n${_.cyan(`1.`)} ${u}
144
+ ${i?``:`${_.cyan(`2.`)} ${r} install\n`}${_.cyan(i?`2.`:`3.`)} ${l} dev
145
+
146
+ ${_.bold(`Your project will be available at:`)}
147
+ ${j?`${k?`${_.cyan(`•`)} Frontend: http://localhost:${M}\n`:``}`:`${_.yellow(`NOTE:`)} You are creating a backend-only app (no frontend selected)\n`}${_.cyan(`•`)} Backend: http://localhost:3000
148
+ ${o?.includes(`starlight`)?`${_.cyan(`•`)} Docs: http://localhost:4321\n`:``}${g?`\n${g.trim()}`:``}${f?`\n${f.trim()}`:``}${p?`\n${p.trim()}`:``}${m?`\n${m.trim()}`:``}${v?`\n${v.trim()}`:``}${y?`\n${y.trim()}`:``}${C?`\n${C.trim()}`:``}${S?`\n${S.trim()}`:``}
149
+
150
+ ${_.bold(`Update all dependencies:
151
+ `)}${_.cyan(N)}
152
+
153
+ ${_.bold(`Like Better-T Stack?`)} Please consider giving us a star on GitHub:
154
+ ${_.cyan(`https://github.com/AmanVarshney01/create-better-t-stack`)}`)}function Ve(){return`${_.yellow(`NOTE:`)} For Expo connectivity issues, update apps/native/.env \nwith your local IP:\nEXPO_PUBLIC_SERVER_URL=http://192.168.0.103:3000\n`}function He(e){return`${_.bold(`Linting and formatting:`)}\n${_.cyan(`•`)} Format and lint fix: ${`${e} check`}\n\n`}function Ue(e,t,n,r){let i=[];return t===`prisma`?(e===`sqlite`&&i.push(`${_.yellow(`NOTE:`)} Turso support with Prisma is in Early Access and requires additional setup.`,`Learn more at: https://www.prisma.io/docs/orm/overview/databases/turso`),r===`bun`&&i.push(`${_.yellow(`NOTE:`)} Prisma with Bun may require additional configuration. If you encounter errors,\nfollow the guidance provided in the error messages`),i.push(`${_.cyan(`•`)} Apply schema: ${`${n} db:push`}`),i.push(`${_.cyan(`•`)} Database UI: ${`${n} db:studio`}`)):t===`drizzle`&&(i.push(`${_.cyan(`•`)} Apply schema: ${`${n} db:push`}`),i.push(`${_.cyan(`•`)} Database UI: ${`${n} db:studio`}`)),i.length?`${_.bold(`Database commands:`)}\n${i.join(`
155
+ `)}\n\n`:``}function We(e){return`\n${_.bold(`Desktop app with Tauri:`)}\n${_.cyan(`•`)} Start desktop app: ${`cd apps/web && ${e} desktop:dev`}\n${_.cyan(`•`)} Build desktop app: ${`cd apps/web && ${e} desktop:build`}\n${_.yellow(`NOTE:`)} Tauri requires Rust and platform-specific dependencies.\nSee: https://v2.tauri.app/start/prerequisites/\n\n`}function Ge(){return`${_.bold(`PWA with React Router v7:`)}\n${_.yellow(`NOTE:`)} There is a known compatibility issue between VitePWA and React Router v7.\nSee: https://github.com/vite-pwa/vite-plugin-pwa/issues/809\n`}function Ke(e){return`${_.bold(`Documentation with Starlight:`)}\n${_.cyan(`•`)} Start docs site: ${`cd apps/docs && ${e} dev`}\n${_.cyan(`•`)} Build docs site: ${`cd apps/docs && ${e} build`}\n`}function qe(){return`\n${_.yellow(`WARNING:`)} Database selected without an ORM. Features requiring database access (e.g., examples, auth) need manual setup.\n`}function Je(){return`\n${_.yellow(`WARNING:`)} 'bun' might cause issues with web + native apps in a monorepo. Use 'pnpm' if problems arise.\n`}async function Ye(e,t){await Xe(e,t),await Ze(e,t)}async function Xe(e,n){let r=t.join(e,`package.json`);if(await g.pathExists(r)){let t=await g.readJson(r);t.name=n.projectName;let i={dev:`turbo dev`,build:`turbo build`,"check-types":`turbo check-types`,"dev:native":`turbo -F native dev`,"dev:web":`turbo -F web dev`,"dev:server":`turbo -F server dev`,"db:push":`turbo -F server db:push`,"db:studio":`turbo -F server db:studio`},a={dev:`pnpm -r dev`,build:`pnpm -r build`,"check-types":`pnpm -r check-types`,"dev:native":`pnpm --filter native dev`,"dev:web":`pnpm --filter web dev`,"dev:server":`pnpm --filter server dev`,"db:push":`pnpm --filter server db:push`,"db:studio":`pnpm --filter server db:studio`},o={dev:`npm run dev --workspaces`,build:`npm run build --workspaces`,"check-types":`npm run check-types --workspaces`,"dev:native":`npm run dev --workspace native`,"dev:web":`npm run dev --workspace web`,"dev:server":`npm run dev --workspace server`,"db:push":`npm run db:push --workspace server`,"db:studio":`npm run db:studio --workspace server`},s={dev:`bun run --filter '*' dev`,build:`bun run --filter '*' build`,"check-types":`bun run --filter '*' check-types`,"dev:native":`bun run --filter native dev`,"dev:web":`bun run --filter web dev`,"dev:server":`bun run --filter server dev`,"db:push":`bun run --filter server db:push`,"db:studio":`bun run --filter server db:studio`};n.addons.includes(`turborepo`)?t.scripts=i:n.packageManager===`pnpm`?t.scripts=a:n.packageManager===`npm`?t.scripts=o:n.packageManager===`bun`?t.scripts=s:t.scripts={};let{stdout:c}=await S(n.packageManager,[`-v`],{cwd:e});t.packageManager=`${n.packageManager}@${c.trim()}`,await g.writeJson(r,t,{spaces:2})}}async function Ze(e,n){let r=t.join(e,`apps/server/package.json`);if(await g.pathExists(r)){let e=await g.readJson(r);n.database!==`none`&&(n.database===`sqlite`&&n.orm===`drizzle`&&(e.scripts[`db:local`]=`turso dev --db-file local.db`),n.orm===`prisma`?(e.scripts[`db:push`]=`prisma db push --schema ./prisma/schema`,e.scripts[`db:studio`]=`prisma studio`):n.orm===`drizzle`&&(e.scripts[`db:push`]=`drizzle-kit push`,e.scripts[`db:studio`]=`drizzle-kit studio`)),await g.writeJson(r,e,{spaces:2})}}async function Qe(e,t){if(!t)return;let n=await x({cwd:e,reject:!1,stderr:`pipe`})`git --version`;if(n.exitCode!==0){s.warn(_.yellow(`Git is not installed`));return}let r=await x({cwd:e,reject:!1,stderr:`pipe`})`git init`;if(r.exitCode!==0)throw Error(`Git initialization failed: ${r.stderr}`)}async function $e(e){let{projectName:n,runtime:r,backend:i}=e,a=t.resolve(process.cwd(),n);if(i===`next`)return;let o=t.join(a,`apps/server`);r===`bun`?await et(o,i):r===`node`&&await tt(o,i)}async function et(e,n){let r=t.join(e,`package.json`),i=await g.readJson(r);i.scripts={...i.scripts,dev:`bun run --hot src/index.ts`,start:`bun run dist/src/index.js`},await g.writeJson(r,i,{spaces:2}),await N({devDependencies:[`@types/bun`],projectDir:e})}async function tt(e,n){let r=t.join(e,`package.json`),i=await g.readJson(r);i.scripts={...i.scripts,dev:`tsx watch src/index.ts`,start:`node dist/src/index.js`},await g.writeJson(r,i,{spaces:2}),await N({devDependencies:[`tsx`,`@types/node`],projectDir:e}),n===`hono`?await N({dependencies:[`@hono/node-server`],projectDir:e}):n===`elysia`&&await N({dependencies:[`@elysiajs/node`],projectDir:e})}async function G(e,n,r){try{let i=await g.readFile(e,`utf-8`),a=T.compile(i),o=a(r);await g.ensureDir(t.dirname(n)),await g.writeFile(n,o)}catch(t){throw m.error(`Error processing template ${e}:`,t),Error(`Failed to process template ${e}`)}}T.registerHelper(`or`,(e,t)=>e||t),T.registerHelper(`eq`,(e,t)=>e===t),T.registerHelper(`includes`,(e,t)=>Array.isArray(e)&&e.includes(t));async function K(e,n,r,i,a=!0){let o=await w(e,{cwd:n,dot:!0,onlyFiles:!0,absolute:!1});for(let e of o){let o=t.join(n,e),s=e;e.endsWith(`.hbs`)&&(s=e.slice(0,-4)),t.basename(e)===`_gitignore`&&(s=t.join(t.dirname(e),`.gitignore`)),t.basename(e)===`_npmrc`&&(s=t.join(t.dirname(e),`.npmrc`));let c=t.join(r,s);if(await g.ensureDir(t.dirname(c)),!a&&await g.pathExists(c))continue;o.endsWith(`.hbs`)?await G(o,c,i):await g.copy(o,c,{overwrite:!0})}}async function nt(e,n){let r=t.join(A,`templates/base`);await K([`**/*`],r,e,n)}async function rt(e,n){let r=n.frontend.some(e=>[`tanstack-router`,`react-router`,`tanstack-start`,`next`].includes(e)),i=n.frontend.includes(`nuxt`),a=n.frontend.includes(`svelte`),o=n.frontend.includes(`native`);if(r||i||a){let o=t.join(e,`apps/web`);if(await g.ensureDir(o),r){let e=t.join(A,`templates/frontend/react/web-base`);await g.pathExists(e)&&await K(`**/*`,e,o,n);let r=n.frontend.find(e=>[`tanstack-router`,`react-router`,`tanstack-start`,`next`].includes(e));if(r){let e=t.join(A,`templates/frontend/react/${r}`);await g.pathExists(e)&&await K(`**/*`,e,o,n);let i=t.join(A,`templates/api/${n.api}/web/react/base`);await g.pathExists(i)&&await K(`**/*`,i,o,n)}}else if(i){let e=t.join(A,`templates/frontend/nuxt`);await g.pathExists(e)&&await K(`**/*`,e,o,n);let r=t.join(A,`templates/api/${n.api}/web/nuxt`);await g.pathExists(r)&&await K(`**/*`,r,o,n)}else if(a){let e=t.join(A,`templates/frontend/svelte`);if(await g.pathExists(e)&&await K(`**/*`,e,o,n),n.api===`orpc`){let e=t.join(A,`templates/api/${n.api}/web/svelte`);await g.pathExists(e)&&await K(`**/*`,e,o,n)}}}if(o){let r=t.join(e,`apps/native`);await g.ensureDir(r);let i=t.join(A,`templates/frontend/native`);if(await g.pathExists(i)&&await K(`**/*`,i,r,n),n.api===`trpc`){let e=t.join(A,`templates/api/${n.api}/native`);await g.pathExists(e)&&await K(`**/*`,e,r,n)}else if(n.api===`orpc`){let e=t.join(A,`templates/api/${n.api}/native`);await g.pathExists(e)&&await K(`**/*`,e,r,n)}}}async function it(e,n){if(n.backend===`none`)return;let r=t.join(e,`apps/server`);await g.ensureDir(r);let i=t.join(A,`templates/backend/server-base`);await g.pathExists(i)?await K(`**/*`,i,r,n):m.warn(_.yellow(`Warning: server-base template not found at ${i}`));let a=t.join(A,`templates/backend/${n.backend}`);await g.pathExists(a)?await K(`**/*`,a,r,n):m.warn(_.yellow(`Warning: Backend template directory not found, skipping: ${a}`));let o=t.join(A,`templates/api/${n.api}/server/base`);await g.pathExists(o)&&await K(`**/*`,o,r,n);let s=t.join(A,`templates/api/${n.api}/server/${n.backend}`);await g.pathExists(s)&&await K(`**/*`,s,r,n)}async function at(e,n){if(n.orm===`none`||n.database===`none`)return;let r=t.join(e,`apps/server`);await g.ensureDir(r);let i=t.join(A,`templates/db/${n.orm}/${n.database}`);await g.pathExists(i)?await K(`**/*`,i,r,n):m.warn(_.yellow(`Warning: Database/ORM template directory not found, skipping: ${i}`))}async function ot(e,n){if(!n.auth)return;let r=t.join(e,`apps/server`),i=t.join(e,`apps/web`),a=t.join(e,`apps/native`),o=await g.pathExists(r),s=await g.pathExists(i),c=await g.pathExists(a),l=n.frontend.some(e=>[`tanstack-router`,`react-router`,`tanstack-start`,`next`].includes(e)),u=n.frontend.includes(`nuxt`),d=n.frontend.includes(`svelte`),f=n.frontend.includes(`native`);if(o){let e=t.join(A,`templates/auth/server/base`);if(await g.pathExists(e)&&await K(`**/*`,e,r,n),n.backend===`next`){let e=t.join(A,`templates/auth/server/next`);await g.pathExists(e)&&await K(`**/*`,e,r,n)}if(n.orm!==`none`&&n.database!==`none`){let e=n.orm,i=n.database,a=``;e===`drizzle`?a=t.join(A,`templates/auth/server/db/drizzle/${i}`):e===`prisma`&&(a=t.join(A,`templates/auth/server/db/prisma/${i}`)),a&&await g.pathExists(a)?await K(`**/*`,a,r,n):m.warn(_.yellow(`Warning: Auth template for ${e}/${i} not found at ${a}`))}}if((l||u||d)&&s){if(l){let e=t.join(A,`templates/auth/web/react/base`);await g.pathExists(e)&&await K(`**/*`,e,i,n);let r=n.frontend.find(e=>[`tanstack-router`,`react-router`,`tanstack-start`,`next`].includes(e));if(r){let e=t.join(A,`templates/auth/web/react/${r}`);await g.pathExists(e)&&await K(`**/*`,e,i,n)}}else if(u){let e=t.join(A,`templates/auth/web/nuxt`);await g.pathExists(e)&&await K(`**/*`,e,i,n)}else if(d&&n.api===`orpc`){let e=t.join(A,`templates/auth/web/svelte`);await g.pathExists(e)&&await K(`**/*`,e,i,n)}}if(f&&c){let e=t.join(A,`templates/auth/native`);await g.pathExists(e)?await K(`**/*`,e,a,n):m.warn(_.yellow(`Warning: Auth native template not found at ${e}`))}}async function st(e,n){if(!(!n.addons||n.addons.length===0))for(let r of n.addons){if(r===`none`)continue;let i=t.join(A,`templates/addons/${r}`),a=e;if(r===`pwa`&&(i=t.join(A,`templates/addons/pwa/apps/web`),a=t.join(e,`apps/web`),!await g.pathExists(a)))continue;await g.pathExists(i)&&await K(`**/*`,i,a,n)}}async function ct(e,n){if(!n.examples||n.examples.length===0)return;let r=t.join(e,`apps/server`),i=t.join(e,`apps/web`),a=await g.pathExists(r),o=await g.pathExists(i),s=n.frontend.some(e=>[`tanstack-router`,`react-router`,`tanstack-start`,`next`].includes(e)),c=n.frontend.includes(`nuxt`),l=n.frontend.includes(`svelte`);for(let e of n.examples){if(e===`none`)continue;let u=t.join(A,`templates/examples/${e}`);if(a){let e=t.join(u,`server`);if(await g.pathExists(e)&&n.orm!==`none`){let i=t.join(e,n.orm,`base`);if(await g.pathExists(i)&&await K(`**/*`,i,r,n,!1),n.database!==`none`){let i=t.join(e,n.orm,n.database);await g.pathExists(i)&&await K(`**/*`,i,r,n,!1)}}}if(s&&o){let e=t.join(u,`web/react`);if(await g.pathExists(e)){let r=n.frontend.find(e=>[`next`,`react-router`,`tanstack-router`,`tanstack-start`].includes(e));if(r){let a=t.join(e,r);await g.pathExists(a)&&await K(`**/*`,a,i,n,!1)}}}else if(c&&o){if(n.api===`orpc`){let e=t.join(u,`web/nuxt`);await g.pathExists(e)&&await K(`**/*`,e,i,n,!1)}}else if(l&&o&&n.api===`orpc`){let e=t.join(u,`web/svelte`);await g.pathExists(e)&&await K(`**/*`,e,i,n,!1)}}}async function lt(e,n){let r=t.join(A,`templates/extras`);if(n.packageManager===`pnpm`){let n=t.join(r,`pnpm-workspace.yaml`),i=t.join(e,`pnpm-workspace.yaml`);await g.pathExists(n)&&await g.copy(n,i)}if(n.packageManager===`pnpm`&&(n.frontend.includes(`native`)||n.frontend.includes(`nuxt`))){let i=t.join(r,`_npmrc.hbs`),a=t.join(e,`.npmrc`);await g.pathExists(i)&&await G(i,a,n)}}async function ut(e){let r=t.resolve(process.cwd(),e.projectName);try{return await g.ensureDir(r),await nt(r,e),await rt(r,e),await it(r,e),await ue(e),await at(r,e),await Fe(e),await ot(r,e),await ce(e),await st(r,e),e.addons.length>0&&e.addons[0]!==`none`&&await ne(e),await ct(r,e),await lt(r,e),e.examples.length>0&&e.examples[0]!==`none`&&await Le(e),await se(e),await $e(e),await Ie(e),await Ye(r,e),await de(r,e),await Qe(r,e.git),s.success(`Project template successfully scaffolded!`),e.install&&await Re({projectDir:r,packageManager:e.packageManager,addons:e.addons}),Be({...e,depsInstalled:e.install}),r}catch(e){e instanceof Error&&(n(_.red(`Error during project creation: ${e.message}`)),console.error(e.stack),process.exit(1))}}async function dt(e,t){if(e!==void 0)return e;let r=t?.includes(`react-router`)||t?.includes(`tanstack-router`),i=t?.includes(`react-router`)||t?.includes(`tanstack-router`)||t?.includes(`nuxt`)||t?.includes(`svelte`),a=[{value:`turborepo`,label:`Turborepo (Recommended)`,hint:`Optimize builds for monorepos`},{value:`starlight`,label:`Starlight`,hint:`Add Astro Starlight documentation site`},{value:`biome`,label:`Biome`,hint:`Add Biome for linting and formatting`},{value:`husky`,label:`Husky`,hint:`Add Git hooks with Husky, lint-staged (requires Biome)`},{value:`pwa`,label:`PWA (Progressive Web App)`,hint:`Make your app installable and work offline`},{value:`tauri`,label:`Tauri Desktop App`,hint:`Build native desktop apps from your web frontend`}],s=a.filter(e=>e.value===`pwa`?r:e.value===`tauri`?i:!0),l=j.addons.filter(e=>s.some(t=>t.value===e)),u=await c({message:`Select addons`,options:s,initialValues:l,required:!1});return o(u)&&(n(_.red(`Operation cancelled`)),process.exit(0)),u.includes(`husky`)&&!u.includes(`biome`)&&u.push(`biome`),u}async function ft(e,t){if(e)return e;let r=t?.includes(`nuxt`),i=t?.includes(`svelte`),a=[{value:`trpc`,label:`tRPC`,hint:`End-to-end typesafe APIs made easy`},{value:`orpc`,label:`oRPC`,hint:`End-to-end type-safe APIs that adhere to OpenAPI standards`}];(r||i)&&(a=[{value:`orpc`,label:`oRPC`,hint:`End-to-end type-safe APIs (Required for ${r?`Nuxt`:`Svelte`} frontend)`}]);let s=await d({message:`Select API type`,options:a,initialValue:r||i?`orpc`:j.api});return o(s)&&(n(_.red(`Operation cancelled`)),process.exit(0)),(r||i)&&s!==`orpc`?`orpc`:s}async function pt(e,t){if(!t)return!1;if(e!==void 0)return e;let i=await r({message:`Add authentication with Better-Auth?`,initialValue:j.auth});return o(i)&&(n(_.red(`Operation cancelled`)),process.exit(0)),i}async function mt(e){if(e!==void 0)return e;let t=await d({message:`Select backend framework`,options:[{value:`hono`,label:`Hono`,hint:`Lightweight, ultrafast web framework`},{value:`next`,label:`Next.js`,hint:`Full-stack framework with API routes`},{value:`express`,label:`Express`,hint:`Fast, unopinionated, minimalist web framework for Node.js`},{value:`elysia`,label:`Elysia`,hint:`Ergonomic web framework for building backend servers`}],initialValue:j.backend});return o(t)&&(n(_.red(`Operation cancelled`)),process.exit(0)),t}async function ht(e){if(e!==void 0)return e;let t=await d({message:`Select database`,options:[{value:`none`,label:`None`,hint:`No database setup`},{value:`sqlite`,label:`SQLite`,hint:`lightweight, server-less, embedded relational database`},{value:`postgres`,label:`PostgreSQL`,hint:`powerful, open source object-relational database system`},{value:`mysql`,label:`MySQL`,hint:`popular open-source relational database system`},{value:`mongodb`,label:`MongoDB`,hint:`open-source NoSQL database that stores data in JSON-like documents called BSON`}],initialValue:j.database});return o(t)&&(n(_.red(`Operation cancelled`)),process.exit(0)),t}async function gt(e,t,r){if(t!==void 0)return t;if(e===`sqlite`&&r===`prisma`)return`none`;let i=[];if(e===`sqlite`)i=[{value:`turso`,label:`Turso`,hint:`SQLite for Production. Powered by libSQL`},{value:`none`,label:`None`,hint:`Manual setup`}];else if(e===`postgres`)i=[{value:`neon`,label:`Neon Postgres`,hint:`Serverless Postgres with branching capability`},...r===`prisma`?[{value:`prisma-postgres`,label:`Prisma Postgres`,hint:`Instant Postgres for Global Applications`}]:[],{value:`none`,label:`None`,hint:`Manual setup`}];else if(e===`mongodb`)i=[{value:`mongodb-atlas`,label:`MongoDB Atlas`,hint:`The most effective way to deploy MongoDB`},{value:`none`,label:`None`,hint:`Manual setup`}];else return`none`;let a=await d({message:`Select ${e} setup option`,options:i,initialValue:`none`});return o(a)&&(n(_.red(`Operation cancelled`)),process.exit(0)),a}async function _t(e,t,r,i){if(e!==void 0)return e;if(t===`none`)return[];let a=r?.includes(`react-router`)||r?.includes(`tanstack-router`)||r?.includes(`tanstack-start`)||r?.includes(`next`)||r?.includes(`nuxt`)||r?.includes(`svelte`);if(!a)return[];let s=[],l=[{value:`todo`,label:`Todo App`,hint:`A simple CRUD example app`}];return i!==`elysia`&&l.push({value:`ai`,label:`AI Chat`,hint:`A simple AI chat interface using AI SDK`}),s=await c({message:`Include examples`,options:l,required:!1,initialValues:j.examples}),o(s)&&(n(_.red(`Operation cancelled`)),process.exit(0)),s}async function vt(e){if(e!==void 0)return e;let t=await c({message:`Select platforms to develop for`,options:[{value:`web`,label:`Web`,hint:`React, Vue or Svelte Web Application`},{value:`native`,label:`Native`,hint:`Create a React Native/Expo app`}],required:!1,initialValues:j.frontend.some(e=>e===`tanstack-router`||e===`react-router`||e===`tanstack-start`||e===`next`||e===`nuxt`||e===`svelte`)?[`web`]:[]});o(t)&&(n(_.red(`Operation cancelled`)),process.exit(0));let r=[];if(t.includes(`web`)){let e=await d({message:`Choose frontend framework`,options:[{value:`tanstack-router`,label:`TanStack Router`,hint:`Modern and scalable routing for React Applications`},{value:`react-router`,label:`React Router`,hint:`A user‑obsessed, standards‑focused, multi‑strategy router`},{value:`next`,label:`Next.js`,hint:`The React Framework for the Web`},{value:`nuxt`,label:`Nuxt`,hint:`The Progressive Web Framework for Vue.js`},{value:`svelte`,label:`Svelte`,hint:`web development for the rest of us`},{value:`tanstack-start`,label:`TanStack Start (beta)`,hint:`SSR, Server Functions, API Routes and more with TanStack Router`}],initialValue:j.frontend.find(e=>e===`tanstack-router`||e===`react-router`||e===`tanstack-start`||e===`next`||e===`nuxt`||e===`svelte`)||`tanstack-router`});o(e)&&(n(_.red(`Operation cancelled`)),process.exit(0)),r.push(e)}return t.includes(`native`)&&r.push(`native`),r}async function yt(e){if(e!==void 0)return e;let t=await r({message:`Initialize git repository?`,initialValue:j.git});return o(t)&&(n(_.red(`Operation cancelled`)),process.exit(0)),t}async function bt(e){if(e!==void 0)return e;let t=await r({message:`Install dependencies?`,initialValue:j.install});return o(t)&&(n(_.red(`Operation cancelled`)),process.exit(0)),t}async function xt(e,t,r){if(!t)return`none`;if(e!==void 0)return e;if(r===`mongodb`)return s.info(`Only Prisma is supported with MongoDB.`),`prisma`;let i=await d({message:`Select ORM`,options:[{value:`drizzle`,label:`Drizzle`,hint:`lightweight and performant TypeScript ORM`},{value:`prisma`,label:`Prisma`,hint:`Powerful, feature-rich ORM`}],initialValue:j.orm});return o(i)&&(n(_.red(`Operation cancelled`)),process.exit(0)),i}async function St(e){if(e!==void 0)return e;let t=D(),r=await d({message:`Choose package manager`,options:[{value:`npm`,label:`npm`,hint:`Node Package Manager`},{value:`pnpm`,label:`pnpm`,hint:`Fast, disk space efficient package manager`},{value:`bun`,label:`bun`,hint:`All-in-one JavaScript runtime & toolkit`}],initialValue:t});return o(r)&&(n(_.red(`Operation cancelled`)),process.exit(0)),r}const Ct=[`<`,`>`,`:`,`"`,`|`,`?`,`*`],q=255;function J(e){if(e!==`.`){if(!e)return`Project name cannot be empty`;if(e.length>q)return`Project name must be less than ${q} characters`;if(Ct.some(t=>e.includes(t)))return`Project name contains invalid characters`;if(e.startsWith(`.`)||e.startsWith(`-`))return`Project name cannot start with a dot or dash`;if(e.toLowerCase()===`node_modules`)return`Project name is reserved`}}async function Y(e){if(e)if(e===`.`){let t=process.cwd();if(g.readdirSync(t).length===0)return e}else{let n=t.basename(e),r=J(n);if(!r){let n=t.resolve(process.cwd(),e);if(!g.pathExistsSync(n)||g.readdirSync(n).length===0)return e}}let r=!1,i=``,a=j.projectName,s=1;for(;g.pathExistsSync(t.resolve(process.cwd(),a));)a=`${j.projectName}-${s}`,s++;for(;!r;){let s=await p({message:`Enter your project name or path (relative to current directory)`,placeholder:a,initialValue:e,defaultValue:a,validate:e=>{let n=e.trim()||a;if(n===`.`){let e=g.readdirSync(process.cwd());if(e.length>0)return`Current directory is not empty. Please choose a different directory.`;r=!0;return}let i=t.resolve(process.cwd(),n),o=t.basename(i),s=J(o);if(s)return s;if(!i.startsWith(process.cwd()))return`Project path must be within current directory`;if(g.pathExistsSync(i)){let e=g.readdirSync(i);if(e.length>0)return`Directory "${n}" already exists and is not empty. Please choose a different name or path.`}r=!0}});o(s)&&(n(_.red(`Operation cancelled.`)),process.exit(0)),i=s||a}return i}async function wt(e,t){if(e!==void 0)return e;if(t===`next`)return`node`;let r=await d({message:`Select runtime`,options:[{value:`bun`,label:`Bun`,hint:`Fast all-in-one JavaScript runtime`},{value:`node`,label:`Node.js`,hint:`Traditional Node.js runtime`}],initialValue:j.runtime});return o(r)&&(n(_.red(`Operation cancelled`)),process.exit(0)),r}async function Tt(e){let t=await i({projectName:async()=>Y(e.projectName),frontend:()=>vt(e.frontend),backend:()=>mt(e.backend),runtime:({results:t})=>wt(e.runtime,t.backend),database:()=>ht(e.database),orm:({results:t})=>xt(e.orm,t.database!==`none`,t.database),api:({results:t})=>ft(e.api,t.frontend),auth:({results:t})=>pt(e.auth,t.database!==`none`),addons:({results:t})=>dt(e.addons,t.frontend),examples:({results:t})=>_t(e.examples,t.database,t.frontend,t.backend),dbSetup:({results:t})=>gt(t.database??`none`,e.dbSetup,t.orm),git:()=>yt(e.git),packageManager:()=>St(e.packageManager),install:()=>bt(e.install)},{onCancel:()=>{n(_.red(`Operation cancelled`)),process.exit(0)}});return{projectName:t.projectName,frontend:t.frontend,database:t.database,orm:t.orm,auth:t.auth,addons:t.addons,examples:t.examples,git:t.git,packageManager:t.packageManager,install:t.install,dbSetup:t.dbSetup,backend:t.backend,runtime:t.runtime,api:t.api}}function X(e){let t=[];if(e.projectName&&t.push(`${_.blue(`Project Name:`)} ${e.projectName}`),e.frontend!==void 0){let n=Array.isArray(e.frontend)?e.frontend:[e.frontend],r=n.length>0&&n[0]!==void 0&&n[0]!==``?n.join(`, `):`none`;t.push(`${_.blue(`Frontend:`)} ${r}`)}if(e.backend!==void 0&&t.push(`${_.blue(`Backend Framework:`)} ${String(e.backend)}`),e.runtime!==void 0&&t.push(`${_.blue(`Runtime:`)} ${String(e.runtime)}`),e.api!==void 0&&t.push(`${_.blue(`API:`)} ${String(e.api)}`),e.database!==void 0&&t.push(`${_.blue(`Database:`)} ${String(e.database)}`),e.orm!==void 0&&t.push(`${_.blue(`ORM:`)} ${String(e.orm)}`),e.auth!==void 0){let n=typeof e.auth==`boolean`?e.auth?`Yes`:`No`:String(e.auth);t.push(`${_.blue(`Authentication:`)} ${n}`)}if(e.addons!==void 0){let n=Array.isArray(e.addons)?e.addons:[e.addons],r=n.length>0&&n[0]!==void 0?n.join(`, `):`none`;t.push(`${_.blue(`Addons:`)} ${r}`)}if(e.examples!==void 0){let n=Array.isArray(e.examples)?e.examples:[e.examples],r=n.length>0&&n[0]!==void 0?n.join(`, `):`none`;t.push(`${_.blue(`Examples:`)} ${r}`)}if(e.git!==void 0){let n=typeof e.git==`boolean`?e.git?`Yes`:`No`:String(e.git);t.push(`${_.blue(`Git Init:`)} ${n}`)}if(e.packageManager!==void 0&&t.push(`${_.blue(`Package Manager:`)} ${String(e.packageManager)}`),e.install!==void 0){let n=typeof e.install==`boolean`?e.install?`Yes`:`No`:String(e.install);t.push(`${_.blue(`Install Dependencies:`)} ${n}`)}return e.dbSetup!==void 0&&t.push(`${_.blue(`Database Setup:`)} ${String(e.dbSetup)}`),t.length===0?_.yellow(`No configuration selected.`):t.join(`
156
+ `)}function Et(e){let t=[];e.database===`none`?t.push(`--database none`):(t.push(`--database ${e.database}`),e.orm&&t.push(`--orm ${e.orm}`),e.dbSetup&&t.push(`--db-setup ${e.dbSetup}`)),e.api&&t.push(`--api ${e.api}`),t.push(e.auth?`--auth`:`--no-auth`),t.push(e.git?`--git`:`--no-git`),t.push(e.install?`--install`:`--no-install`),e.runtime&&t.push(`--runtime ${e.runtime}`),e.backend&&t.push(`--backend ${e.backend}`),e.frontend&&e.frontend.length>0&&t.push(`--frontend ${e.frontend.join(` `)}`),e.addons&&e.addons.length>0?t.push(`--addons ${e.addons.join(` `)}`):t.push(`--addons none`),e.examples&&e.examples.length>0?t.push(`--examples ${e.examples.join(` `)}`):t.push(`--examples none`),e.packageManager&&t.push(`--package-manager ${e.packageManager}`);let n=``,r=e.packageManager;r===`npm`?n=`npx create-better-t-stack@latest`:r===`pnpm`?n=`pnpm create better-t-stack@latest`:r===`bun`&&(n=`bun create better-t-stack@latest`);let i=e.projectName?` ${e.projectName}`:``;return`${n}${i} ${t.join(` `)}`}const Dt=()=>{let e=t.join(A,`package.json`),n=g.readJSONSync(e);return n.version??`1.0.0`},Z=`
157
+ ██████╗ ███████╗████████╗████████╗███████╗██████╗
158
+ ██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗
159
+ ██████╔╝█████╗ ██║ ██║ █████╗ ██████╔╝
160
+ ██╔══██╗██╔══╝ ██║ ██║ ██╔══╝ ██╔══██╗
161
+ ██████╔╝███████╗ ██║ ██║ ███████╗██║ ██║
162
+ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
163
+
164
+ ████████╗ ███████╗████████╗ █████╗ ██████╗██╗ ██╗
165
+ ╚══██╔══╝ ██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝
166
+ ██║ ███████╗ ██║ ███████║██║ █████╔╝
167
+ ██║ ╚════██║ ██║ ██╔══██║██║ ██╔═██╗
168
+ ██║ ███████║ ██║ ██║ ██║╚██████╗██║ ██╗
169
+ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
170
+ `,Q={pink:`#F5C2E7`,mauve:`#CBA6F7`,red:`#F38BA8`,maroon:`#E78284`,peach:`#FAB387`,yellow:`#F9E2AF`,green:`#A6E3A1`,teal:`#94E2D5`,sky:`#89DCEB`,sapphire:`#74C7EC`,lavender:`#B4BEFE`},Ot=()=>{let e=process.stdout.columns||80,t=Z.split(`
171
+ `),n=Math.max(...t.map(e=>e.length));if(e<n){let e=`
172
+ ╔══════════════════╗
173
+ ║ Better T-Stack ║
174
+ ╚══════════════════╝
175
+ `;console.log(E(Object.values(Q)).multiline(e))}else console.log(E(Object.values(Q)).multiline(Z))},$=()=>process.exit(0);process.on(`SIGINT`,$),process.on(`SIGTERM`,$);async function kt(){let e=Date.now();try{let n=await v(y(process.argv)).scriptName(`create-better-t-stack`).usage(`$0 [project-directory] [options]`,`Create a new Better-T Stack project`).positional(`project-directory`,{describe:`Project name/directory`,type:`string`}).option(`yes`,{alias:`y`,type:`boolean`,describe:`Use default configuration and skip prompts`,default:!1}).option(`database`,{type:`string`,describe:`Database type`,choices:[`none`,`sqlite`,`postgres`,`mysql`,`mongodb`]}).option(`orm`,{type:`string`,describe:`ORM type`,choices:[`drizzle`,`prisma`,`none`]}).option(`auth`,{type:`boolean`,describe:`Include authentication (use --no-auth to exclude)`}).option(`frontend`,{type:`array`,string:!0,describe:`Frontend types`,choices:[`tanstack-router`,`react-router`,`tanstack-start`,`next`,`nuxt`,`native`,`svelte`,`none`]}).option(`addons`,{type:`array`,string:!0,describe:`Additional addons`,choices:[`pwa`,`tauri`,`starlight`,`biome`,`husky`,`turborepo`,`none`]}).option(`examples`,{type:`array`,string:!0,describe:`Examples to include`,choices:[`todo`,`ai`,`none`]}).option(`git`,{type:`boolean`,describe:`Initialize git repository (use --no-git to skip)`}).option(`package-manager`,{alias:`pm`,type:`string`,describe:`Package manager`,choices:[`npm`,`pnpm`,`bun`]}).option(`install`,{type:`boolean`,describe:`Install dependencies (use --no-install to skip)`}).option(`db-setup`,{type:`string`,describe:`Database setup`,choices:[`turso`,`neon`,`prisma-postgres`,`mongodb-atlas`,`none`]}).option(`backend`,{type:`string`,describe:`Backend framework`,choices:[`hono`,`express`,`next`,`elysia`]}).option(`runtime`,{type:`string`,describe:`Runtime`,choices:[`bun`,`node`]}).option(`api`,{type:`string`,describe:`API type`,choices:[`trpc`,`orpc`]}).completion().recommendCommands().version(Dt()).alias(`version`,`v`).help().alias(`help`,`h`).strict().wrap(null).parse(),r=n,i=r.projectDirectory;Ot();let o=At(r,i);a(_.magenta(`Creating a new Better-T-Stack project`)),!r.yes&&Object.keys(o).length>0&&(s.info(_.yellow(`Using these pre-selected options:`)),s.message(X(o)),s.message(``));let c;r.yes?(c={...j,projectName:i??j.projectName,...o},c.database===`none`&&(c.orm=`none`,c.auth=!1,c.dbSetup=`none`,c.examples=c.examples.filter(e=>e!==`todo`)),s.info(_.yellow(`Using these default/flag options:`)),s.message(X(c)),s.message(``)):c=await Tt(o);let u=t.resolve(process.cwd(),c.projectName);if(g.pathExistsSync(u)&&g.readdirSync(u).length>0){let e=await Y();c.projectName=e}await ut(c),s.success(_.blue(`You can reproduce this setup with the following command:\n${Et(c)}`));let d=((Date.now()-e)/1e3).toFixed(2);l(_.magenta(`Project created successfully in ${_.bold(d)} seconds!`))}catch(e){e instanceof Error?(e.name===`YError`?n(_.red(`Invalid arguments: ${e.message}`)):(h.error(`An unexpected error occurred: ${e.message}`),h.error(e.stack)),process.exit(1)):(h.error(`An unexpected error occurred.`),console.error(e),process.exit(1))}}function At(e,t){let n={};if(e.database&&(n.database=e.database),e.orm&&(n.orm=e.orm),e.auth!==void 0&&(n.auth=e.auth),e.git!==void 0&&(n.git=e.git),e.install!==void 0&&(n.install=e.install),e.backend&&(n.backend=e.backend),e.runtime&&(n.runtime=e.runtime),e.frontend&&e.frontend.length>0)if(e.frontend.includes(`none`))e.frontend.length>1&&(h.fatal(`Cannot combine 'none' with other frontend options.`),process.exit(1)),n.frontend=[];else{let t=e.frontend.filter(e=>e!==`none`),r=t.filter(e=>e===`tanstack-router`||e===`react-router`||e===`tanstack-start`||e===`next`||e===`nuxt`||e===`svelte`);r.length>1&&(h.fatal(`Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router, next, nuxt, svelte`),process.exit(1)),n.frontend=t}e.api&&(n.api=e.api),e.addons&&e.addons.length>0&&(e.addons.includes(`none`)?(e.addons.length>1&&(h.fatal(`Cannot combine 'none' with other addons.`),process.exit(1)),n.addons=[]):n.addons=e.addons.filter(e=>e!==`none`)),e.examples&&e.examples.length>0&&(e.examples.includes(`none`)?(e.examples.length>1&&(h.fatal(`Cannot combine 'none' with other examples.`),process.exit(1)),n.examples=[]):n.examples=e.examples.filter(e=>e!==`none`)),e.packageManager&&(n.packageManager=e.packageManager),t&&(n.projectName=t),e.dbSetup&&(n.dbSetup=e.dbSetup);let r=n.database??(e.yes?j.database:void 0),i=n.orm??(e.yes?j.orm:void 0),a=n.auth??(e.yes?j.auth:void 0),o=n.dbSetup??(e.yes?j.dbSetup:void 0),s=n.examples??(e.yes?j.examples:void 0),c=n.frontend??(e.yes?j.frontend:void 0),l=n.api??(e.yes?j.api:void 0),u=n.backend??(e.yes?j.backend:void 0);if(r===`none`&&(i&&i!==`none`&&(h.fatal(`Cannot use ORM '--orm ${i}' when database is 'none'.`),process.exit(1)),n.orm=`none`,a===!0&&(h.fatal(`Authentication requires a database. Cannot use --auth when database is 'none'.`),process.exit(1)),n.auth=!1,o&&o!==`none`&&(h.fatal(`Database setup '--db-setup ${o}' requires a database. Cannot use when database is 'none'.`),process.exit(1)),n.dbSetup=`none`,s?.includes(`todo`)&&(h.fatal(`The 'todo' example requires a database. Cannot use --examples todo when database is 'none'.`),process.exit(1)),n.examples&&=n.examples.filter(e=>e!==`todo`)),r===`mongodb`&&i===`drizzle`&&(h.fatal(`MongoDB is only available with Prisma. Cannot use --database mongodb with --orm drizzle`),process.exit(1)),n.dbSetup&&n.dbSetup!==`none`){let e=n.dbSetup;e===`turso`?(r&&r!==`sqlite`&&(h.fatal(`Turso setup requires SQLite. Cannot use --db-setup turso with --database ${r}`),process.exit(1)),i===`prisma`&&(h.fatal(`Turso setup is not compatible with Prisma. Cannot use --db-setup turso with --orm prisma`),process.exit(1)),n.database=`sqlite`,n.orm=`drizzle`):e===`prisma-postgres`?(r&&r!==`postgres`&&(h.fatal(`Prisma PostgreSQL setup requires PostgreSQL. Cannot use --db-setup prisma-postgres with --database ${r}.`),process.exit(1)),i&&i!==`prisma`&&i!==`none`&&(h.fatal(`Prisma PostgreSQL setup requires Prisma ORM. Cannot use --db-setup prisma-postgres with --orm ${i}.`),process.exit(1)),n.database=`postgres`,n.orm=`prisma`):e===`mongodb-atlas`?(r&&r!==`mongodb`&&(h.fatal(`MongoDB Atlas setup requires MongoDB. Cannot use --db-setup mongodb-atlas with --database ${r}.`),process.exit(1)),i&&i!==`prisma`&&i!==`none`&&(h.fatal(`MongoDB Atlas setup requires Prisma ORM. Cannot use --db-setup mongodb-atlas with --orm ${i}.`),process.exit(1)),n.database=`mongodb`,n.orm=`prisma`):e===`neon`&&(r&&r!==`postgres`&&(h.fatal(`Neon PostgreSQL setup requires PostgreSQL. Cannot use --db-setup neon with --database ${r}.`),process.exit(1)),n.database=`postgres`)}let d=c?.includes(`nuxt`),f=c?.includes(`svelte`);if((d||f)&&l===`trpc`&&(h.fatal(`tRPC API is not supported with '${d?`nuxt`:`svelte`}' frontend. Please use --api orpc or remove '${d?`nuxt`:`svelte`}' from --frontend.`),process.exit(1)),(d||f)&&l!==`orpc`&&(!e.api||e.yes&&e.api!==`trpc`)&&(n.api=`orpc`),n.addons&&n.addons.length>0){let e=[`pwa`,`tauri`],t=n.addons.some(t=>e.includes(t)),r=c?.some(e=>e===`tanstack-router`||e===`react-router`||e===`nuxt`&&n.addons?.includes(`tauri`)&&!n.addons?.includes(`pwa`)||e===`svelte`&&n.addons?.includes(`tauri`)&&!n.addons?.includes(`pwa`));if(t&&!r){let e=``;n.addons.includes(`pwa`)&&d?e=`PWA addon is not compatible with Nuxt.`:(n.addons.includes(`pwa`)||n.addons.includes(`tauri`))&&(e=`PWA and Tauri addons require tanstack-router, react-router, or Nuxt/Svelte (Tauri only).`),h.fatal(`${e} Cannot use these addons with your frontend selection.`),process.exit(1)}n.addons.includes(`husky`)&&!n.addons.includes(`biome`)&&h.warn(`Husky addon is recommended to be used with Biome for lint-staged configuration.`),n.addons=[...new Set(n.addons)]}if(n.examples&&n.examples.length>0){n.examples.includes(`ai`)&&u===`elysia`&&(h.fatal(`The 'ai' example is not compatible with the Elysia backend.`),process.exit(1));let e=c?.some(e=>[`tanstack-router`,`react-router`,`tanstack-start`,`next`,`nuxt`,`svelte`].includes(e));n.examples.length>0&&!e&&(h.fatal(`Examples require a web frontend (tanstack-router, react-router, tanstack-start, next, nuxt, or svelte).`),process.exit(1))}return n}kt().catch(e=>{h.error(`Aborting installation due to unexpected error...`),e instanceof Error?h.error(e.message):console.error(e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "2.2.3",
3
+ "version": "2.2.4",
4
4
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -45,8 +45,8 @@
45
45
  },
46
46
  "homepage": "https://better-t-stack.amanv.dev/",
47
47
  "scripts": {
48
- "build": "tsup",
49
- "dev": "tsup --watch",
48
+ "build": "tsdown",
49
+ "dev": "tsdown --watch",
50
50
  "check-types": "tsc --noEmit",
51
51
  "check": "biome check --write .",
52
52
  "test": "vitest run",
@@ -68,7 +68,7 @@
68
68
  "@types/globby": "^9.1.0",
69
69
  "@types/node": "^22.14.1",
70
70
  "@types/yargs": "^17.0.33",
71
- "tsup": "^8.4.0",
71
+ "tsdown": "^0.9.9",
72
72
  "typescript": "^5.8.3"
73
73
  }
74
74
  }
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
-
2
- export { }