create-better-t-stack 2.0.12 → 2.1.1

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.
Files changed (125) hide show
  1. package/dist/index.js +81 -81
  2. package/package.json +1 -1
  3. package/templates/api/orpc/native/utils/orpc.ts.hbs +49 -0
  4. package/templates/api/orpc/web/nuxt/app/plugins/orpc.ts.hbs +35 -0
  5. package/templates/{auth/native/utils/trpc.ts → api/trpc/native/utils/trpc.ts.hbs} +4 -0
  6. package/templates/api/trpc/web/{base → react/base}/src/utils/trpc.ts.hbs +1 -1
  7. package/templates/auth/native/app/(drawer)/{index.tsx → index.tsx.hbs} +11 -0
  8. package/templates/auth/native/components/{sign-in.tsx → sign-in.tsx.hbs} +6 -1
  9. package/templates/auth/native/components/{sign-up.tsx → sign-up.tsx.hbs} +5 -0
  10. package/templates/auth/server/base/src/lib/auth.ts.hbs +48 -9
  11. package/templates/auth/web/nuxt/app/components/SignInForm.vue +78 -0
  12. package/templates/auth/web/nuxt/app/components/SignUpForm.vue +85 -0
  13. package/templates/auth/web/nuxt/app/components/UserMenu.vue +43 -0
  14. package/templates/auth/web/nuxt/app/middleware/auth.ts +12 -0
  15. package/templates/auth/web/nuxt/app/pages/dashboard.vue +27 -0
  16. package/templates/auth/web/nuxt/app/pages/login.vue +24 -0
  17. package/templates/auth/web/nuxt/app/plugins/auth-client.ts +16 -0
  18. package/templates/examples/ai/web/nuxt/app/pages/ai.vue +64 -0
  19. package/templates/examples/todo/server/prisma/base/{trpc/src/routers/todo.ts → src/routers/todo.ts.hbs} +47 -0
  20. package/templates/examples/todo/web/nuxt/app/pages/todos.vue +108 -0
  21. package/templates/extras/_npmrc.hbs +5 -0
  22. package/templates/frontend/native/app/(drawer)/{index.tsx → index.tsx.hbs} +10 -0
  23. package/templates/frontend/native/app/{_layout.tsx → _layout.tsx.hbs} +8 -3
  24. package/templates/frontend/native/package.json +0 -3
  25. package/templates/frontend/nuxt/_gitignore +24 -0
  26. package/templates/frontend/nuxt/app/app.config.ts +15 -0
  27. package/templates/frontend/nuxt/app/app.vue +13 -0
  28. package/templates/frontend/nuxt/app/assets/css/main.css +2 -0
  29. package/templates/frontend/nuxt/app/components/Header.vue.hbs +45 -0
  30. package/templates/frontend/nuxt/app/components/Loader.vue +5 -0
  31. package/templates/frontend/nuxt/app/components/ModeToggle.vue +23 -0
  32. package/templates/frontend/nuxt/app/layouts/default.vue +11 -0
  33. package/templates/frontend/nuxt/app/pages/index.vue +63 -0
  34. package/templates/frontend/nuxt/app/plugins/vue-query.ts +44 -0
  35. package/templates/frontend/nuxt/nuxt.config.ts.hbs +19 -0
  36. package/templates/frontend/nuxt/package.json +25 -0
  37. package/templates/frontend/nuxt/public/favicon.ico +0 -0
  38. package/templates/frontend/nuxt/public/robots.txt +2 -0
  39. package/templates/frontend/nuxt/server/tsconfig.json +3 -0
  40. package/templates/frontend/nuxt/tsconfig.json +4 -0
  41. package/templates/extras/_npmrc +0 -1
  42. package/templates/frontend/native/utils/trpc.ts +0 -19
  43. /package/templates/api/orpc/web/{base → react/base}/src/utils/orpc.ts.hbs +0 -0
  44. /package/templates/auth/web/{base → react/base}/src/lib/auth-client.ts.hbs +0 -0
  45. /package/templates/auth/web/{next → react/next}/src/app/dashboard/page.tsx.hbs +0 -0
  46. /package/templates/auth/web/{next → react/next}/src/app/login/page.tsx +0 -0
  47. /package/templates/auth/web/{next → react/next}/src/components/sign-in-form.tsx +0 -0
  48. /package/templates/auth/web/{next → react/next}/src/components/sign-up-form.tsx +0 -0
  49. /package/templates/auth/web/{next → react/next}/src/components/theme-provider.tsx +0 -0
  50. /package/templates/auth/web/{next → react/next}/src/components/user-menu.tsx +0 -0
  51. /package/templates/auth/web/{react-router → react/react-router}/src/components/sign-in-form.tsx +0 -0
  52. /package/templates/auth/web/{react-router → react/react-router}/src/components/sign-up-form.tsx +0 -0
  53. /package/templates/auth/web/{react-router → react/react-router}/src/components/user-menu.tsx +0 -0
  54. /package/templates/auth/web/{react-router → react/react-router}/src/routes/dashboard.tsx.hbs +0 -0
  55. /package/templates/auth/web/{react-router → react/react-router}/src/routes/login.tsx +0 -0
  56. /package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/components/sign-in-form.tsx +0 -0
  57. /package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/components/sign-up-form.tsx +0 -0
  58. /package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/components/user-menu.tsx +0 -0
  59. /package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/routes/dashboard.tsx.hbs +0 -0
  60. /package/templates/auth/web/{tanstack-router → react/tanstack-router}/src/routes/login.tsx +0 -0
  61. /package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/components/sign-in-form.tsx +0 -0
  62. /package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/components/sign-up-form.tsx +0 -0
  63. /package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/components/user-menu.tsx +0 -0
  64. /package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/routes/dashboard.tsx.hbs +0 -0
  65. /package/templates/auth/web/{tanstack-start → react/tanstack-start}/src/routes/login.tsx +0 -0
  66. /package/templates/examples/ai/web/{react-router → react/react-router}/src/routes/ai.tsx +0 -0
  67. /package/templates/examples/ai/web/{tanstack-router → react/tanstack-router}/src/routes/ai.tsx +0 -0
  68. /package/templates/examples/ai/web/{tanstack-start → react/tanstack-start}/src/routes/ai.tsx +0 -0
  69. /package/templates/examples/todo/web/{react-router → react/react-router}/src/routes/todos.tsx.hbs +0 -0
  70. /package/templates/examples/todo/web/{tanstack-router → react/tanstack-router}/src/routes/todos.tsx.hbs +0 -0
  71. /package/templates/examples/todo/web/{tanstack-start → react/tanstack-start}/src/routes/todos.tsx.hbs +0 -0
  72. /package/templates/frontend/{next → react/next}/next-env.d.ts +0 -0
  73. /package/templates/frontend/{next → react/next}/next.config.ts +0 -0
  74. /package/templates/frontend/{next → react/next}/package.json +0 -0
  75. /package/templates/frontend/{next → react/next}/postcss.config.mjs +0 -0
  76. /package/templates/frontend/{next → react/next}/src/app/favicon.ico +0 -0
  77. /package/templates/frontend/{next → react/next}/src/app/layout.tsx +0 -0
  78. /package/templates/frontend/{next → react/next}/src/app/page.tsx.hbs +0 -0
  79. /package/templates/frontend/{next → react/next}/src/components/mode-toggle.tsx +0 -0
  80. /package/templates/frontend/{next → react/next}/src/components/providers.tsx.hbs +0 -0
  81. /package/templates/frontend/{next → react/next}/src/components/theme-provider.tsx +0 -0
  82. /package/templates/frontend/{next → react/next}/tsconfig.json +0 -0
  83. /package/templates/frontend/{react-router → react/react-router}/package.json +0 -0
  84. /package/templates/frontend/{react-router → react/react-router}/public/favicon.ico +0 -0
  85. /package/templates/frontend/{react-router → react/react-router}/react-router.config.ts +0 -0
  86. /package/templates/frontend/{react-router → react/react-router}/src/components/mode-toggle.tsx +0 -0
  87. /package/templates/frontend/{react-router → react/react-router}/src/components/theme-provider.tsx +0 -0
  88. /package/templates/frontend/{react-router → react/react-router}/src/root.tsx.hbs +0 -0
  89. /package/templates/frontend/{react-router → react/react-router}/src/routes/_index.tsx.hbs +0 -0
  90. /package/templates/frontend/{react-router → react/react-router}/src/routes.ts +0 -0
  91. /package/templates/frontend/{react-router → react/react-router}/tsconfig.json +0 -0
  92. /package/templates/frontend/{react-router → react/react-router}/vite.config.ts.hbs +0 -0
  93. /package/templates/frontend/{tanstack-router → react/tanstack-router}/index.html +0 -0
  94. /package/templates/frontend/{tanstack-router → react/tanstack-router}/package.json +0 -0
  95. /package/templates/frontend/{tanstack-router → react/tanstack-router}/src/components/mode-toggle.tsx +0 -0
  96. /package/templates/frontend/{tanstack-router → react/tanstack-router}/src/components/theme-provider.tsx +0 -0
  97. /package/templates/frontend/{tanstack-router → react/tanstack-router}/src/main.tsx.hbs +0 -0
  98. /package/templates/frontend/{tanstack-router → react/tanstack-router}/src/routes/__root.tsx.hbs +0 -0
  99. /package/templates/frontend/{tanstack-router → react/tanstack-router}/src/routes/index.tsx.hbs +0 -0
  100. /package/templates/frontend/{tanstack-router → react/tanstack-router}/tsconfig.json +0 -0
  101. /package/templates/frontend/{tanstack-router → react/tanstack-router}/vite.config.ts.hbs +0 -0
  102. /package/templates/frontend/{tanstack-start → react/tanstack-start}/app.config.ts +0 -0
  103. /package/templates/frontend/{tanstack-start → react/tanstack-start}/package.json +0 -0
  104. /package/templates/frontend/{tanstack-start → react/tanstack-start}/public/robots.txt +0 -0
  105. /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/api.ts +0 -0
  106. /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/client.tsx +0 -0
  107. /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/router.tsx.hbs +0 -0
  108. /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/routes/__root.tsx.hbs +0 -0
  109. /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/routes/index.tsx.hbs +0 -0
  110. /package/templates/frontend/{tanstack-start → react/tanstack-start}/src/ssr.tsx +0 -0
  111. /package/templates/frontend/{tanstack-start → react/tanstack-start}/tsconfig.json +0 -0
  112. /package/templates/frontend/{web-base → react/web-base}/_gitignore +0 -0
  113. /package/templates/frontend/{web-base → react/web-base}/components.json +0 -0
  114. /package/templates/frontend/{web-base → react/web-base}/src/components/header.tsx.hbs +0 -0
  115. /package/templates/frontend/{web-base → react/web-base}/src/components/loader.tsx +0 -0
  116. /package/templates/frontend/{web-base → react/web-base}/src/components/ui/button.tsx +0 -0
  117. /package/templates/frontend/{web-base → react/web-base}/src/components/ui/card.tsx +0 -0
  118. /package/templates/frontend/{web-base → react/web-base}/src/components/ui/checkbox.tsx +0 -0
  119. /package/templates/frontend/{web-base → react/web-base}/src/components/ui/dropdown-menu.tsx +0 -0
  120. /package/templates/frontend/{web-base → react/web-base}/src/components/ui/input.tsx +0 -0
  121. /package/templates/frontend/{web-base → react/web-base}/src/components/ui/label.tsx +0 -0
  122. /package/templates/frontend/{web-base → react/web-base}/src/components/ui/skeleton.tsx +0 -0
  123. /package/templates/frontend/{web-base → react/web-base}/src/components/ui/sonner.tsx +0 -0
  124. /package/templates/frontend/{web-base → react/web-base}/src/index.css +0 -0
  125. /package/templates/frontend/{web-base → react/web-base}/src/lib/utils.ts +0 -0
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import ro from"node:path";import{cancel as ao,intro as no,log as _,outro as oo}from"@clack/prompts";import{consola as k}from"consola";import pr from"fs-extra";import W from"picocolors";import so from"yargs";import{hideBin as io}from"yargs/helpers";import Oe from"node:path";import{fileURLToPath as yr}from"node:url";var re=()=>{let e=process.env.npm_config_user_agent;return e?.startsWith("pnpm")?"pnpm":e?.startsWith("bun")?"bun":"npm"};var Pr=yr(import.meta.url),vr=Oe.dirname(Pr),v=Oe.join(vr,"../"),g={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"},be={"better-auth":"^1.2.6","@better-auth/expo":"^1.2.6","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","@prisma/extension-accelerate":"^1.3.0","@orpc/server":"^1.0.3","@orpc/react-query":"^1.0.3","@orpc/client":"^1.0.3","@trpc/tanstack-react-query":"^11.0.0","@trpc/server":"^11.0.0","@trpc/client":"^11.0.0"};import qa from"node:path";import{cancel as Va,log as Ga,spinner as Ja}from"@clack/prompts";import Qa from"fs-extra";import Bt from"picocolors";import H from"node:path";import N from"fs-extra";import jr from"node:path";import Ue from"fs-extra";var w=async e=>{let{dependencies:r=[],devDependencies:t=[],projectDir:a}=e,n=jr.join(a,"package.json"),o=await Ue.readJson(n);o.dependencies||(o.dependencies={}),o.devDependencies||(o.devDependencies={});for(let s of r){let i=be[s];i?o.dependencies[s]=i:console.warn(`Warning: Dependency ${s} not found in version map.`)}for(let s of t){let i=be[s];i?o.devDependencies[s]=i:console.warn(`Warning: Dev dependency ${s} not found in version map.`)}await Ue.writeJson(n,o,{spaces:2})};import _e from"node:path";import{spinner as kr}from"@clack/prompts";import xr from"consola";import{execa as Ar}from"execa";import We from"picocolors";function R(e,r){switch(e){case"pnpm":return`pnpm dlx ${r}`;case"bun":return`bunx ${r}`;default:return`npx ${r}`}}async function ze(e){let{projectName:r,packageManager:t}=e,a=_e.resolve(process.cwd(),r),n=kr();try{n.start("Setting up Starlight docs...");let i=`create-astro@latest ${["docs","--template","starlight","--no-install","--add","tailwind","--no-git","--skip-houston"].join(" ")}`,c=R(t,i);await Ar(c,{cwd:_e.join(a,"apps"),env:{CI:"true"},shell:!0}),n.stop("Starlight docs setup successfully!")}catch(o){throw n.stop(We.red("Failed to set up Starlight docs")),o instanceof Error&&xr.error(We.red(o.message)),o}}import Q from"node:path";import{spinner as Sr}from"@clack/prompts";import{consola as Dr}from"consola";import{execa as $r}from"execa";import ae from"fs-extra";import qe from"picocolors";async function Ve(e){let{projectName:r,packageManager:t,frontend:a}=e,n=Q.resolve(process.cwd(),r),o=Sr(),s=Q.join(n,"apps/web");if(await ae.pathExists(s))try{o.start("Setting up Tauri desktop app support..."),await w({devDependencies:["@tauri-apps/cli"],projectDir:s});let i=Q.join(s,"package.json");if(await ae.pathExists(i)){let j=await ae.readJson(i);j.scripts={...j.scripts,tauri:"tauri","desktop:dev":"tauri dev","desktop:build":"tauri build"},await ae.writeJson(i,j,{spaces:2})}let l=a.includes("react-router")?"http://localhost:5173":"http://localhost:3001",p=`@tauri-apps/cli@latest ${["init",`--app-name=${Q.basename(n)}`,`--window-title=${Q.basename(n)}`,"--frontend-dist=../dist",`--dev-url=${l}`,`--before-dev-command="${t} run dev"`,`--before-build-command="${t} run build"`].join(" ")}`,b=R(t,p);await $r(b,{cwd:s,env:{CI:"true"},shell:!0}),o.stop("Tauri desktop app support configured successfully!")}catch(i){throw o.stop(qe.red("Failed to set up Tauri")),i instanceof Error&&Dr.error(qe.red(i.message)),i}}async function Ge(e){let{projectName:r,addons:t,frontend:a}=e,n=H.resolve(process.cwd(),r),o=a.includes("react-router")||a.includes("tanstack-router");t.includes("turborepo")&&await w({devDependencies:["turbo"],projectDir:n}),t.includes("pwa")&&o&&await Fr(n,a),t.includes("tauri")&&o&&await Ve(e),t.includes("biome")&&await Cr(n),t.includes("husky")&&await Tr(n),t.includes("starlight")&&await ze(e)}function Er(e,r){return H.join(e,"apps/web")}async function Cr(e){await w({devDependencies:["@biomejs/biome"],projectDir:e});let r=H.join(e,"package.json");if(await N.pathExists(r)){let t=await N.readJson(r);t.scripts={...t.scripts,check:"biome check --write ."},await N.writeJson(r,t,{spaces:2})}}async function Tr(e){await w({devDependencies:["husky","lint-staged"],projectDir:e});let r=H.join(e,"package.json");if(await N.pathExists(r)){let t=await N.readJson(r);t.scripts={...t.scripts,prepare:"husky"},t["lint-staged"]={"*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}":["biome check --write ."]},await N.writeJson(r,t,{spaces:2})}}async function Fr(e,r){let t=Er(e,r);if(!await N.pathExists(t))return;await w({dependencies:["vite-plugin-pwa"],devDependencies:["@vite-pwa/assets-generator"],projectDir:t});let a=H.join(t,"package.json");if(await N.pathExists(a)){let n=await N.readJson(a);n.scripts={...n.scripts,"generate-pwa-assets":"pwa-assets-generator"},await N.writeJson(a,n,{spaces:2})}}import*as Y from"node:path";import Rr from"fs-extra";async function Je(e){let{api:r,projectName:t}=e,a=Y.resolve(process.cwd(),t),n=Y.join(a,"apps/web"),o=Y.join(a,"apps/server"),s=await Rr.pathExists(n);r==="orpc"&&(s&&await w({dependencies:["@orpc/react-query","@orpc/server","@orpc/client"],projectDir:n}),await w({dependencies:["@orpc/server","@orpc/client"],projectDir:o})),r==="trpc"&&(s&&await w({dependencies:["@trpc/tanstack-react-query","@trpc/server","@trpc/client"],projectDir:n}),await w({dependencies:["@trpc/server","@trpc/client"],projectDir:o}))}import ne from"node:path";import Qe from"consola";import He from"fs-extra";import Ye from"picocolors";async function Ke(e){let{projectName:r,auth:t,frontend:a}=e;if(!t)return;let n=ne.resolve(process.cwd(),r),o=ne.join(n,"apps/server"),s=ne.join(n,"apps/web"),i=ne.join(n,"apps/native"),c=await He.pathExists(s),l=await He.pathExists(i);try{await w({dependencies:["better-auth"],projectDir:o}),(a.includes("react-router")||a.includes("tanstack-router")||a.includes("tanstack-start")||a.includes("next"))&&c&&await w({dependencies:["better-auth"],projectDir:s}),a.includes("native")&&l&&(await w({dependencies:["better-auth","@better-auth/expo"],projectDir:i}),await w({dependencies:["@better-auth/expo"],projectDir:o}))}catch(d){Qe.error(Ye.red("Failed to configure authentication dependencies")),d instanceof Error&&Qe.error(Ye.red(d.message))}}function Xe(e=32){let r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t="",a=r.length;for(let n=0;n<e;n++)t+=r.charAt(Math.floor(Math.random()*a));return t}import Ze from"node:path";async function et(e){let{projectName:r,backend:t,runtime:a,api:n}=e,o=Ze.resolve(process.cwd(),r),s=t,i=Ze.join(o,"apps/server"),c=[],l=[];s==="hono"?(c.push("hono"),n==="trpc"&&c.push("@hono/trpc-server"),a==="node"&&(c.push("@hono/node-server"),l.push("tsx","@types/node"))):s==="elysia"?(c.push("elysia","@elysiajs/cors"),n==="trpc"&&c.push("@elysiajs/trpc"),a==="node"&&(c.push("@elysiajs/node"),l.push("tsx","@types/node"))):s==="express"&&(c.push("express","cors"),l.push("@types/express","@types/cors"),a==="node"&&l.push("tsx","@types/node")),a==="bun"&&l.push("@types/bun"),await w({dependencies:c,devDependencies:l,projectDir:i})}import Nr from"node:path";import Br from"consola";import Ir from"fs-extra";async function tt(e,r){let t=Nr.join(e,"README.md"),a=Lr(r);try{await Ir.writeFile(t,a)}catch(n){Br.error("Failed to create README.md file:",n)}}function Lr(e){let{projectName:r,packageManager:t,database:a,auth:n,addons:o=[],orm:s="drizzle",runtime:i="bun",frontend:c=["tanstack-router"],backend:l="hono"}=e,d=c.includes("react-router"),P=c.includes("tanstack-router"),p=c.includes("native"),b=c.includes("next"),j=c.includes("tanstack-start"),A=t==="npm"?"npm run":t,S="3001";return d?S="5173":b&&(S="3000"),`# ${r}
2
+ import rs from"node:path";import{cancel as as,intro as ns,log as O,outro as ss}from"@clack/prompts";import{consola as S}from"consola";import ir from"fs-extra";import U from"picocolors";import os from"yargs";import{hideBin as is}from"yargs/helpers";import Oe 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),Pr=Oe.dirname(yr),j=Oe.join(Pr,"../"),y={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"},be={"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","@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","@trpc/tanstack-react-query":"^11.0.0","@trpc/server":"^11.0.0","@trpc/client":"^11.0.0"};import Wa from"node:path";import{cancel as qa,log as Va,spinner as Ga}from"@clack/prompts";import Ja from"fs-extra";import Ft from"picocolors";import K from"node:path";import R from"fs-extra";import vr from"node:path";import Ue from"fs-extra";var w=async e=>{let{dependencies:r=[],devDependencies:t=[],projectDir:a}=e,n=vr.join(a,"package.json"),s=await Ue.readJson(n);s.dependencies||(s.dependencies={}),s.devDependencies||(s.devDependencies={});for(let o of r){let i=be[o];i?s.dependencies[o]=i:console.warn(`Warning: Dependency ${o} not found in version map.`)}for(let o of t){let i=be[o];i?s.devDependencies[o]=i:console.warn(`Warning: Dev dependency ${o} not found in version map.`)}await Ue.writeJson(n,s,{spaces:2})};import _e from"node:path";import{spinner as jr}from"@clack/prompts";import kr from"consola";import{execa as xr}from"execa";import ze from"picocolors";function T(e,r){switch(e){case"pnpm":return`pnpm dlx ${r}`;case"bun":return`bunx ${r}`;default:return`npx ${r}`}}async function We(e){let{projectName:r,packageManager:t}=e,a=_e.resolve(process.cwd(),r),n=jr();try{n.start("Setting up Starlight docs...");let i=`create-astro@latest ${["docs","--template","starlight","--no-install","--add","tailwind","--no-git","--skip-houston"].join(" ")}`,c=T(t,i);await xr(c,{cwd:_e.join(a,"apps"),env:{CI:"true"},shell:!0}),n.stop("Starlight docs setup successfully!")}catch(s){throw n.stop(ze.red("Failed to set up Starlight docs")),s instanceof Error&&kr.error(ze.red(s.message)),s}}import Y 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 qe from"picocolors";async function Ve(e){let{projectName:r,packageManager:t,frontend:a}=e,n=Y.resolve(process.cwd(),r),s=Sr(),o=Y.join(n,"apps/web");if(await ae.pathExists(o))try{s.start("Setting up Tauri desktop app support..."),await w({devDependencies:["@tauri-apps/cli"],projectDir:o});let i=Y.join(o,"package.json");if(await ae.pathExists(i)){let v=await ae.readJson(i);v.scripts={...v.scripts,tauri:"tauri","desktop:dev":"tauri dev","desktop:build":"tauri build"},await ae.writeJson(i,v,{spaces:2})}let c=a.includes("react-router"),p=a.includes("nuxt"),f=c?"http://localhost:5173":"http://localhost:3001",b=p?"../.output/public":"../dist",k=`@tauri-apps/cli@latest ${["init",`--app-name=${Y.basename(n)}`,`--window-title=${Y.basename(n)}`,`--frontend-dist=${b}`,`--dev-url=${f}`,`--before-dev-command="${t} run dev"`,`--before-build-command="${t} run build"`].join(" ")}`,D=T(t,k);await Ar(D,{cwd:o,env:{CI:"true"},shell:!0}),s.stop("Tauri desktop app support configured successfully!")}catch(i){throw s.stop(qe.red("Failed to set up Tauri")),i instanceof Error&&Dr.error(qe.red(i.message)),i}}async function Ge(e){let{projectName:r,addons:t,frontend:a}=e,n=K.resolve(process.cwd(),r),s=a.includes("react-router")||a.includes("tanstack-router"),o=a.includes("nuxt");t.includes("turborepo")&&await w({devDependencies:["turbo"],projectDir:n}),t.includes("pwa")&&s&&await Tr(n,a),t.includes("tauri")&&(s||o)&&await Ve(e),t.includes("biome")&&await Er(n),t.includes("husky")&&await Cr(n),t.includes("starlight")&&await We(e)}function $r(e,r){return K.join(e,"apps/web")}async function Er(e){await w({devDependencies:["@biomejs/biome"],projectDir:e});let r=K.join(e,"package.json");if(await R.pathExists(r)){let t=await R.readJson(r);t.scripts={...t.scripts,check:"biome check --write ."},await R.writeJson(r,t,{spaces:2})}}async function Cr(e){await w({devDependencies:["husky","lint-staged"],projectDir:e});let r=K.join(e,"package.json");if(await R.pathExists(r)){let t=await R.readJson(r);t.scripts={...t.scripts,prepare:"husky"},t["lint-staged"]={"*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}":["biome check --write ."]},await R.writeJson(r,t,{spaces:2})}}async function Tr(e,r){if(!r.some(s=>["react-router","tanstack-router"].includes(s)))return;let a=$r(e,r);if(!await R.pathExists(a))return;await w({dependencies:["vite-plugin-pwa"],devDependencies:["@vite-pwa/assets-generator"],projectDir:a});let n=K.join(a,"package.json");if(await R.pathExists(n)){let s=await R.readJson(n);s.scripts={...s.scripts,"generate-pwa-assets":"pwa-assets-generator"},await R.writeJson(n,s,{spaces:2})}}import*as z from"node:path";import Je from"fs-extra";async function Qe(e){let{api:r,projectName:t,frontend:a}=e,n=z.resolve(process.cwd(),t),s=z.join(n,"apps/web"),o=z.join(n,"apps/server"),i=await Je.pathExists(s),c=a.some(f=>["tanstack-router","react-router","tanstack-start","next"].includes(f)),p=a.includes("nuxt");if(r==="orpc"?await w({dependencies:["@orpc/server","@orpc/client"],projectDir:o}):r==="trpc"&&(await w({dependencies:["@trpc/server","@trpc/client"],projectDir:o}),e.backend==="hono"?await w({dependencies:["@hono/trpc-server"],projectDir:o}):e.backend==="elysia"&&await w({dependencies:["@elysiajs/trpc"],projectDir:o})),i&&(c?r==="orpc"?await w({dependencies:["@orpc/react-query","@orpc/client","@orpc/server"],projectDir:s}):r==="trpc"&&await w({dependencies:["@trpc/tanstack-react-query","@trpc/client","@trpc/server"],projectDir:s}):p&&r==="orpc"&&await w({dependencies:["@orpc/vue-query","@orpc/client","@orpc/server"],projectDir:s})),a.includes("native")){let f=z.join(n,"apps/native");await Je.pathExists(f)&&(r==="trpc"?await w({dependencies:["@trpc/tanstack-react-query","@trpc/client","@trpc/server"],projectDir:f}):r==="orpc"&&await w({dependencies:["@orpc/react-query","@orpc/client","@orpc/server"],projectDir:f}))}}import ne from"node:path";import He from"consola";import Ye from"fs-extra";import Ke from"picocolors";async function Xe(e){let{projectName:r,auth:t,frontend:a}=e;if(!t)return;let n=ne.resolve(process.cwd(),r),s=ne.join(n,"apps/server"),o=ne.join(n,"apps/web"),i=ne.join(n,"apps/native"),c=await Ye.pathExists(o),p=await Ye.pathExists(i);try{await w({dependencies:["better-auth"],projectDir:s}),a.some(b=>["react-router","tanstack-router","tanstack-start","next","nuxt"].includes(b))&&c&&await w({dependencies:["better-auth"],projectDir:o}),a.includes("native")&&p&&(await w({dependencies:["better-auth","@better-auth/expo"],projectDir:i}),await w({dependencies:["@better-auth/expo"],projectDir:s}))}catch(f){He.error(Ke.red("Failed to configure authentication dependencies")),f instanceof Error&&He.error(Ke.red(f.message))}}function Ze(e=32){let r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t="",a=r.length;for(let n=0;n<e;n++)t+=r.charAt(Math.floor(Math.random()*a));return t}import et from"node:path";async function tt(e){let{projectName:r,backend:t,runtime:a,api:n}=e,s=et.resolve(process.cwd(),r),o=t,i=et.join(s,"apps/server"),c=[],p=[];o==="hono"?(c.push("hono"),n==="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"),n==="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 w({dependencies:c,devDependencies:p,projectDir:i})}import Rr from"node:path";import Nr from"consola";import Fr from"fs-extra";async function rt(e,r){let t=Rr.join(e,"README.md"),a=Br(r);try{await Fr.writeFile(t,a)}catch(n){Nr.error("Failed to create README.md file:",n)}}function Br(e){let{projectName:r,packageManager:t,database:a,auth:n,addons:s=[],orm:o="drizzle",runtime:i="bun",frontend:c=["tanstack-router"],backend:p="hono"}=e,f=c.includes("react-router"),b=c.includes("tanstack-router"),l=c.includes("native"),d=c.includes("next"),k=c.includes("tanstack-start"),D=t==="npm"?"npm run":t,v="3001";return f?v="5173":d&&(v="3000"),`# ${r}
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, ${P?"TanStack Router":d?"React Router":b?"Next.js":j?"TanStack Start":""}, ${l[0].toUpperCase()+l.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, ${b?"TanStack Router":f?"React Router":d?"Next.js":k?"TanStack Start":""}, ${p[0].toUpperCase()+p.slice(1)}, tRPC, and more.
5
5
 
6
6
  ## Features
7
7
 
8
- ${Mr(a,n,o,s,i,c,l)}
8
+ ${Ir(a,n,s,o,i,c,p)}
9
9
 
10
10
  ## Getting Started
11
11
 
@@ -15,20 +15,20 @@ First, install the dependencies:
15
15
  ${t} install
16
16
  \`\`\`
17
17
 
18
- ${Or(a,n,A,s)}
18
+ ${Lr(a,n,D,o)}
19
19
 
20
20
  Then, run the development server:
21
21
 
22
22
  \`\`\`bash
23
- ${A} dev
23
+ ${D} dev
24
24
  \`\`\`
25
25
 
26
- ${P||d||b||j?`Open [http://localhost:${S}](http://localhost:${S}) in your browser to see the web application.`:""}
27
- ${p?`Use the Expo Go app to run the mobile application.
26
+ ${b||f||d||k?`Open [http://localhost:${v}](http://localhost:${v}) in your browser to see the web application.`:""}
27
+ ${l?`Use the Expo Go app to run the mobile application.
28
28
  `:""}
29
29
  The API is running at [http://localhost:3000](http://localhost:3000).
30
30
 
31
- ${o.includes("pwa")&&d?`
31
+ ${s.includes("pwa")&&f?`
32
32
  ## PWA Support with React Router v7
33
33
 
34
34
  There is a known compatibility issue between VitePWA and React Router v7.
@@ -40,17 +40,17 @@ See: https://github.com/vite-pwa/vite-plugin-pwa/issues/809
40
40
  \`\`\`
41
41
  ${r}/
42
42
  \u251C\u2500\u2500 apps/
43
- ${P||d||b||j?`\u2502 \u251C\u2500\u2500 web/ # Frontend application (${P?"React + TanStack Router":d?"React + React Router":b?"Next.js":"React + TanStack Start"})
44
- `:""}${p?`\u2502 \u251C\u2500\u2500 native/ # Mobile application (React Native, Expo)
45
- `:""}${o.includes("starlight")?`\u2502 \u251C\u2500\u2500 docs/ # Documentation site (Astro Starlight)
46
- `:""}\u2502 \u2514\u2500\u2500 server/ # Backend API (${l[0].toUpperCase()+l.slice(1)}, tRPC)
43
+ ${b||f||d||k?`\u2502 \u251C\u2500\u2500 web/ # Frontend application (${b?"React + TanStack Router":f?"React + React Router":d?"Next.js":"React + TanStack Start"})
44
+ `:""}${l?`\u2502 \u251C\u2500\u2500 native/ # Mobile application (React Native, Expo)
45
+ `:""}${s.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)
47
47
  \`\`\`
48
48
 
49
49
  ## Available Scripts
50
50
 
51
- ${Ur(A,a,s,n,p,o,l)}
52
- `}function Mr(e,r,t,a,n,o,s){let i=o.includes("tanstack-router"),c=o.includes("react-router"),l=o.includes("native"),d=o.includes("next"),P=o.includes("tanstack-start"),p=["- **TypeScript** - For type safety and improved developer experience"];i?p.push("- **TanStack Router** - File-based routing with full type safety"):c?p.push("- **React Router** - Declarative routing for React"):d?p.push("- **Next.js** - Full-stack React framework"):P&&p.push("- **TanStack Start** - SSR framework with TanStack Router"),l&&(p.push("- **React Native** - Build mobile apps using React"),p.push("- **Expo** - Tools for React Native development")),p.push("- **TailwindCSS** - Utility-first CSS for rapid UI development","- **shadcn/ui** - Reusable UI components"),s==="hono"?p.push("- **Hono** - Lightweight, performant server framework"):s==="express"?p.push("- **Express** - Fast, unopinionated web framework"):s==="elysia"?p.push("- **Elysia** - Type-safe, high-performance framework"):s==="next"&&p.push("- **Next.js** - Full-stack React framework"),p.push("- **tRPC** - End-to-end type-safe APIs",`- **${n==="bun"?"Bun":"Node.js"}** - Runtime environment`),e!=="none"&&p.push(`- **${a==="drizzle"?"Drizzle":"Prisma"}** - TypeScript-first ORM`,`- **${e==="sqlite"?"SQLite/Turso":e==="postgres"?"PostgreSQL":e==="mysql"?"MySQL":"MongoDB"}** - Database engine`),r&&p.push("- **Authentication** - Email & password authentication with Better Auth");for(let b of t)b==="pwa"?p.push("- **PWA** - Progressive Web App support"):b==="tauri"?p.push("- **Tauri** - Build native desktop applications"):b==="biome"?p.push("- **Biome** - Linting and formatting"):b==="husky"?p.push("- **Husky** - Git hooks for code quality"):b==="starlight"&&p.push("- **Starlight** - Documentation site with Astro");return p.join(`
53
- `)}function Or(e,r,t,a){if(e==="none")return"";let n=`## Database Setup
51
+ ${Mr(D,a,o,n,l,s,p)}
52
+ `}function Ir(e,r,t,a,n,s,o){let i=s.includes("tanstack-router"),c=s.includes("react-router"),p=s.includes("native"),f=s.includes("next"),b=s.includes("tanstack-start"),l=["- **TypeScript** - For type safety and improved developer experience"];i?l.push("- **TanStack Router** - File-based routing with full type safety"):c?l.push("- **React Router** - Declarative routing for React"):f?l.push("- **Next.js** - Full-stack React framework"):b&&l.push("- **TanStack Start** - SSR framework with TanStack Router"),p&&(l.push("- **React Native** - Build mobile apps using React"),l.push("- **Expo** - Tools for React Native development")),l.push("- **TailwindCSS** - Utility-first CSS for rapid UI development","- **shadcn/ui** - Reusable UI components"),o==="hono"?l.push("- **Hono** - Lightweight, performant server framework"):o==="express"?l.push("- **Express** - Fast, unopinionated web framework"):o==="elysia"?l.push("- **Elysia** - Type-safe, high-performance framework"):o==="next"&&l.push("- **Next.js** - Full-stack React framework"),l.push("- **tRPC** - End-to-end type-safe APIs",`- **${n==="bun"?"Bun":"Node.js"}** - Runtime environment`),e!=="none"&&l.push(`- **${a==="drizzle"?"Drizzle":"Prisma"}** - TypeScript-first ORM`,`- **${e==="sqlite"?"SQLite/Turso":e==="postgres"?"PostgreSQL":e==="mysql"?"MySQL":"MongoDB"}** - Database engine`),r&&l.push("- **Authentication** - Email & password authentication with Better Auth");for(let d of t)d==="pwa"?l.push("- **PWA** - Progressive Web App support"):d==="tauri"?l.push("- **Tauri** - Build native desktop applications"):d==="biome"?l.push("- **Biome** - Linting and formatting"):d==="husky"?l.push("- **Husky** - Git hooks for code quality"):d==="starlight"&&l.push("- **Starlight** - Documentation site with Astro");return l.join(`
53
+ `)}function Lr(e,r,t,a){if(e==="none")return"";let n=`## Database Setup
54
54
 
55
55
  `;return e==="sqlite"?n+=`This project uses SQLite${a==="drizzle"?" with Drizzle ORM":" with Prisma"}.
56
56
 
@@ -80,7 +80,7 @@ ${t} db:push
80
80
  \`\`\`bash
81
81
  ${t} db:push
82
82
  \`\`\``}
83
- `,n}function Ur(e,r,t,a,n,o,s){let i=`- \`${e} dev\`: Start all applications in development mode
83
+ `,n}function Mr(e,r,t,a,n,s,o){let i=`- \`${e} dev\`: Start all applications in development mode
84
84
  - \`${e} build\`: Build all applications
85
85
  - \`${e} dev:web\`: Start only the web application
86
86
  - \`${e} dev:server\`: Start only the server
@@ -88,48 +88,48 @@ ${t} db:push
88
88
  - \`${e} dev:native\`: Start the React Native/Expo development server`),r!=="none"&&(i+=`
89
89
  - \`${e} db:push\`: Push schema changes to database
90
90
  - \`${e} db:studio\`: Open database studio UI`,r==="sqlite"&&t==="drizzle"&&(i+=`
91
- - \`cd apps/server && ${e} db:local\`: Start the local SQLite database`)),o.includes("biome")&&(i+=`
92
- - \`${e} check\`: Run Biome formatting and linting`),o.includes("pwa")&&(i+=`
93
- - \`cd apps/web && ${e} generate-pwa-assets\`: Generate PWA assets`),o.includes("tauri")&&(i+=`
91
+ - \`cd apps/server && ${e} db:local\`: Start the local SQLite database`)),s.includes("biome")&&(i+=`
92
+ - \`${e} check\`: Run Biome formatting and linting`),s.includes("pwa")&&(i+=`
93
+ - \`cd apps/web && ${e} generate-pwa-assets\`: Generate PWA assets`),s.includes("tauri")&&(i+=`
94
94
  - \`cd apps/web && ${e} desktop:dev\`: Start Tauri desktop app in development
95
- - \`cd apps/web && ${e} desktop:build\`: Build Tauri desktop app`),o.includes("starlight")&&(i+=`
95
+ - \`cd apps/web && ${e} desktop:build\`: Build Tauri desktop app`),s.includes("starlight")&&(i+=`
96
96
  - \`cd apps/docs && ${e} dev\`: Start documentation site
97
- - \`cd apps/docs && ${e} build\`: Build documentation site`),i}import Ee from"node:path";import{spinner as ya}from"@clack/prompts";import Pa from"consola";import va from"fs-extra";import ut from"picocolors";import se from"node:path";import{cancel as _r,isCancel as Wr,log as z,spinner as nt,text as zr}from"@clack/prompts";import ie from"consola";import{execa as qr}from"execa";import K from"fs-extra";import D from"picocolors";import{execa as rt}from"execa";async function oe(e){try{return process.platform==="win32"?(await rt("where",[e])).exitCode===0:(await rt("which",[e])).exitCode===0}catch{return!1}}async function Vr(){let e=nt();e.start("Checking for MongoDB Atlas CLI");try{let r=await oe("atlas");return e.stop(r?"MongoDB Atlas CLI found":D.yellow("MongoDB Atlas CLI not found")),r}catch{return e.stop(D.red("Error checking for MongoDB Atlas CLI")),!1}}async function Gr(e){try{if(!await Vr())return ie.error(D.red("MongoDB Atlas CLI not found.")),z.info(D.yellow("Please install it from: https://www.mongodb.com/docs/atlas/cli/current/install-atlas-cli/")),null;z.info(D.blue("Running MongoDB Atlas setup...")),await qr("atlas",["deployments","setup"],{cwd:e,stdio:"inherit"}),z.info(D.green("Atlas setup complete!"));let t=await zr({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 Wr(t)?(_r("MongoDB setup cancelled"),null):{connectionString:t}}catch(r){return r instanceof Error&&ie.error(D.red(r.message)),null}}async function we(e,r){try{let t=se.join(e,"apps/server",".env");await K.ensureDir(se.dirname(t));let a="";await K.pathExists(t)&&(a=await K.readFile(t,"utf8"));let n=r?`DATABASE_URL="${r.connectionString}"`:'DATABASE_URL="mongodb://localhost:27017/mydb"';a.includes("DATABASE_URL=")?a=a.replace(/DATABASE_URL=.*(\r?\n|$)/,`${n}$1`):a+=`
98
- ${n}`,await K.writeFile(t,a.trim())}catch(t){throw ie.error("Failed to update environment configuration"),t}}function at(){z.info(`
99
- ${D.green("MongoDB Atlas Manual Setup Instructions:")}
97
+ - \`cd apps/docs && ${e} build\`: Build documentation site`),i}import Ee from"node:path";import{spinner as ba}from"@clack/prompts";import wa from"consola";import ya from"fs-extra";import mt from"picocolors";import oe from"node:path";import{cancel as Or,isCancel as Ur,log as W,spinner as st,text as _r}from"@clack/prompts";import ie from"consola";import{execa as zr}from"execa";import X from"fs-extra";import A from"picocolors";import{execa as at}from"execa";async function se(e){try{return process.platform==="win32"?(await at("where",[e])).exitCode===0:(await at("which",[e])).exitCode===0}catch{return!1}}async function Wr(){let e=st();e.start("Checking for MongoDB Atlas CLI");try{let r=await se("atlas");return e.stop(r?"MongoDB Atlas CLI found":A.yellow("MongoDB Atlas CLI not found")),r}catch{return e.stop(A.red("Error checking for MongoDB Atlas CLI")),!1}}async function qr(e){try{if(!await Wr())return ie.error(A.red("MongoDB Atlas CLI not found.")),W.info(A.yellow("Please install it from: https://www.mongodb.com/docs/atlas/cli/current/install-atlas-cli/")),null;W.info(A.blue("Running MongoDB Atlas setup...")),await zr("atlas",["deployments","setup"],{cwd:e,stdio:"inherit"}),W.info(A.green("Atlas setup complete!"));let t=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(t)?(Or("MongoDB setup cancelled"),null):{connectionString:t}}catch(r){return r instanceof Error&&ie.error(A.red(r.message)),null}}async function we(e,r){try{let t=oe.join(e,"apps/server",".env");await X.ensureDir(oe.dirname(t));let a="";await X.pathExists(t)&&(a=await X.readFile(t,"utf8"));let n=r?`DATABASE_URL="${r.connectionString}"`:'DATABASE_URL="mongodb://localhost:27017/mydb"';a.includes("DATABASE_URL=")?a=a.replace(/DATABASE_URL=.*(\r?\n|$)/,`${n}$1`):a+=`
98
+ ${n}`,await X.writeFile(t,a.trim())}catch(t){throw ie.error("Failed to update environment configuration"),t}}function nt(){W.info(`
99
+ ${A.green("MongoDB Atlas Manual Setup Instructions:")}
100
100
 
101
101
  1. Install Atlas CLI:
102
- ${D.blue("https://www.mongodb.com/docs/atlas/cli/stable/install-atlas-cli/")}
102
+ ${A.blue("https://www.mongodb.com/docs/atlas/cli/stable/install-atlas-cli/")}
103
103
 
104
104
  2. Run the following command and follow the prompts:
105
- ${D.blue("atlas deployments setup")}
105
+ ${A.blue("atlas deployments setup")}
106
106
 
107
107
  3. Get your connection string from the Atlas dashboard:
108
- Format: ${D.dim("mongodb+srv://USERNAME:PASSWORD@CLUSTER.mongodb.net/DATABASE_NAME")}
108
+ Format: ${A.dim("mongodb+srv://USERNAME:PASSWORD@CLUSTER.mongodb.net/DATABASE_NAME")}
109
109
 
110
110
  4. Add the connection string to your .env file:
111
- ${D.dim('DATABASE_URL="your_connection_string"')}
112
- `)}async function ot(e){let{projectName:r}=e,t=se.resolve(process.cwd(),r),a=nt();a.start("Setting up MongoDB Atlas");let n=se.join(t,"apps/server");try{await K.ensureDir(n),a.stop("Starting MongoDB Atlas setup");let o=await Gr(n);o?(await we(t,o),z.success(D.green("MongoDB Atlas setup complete! Connection saved to .env file."))):(z.warn(D.yellow("Falling back to local MongoDB configuration")),await we(t),at())}catch(o){a.stop(D.red("MongoDB Atlas setup failed")),ie.error(D.red(`Error during MongoDB Atlas setup: ${o instanceof Error?o.message:String(o)}`));try{await we(t),at()}catch{}}}import M from"node:path";import{cancel as Jr,isCancel as Qr,log as X,password as Hr,spinner as Pe}from"@clack/prompts";import{consola as ve}from"consola";import{execa as Yr}from"execa";import B from"fs-extra";import q from"picocolors";async function Kr(e,r){let t=Pe();try{t.start("Initializing Prisma PostgreSQL");let a=M.join(e,"prisma");await B.ensureDir(a),t.stop("Initializing Prisma. Follow the prompts below:");let n=R(r,"prisma init --db");await Yr(n,{cwd:e,stdio:"inherit",shell:!0}),X.info(q.yellow(`Please copy the Prisma Postgres URL from the output above.
113
- It looks like: prisma+postgres://accelerate.prisma-data.net/?api_key=...`));let o=await Hr({message:"Paste your Prisma Postgres database URL:",validate(s){if(!s)return"Please enter a database URL";if(!s.startsWith("prisma+postgres://"))return"URL should start with prisma+postgres://"}});return Qr(o)?(Jr("Database setup cancelled"),null):{databaseUrl:o}}catch(a){return t.stop(q.red("Failed to initialize Prisma PostgreSQL")),a instanceof Error&&ve.error(a.message),null}}async function ye(e,r){try{let t=M.join(e,"apps/server",".env");await B.ensureDir(M.dirname(t));let a="";await B.pathExists(t)&&(a=await B.readFile(t,"utf8"));let n=r?`DATABASE_URL="${r.databaseUrl}"`:'DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"';a.includes("DATABASE_URL=")?a=a.replace(/DATABASE_URL=.*(\r?\n|$)/,`${n}$1`):a+=`
114
- ${n}`,await B.writeFile(t,a.trim())}catch(t){throw ve.error("Failed to update environment configuration"),t}}function st(){X.info(`Manual Prisma PostgreSQL Setup Instructions:
111
+ ${A.dim('DATABASE_URL="your_connection_string"')}
112
+ `)}async function ot(e){let{projectName:r}=e,t=oe.resolve(process.cwd(),r),a=st();a.start("Setting up MongoDB Atlas");let n=oe.join(t,"apps/server");try{await X.ensureDir(n),a.stop("Starting MongoDB Atlas setup");let s=await qr(n);s?(await we(t,s),W.success(A.green("MongoDB Atlas setup complete! Connection saved to .env file."))):(W.warn(A.yellow("Falling back to local MongoDB configuration")),await we(t),nt())}catch(s){a.stop(A.red("MongoDB Atlas setup failed")),ie.error(A.red(`Error during MongoDB Atlas setup: ${s instanceof Error?s.message:String(s)}`));try{await we(t),nt()}catch{}}}import I from"node:path";import{cancel as Vr,isCancel as Gr,log as Z,password as Jr,spinner as Pe}from"@clack/prompts";import{consola as ve}from"consola";import{execa as Qr}from"execa";import N from"fs-extra";import q from"picocolors";async function Hr(e,r){let t=Pe();try{t.start("Initializing Prisma PostgreSQL");let a=I.join(e,"prisma");await N.ensureDir(a),t.stop("Initializing Prisma. Follow the prompts below:");let n=T(r,"prisma init --db");await Qr(n,{cwd:e,stdio:"inherit",shell:!0}),Z.info(q.yellow(`Please copy the Prisma Postgres URL from the output above.
113
+ It looks like: prisma+postgres://accelerate.prisma-data.net/?api_key=...`));let s=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(s)?(Vr("Database setup cancelled"),null):{databaseUrl:s}}catch(a){return t.stop(q.red("Failed to initialize Prisma PostgreSQL")),a instanceof Error&&ve.error(a.message),null}}async function ye(e,r){try{let t=I.join(e,"apps/server",".env");await N.ensureDir(I.dirname(t));let a="";await N.pathExists(t)&&(a=await N.readFile(t,"utf8"));let n=r?`DATABASE_URL="${r.databaseUrl}"`:'DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"';a.includes("DATABASE_URL=")?a=a.replace(/DATABASE_URL=.*(\r?\n|$)/,`${n}$1`):a+=`
114
+ ${n}`,await N.writeFile(t,a.trim())}catch(t){throw ve.error("Failed to update environment configuration"),t}}function it(){Z.info(`Manual Prisma PostgreSQL Setup Instructions:
115
115
 
116
116
  1. Visit https://console.prisma.io and create an account
117
117
  2. Create a new PostgreSQL database from the dashboard
118
118
  3. Get your database URL
119
119
  4. Add the database URL to the .env file in apps/server/.env
120
120
 
121
- DATABASE_URL="your_database_url"`)}async function Xr(e){try{await w({dependencies:["@prisma/extension-accelerate"],projectDir:e});let r=M.join(e,"prisma/index.ts");await B.writeFile(r,`
121
+ DATABASE_URL="your_database_url"`)}async function Yr(e){try{await w({dependencies:["@prisma/extension-accelerate"],projectDir:e});let r=I.join(e,"prisma/index.ts");await N.writeFile(r,`
122
122
  import { PrismaClient } from '@prisma/client';
123
123
  import { withAccelerate } from "@prisma/extension-accelerate";
124
124
 
125
125
  const prisma = new PrismaClient().$extends(withAccelerate());
126
126
 
127
127
  export default prisma;
128
- `.trim());let a=M.join(e,"src/db/index.ts");if(await B.pathExists(a)){let n=await B.readFile(a,"utf8");n.includes("@prisma/extension-accelerate")||(n=`import { withAccelerate } from "@prisma/extension-accelerate";
129
- ${n}`,n=n.replace("export const db = new PrismaClient();","export const db = new PrismaClient().$extends(withAccelerate());"),await B.writeFile(a,n))}return!0}catch{return X.warn(q.yellow("Could not add Prisma Accelerate extension automatically")),!1}}async function it(e){let{projectName:r,packageManager:t}=e,a=M.resolve(process.cwd(),r),n=M.join(a,"apps/server"),o=Pe();o.start("Setting up Prisma PostgreSQL");try{await B.ensureDir(n),o.stop("Starting Prisma setup");let s=await Kr(n,t);if(s)await ye(a,s),await Xr(n),X.success(q.green("Prisma PostgreSQL database configured successfully!"));else{let i=Pe();i.start("Setting up fallback configuration"),await ye(a),i.stop("Manual setup required"),st()}}catch(s){o.stop(q.red("Prisma PostgreSQL setup failed")),ve.error(q.red(`Error during Prisma PostgreSQL setup: ${s instanceof Error?s.message:String(s)}`));try{await ye(a),st()}catch{}X.info("Setup completed with manual configuration required.")}}import Zr from"node:os";import pe from"node:path";import{cancel as ke,confirm as ea,isCancel as xe,log as V,select as ta,spinner as G,text as ra}from"@clack/prompts";import aa from"consola";import{$ as I}from"execa";import ct from"fs-extra";import $ from"picocolors";async function na(){return oe("turso")}async function oa(){try{return!(await I`turso auth whoami`).stdout.includes("You are not logged in")}catch{return!1}}async function sa(){let e=G();try{return e.start("Logging in to Turso..."),await I`turso auth login`,e.stop("Logged in to Turso successfully!"),!0}catch(r){throw e.stop($.red("Failed to log in to Turso")),r}}async function ia(e){let r=G();try{if(r.start("Installing Turso CLI..."),e)await I`brew install tursodatabase/tap/turso`;else{let{stdout:t}=await I`curl -sSfL https://get.tur.so/install.sh`;await I`bash -c '${t}'`}return r.stop("Turso CLI installed successfully!"),!0}catch(t){throw t instanceof Error&&t.message.includes("User force closed")?(r.stop("Turso CLI installation cancelled"),V.warn($.yellow("Turso CLI installation cancelled by user")),new Error("Installation cancelled")):(r.stop($.red("Failed to install Turso CLI")),t)}}async function ca(){let e=G();try{e.start("Fetching Turso groups...");let{stdout:r}=await I`turso group list`,t=r.trim().split(`
130
- `);if(t.length<=1)return e.stop("No Turso groups found"),[];let a=t.slice(1).map(n=>{let[o,s,i,c]=n.trim().split(/\s{2,}/);return{name:o,locations:s,version:i,status:c}});return e.stop(`Found ${a.length} Turso groups`),a}catch(r){return e.stop($.red("Error fetching Turso groups")),console.error("Error fetching Turso groups:",r),[]}}async function pa(){let e=await ca();if(e.length===0)return null;if(e.length===1)return V.info(`Using the only available group: ${$.blue(e[0].name)}`),e[0].name;let r=e.map(a=>({value:a.name,label:`${a.name} (${a.locations})`})),t=await ta({message:"Select a Turso database group:",options:r});return xe(t)&&(ke($.red("Operation cancelled")),process.exit(0)),t}async function la(e,r){let t=G();try{t.start(`Creating Turso database "${e}"${r?` in group "${r}"`:""}...`),r?await I`turso db create ${e} --group ${r}`:await I`turso db create ${e}`,t.stop(`Created database "${e}"`)}catch(a){throw t.stop($.red(`Failed to create database "${e}"`)),a instanceof Error&&a.message.includes("already exists")?new Error("DATABASE_EXISTS"):a}t.start("Retrieving database connection details...");try{let{stdout:a}=await I`turso db show ${e} --url`,{stdout:n}=await I`turso db tokens create ${e}`;return t.stop("Retrieved database connection details"),{dbUrl:a.trim(),authToken:n.trim()}}catch(a){throw t.stop($.red("Failed to retrieve database connection details")),a}}async function ce(e,r){let t=pe.join(e,"apps/server",".env"),a=r?`DATABASE_URL="${r.dbUrl}"
128
+ `.trim());let a=I.join(e,"src/db/index.ts");if(await N.pathExists(a)){let n=await N.readFile(a,"utf8");n.includes("@prisma/extension-accelerate")||(n=`import { withAccelerate } from "@prisma/extension-accelerate";
129
+ ${n}`,n=n.replace("export const db = new PrismaClient();","export const db = new PrismaClient().$extends(withAccelerate());"),await N.writeFile(a,n))}return!0}catch{return Z.warn(q.yellow("Could not add Prisma Accelerate extension automatically")),!1}}async function ct(e){let{projectName:r,packageManager:t}=e,a=I.resolve(process.cwd(),r),n=I.join(a,"apps/server"),s=Pe();s.start("Setting up Prisma PostgreSQL");try{await N.ensureDir(n),s.stop("Starting Prisma setup");let o=await Hr(n,t);if(o)await ye(a,o),await Yr(n),Z.success(q.green("Prisma PostgreSQL database configured successfully!"));else{let i=Pe();i.start("Setting up fallback configuration"),await ye(a),i.stop("Manual setup required"),it()}}catch(o){s.stop(q.red("Prisma PostgreSQL setup failed")),ve.error(q.red(`Error during Prisma PostgreSQL setup: ${o instanceof Error?o.message:String(o)}`));try{await ye(a),it()}catch{}Z.info("Setup completed with manual configuration required.")}}import Kr from"node:os";import pe from"node:path";import{cancel as ke,confirm as Xr,isCancel as xe,log as V,select as Zr,spinner as G,text as ea}from"@clack/prompts";import ta from"consola";import{$ as F}from"execa";import pt from"fs-extra";import $ from"picocolors";async function ra(){return se("turso")}async function aa(){try{return!(await F`turso auth whoami`).stdout.includes("You are not logged in")}catch{return!1}}async function na(){let e=G();try{return e.start("Logging in to Turso..."),await F`turso auth login`,e.stop("Logged in to Turso successfully!"),!0}catch(r){throw e.stop($.red("Failed to log in to Turso")),r}}async function sa(e){let r=G();try{if(r.start("Installing Turso CLI..."),e)await F`brew install tursodatabase/tap/turso`;else{let{stdout:t}=await F`curl -sSfL https://get.tur.so/install.sh`;await F`bash -c '${t}'`}return r.stop("Turso CLI installed successfully!"),!0}catch(t){throw t instanceof Error&&t.message.includes("User force closed")?(r.stop("Turso CLI installation cancelled"),V.warn($.yellow("Turso CLI installation cancelled by user")),new Error("Installation cancelled")):(r.stop($.red("Failed to install Turso CLI")),t)}}async function oa(){let e=G();try{e.start("Fetching Turso groups...");let{stdout:r}=await F`turso group list`,t=r.trim().split(`
130
+ `);if(t.length<=1)return e.stop("No Turso groups found"),[];let a=t.slice(1).map(n=>{let[s,o,i,c]=n.trim().split(/\s{2,}/);return{name:s,locations:o,version:i,status:c}});return e.stop(`Found ${a.length} Turso groups`),a}catch(r){return e.stop($.red("Error fetching Turso groups")),console.error("Error fetching Turso groups:",r),[]}}async function ia(){let e=await oa();if(e.length===0)return null;if(e.length===1)return V.info(`Using the only available group: ${$.blue(e[0].name)}`),e[0].name;let r=e.map(a=>({value:a.name,label:`${a.name} (${a.locations})`})),t=await Zr({message:"Select a Turso database group:",options:r});return xe(t)&&(ke($.red("Operation cancelled")),process.exit(0)),t}async function ca(e,r){let t=G();try{t.start(`Creating Turso database "${e}"${r?` in group "${r}"`:""}...`),r?await F`turso db create ${e} --group ${r}`:await F`turso db create ${e}`,t.stop(`Created database "${e}"`)}catch(a){throw t.stop($.red(`Failed to create database "${e}"`)),a instanceof Error&&a.message.includes("already exists")?new Error("DATABASE_EXISTS"):a}t.start("Retrieving database connection details...");try{let{stdout:a}=await F`turso db show ${e} --url`,{stdout:n}=await F`turso db tokens create ${e}`;return t.stop("Retrieved database connection details"),{dbUrl:a.trim(),authToken:n.trim()}}catch(a){throw t.stop($.red("Failed to retrieve database connection details")),a}}async function ce(e,r){let t=pe.join(e,"apps/server",".env"),a=r?`DATABASE_URL="${r.dbUrl}"
131
131
  DATABASE_AUTH_TOKEN="${r.authToken}"`:`DATABASE_URL=
132
- DATABASE_AUTH_TOKEN=`;await ct.ensureDir(pe.dirname(t)),await ct.writeFile(t,a)}function je(){V.info(`Manual Turso Setup Instructions:
132
+ DATABASE_AUTH_TOKEN=`;await pt.ensureDir(pe.dirname(t)),await pt.writeFile(t,a)}function je(){V.info(`Manual Turso Setup Instructions:
133
133
 
134
134
  1. Visit https://turso.tech and create an account
135
135
  2. Create a new database from the dashboard
@@ -137,68 +137,68 @@ DATABASE_AUTH_TOKEN=`;await ct.ensureDir(pe.dirname(t)),await ct.writeFile(t,a)}
137
137
  4. Add these credentials to the .env file in apps/server/.env
138
138
 
139
139
  DATABASE_URL=your_database_url
140
- DATABASE_AUTH_TOKEN=your_auth_token`)}async function pt(e){let{projectName:r,orm:t}=e,a=pe.resolve(process.cwd(),r),n=t==="drizzle",o=G();o.start("Setting up Turso database");try{let s=Zr.platform(),i=s==="darwin",c=s==="linux";if(s==="win32"){o.stop($.yellow("Turso setup not supported on Windows")),V.warn($.yellow("Automatic Turso setup is not supported on Windows.")),await ce(a),je();return}if(o.stop("Checking Turso CLI"),!await na()){let S=await ea({message:"Would you like to install Turso CLI?",initialValue:!0});if(xe(S)&&(ke($.red("Operation cancelled")),process.exit(0)),!S){await ce(a),je();return}await ia(i)}await oa()||await sa();let p=await pa(),b=!1,j="",A=pe.basename(a);for(;!b;){let S=await ra({message:"Enter a name for your database:",defaultValue:A,initialValue:A,placeholder:A});xe(S)&&(ke($.red("Operation cancelled")),process.exit(0)),j=S;try{let F=await la(j,p),te=G();te.start("Writing configuration to .env file"),await ce(a,F),te.stop("Turso database configured successfully!"),b=!0}catch(F){if(F instanceof Error&&F.message==="DATABASE_EXISTS")V.warn($.yellow(`Database "${$.red(j)}" already exists`)),A=`${j}-${Math.floor(Math.random()*1e3)}`;else throw F}}}catch(s){o.stop($.red("Failed to set up Turso database")),aa.error($.red(`Error during Turso setup: ${s instanceof Error?s.message:String(s)}`)),await ce(a),je(),V.success("Setup completed with manual configuration required.")}}import Z from"node:path";import{cancel as da,isCancel as ua,log as De,spinner as Ae,text as ma}from"@clack/prompts";import{consola as le}from"consola";import{execa as fa}from"execa";import Se from"fs-extra";import O from"picocolors";async function $e(e,r,t){let a=Ae();try{let n=R(e,r);a&&a.start(t);let o=await fa(n,{shell:!0});return a&&a.stop(t),o}catch(n){throw a&&a.stop(O.red(`Failed: ${t}`)),n}}async function ha(e){try{let t=await $e(e,"neonctl projects list");return!t.stdout.includes("not authenticated")&&!t.stdout.includes("error")}catch{return!1}}async function ga(e){try{return await $e(e,"neonctl auth","Authenticating with Neon..."),De.success("Authenticated with Neon successfully!"),!0}catch(r){throw le.error(O.red("Failed to authenticate with Neon")),r}}async function ba(e,r){try{let t=`neonctl projects create --name "${e}" --output json`,{stdout:a}=await $e(r,t,`Creating Neon project "${e}"...`),n=JSON.parse(a);if(n.project&&n.connection_uris&&n.connection_uris.length>0){let o=n.project.id,s=n.connection_uris[0].connection_uri,i=n.connection_uris[0].connection_parameters;return{connectionString:s,projectId:o,dbName:i.database,roleName:i.role}}return le.error(O.red("Failed to extract connection information from response")),null}catch(t){throw le.error(O.red("Failed to create Neon project")),t}}async function lt(e,r){let t=Z.join(e,"apps/server",".env"),a=r?`DATABASE_URL="${r.connectionString}"`:'DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"';return await Se.ensureDir(Z.dirname(t)),await Se.writeFile(t,a),!0}function wa(){De.info(`Manual Neon PostgreSQL Setup Instructions:
140
+ DATABASE_AUTH_TOKEN=your_auth_token`)}async function lt(e){let{projectName:r,orm:t}=e,a=pe.resolve(process.cwd(),r),n=t==="drizzle",s=G();s.start("Setting up Turso database");try{let o=Kr.platform(),i=o==="darwin",c=o==="linux";if(o==="win32"){s.stop($.yellow("Turso setup not supported on Windows")),V.warn($.yellow("Automatic Turso setup is not supported on Windows.")),await ce(a),je();return}if(s.stop("Checking Turso CLI"),!await ra()){let v=await Xr({message:"Would you like to install Turso CLI?",initialValue:!0});if(xe(v)&&(ke($.red("Operation cancelled")),process.exit(0)),!v){await ce(a),je();return}await sa(i)}await aa()||await na();let l=await ia(),d=!1,k="",D=pe.basename(a);for(;!d;){let v=await ea({message:"Enter a name for your database:",defaultValue:D,initialValue:D,placeholder:D});xe(v)&&(ke($.red("Operation cancelled")),process.exit(0)),k=v;try{let C=await ca(k,l),_=G();_.start("Writing configuration to .env file"),await ce(a,C),_.stop("Turso database configured successfully!"),d=!0}catch(C){if(C instanceof Error&&C.message==="DATABASE_EXISTS")V.warn($.yellow(`Database "${$.red(k)}" already exists`)),D=`${k}-${Math.floor(Math.random()*1e3)}`;else throw C}}}catch(o){s.stop($.red("Failed to set up Turso database")),ta.error($.red(`Error during Turso setup: ${o instanceof Error?o.message:String(o)}`)),await ce(a),je(),V.success("Setup completed with manual configuration required.")}}import ee from"node:path";import{cancel as pa,isCancel as la,log as Ae,spinner as Se,text as da}from"@clack/prompts";import{consola as le}from"consola";import{execa as ua}from"execa";import De from"fs-extra";import L from"picocolors";async function $e(e,r,t){let a=Se();try{let n=T(e,r);a&&a.start(t);let s=await ua(n,{shell:!0});return a&&a.stop(t),s}catch(n){throw a&&a.stop(L.red(`Failed: ${t}`)),n}}async function ma(e){try{let t=await $e(e,"neonctl projects list");return!t.stdout.includes("not authenticated")&&!t.stdout.includes("error")}catch{return!1}}async function fa(e){try{return await $e(e,"neonctl auth","Authenticating with Neon..."),Ae.success("Authenticated with Neon successfully!"),!0}catch(r){throw le.error(L.red("Failed to authenticate with Neon")),r}}async function ha(e,r){try{let t=`neonctl projects create --name "${e}" --output json`,{stdout:a}=await $e(r,t,`Creating Neon project "${e}"...`),n=JSON.parse(a);if(n.project&&n.connection_uris&&n.connection_uris.length>0){let s=n.project.id,o=n.connection_uris[0].connection_uri,i=n.connection_uris[0].connection_parameters;return{connectionString:o,projectId:s,dbName:i.database,roleName:i.role}}return le.error(L.red("Failed to extract connection information from response")),null}catch(t){throw le.error(L.red("Failed to create Neon project")),t}}async function dt(e,r){let t=ee.join(e,"apps/server",".env"),a=r?`DATABASE_URL="${r.connectionString}"`:'DATABASE_URL="postgresql://postgres:postgres@localhost:5432/mydb?schema=public"';return await De.ensureDir(ee.dirname(t)),await De.writeFile(t,a),!0}function ga(){Ae.info(`Manual Neon PostgreSQL Setup Instructions:
141
141
 
142
142
  1. Visit https://neon.tech and create an account
143
143
  2. Create a new project from the dashboard
144
144
  3. Get your connection string
145
145
  4. Add the database URL to the .env file in apps/server/.env
146
146
 
147
- DATABASE_URL="your_connection_string"`)}async function dt(e){let{projectName:r,packageManager:t}=e,a=Z.resolve(process.cwd(),r),n=Ae();n.start("Setting up Neon PostgreSQL");try{let o=await ha(t);n.stop("Setting up Neon PostgreSQL"),o||(De.info("Please authenticate with Neon to continue:"),await ga(t));let s=Z.basename(a),i=await ma({message:"Enter a name for your Neon project:",defaultValue:s,initialValue:s});ua(i)&&(da(O.red("Operation cancelled")),process.exit(0));let c=await ba(i,t);if(!c)throw new Error("Failed to create project - couldn't get connection information");let l=Ae();l.start("Configuring database connection"),await Se.ensureDir(Z.join(a,"apps/server")),await lt(a,c),l.stop("Neon database configured successfully!")}catch(o){n.stop(O.red("Neon PostgreSQL setup failed")),o instanceof Error&&le.error(O.red(o.message)),await lt(a),wa()}}async function mt(e){let{projectName:r,database:t,orm:a,dbSetup:n}=e,o=Ee.resolve(process.cwd(),r),s=ya(),i=Ee.join(o,"apps/server");if(t==="none"){await va.remove(Ee.join(i,"src/db"));return}try{a==="prisma"?await w({dependencies:["@prisma/client"],devDependencies:["prisma"],projectDir:i}):a==="drizzle"&&(t==="sqlite"?await w({dependencies:["drizzle-orm","@libsql/client"],devDependencies:["drizzle-kit"],projectDir:i}):t==="postgres"?await w({dependencies:["drizzle-orm","pg"],devDependencies:["drizzle-kit","@types/pg"],projectDir:i}):t==="mysql"&&await w({dependencies:["drizzle-orm","mysql2"],devDependencies:["drizzle-kit"],projectDir:i})),t==="sqlite"&&n==="turso"?await pt(e):t==="postgres"?a==="prisma"&&n==="prisma-postgres"?await it(e):n==="neon"&&await dt(e):t==="mongodb"&&n==="mongodb-atlas"&&await ot(e)}catch(c){throw s.stop(ut.red("Failed to set up database")),c instanceof Error&&Pa.error(ut.red(c.message)),c}}import L from"node:path";import de from"fs-extra";async function Ce(e,r){await de.ensureDir(L.dirname(e));let t="";await de.pathExists(e)&&(t=await de.readFile(e,"utf8"));let a=!1;for(let{key:n,value:o,condition:s}of r)if(s){let i=new RegExp(`^${n}=.*$`,"m");i.test(t)?o&&(t=t.replace(i,`${n}=${o}`),a=!0):(t+=`
148
- ${n}=${o}`,a=!0)}a&&await de.writeFile(e,t.trim())}async function ft(e){let{projectName:r}=e,t=L.resolve(process.cwd(),r),a=e,n=L.join(t,"apps/server"),o=L.join(n,".env"),s=a.frontend.includes("react-router"),i=a.frontend.includes("tanstack-router"),c=a.frontend.includes("tanstack-start"),l=a.frontend.includes("next"),d=s||i||c||l,P="http://localhost:3000";s?P="http://localhost:5173":(i||c||l)&&(P="http://localhost:3001");let p="",b=a.dbSetup==="turso"||a.dbSetup==="prisma-postgres"||a.dbSetup==="mongodb-atlas"||a.dbSetup==="neon";b||(a.database==="postgres"?p="postgresql://postgres:postgres@localhost:5432/mydb?schema=public":a.database==="mysql"?p="mysql://root:password@localhost:3306/mydb":a.database==="mongodb"?p="mongodb://localhost:27017/mydatabase":a.database==="sqlite"&&(p="file:./local.db"));let j=[{key:"CORS_ORIGIN",value:P,condition:!0},{key:"BETTER_AUTH_SECRET",value:Xe(),condition:!!a.auth},{key:"BETTER_AUTH_URL",value:"http://localhost:3000",condition:!!a.auth},{key:"DATABASE_URL",value:p,condition:a.database!=="none"&&p!==""&&!b},{key:"GOOGLE_GENERATIVE_AI_API_KEY",value:"",condition:a.examples?.includes("ai")||!1}];if(await Ce(o,j),d){let A=L.join(t,"apps/web"),S="VITE_SERVER_URL";l&&(S="NEXT_PUBLIC_SERVER_URL");let F=[{key:S,value:"http://localhost:3000",condition:!0}];await Ce(L.join(A,".env"),F)}if(a.frontend.includes("native")){let A=L.join(t,"apps/native"),S=[{key:"EXPO_PUBLIC_SERVER_URL",value:"http://localhost:3000",condition:!0}];await Ce(L.join(A,".env"),S)}}import Te from"node:path";import ja from"fs-extra";async function ht(e){let{projectName:r,examples:t}=e,a=Te.resolve(process.cwd(),r);if(t.includes("ai")){let n=Te.join(a,"apps/web"),o=Te.join(a,"apps/server");await ja.pathExists(n)&&await w({dependencies:["ai"],projectDir:n}),await w({dependencies:["ai","@ai-sdk/google"],projectDir:o})}}import{log as ka,spinner as gt}from"@clack/prompts";import xa from"consola";import{$ as bt}from"execa";import ue from"picocolors";async function wt({projectDir:e,packageManager:r,addons:t=[]}){let a=gt();try{a.start(`Running ${r} install...`),await bt({cwd:e,stderr:"inherit"})`${r} install`,a.stop("Dependencies installed successfully"),(t.includes("biome")||t.includes("husky"))&&await Aa(e,r)}catch(n){throw a.stop(ue.red("Failed to install dependencies")),n instanceof Error&&xa.error(ue.red(`Installation error: ${n.message}`)),n}}async function Aa(e,r){let t=gt();try{t.start("Running Biome format check..."),await bt({cwd:e,stderr:"inherit"})`${r} biome check --write .`,t.stop("Biome check completed successfully")}catch{t.stop(ue.yellow("Biome check encountered issues")),ka.warn(ue.yellow("Some files may need manual formatting"))}}import{consola as Sa}from"consola";import y from"picocolors";function yt(e){let{database:r,projectName:t,packageManager:a,depsInstalled:n,orm:o,addons:s,runtime:i,frontend:c}=e,l=a==="npm"?"npm run":a,d=`cd ${t}`,P=s?.includes("husky")||s?.includes("biome"),p=r!=="none"?Ea(r,o,l,i):"",b=s?.includes("tauri")?Ca(l):"",j=P?$a(l):"",A=c?.includes("native")?Da():"",S=s?.includes("pwa")&&c?.includes("react-router")?Ta():"",F=s?.includes("starlight")?Fa(l):"",te=c?.some(wr=>["tanstack-router","react-router","next","tanstack-start"].includes(wr)),dr=c?.includes("native"),Be=a==="bun"&&dr&&te?Na():"",Ie=r!=="none"&&o==="none"?Ra():"",ur=c?.includes("tanstack-router"),mr=c?.includes("tanstack-start"),Le=c?.includes("react-router"),Me=ur||Le||mr,fr=c?.includes("native"),hr=Me||fr,gr=Le?"5173":"3001",br=R(a,"taze -r");Sa.box(`${y.bold("Next steps")}
149
- ${y.cyan("1.")} ${d}
150
- ${n?"":`${y.cyan("2.")} ${a} install
151
- `}${y.cyan(n?"2.":"3.")} ${l} dev
152
-
153
- ${y.bold("Your project will be available at:")}
154
- ${hr?`${Me?`${y.cyan("\u2022")} Frontend: http://localhost:${gr}
155
- `:""}`:`${y.yellow("NOTE:")} You are creating a backend-only app (no frontend selected)
156
- `}${y.cyan("\u2022")} Backend: http://localhost:3000
157
- ${s?.includes("starlight")?`${y.cyan("\u2022")} Docs: http://localhost:4321
158
- `:""}${A?`
159
- ${A.trim()}`:""}${p?`
160
- ${p.trim()}`:""}${b?`
161
- ${b.trim()}`:""}${j?`
162
- ${j.trim()}`:""}${S?`
163
- ${S.trim()}`:""}${F?`
164
- ${F.trim()}`:""}${Ie?`
147
+ DATABASE_URL="your_connection_string"`)}async function ut(e){let{projectName:r,packageManager:t}=e,a=ee.resolve(process.cwd(),r),n=Se();n.start("Setting up Neon PostgreSQL");try{let s=await ma(t);n.stop("Setting up Neon PostgreSQL"),s||(Ae.info("Please authenticate with Neon to continue:"),await fa(t));let o=ee.basename(a),i=await da({message:"Enter a name for your Neon project:",defaultValue:o,initialValue:o});la(i)&&(pa(L.red("Operation cancelled")),process.exit(0));let c=await ha(i,t);if(!c)throw new Error("Failed to create project - couldn't get connection information");let p=Se();p.start("Configuring database connection"),await De.ensureDir(ee.join(a,"apps/server")),await dt(a,c),p.stop("Neon database configured successfully!")}catch(s){n.stop(L.red("Neon PostgreSQL setup failed")),s instanceof Error&&le.error(L.red(s.message)),await dt(a),ga()}}async function ft(e){let{projectName:r,database:t,orm:a,dbSetup:n}=e,s=Ee.resolve(process.cwd(),r),o=ba(),i=Ee.join(s,"apps/server");if(t==="none"){await ya.remove(Ee.join(i,"src/db"));return}try{a==="prisma"?await w({dependencies:["@prisma/client"],devDependencies:["prisma"],projectDir:i}):a==="drizzle"&&(t==="sqlite"?await w({dependencies:["drizzle-orm","@libsql/client"],devDependencies:["drizzle-kit"],projectDir:i}):t==="postgres"?await w({dependencies:["drizzle-orm","pg"],devDependencies:["drizzle-kit","@types/pg"],projectDir:i}):t==="mysql"&&await w({dependencies:["drizzle-orm","mysql2"],devDependencies:["drizzle-kit"],projectDir:i})),t==="sqlite"&&n==="turso"?await lt(e):t==="postgres"?a==="prisma"&&n==="prisma-postgres"?await ct(e):n==="neon"&&await ut(e):t==="mongodb"&&n==="mongodb-atlas"&&await ot(e)}catch(c){throw o.stop(mt.red("Failed to set up database")),c instanceof Error&&wa.error(mt.red(c.message)),c}}import B from"node:path";import de from"fs-extra";async function Ce(e,r){await de.ensureDir(B.dirname(e));let t="";await de.pathExists(e)&&(t=await de.readFile(e,"utf8"));let a=!1;for(let{key:n,value:s,condition:o}of r)if(o){let i=new RegExp(`^${n}=.*$`,"m");i.test(t)?s&&(t=t.replace(i,`${n}=${s}`),a=!0):(t+=`
148
+ ${n}=${s}`,a=!0)}a&&await de.writeFile(e,t.trim())}async function ht(e){let{projectName:r}=e,t=B.resolve(process.cwd(),r),a=e,n=B.join(t,"apps/server"),s=B.join(n,".env"),o=a.frontend.includes("react-router"),i=a.frontend.includes("tanstack-router"),c=a.frontend.includes("tanstack-start"),p=a.frontend.includes("next"),f=a.frontend.includes("nuxt"),b=o||i||c||p||f,l="http://localhost:3001";o?l="http://localhost:5173":(i||c||p||f)&&(l="http://localhost:3001");let d="",k=a.dbSetup==="turso"||a.dbSetup==="prisma-postgres"||a.dbSetup==="mongodb-atlas"||a.dbSetup==="neon";k||(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 D=[{key:"CORS_ORIGIN",value:l,condition:!0},{key:"BETTER_AUTH_SECRET",value:Ze(),condition:!!a.auth},{key:"BETTER_AUTH_URL",value:"http://localhost:3000",condition:!!a.auth},{key:"DATABASE_URL",value:d,condition:a.database!=="none"&&d!==""&&!k},{key:"GOOGLE_GENERATIVE_AI_API_KEY",value:"",condition:a.examples?.includes("ai")||!1}];if(await Ce(s,D),b){let v=B.join(t,"apps/web"),C="VITE_SERVER_URL";p?C="NEXT_PUBLIC_SERVER_URL":f&&(C="NUXT_PUBLIC_SERVER_URL");let _=[{key:C,value:"http://localhost:3000",condition:!0}];await Ce(B.join(v,".env"),_)}if(a.frontend.includes("native")){let v=B.join(t,"apps/native"),C=[{key:"EXPO_PUBLIC_SERVER_URL",value:"http://localhost:3000",condition:!0}];await Ce(B.join(v,".env"),C)}}import Te from"node:path";import Pa from"fs-extra";async function gt(e){let{projectName:r,examples:t,frontend:a}=e,n=Te.resolve(process.cwd(),r);if(t.includes("ai")){let s=Te.join(n,"apps/web"),o=Te.join(n,"apps/server"),i=await Pa.pathExists(s),c=a.includes("nuxt");if(i){let p=["ai"];c&&p.push("@ai-sdk/vue"),await w({dependencies:p,projectDir:s})}await w({dependencies:["ai","@ai-sdk/google"],projectDir:o})}}import{log as va,spinner as bt}from"@clack/prompts";import ja from"consola";import{$ as wt}from"execa";import ue from"picocolors";async function yt({projectDir:e,packageManager:r,addons:t=[]}){let a=bt();try{a.start(`Running ${r} install...`),await wt({cwd:e,stderr:"inherit"})`${r} install`,a.stop("Dependencies installed successfully"),(t.includes("biome")||t.includes("husky"))&&await ka(e,r)}catch(n){throw a.stop(ue.red("Failed to install dependencies")),n instanceof Error&&ja.error(ue.red(`Installation error: ${n.message}`)),n}}async function ka(e,r){let t=bt();try{t.start("Running Biome format check..."),await wt({cwd:e,stderr:"inherit"})`${r} biome check --write .`,t.stop("Biome check completed successfully")}catch{t.stop(ue.yellow("Biome check encountered issues")),va.warn(ue.yellow("Some files may need manual formatting"))}}import{consola as xa}from"consola";import P from"picocolors";function Pt(e){let{database:r,projectName:t,packageManager:a,depsInstalled:n,orm:s,addons:o,runtime:i,frontend:c}=e,p=a==="npm"?"npm run":a,f=`cd ${t}`,b=o?.includes("husky")||o?.includes("biome"),l=r!=="none"?Aa(r,s,p,i):"",d=o?.includes("tauri")?$a(p):"",k=b?Da(p):"",D=c?.includes("native")?Sa():"",v=o?.includes("pwa")&&(c?.includes("react-router")||c?.includes("tanstack-router"))?Ea():"",C=o?.includes("starlight")?Ca(p):"",_=c?.some(br=>["tanstack-router","react-router","next","tanstack-start","nuxt"].includes(br)),pr=c?.includes("native"),Be=a==="bun"&&pr&&_?Ra():"",Ie=r!=="none"&&s==="none"?Ta():"",lr=c?.includes("tanstack-router"),dr=c?.includes("tanstack-start"),Le=c?.includes("react-router"),ur=c?.includes("nuxt"),Me=lr||Le||dr||ur,mr=c?.includes("native"),fr=Me||mr,hr=Le?"5173":"3001",gr=T(a,"taze -r");xa.box(`${P.bold("Next steps")}
149
+ ${P.cyan("1.")} ${f}
150
+ ${n?"":`${P.cyan("2.")} ${a} install
151
+ `}${P.cyan(n?"2.":"3.")} ${p} dev
152
+
153
+ ${P.bold("Your project will be available at:")}
154
+ ${fr?`${Me?`${P.cyan("\u2022")} Frontend: http://localhost:${hr}
155
+ `:""}`:`${P.yellow("NOTE:")} You are creating a backend-only app (no frontend selected)
156
+ `}${P.cyan("\u2022")} Backend: http://localhost:3000
157
+ ${o?.includes("starlight")?`${P.cyan("\u2022")} Docs: http://localhost:4321
158
+ `:""}${D?`
159
+ ${D.trim()}`:""}${l?`
160
+ ${l.trim()}`:""}${d?`
161
+ ${d.trim()}`:""}${k?`
162
+ ${k.trim()}`:""}${v?`
163
+ ${v.trim()}`:""}${C?`
164
+ ${C.trim()}`:""}${Ie?`
165
165
  ${Ie.trim()}`:""}${Be?`
166
166
  ${Be.trim()}`:""}
167
167
 
168
- ${y.bold(`Update all dependencies:
169
- `)}${y.cyan(br)}
168
+ ${P.bold(`Update all dependencies:
169
+ `)}${P.cyan(gr)}
170
170
 
171
- ${y.bold("Like Better-T Stack?")} Please consider giving us a star on GitHub:
172
- ${y.cyan("https://github.com/AmanVarshney01/create-better-t-stack")}`)}function Da(){return`${y.yellow("NOTE:")} For Expo connectivity issues, update apps/native/.env
171
+ ${P.bold("Like Better-T Stack?")} Please consider giving us a star on GitHub:
172
+ ${P.cyan("https://github.com/AmanVarshney01/create-better-t-stack")}`)}function Sa(){return`${P.yellow("NOTE:")} For Expo connectivity issues, update apps/native/.env
173
173
  with your local IP:
174
174
  EXPO_PUBLIC_SERVER_URL=http://192.168.0.103:3000
175
- `}function $a(e){return`${y.bold("Linting and formatting:")}
176
- ${y.cyan("\u2022")} Format and lint fix: ${`${e} check`}
175
+ `}function Da(e){return`${P.bold("Linting and formatting:")}
176
+ ${P.cyan("\u2022")} Format and lint fix: ${`${e} check`}
177
177
 
178
- `}function Ea(e,r,t,a){let n=[];return r==="prisma"?(e==="sqlite"&&n.push(`${y.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"&&n.push(`${y.yellow("NOTE:")} Prisma with Bun may require additional configuration. If you encounter errors,
179
- follow the guidance provided in the error messages`),n.push(`${y.cyan("\u2022")} Apply schema: ${`${t} db:push`}`),n.push(`${y.cyan("\u2022")} Database UI: ${`${t} db:studio`}`)):r==="drizzle"&&(n.push(`${y.cyan("\u2022")} Apply schema: ${`${t} db:push`}`),n.push(`${y.cyan("\u2022")} Database UI: ${`${t} db:studio`}`)),n.length?`${y.bold("Database commands:")}
178
+ `}function Aa(e,r,t,a){let n=[];return r==="prisma"?(e==="sqlite"&&n.push(`${P.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"&&n.push(`${P.yellow("NOTE:")} Prisma with Bun may require additional configuration. If you encounter errors,
179
+ follow the guidance provided in the error messages`),n.push(`${P.cyan("\u2022")} Apply schema: ${`${t} db:push`}`),n.push(`${P.cyan("\u2022")} Database UI: ${`${t} db:studio`}`)):r==="drizzle"&&(n.push(`${P.cyan("\u2022")} Apply schema: ${`${t} db:push`}`),n.push(`${P.cyan("\u2022")} Database UI: ${`${t} db:studio`}`)),n.length?`${P.bold("Database commands:")}
180
180
  ${n.join(`
181
181
  `)}
182
182
 
183
- `:""}function Ca(e){return`
184
- ${y.bold("Desktop app with Tauri:")}
185
- ${y.cyan("\u2022")} Start desktop app: ${`cd apps/web && ${e} desktop:dev`}
186
- ${y.cyan("\u2022")} Build desktop app: ${`cd apps/web && ${e} desktop:build`}
187
- ${y.yellow("NOTE:")} Tauri requires Rust and platform-specific dependencies.
183
+ `:""}function $a(e){return`
184
+ ${P.bold("Desktop app with Tauri:")}
185
+ ${P.cyan("\u2022")} Start desktop app: ${`cd apps/web && ${e} desktop:dev`}
186
+ ${P.cyan("\u2022")} Build desktop app: ${`cd apps/web && ${e} desktop:build`}
187
+ ${P.yellow("NOTE:")} Tauri requires Rust and platform-specific dependencies.
188
188
  See: https://v2.tauri.app/start/prerequisites/
189
189
 
190
- `}function Ta(){return`${y.bold("PWA with React Router v7:")}
191
- ${y.yellow("NOTE:")} There is a known compatibility issue between VitePWA and React Router v7.
190
+ `}function Ea(){return`${P.bold("PWA with React Router v7:")}
191
+ ${P.yellow("NOTE:")} There is a known compatibility issue between VitePWA and React Router v7.
192
192
  See: https://github.com/vite-pwa/vite-plugin-pwa/issues/809
193
- `}function Fa(e){return`${y.bold("Documentation with Starlight:")}
194
- ${y.cyan("\u2022")} Start docs site: ${`cd apps/docs && ${e} dev`}
195
- ${y.cyan("\u2022")} Build docs site: ${`cd apps/docs && ${e} build`}
193
+ `}function Ca(e){return`${P.bold("Documentation with Starlight:")}
194
+ ${P.cyan("\u2022")} Start docs site: ${`cd apps/docs && ${e} dev`}
195
+ ${P.cyan("\u2022")} Build docs site: ${`cd apps/docs && ${e} build`}
196
+ `}function Ta(){return`
197
+ ${P.yellow("WARNING:")} Database selected without an ORM. Features requiring database access (e.g., examples, auth) need manual setup.
196
198
  `}function Ra(){return`
197
- ${y.yellow("WARNING:")} Database selected without an ORM. Features requiring database access (e.g., examples, auth) need manual setup.
198
- `}function Na(){return`
199
- ${y.yellow("WARNING:")} 'bun' might cause issues with web + native apps in a monorepo. Use 'pnpm' if problems arise.
200
- `}import vt from"node:path";import{log as Ba}from"@clack/prompts";import{$ as Pt,execa as Ia}from"execa";import J from"fs-extra";import La from"picocolors";async function jt(e,r){await Ma(e,r),await Oa(e,r)}async function Ma(e,r){let t=vt.join(e,"package.json");if(await J.pathExists(t)){let a=await J.readJson(t);a.name=r.projectName;let n={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"},o={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"},s={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"};r.addons.includes("turborepo")?a.scripts=n:r.packageManager==="pnpm"?a.scripts=o:r.packageManager==="npm"?a.scripts=s:r.packageManager==="bun"?a.scripts=i:a.scripts={};let{stdout:c}=await Ia(r.packageManager,["-v"],{cwd:e});a.packageManager=`${r.packageManager}@${c.trim()}`,await J.writeJson(t,a,{spaces:2})}}async function Oa(e,r){let t=vt.join(e,"apps/server/package.json");if(await J.pathExists(t)){let a=await J.readJson(t);r.database!=="none"&&(r.database==="sqlite"&&r.orm==="drizzle"&&(a.scripts["db:local"]="turso dev --db-file local.db"),r.orm==="prisma"?(a.scripts["db:push"]="prisma db push --schema ./prisma/schema",a.scripts["db:studio"]="prisma studio"):r.orm==="drizzle"&&(a.scripts["db:push"]="drizzle-kit push",a.scripts["db:studio"]="drizzle-kit studio")),await J.writeJson(t,a,{spaces:2})}}async function kt(e,r){if(!r)return;if((await Pt({cwd:e,reject:!1,stderr:"pipe"})`git --version`).exitCode!==0){Ba.warn(La.yellow("Git is not installed"));return}let a=await Pt({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 xt(e){let{projectName:r,runtime:t,backend:a}=e,n=me.resolve(process.cwd(),r);if(a==="next")return;let o=me.join(n,"apps/server");t==="bun"?await Ua(o,a):t==="node"&&await _a(o,a)}async function Ua(e,r){let t=me.join(e,"package.json"),a=await fe.readJson(t);a.scripts={...a.scripts,dev:"bun run --hot src/index.ts",start:"bun run dist/src/index.js"},await fe.writeJson(t,a,{spaces:2}),await w({devDependencies:["@types/bun"],projectDir:e})}async function _a(e,r){let t=me.join(e,"package.json"),a=await fe.readJson(t);a.scripts={...a.scripts,dev:"tsx watch src/index.ts",start:"node dist/src/index.js"},await fe.writeJson(t,a,{spaces:2}),await w({devDependencies:["tsx","@types/node"],projectDir:e}),r==="hono"?await w({dependencies:["@hono/node-server"],projectDir:e}):r==="elysia"&&await w({dependencies:["@elysiajs/node"],projectDir:e})}import u from"node:path";import E from"consola";import f from"fs-extra";import{globby as At}from"globby";import C from"picocolors";import Wa from"node:path";import za from"consola";import Fe from"fs-extra";import he from"handlebars";async function Re(e,r,t){try{let a=await Fe.readFile(e,"utf-8"),o=he.compile(a)(t);await Fe.ensureDir(Wa.dirname(r)),await Fe.writeFile(r,o)}catch(a){throw za.error(`Error processing template ${e}:`,a),new Error(`Failed to process template ${e}`)}}he.registerHelper("or",(e,r)=>e||r);he.registerHelper("eq",(e,r)=>e===r);he.registerHelper("includes",(e,r)=>Array.isArray(e)&&e.includes(r));async function x(e,r,t,a,n=!0){let o=await At(e,{cwd:r,dot:!0,onlyFiles:!0,absolute:!1});for(let s of o){let i=u.join(r,s),c=s;s.endsWith(".hbs")&&(c=s.slice(0,-4));let l=u.join(t,c);if(await f.ensureDir(u.dirname(l)),i.endsWith(".hbs"))await Re(i,l,a);else{if(!n&&await f.pathExists(l))continue;await f.copy(i,l,{overwrite:!0})}}}async function St(e,r){let t=u.join(v,"templates/base");await x(["package.json","_gitignore"],t,e,r)}async function Dt(e,r){let t=r.frontend.filter(n=>n==="tanstack-router"||n==="react-router"||n==="tanstack-start"||n==="next"),a=r.frontend.includes("native");if(t.length>0){let n=u.join(e,"apps/web");await f.ensureDir(n);let o=u.join(v,"templates/frontend/web-base");await f.pathExists(o)&&await x("**/*",o,n,r);for(let l of t){let d=u.join(v,`templates/frontend/${l}`);await f.pathExists(d)&&await x("**/*",d,n,r)}let s=t[0],i=u.join(v,`templates/api/${r.api}/web/base`);await f.pathExists(i)&&await x("**/*",i,n,r);let c=u.join(v,`templates/api/${r.api}/web/${s}`);await f.pathExists(c)&&await x("**/*",c,n,r)}if(a){let n=u.join(e,"apps/native");await f.ensureDir(n);let o=u.join(v,"templates/frontend/native");await f.pathExists(o)&&await x("**/*",o,n,r);let s=u.join(v,`templates/api/${r.api}/native`);await f.pathExists(s)&&await x("**/*",s,n,r)}}async function $t(e,r){if(r.backend==="none")return;let t=u.join(e,"apps/server");await f.ensureDir(t);let a=u.join(v,"templates/backend/server-base");await f.pathExists(a)?await x("**/*",a,t,r):E.warn(C.yellow(`Warning: server-base template not found at ${a}`));let n=u.join(v,`templates/backend/${r.backend}`);await f.pathExists(n)?await x("**/*",n,t,r):E.warn(C.yellow(`Warning: Backend template directory not found, skipping: ${n}`));let o=u.join(v,`templates/api/${r.api}/server/base`);await f.pathExists(o)&&await x("**/*",o,t,r);let s=u.join(v,`templates/api/${r.api}/server/${r.backend}`);await f.pathExists(s)&&await x("**/*",s,t,r)}async function Et(e,r){if(r.orm==="none"||r.database==="none")return;let t=u.join(e,"apps/server");await f.ensureDir(t);let a=u.join(v,`templates/db/${r.orm}/${r.database}`);await f.pathExists(a)?await x("**/*",a,t,r):E.warn(C.yellow(`Warning: Database/ORM template directory not found, skipping: ${a}`))}async function Ct(e,r){if(!r.auth)return;let t=u.join(e,"apps/server"),a=u.join(e,"apps/web"),n=u.join(e,"apps/native"),o=await f.pathExists(t),s=await f.pathExists(a),i=await f.pathExists(n),c=r.frontend.filter(d=>d==="tanstack-router"||d==="react-router"||d==="tanstack-start"||d==="next"),l=r.frontend.includes("native");if(o){let d=u.join(v,"templates/auth/server/base");if(await f.pathExists(d)?await x("**/*",d,t,r):E.warn(C.yellow(`Warning: Base auth server template not found at ${d}`)),r.backend==="next"){let P=u.join(v,"templates/auth/server/next");await f.pathExists(P)?await x("**/*",P,t,r):E.warn(C.yellow(`Warning: Next auth server template not found at ${P}`))}if(r.orm!=="none"&&r.database!=="none"){let P=r.orm,p=r.database,b="";P==="drizzle"?b=u.join(v,`templates/auth/server/db/drizzle/${p}`):P==="prisma"&&(b=u.join(v,`templates/auth/server/db/prisma/${p}`)),b&&await f.pathExists(b)?await x("**/*",b,t,r):E.warn(C.yellow(`Warning: Auth template for ${P}/${p} not found at ${b}`))}}else E.warn(C.yellow("Warning: apps/server directory does not exist, skipping server-side auth template setup."));if(c.length>0&&s){let d=u.join(v,"templates/auth/web/base");await f.pathExists(d)?await x("**/*",d,a,r):E.warn(C.yellow(`Warning: Base auth web template not found at ${d}`));for(let P of c){let p=u.join(v,`templates/auth/web/${P}`);await f.pathExists(p)?await x("**/*",p,a,r):E.warn(C.yellow(`Warning: Auth web template for ${P} not found at ${p}`))}}if(l&&i){let d=u.join(v,"templates/auth/native");await f.pathExists(d)?await x("**/*",d,n,r):E.warn(C.yellow(`Warning: Auth native template not found at ${d}`))}}async function Tt(e,r){if(r.addons.includes("turborepo")){let t=u.join(v,"templates/addons/turborepo");await f.pathExists(t)?await x("**/*",t,e,r):E.warn(C.yellow("Warning: Turborepo addon template not found."))}if(r.addons.includes("husky")){let t=u.join(v,"templates/addons/husky");await f.pathExists(t)?await x("**/*",t,e,r):E.warn(C.yellow("Warning: Husky addon template not found."))}if(r.addons.includes("biome")){let t=u.join(v,"templates/addons/biome");await f.pathExists(t)?await x("**/*",t,e,r):E.warn(C.yellow("Warning: Biome addon template not found."))}if(r.addons.includes("pwa")){let t=u.join(v,"templates/addons/pwa/apps/web"),a=u.join(e,"apps/web"),n=await f.pathExists(a);await f.pathExists(t)?n?await x("**/*",t,a,r):E.warn(C.yellow("Warning: apps/web directory not found, cannot setup PWA addon template.")):E.warn(C.yellow("Warning: PWA addon template not found."))}}async function Ft(e,r){if(!r.examples||r.examples.length===0)return;let t=u.join(e,"apps/server"),a=u.join(e,"apps/web"),n=await f.pathExists(t),o=await f.pathExists(a);for(let s of r.examples){let i=u.join(v,`templates/examples/${s}`);if(n){let c=u.join(i,"server");if(await f.pathExists(c)&&r.orm!=="none"){let l=u.join(c,r.orm,"base");if(await f.pathExists(l)&&await x("**/*",l,t,r,!1),r.database!=="none"){let d=u.join(c,r.orm,r.database);await f.pathExists(d)&&await x("**/*",d,t,r,!1)}}}if(o){let c=u.join(i,"web");if(await f.pathExists(c)){let l=r.frontend.filter(d=>["next","react-router","tanstack-router","tanstack-start"].includes(d));for(let d of l){let P=u.join(c,d);await f.pathExists(P)&&await x("**/*",P,a,r,!1)}}}}}async function Rt(e,r){let t=await At(["**/.gitignore.hbs","**/_gitignore"],{cwd:e,dot:!0,onlyFiles:!0,absolute:!0,ignore:["**/node_modules/**","**/.git/**"]});for(let a of t){let n=u.dirname(a),o=u.basename(a),s=u.join(n,".gitignore");try{o===".gitignore.hbs"?(await Re(a,s,r),await f.remove(a)):o==="_gitignore"&&await f.move(a,s,{overwrite:!0})}catch(i){E.error(`Error processing gitignore file ${a}:`,i)}}}async function Nt(e,r){if(r.packageManager==="pnpm"){let t=u.join(v,"templates/extras/pnpm-workspace.yaml"),a=u.join(e,"pnpm-workspace.yaml");await f.pathExists(t)&&await f.copy(t,a)}if(r.frontend.includes("native")){let t=u.join(v,"templates/extras/_npmrc"),a=u.join(e,".npmrc");await f.pathExists(t)&&await f.copy(t,a)}}async function It(e){let r=Ja(),t=qa.resolve(process.cwd(),e.projectName);try{return await Qa.ensureDir(t),await St(t,e),await Dt(t,e),await $t(t,e),await et(e),await Et(t,e),await mt(e),await Ct(t,e),await Ke(e),await Tt(t,e),e.addons.length>0&&e.addons[0]!=="none"&&await Ge(e),await Ft(t,e),await Nt(t,e),e.examples.length>0&&e.examples[0]!=="none"&&await ht(e),await Je(e),await xt(e),await ft(e),await jt(t,e),await tt(t,e),await kt(t,e.git),await Rt(t,e),Ga.success("Project template successfully scaffolded!"),e.install&&await wt({projectDir:t,packageManager:e.packageManager,addons:e.addons}),yt({...e,depsInstalled:e.install}),t}catch(a){throw r.stop(Bt.red("Failed")),a instanceof Error&&(Va(Bt.red(`Error during project creation: ${a.message}`)),console.error(a.stack),process.exit(1)),a}}import{cancel as Kn,group as Xn}from"@clack/prompts";import Zn from"picocolors";import{cancel as Ha,isCancel as Ya,multiselect as Ka}from"@clack/prompts";import Xa from"picocolors";async function Lt(e,r){if(e!==void 0)return e;let t=r?.includes("react-router")||r?.includes("tanstack-router"),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)"}],n=[{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"}],o=t?[...a,...n]:a,s=g.addons.filter(c=>t||c!=="pwa"&&c!=="tauri"),i=await Ka({message:"Select addons",options:o,initialValues:s,required:!1});return Ya(i)&&(Ha(Xa.red("Operation cancelled")),process.exit(0)),i.includes("husky")&&!i.includes("biome")&&i.push("biome"),i}import{cancel as Za,isCancel as en,select as tn}from"@clack/prompts";import rn from"picocolors";async function Mt(e,r){if(e)return e;let t=r?.includes("native"),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"}];t&&(a=[{value:"trpc",label:"tRPC",hint:"End-to-end typesafe APIs made easy (Required for Native frontend)"}]);let n=await tn({message:"Select API type",options:a,initialValue:t?"trpc":g.api});return en(n)&&(Za(rn.red("Operation cancelled")),process.exit(0)),t&&n!=="trpc"?"trpc":n}import{cancel as an,confirm as nn,isCancel as on}from"@clack/prompts";import sn from"picocolors";async function Ot(e,r){if(!r)return!1;if(e!==void 0)return e;let t=await nn({message:"Add authentication with Better-Auth?",initialValue:g.auth});return on(t)&&(an(sn.red("Operation cancelled")),process.exit(0)),t}import{cancel as cn,isCancel as pn,select as ln}from"@clack/prompts";import dn from"picocolors";async function Ut(e){if(e!==void 0)return e;let r=await ln({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:g.backend});return pn(r)&&(cn(dn.red("Operation cancelled")),process.exit(0)),r}import{cancel as un,isCancel as mn,select as fn}from"@clack/prompts";import hn from"picocolors";async function _t(e){if(e!==void 0)return e;let r=await fn({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:g.database});return mn(r)&&(un(hn.red("Operation cancelled")),process.exit(0)),r}import{cancel as gn,isCancel as bn,select as wn}from"@clack/prompts";import yn from"picocolors";async function Wt(e,r,t){if(r!==void 0)return r;if(e==="sqlite"&&t==="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"},...t==="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 n=await wn({message:`Select ${e} setup option`,options:a,initialValue:"none"});return bn(n)&&(gn(yn.red("Operation cancelled")),process.exit(0)),n}import{cancel as Pn,isCancel as vn,multiselect as zt}from"@clack/prompts";import jn from"picocolors";async function qt(e,r,t,a){if(e!==void 0)return e;if(r==="none")return[];if(!(t?.includes("react-router")||t?.includes("tanstack-router")||t?.includes("tanstack-start")))return[];let o=[];return a==="elysia"&&(o=await zt({message:"Include examples",options:[{value:"todo",label:"Todo App",hint:"A simple CRUD example app"}],required:!1,initialValues:g.examples})),(a==="hono"||a==="express")&&(o=await zt({message:"Include examples",options:[{value:"todo",label:"Todo App",hint:"A simple CRUD example app"},{value:"ai",label:"AI Chat",hint:"A simple AI chat interface using AI SDK"}],required:!1,initialValues:g.examples})),vn(o)&&(Pn(jn.red("Operation cancelled")),process.exit(0)),o}import{cancel as Vt,isCancel as Gt,multiselect as kn,select as xn}from"@clack/prompts";import Jt from"picocolors";async function Qt(e){if(e!==void 0)return e;let r=await kn({message:"Select platforms to develop for",options:[{value:"web",label:"Web",hint:"React Web Application"},{value:"native",label:"Native",hint:"Create a React Native/Expo app"}],required:!1,initialValues:g.frontend.some(a=>a==="tanstack-router"||a==="react-router"||a==="tanstack-start"||a==="next")?["web"]:[]});Gt(r)&&(Vt(Jt.red("Operation cancelled")),process.exit(0));let t=[];if(r.includes("web")){let a=await xn({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:"tanstack-start",label:"TanStack Start (beta)",hint:"SSR, Server Functions, API Routes and more with TanStack Router"}],initialValue:g.frontend.find(n=>n==="tanstack-router"||n==="react-router"||n==="tanstack-start"||n==="next")||"tanstack-router"});Gt(a)&&(Vt(Jt.red("Operation cancelled")),process.exit(0)),t.push(a)}return r.includes("native")&&t.push("native"),t}import{cancel as An,confirm as Sn,isCancel as Dn}from"@clack/prompts";import $n from"picocolors";async function Ht(e){if(e!==void 0)return e;let r=await Sn({message:"Initialize git repository?",initialValue:g.git});return Dn(r)&&(An($n.red("Operation cancelled")),process.exit(0)),r}import{cancel as En,confirm as Cn,isCancel as Tn}from"@clack/prompts";import Fn from"picocolors";async function Yt(e){if(e!==void 0)return e;let r=await Cn({message:"Install dependencies?",initialValue:g.install});return Tn(r)&&(En(Fn.red("Operation cancelled")),process.exit(0)),r}import{cancel as Rn,isCancel as Nn,log as Bn,select as In}from"@clack/prompts";import Ln from"picocolors";async function Kt(e,r,t){if(!r)return"none";if(e!==void 0)return e;if(t==="mongodb")return Bn.info("Only Prisma is supported with MongoDB."),"prisma";let a=await In({message:"Select ORM",options:[{value:"drizzle",label:"Drizzle",hint:"lightweight and performant TypeScript ORM"},{value:"prisma",label:"Prisma",hint:"Powerful, feature-rich ORM"}],initialValue:g.orm});return Nn(a)&&(Rn(Ln.red("Operation cancelled")),process.exit(0)),a}import{cancel as Mn,isCancel as On,select as Un}from"@clack/prompts";import _n from"picocolors";async function Xt(e){if(e!==void 0)return e;let r=re(),t=await Un({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:r});return On(t)&&(Mn(_n.red("Operation cancelled")),process.exit(0)),t}import ee from"node:path";import{cancel as Wn,isCancel as zn,text as qn}from"@clack/prompts";import U from"fs-extra";import Vn from"picocolors";var Gn=["<",">",":",'"',"|","?","*"],Zt=255;function er(e){if(e!=="."){if(!e)return"Project name cannot be empty";if(e.length>Zt)return`Project name must be less than ${Zt} characters`;if(Gn.some(r=>e.includes(r)))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 o=process.cwd();if(U.readdirSync(o).length===0)return e}else{let o=ee.basename(e);if(!er(o)){let i=ee.resolve(process.cwd(),e);if(!U.pathExistsSync(i)||U.readdirSync(i).length===0)return e}}let r=!1,t="",a=g.projectName,n=1;for(;U.pathExistsSync(ee.resolve(process.cwd(),a));)a=`${g.projectName}-${n}`,n++;for(;!r;){let o=await qn({message:"Enter your project name or path (relative to current directory)",placeholder:a,initialValue:e,defaultValue:a,validate:s=>{let i=s.trim()||a;if(i==="."){if(U.readdirSync(process.cwd()).length>0)return"Current directory is not empty. Please choose a different directory.";r=!0;return}let c=ee.resolve(process.cwd(),i),l=ee.basename(c),d=er(l);if(d)return d;if(!c.startsWith(process.cwd()))return"Project path must be within current directory";if(U.pathExistsSync(c)&&U.readdirSync(c).length>0)return`Directory "${i}" already exists and is not empty. Please choose a different name or path.`;r=!0}});zn(o)&&(Wn(Vn.red("Operation cancelled.")),process.exit(0)),t=o||a}return t}import{cancel as Jn,isCancel as Qn,select as Hn}from"@clack/prompts";import Yn from"picocolors";async function tr(e,r){if(e!==void 0)return e;if(r==="next")return"node";let t=await Hn({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:g.runtime});return Qn(t)&&(Jn(Yn.red("Operation cancelled")),process.exit(0)),t}async function rr(e){let r=await Xn({projectName:async()=>ge(e.projectName),frontend:()=>Qt(e.frontend),backend:()=>Ut(e.backend),runtime:({results:t})=>tr(e.runtime,t.backend),database:()=>_t(e.database),orm:({results:t})=>Kt(e.orm,t.database!=="none",t.database),api:({results:t})=>Mt(e.api,t.frontend),auth:({results:t})=>Ot(e.auth,t.database!=="none"),addons:({results:t})=>Lt(e.addons,t.frontend),examples:({results:t})=>qt(e.examples,t.database,t.frontend,t.backend),dbSetup:({results:t})=>Wt(t.database??"none",e.dbSetup,t.orm),git:()=>Ht(e.git),packageManager:()=>Xt(e.packageManager),install:()=>Yt(e.install)},{onCancel:()=>{Kn(Zn.red("Operation cancelled")),process.exit(0)}});return{projectName:r.projectName,frontend:r.frontend,database:r.database,orm:r.orm,auth:r.auth,addons:r.addons,examples:r.examples,git:r.git,packageManager:r.packageManager,install:r.install,dbSetup:r.dbSetup,backend:r.backend,runtime:r.runtime,api:r.api}}import T from"picocolors";function Ne(e){let r=[];if(e.projectName&&r.push(`${T.blue("Project Name:")} ${e.projectName}`),e.frontend!==void 0){let t=Array.isArray(e.frontend)?e.frontend:[e.frontend],a=t.length>0&&t[0]!==void 0&&t[0]!==""?t.join(", "):"none";r.push(`${T.blue("Frontend:")} ${a}`)}if(e.backend!==void 0&&r.push(`${T.blue("Backend Framework:")} ${String(e.backend)}`),e.runtime!==void 0&&r.push(`${T.blue("Runtime:")} ${String(e.runtime)}`),e.api!==void 0&&r.push(`${T.blue("API:")} ${String(e.api)}`),e.database!==void 0&&r.push(`${T.blue("Database:")} ${String(e.database)}`),e.orm!==void 0&&r.push(`${T.blue("ORM:")} ${String(e.orm)}`),e.auth!==void 0){let t=typeof e.auth=="boolean"?e.auth?"Yes":"No":String(e.auth);r.push(`${T.blue("Authentication:")} ${t}`)}if(e.addons!==void 0){let t=Array.isArray(e.addons)?e.addons:[e.addons],a=t.length>0&&t[0]!==void 0?t.join(", "):"none";r.push(`${T.blue("Addons:")} ${a}`)}if(e.examples!==void 0){let t=Array.isArray(e.examples)?e.examples:[e.examples],a=t.length>0&&t[0]!==void 0?t.join(", "):"none";r.push(`${T.blue("Examples:")} ${a}`)}if(e.git!==void 0){let t=typeof e.git=="boolean"?e.git?"Yes":"No":String(e.git);r.push(`${T.blue("Git Init:")} ${t}`)}if(e.packageManager!==void 0&&r.push(`${T.blue("Package Manager:")} ${String(e.packageManager)}`),e.install!==void 0){let t=typeof e.install=="boolean"?e.install?"Yes":"No":String(e.install);r.push(`${T.blue("Install Dependencies:")} ${t}`)}return e.dbSetup!==void 0&&r.push(`${T.blue("Database Setup:")} ${String(e.dbSetup)}`),r.length===0?T.yellow("No configuration selected."):r.join(`
201
- `)}function ar(e){let r=[];e.database==="none"?r.push("--database none"):(r.push(`--database ${e.database}`),e.orm&&r.push(`--orm ${e.orm}`),e.dbSetup&&r.push(`--db-setup ${e.dbSetup}`)),e.api&&r.push(`--api ${e.api}`),r.push(e.auth?"--auth":"--no-auth"),r.push(e.git?"--git":"--no-git"),r.push(e.install?"--install":"--no-install"),e.runtime&&r.push(`--runtime ${e.runtime}`),e.backend&&r.push(`--backend ${e.backend}`),e.frontend&&e.frontend.length>0&&r.push(`--frontend ${e.frontend.join(" ")}`),e.addons&&e.addons.length>0?r.push(`--addons ${e.addons.join(" ")}`):r.push("--addons none"),e.examples&&e.examples.length>0?r.push(`--examples ${e.examples.join(" ")}`):r.push("--examples none"),e.packageManager&&r.push(`--package-manager ${e.packageManager}`);let t="",a=e.packageManager;a==="npm"?t="npx create-better-t-stack@latest":a==="pnpm"?t="pnpm create better-t-stack@latest":a==="bun"&&(t="bun create better-t-stack@latest");let n=e.projectName?` ${e.projectName}`:"";return`${t}${n} ${r.join(" ")}`}import eo from"node:path";import to from"fs-extra";var nr=()=>{let e=eo.join(v,"package.json");return to.readJSONSync(e).version??"1.0.0"};import or from"gradient-string";var sr=`
199
+ ${P.yellow("WARNING:")} 'bun' might cause issues with web + native apps in a monorepo. Use 'pnpm' if problems arise.
200
+ `}import jt from"node:path";import{log as Na}from"@clack/prompts";import{$ as vt,execa as Fa}from"execa";import J from"fs-extra";import Ba from"picocolors";async function kt(e,r){await Ia(e,r),await La(e,r)}async function Ia(e,r){let t=jt.join(e,"package.json");if(await J.pathExists(t)){let a=await J.readJson(t);a.name=r.projectName;let n={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"},s={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"};r.addons.includes("turborepo")?a.scripts=n:r.packageManager==="pnpm"?a.scripts=s:r.packageManager==="npm"?a.scripts=o:r.packageManager==="bun"?a.scripts=i:a.scripts={};let{stdout:c}=await Fa(r.packageManager,["-v"],{cwd:e});a.packageManager=`${r.packageManager}@${c.trim()}`,await J.writeJson(t,a,{spaces:2})}}async function La(e,r){let t=jt.join(e,"apps/server/package.json");if(await J.pathExists(t)){let a=await J.readJson(t);r.database!=="none"&&(r.database==="sqlite"&&r.orm==="drizzle"&&(a.scripts["db:local"]="turso dev --db-file local.db"),r.orm==="prisma"?(a.scripts["db:push"]="prisma db push --schema ./prisma/schema",a.scripts["db:studio"]="prisma studio"):r.orm==="drizzle"&&(a.scripts["db:push"]="drizzle-kit push",a.scripts["db:studio"]="drizzle-kit studio")),await J.writeJson(t,a,{spaces:2})}}async function xt(e,r){if(!r)return;if((await vt({cwd:e,reject:!1,stderr:"pipe"})`git --version`).exitCode!==0){Na.warn(Ba.yellow("Git is not installed"));return}let a=await vt({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 St(e){let{projectName:r,runtime:t,backend:a}=e,n=me.resolve(process.cwd(),r);if(a==="next")return;let s=me.join(n,"apps/server");t==="bun"?await Ma(s,a):t==="node"&&await Oa(s,a)}async function Ma(e,r){let t=me.join(e,"package.json"),a=await fe.readJson(t);a.scripts={...a.scripts,dev:"bun run --hot src/index.ts",start:"bun run dist/src/index.js"},await fe.writeJson(t,a,{spaces:2}),await w({devDependencies:["@types/bun"],projectDir:e})}async function Oa(e,r){let t=me.join(e,"package.json"),a=await fe.readJson(t);a.scripts={...a.scripts,dev:"tsx watch src/index.ts",start:"node dist/src/index.js"},await fe.writeJson(t,a,{spaces:2}),await w({devDependencies:["tsx","@types/node"],projectDir:e}),r==="hono"?await w({dependencies:["@hono/node-server"],projectDir:e}):r==="elysia"&&await w({dependencies:["@elysiajs/node"],projectDir:e})}import u from"node:path";import Q from"consola";import g from"fs-extra";import{globby as za}from"globby";import H from"picocolors";import Ua from"node:path";import _a from"consola";import Re from"fs-extra";import he from"handlebars";async function Ne(e,r,t){try{let a=await Re.readFile(e,"utf-8"),s=he.compile(a)(t);await Re.ensureDir(Ua.dirname(r)),await Re.writeFile(r,s)}catch(a){throw _a.error(`Error processing template ${e}:`,a),new Error(`Failed to process template ${e}`)}}he.registerHelper("or",(e,r)=>e||r);he.registerHelper("eq",(e,r)=>e===r);he.registerHelper("includes",(e,r)=>Array.isArray(e)&&e.includes(r));async function x(e,r,t,a,n=!0){let s=await za(e,{cwd:r,dot:!0,onlyFiles:!0,absolute:!1});for(let o of s){let i=u.join(r,o),c=o;o.endsWith(".hbs")&&(c=o.slice(0,-4)),u.basename(o)==="_gitignore"&&(c=u.join(u.dirname(o),".gitignore"));let p=u.join(t,c);await g.ensureDir(u.dirname(p)),!(!n&&await g.pathExists(p))&&(i.endsWith(".hbs")?await Ne(i,p,a):await g.copy(i,p,{overwrite:!0}))}}async function Dt(e,r){let t=u.join(j,"templates/base");await x(["**/*"],t,e,r)}async function At(e,r){let t=r.frontend.some(s=>["tanstack-router","react-router","tanstack-start","next"].includes(s)),a=r.frontend.includes("nuxt"),n=r.frontend.includes("native");if(t||a){let s=u.join(e,"apps/web");if(await g.ensureDir(s),t){let o=u.join(j,"templates/frontend/react/web-base");await g.pathExists(o)&&await x("**/*",o,s,r);let i=r.frontend.find(c=>["tanstack-router","react-router","tanstack-start","next"].includes(c));if(i){let c=u.join(j,`templates/frontend/react/${i}`);await g.pathExists(c)&&await x("**/*",c,s,r);let p=u.join(j,`templates/api/${r.api}/web/react/base`);await g.pathExists(p)&&await x("**/*",p,s,r)}}else if(a){let o=u.join(j,"templates/frontend/nuxt");await g.pathExists(o)&&await x("**/*",o,s,r);let i=u.join(j,`templates/api/${r.api}/web/nuxt`);await g.pathExists(i)&&await x("**/*",i,s,r)}}if(n){let s=u.join(e,"apps/native");await g.ensureDir(s);let o=u.join(j,"templates/frontend/native");if(await g.pathExists(o)&&await x("**/*",o,s,r),r.api==="trpc"){let i=u.join(j,`templates/api/${r.api}/native`);await g.pathExists(i)&&await x("**/*",i,s,r)}else if(r.api==="orpc"){let i=u.join(j,`templates/api/${r.api}/native`);await g.pathExists(i)&&await x("**/*",i,s,r)}}}async function $t(e,r){if(r.backend==="none")return;let t=u.join(e,"apps/server");await g.ensureDir(t);let a=u.join(j,"templates/backend/server-base");await g.pathExists(a)?await x("**/*",a,t,r):Q.warn(H.yellow(`Warning: server-base template not found at ${a}`));let n=u.join(j,`templates/backend/${r.backend}`);await g.pathExists(n)?await x("**/*",n,t,r):Q.warn(H.yellow(`Warning: Backend template directory not found, skipping: ${n}`));let s=u.join(j,`templates/api/${r.api}/server/base`);await g.pathExists(s)&&await x("**/*",s,t,r);let o=u.join(j,`templates/api/${r.api}/server/${r.backend}`);await g.pathExists(o)&&await x("**/*",o,t,r)}async function Et(e,r){if(r.orm==="none"||r.database==="none")return;let t=u.join(e,"apps/server");await g.ensureDir(t);let a=u.join(j,`templates/db/${r.orm}/${r.database}`);await g.pathExists(a)?await x("**/*",a,t,r):Q.warn(H.yellow(`Warning: Database/ORM template directory not found, skipping: ${a}`))}async function Ct(e,r){if(!r.auth)return;let t=u.join(e,"apps/server"),a=u.join(e,"apps/web"),n=u.join(e,"apps/native"),s=await g.pathExists(t),o=await g.pathExists(a),i=await g.pathExists(n),c=r.frontend.some(b=>["tanstack-router","react-router","tanstack-start","next"].includes(b)),p=r.frontend.includes("nuxt"),f=r.frontend.includes("native");if(s){let b=u.join(j,"templates/auth/server/base");if(await g.pathExists(b)&&await x("**/*",b,t,r),r.backend==="next"){let l=u.join(j,"templates/auth/server/next");await g.pathExists(l)&&await x("**/*",l,t,r)}if(r.orm!=="none"&&r.database!=="none"){let l=r.orm,d=r.database,k="";l==="drizzle"?k=u.join(j,`templates/auth/server/db/drizzle/${d}`):l==="prisma"&&(k=u.join(j,`templates/auth/server/db/prisma/${d}`)),k&&await g.pathExists(k)?await x("**/*",k,t,r):Q.warn(H.yellow(`Warning: Auth template for ${l}/${d} not found at ${k}`))}}if((c||p)&&o){if(c){let b=u.join(j,"templates/auth/web/react/base");await g.pathExists(b)&&await x("**/*",b,a,r);let l=r.frontend.find(d=>["tanstack-router","react-router","tanstack-start","next"].includes(d));if(l){let d=u.join(j,`templates/auth/web/react/${l}`);await g.pathExists(d)&&await x("**/*",d,a,r)}}else if(p){let b=u.join(j,"templates/auth/web/nuxt");await g.pathExists(b)&&await x("**/*",b,a,r)}}if(f&&i){let b=u.join(j,"templates/auth/native");await g.pathExists(b)?await x("**/*",b,n,r):Q.warn(H.yellow(`Warning: Auth native template not found at ${b}`))}}async function Tt(e,r){if(!(!r.addons||r.addons.length===0))for(let t of r.addons){if(t==="none")continue;let a=u.join(j,`templates/addons/${t}`),n=e;t==="pwa"&&(a=u.join(j,"templates/addons/pwa/apps/web"),n=u.join(e,"apps/web"),!await g.pathExists(n))||await g.pathExists(a)&&await x("**/*",a,n,r)}}async function Rt(e,r){if(!r.examples||r.examples.length===0)return;let t=u.join(e,"apps/server"),a=u.join(e,"apps/web"),n=await g.pathExists(t),s=await g.pathExists(a),o=r.frontend.some(c=>["tanstack-router","react-router","tanstack-start","next"].includes(c)),i=r.frontend.includes("nuxt");for(let c of r.examples){if(c==="none")continue;let p=u.join(j,`templates/examples/${c}`);if(n){let f=u.join(p,"server");if(await g.pathExists(f)&&r.orm!=="none"){let b=u.join(f,r.orm,"base");if(await g.pathExists(b)&&await x("**/*",b,t,r,!1),r.database!=="none"){let l=u.join(f,r.orm,r.database);await g.pathExists(l)&&await x("**/*",l,t,r,!1)}}}if(o&&s){let f=u.join(p,"web/react");if(await g.pathExists(f)){let b=r.frontend.find(l=>["next","react-router","tanstack-router","tanstack-start"].includes(l));if(b){let l=u.join(f,b);await g.pathExists(l)&&await x("**/*",l,a,r,!1)}}}else if(i&&s&&r.api==="orpc"){let f=u.join(p,"web/nuxt");await g.pathExists(f)?await x("**/*",f,a,r,!1):Q.info(H.gray(`Skipping Nuxt web template for example '${c}' (template not found).`))}}}async function Nt(e,r){let t=u.join(j,"templates/extras");if(r.packageManager==="pnpm"){let a=u.join(t,"pnpm-workspace.yaml"),n=u.join(e,"pnpm-workspace.yaml");await g.pathExists(a)&&await g.copy(a,n)}if(r.packageManager==="pnpm"&&(r.frontend.includes("native")||r.frontend.includes("nuxt"))){let a=u.join(t,"_npmrc.hbs"),n=u.join(e,".npmrc");await g.pathExists(a)&&await Ne(a,n,r)}}async function Bt(e){let r=Ga(),t=Wa.resolve(process.cwd(),e.projectName);try{return await Ja.ensureDir(t),await Dt(t,e),await At(t,e),await $t(t,e),await tt(e),await Et(t,e),await ft(e),await Ct(t,e),await Xe(e),await Tt(t,e),e.addons.length>0&&e.addons[0]!=="none"&&await Ge(e),await Rt(t,e),await Nt(t,e),e.examples.length>0&&e.examples[0]!=="none"&&await gt(e),await Qe(e),await St(e),await ht(e),await kt(t,e),await rt(t,e),await xt(t,e.git),Va.success("Project template successfully scaffolded!"),e.install&&await yt({projectDir:t,packageManager:e.packageManager,addons:e.addons}),Pt({...e,depsInstalled:e.install}),t}catch(a){throw r.stop(Ft.red("Failed")),a instanceof Error&&(qa(Ft.red(`Error during project creation: ${a.message}`)),console.error(a.stack),process.exit(1)),a}}import{cancel as Kn,group as Xn}from"@clack/prompts";import Zn from"picocolors";import{cancel as Qa,isCancel as Ha,multiselect as Ya}from"@clack/prompts";import Ka from"picocolors";async function It(e,r){if(e!==void 0)return e;let t=r?.includes("react-router")||r?.includes("tanstack-router"),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)"}],n=[{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=t?[...a,...n]:a,o=y.addons.filter(c=>t||c!=="pwa"&&c!=="tauri"),i=await Ya({message:"Select addons",options:s,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 en}from"@clack/prompts";import tn from"picocolors";async function Lt(e,r){if(e)return e;let t=r?.includes("nuxt"),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"}];t&&(a=[{value:"orpc",label:"oRPC",hint:"End-to-end type-safe APIs (Required for Nuxt frontend)"}]);let n=await en({message:"Select API type",options:a,initialValue:t?"orpc":y.api});return Za(n)&&(Xa(tn.red("Operation cancelled")),process.exit(0)),t&&n!=="orpc"?"orpc":n}import{cancel as rn,confirm as an,isCancel as nn}from"@clack/prompts";import sn from"picocolors";async function Mt(e,r){if(!r)return!1;if(e!==void 0)return e;let t=await an({message:"Add authentication with Better-Auth?",initialValue:y.auth});return nn(t)&&(rn(sn.red("Operation cancelled")),process.exit(0)),t}import{cancel as on,isCancel as cn,select as pn}from"@clack/prompts";import ln from"picocolors";async function Ot(e){if(e!==void 0)return e;let r=await pn({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:y.backend});return cn(r)&&(on(ln.red("Operation cancelled")),process.exit(0)),r}import{cancel as dn,isCancel as un,select as mn}from"@clack/prompts";import fn from"picocolors";async function Ut(e){if(e!==void 0)return e;let r=await mn({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:y.database});return un(r)&&(dn(fn.red("Operation cancelled")),process.exit(0)),r}import{cancel as hn,isCancel as gn,select as bn}from"@clack/prompts";import wn from"picocolors";async function _t(e,r,t){if(r!==void 0)return r;if(e==="sqlite"&&t==="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"},...t==="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 n=await bn({message:`Select ${e} setup option`,options:a,initialValue:"none"});return gn(n)&&(hn(wn.red("Operation cancelled")),process.exit(0)),n}import{cancel as yn,isCancel as Pn,multiselect as vn}from"@clack/prompts";import jn from"picocolors";async function zt(e,r,t,a){if(e!==void 0)return e;if(r==="none")return[];if(!(t?.includes("react-router")||t?.includes("tanstack-router")||t?.includes("tanstack-start")||t?.includes("next")||t?.includes("nuxt")))return[];let s=[],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"}),s=await vn({message:"Include examples",options:o,required:!1,initialValues:y.examples}),Pn(s)&&(yn(jn.red("Operation cancelled")),process.exit(0)),s}import{cancel as Wt,isCancel as qt,multiselect as kn,select as xn}from"@clack/prompts";import Vt from"picocolors";async function Gt(e){if(e!==void 0)return e;let r=await kn({message:"Select platforms to develop for",options:[{value:"web",label:"Web",hint:"React or Vue Web Application"},{value:"native",label:"Native",hint:"Create a React Native/Expo app"}],required:!1,initialValues:y.frontend.some(a=>a==="tanstack-router"||a==="react-router"||a==="tanstack-start"||a==="next"||a==="nuxt")?["web"]:[]});qt(r)&&(Wt(Vt.red("Operation cancelled")),process.exit(0));let t=[];if(r.includes("web")){let a=await xn({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:"tanstack-start",label:"TanStack Start (beta)",hint:"SSR, Server Functions, API Routes and more with TanStack Router"}],initialValue:y.frontend.find(n=>n==="tanstack-router"||n==="react-router"||n==="tanstack-start"||n==="next")||"tanstack-router"});qt(a)&&(Wt(Vt.red("Operation cancelled")),process.exit(0)),t.push(a)}return r.includes("native")&&t.push("native"),t}import{cancel as Sn,confirm as Dn,isCancel as An}from"@clack/prompts";import $n from"picocolors";async function Jt(e){if(e!==void 0)return e;let r=await Dn({message:"Initialize git repository?",initialValue:y.git});return An(r)&&(Sn($n.red("Operation cancelled")),process.exit(0)),r}import{cancel as En,confirm as Cn,isCancel as Tn}from"@clack/prompts";import Rn from"picocolors";async function Qt(e){if(e!==void 0)return e;let r=await Cn({message:"Install dependencies?",initialValue:y.install});return Tn(r)&&(En(Rn.red("Operation cancelled")),process.exit(0)),r}import{cancel as Nn,isCancel as Fn,log as Bn,select as In}from"@clack/prompts";import Ln from"picocolors";async function Ht(e,r,t){if(!r)return"none";if(e!==void 0)return e;if(t==="mongodb")return Bn.info("Only Prisma is supported with MongoDB."),"prisma";let a=await In({message:"Select ORM",options:[{value:"drizzle",label:"Drizzle",hint:"lightweight and performant TypeScript ORM"},{value:"prisma",label:"Prisma",hint:"Powerful, feature-rich ORM"}],initialValue:y.orm});return Fn(a)&&(Nn(Ln.red("Operation cancelled")),process.exit(0)),a}import{cancel as Mn,isCancel as On,select as Un}from"@clack/prompts";import _n from"picocolors";async function Yt(e){if(e!==void 0)return e;let r=re(),t=await Un({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:r});return On(t)&&(Mn(_n.red("Operation cancelled")),process.exit(0)),t}import te from"node:path";import{cancel as zn,isCancel as Wn,text as qn}from"@clack/prompts";import M from"fs-extra";import Vn from"picocolors";var Gn=["<",">",":",'"',"|","?","*"],Kt=255;function Xt(e){if(e!=="."){if(!e)return"Project name cannot be empty";if(e.length>Kt)return`Project name must be less than ${Kt} characters`;if(Gn.some(r=>e.includes(r)))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 s=process.cwd();if(M.readdirSync(s).length===0)return e}else{let s=te.basename(e);if(!Xt(s)){let i=te.resolve(process.cwd(),e);if(!M.pathExistsSync(i)||M.readdirSync(i).length===0)return e}}let r=!1,t="",a=y.projectName,n=1;for(;M.pathExistsSync(te.resolve(process.cwd(),a));)a=`${y.projectName}-${n}`,n++;for(;!r;){let s=await qn({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(M.readdirSync(process.cwd()).length>0)return"Current directory is not empty. Please choose a different directory.";r=!0;return}let c=te.resolve(process.cwd(),i),p=te.basename(c),f=Xt(p);if(f)return f;if(!c.startsWith(process.cwd()))return"Project path must be within current directory";if(M.pathExistsSync(c)&&M.readdirSync(c).length>0)return`Directory "${i}" already exists and is not empty. Please choose a different name or path.`;r=!0}});Wn(s)&&(zn(Vn.red("Operation cancelled.")),process.exit(0)),t=s||a}return t}import{cancel as Jn,isCancel as Qn,select as Hn}from"@clack/prompts";import Yn from"picocolors";async function Zt(e,r){if(e!==void 0)return e;if(r==="next")return"node";let t=await Hn({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:y.runtime});return Qn(t)&&(Jn(Yn.red("Operation cancelled")),process.exit(0)),t}async function er(e){let r=await Xn({projectName:async()=>ge(e.projectName),frontend:()=>Gt(e.frontend),backend:()=>Ot(e.backend),runtime:({results:t})=>Zt(e.runtime,t.backend),database:()=>Ut(e.database),orm:({results:t})=>Ht(e.orm,t.database!=="none",t.database),api:({results:t})=>Lt(e.api,t.frontend),auth:({results:t})=>Mt(e.auth,t.database!=="none"),addons:({results:t})=>It(e.addons,t.frontend),examples:({results:t})=>zt(e.examples,t.database,t.frontend,t.backend),dbSetup:({results:t})=>_t(t.database??"none",e.dbSetup,t.orm),git:()=>Jt(e.git),packageManager:()=>Yt(e.packageManager),install:()=>Qt(e.install)},{onCancel:()=>{Kn(Zn.red("Operation cancelled")),process.exit(0)}});return{projectName:r.projectName,frontend:r.frontend,database:r.database,orm:r.orm,auth:r.auth,addons:r.addons,examples:r.examples,git:r.git,packageManager:r.packageManager,install:r.install,dbSetup:r.dbSetup,backend:r.backend,runtime:r.runtime,api:r.api}}import E from"picocolors";function Fe(e){let r=[];if(e.projectName&&r.push(`${E.blue("Project Name:")} ${e.projectName}`),e.frontend!==void 0){let t=Array.isArray(e.frontend)?e.frontend:[e.frontend],a=t.length>0&&t[0]!==void 0&&t[0]!==""?t.join(", "):"none";r.push(`${E.blue("Frontend:")} ${a}`)}if(e.backend!==void 0&&r.push(`${E.blue("Backend Framework:")} ${String(e.backend)}`),e.runtime!==void 0&&r.push(`${E.blue("Runtime:")} ${String(e.runtime)}`),e.api!==void 0&&r.push(`${E.blue("API:")} ${String(e.api)}`),e.database!==void 0&&r.push(`${E.blue("Database:")} ${String(e.database)}`),e.orm!==void 0&&r.push(`${E.blue("ORM:")} ${String(e.orm)}`),e.auth!==void 0){let t=typeof e.auth=="boolean"?e.auth?"Yes":"No":String(e.auth);r.push(`${E.blue("Authentication:")} ${t}`)}if(e.addons!==void 0){let t=Array.isArray(e.addons)?e.addons:[e.addons],a=t.length>0&&t[0]!==void 0?t.join(", "):"none";r.push(`${E.blue("Addons:")} ${a}`)}if(e.examples!==void 0){let t=Array.isArray(e.examples)?e.examples:[e.examples],a=t.length>0&&t[0]!==void 0?t.join(", "):"none";r.push(`${E.blue("Examples:")} ${a}`)}if(e.git!==void 0){let t=typeof e.git=="boolean"?e.git?"Yes":"No":String(e.git);r.push(`${E.blue("Git Init:")} ${t}`)}if(e.packageManager!==void 0&&r.push(`${E.blue("Package Manager:")} ${String(e.packageManager)}`),e.install!==void 0){let t=typeof e.install=="boolean"?e.install?"Yes":"No":String(e.install);r.push(`${E.blue("Install Dependencies:")} ${t}`)}return e.dbSetup!==void 0&&r.push(`${E.blue("Database Setup:")} ${String(e.dbSetup)}`),r.length===0?E.yellow("No configuration selected."):r.join(`
201
+ `)}function tr(e){let r=[];e.database==="none"?r.push("--database none"):(r.push(`--database ${e.database}`),e.orm&&r.push(`--orm ${e.orm}`),e.dbSetup&&r.push(`--db-setup ${e.dbSetup}`)),e.api&&r.push(`--api ${e.api}`),r.push(e.auth?"--auth":"--no-auth"),r.push(e.git?"--git":"--no-git"),r.push(e.install?"--install":"--no-install"),e.runtime&&r.push(`--runtime ${e.runtime}`),e.backend&&r.push(`--backend ${e.backend}`),e.frontend&&e.frontend.length>0&&r.push(`--frontend ${e.frontend.join(" ")}`),e.addons&&e.addons.length>0?r.push(`--addons ${e.addons.join(" ")}`):r.push("--addons none"),e.examples&&e.examples.length>0?r.push(`--examples ${e.examples.join(" ")}`):r.push("--examples none"),e.packageManager&&r.push(`--package-manager ${e.packageManager}`);let t="",a=e.packageManager;a==="npm"?t="npx create-better-t-stack@latest":a==="pnpm"?t="pnpm create better-t-stack@latest":a==="bun"&&(t="bun create better-t-stack@latest");let n=e.projectName?` ${e.projectName}`:"";return`${t}${n} ${r.join(" ")}`}import es from"node:path";import ts from"fs-extra";var rr=()=>{let e=es.join(j,"package.json");return ts.readJSONSync(e).version??"1.0.0"};import ar from"gradient-string";var nr=`
202
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
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
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
@@ -212,10 +212,10 @@ ${y.yellow("WARNING:")} 'bun' might cause issues with web + native apps in a mon
212
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
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
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
- `,ir={pink:"#F5C2E7",mauve:"#CBA6F7",red:"#F38BA8",maroon:"#E78284",peach:"#FAB387",yellow:"#F9E2AF",green:"#A6E3A1",teal:"#94E2D5",sky:"#89DCEB",sapphire:"#74C7EC",lavender:"#B4BEFE"},cr=()=>{let e=process.stdout.columns||80,r=sr.split(`
216
- `),t=Math.max(...r.map(a=>a.length));e<t?console.log(or(Object.values(ir)).multiline(`
215
+ `,sr={pink:"#F5C2E7",mauve:"#CBA6F7",red:"#F38BA8",maroon:"#E78284",peach:"#FAB387",yellow:"#F9E2AF",green:"#A6E3A1",teal:"#94E2D5",sky:"#89DCEB",sapphire:"#74C7EC",lavender:"#B4BEFE"},or=()=>{let e=process.stdout.columns||80,r=nr.split(`
216
+ `),t=Math.max(...r.map(a=>a.length));e<t?console.log(ar(Object.values(sr)).multiline(`
217
217
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
218
218
  \u2551 Better T-Stack \u2551
219
219
  \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
220
- `)):console.log(or(Object.values(ir)).multiline(sr))};var lr=()=>process.exit(0);process.on("SIGINT",lr);process.on("SIGTERM",lr);async function co(){let e=Date.now();try{let t=await so(io(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","native","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(nr()).alias("version","v").help().alias("help","h").strict().wrap(null).parse(),a=t.projectDirectory;cr();let n=po(t,a);no(W.magenta("Creating a new Better-T-Stack project")),!t.yes&&Object.keys(n).length>0&&(_.info(W.yellow("Using these pre-selected options:")),_.message(Ne(n)),_.message(""));let o;t.yes?(o={...g,projectName:a??g.projectName,...n},o.database==="none"&&(o.orm="none",o.auth=!1,o.dbSetup="none",o.examples=o.examples.filter(c=>c!=="todo")),_.info(W.yellow("Using these default/flag options:")),_.message(Ne(o)),_.message("")):o=await rr(n);let s=ro.resolve(process.cwd(),o.projectName);if(pr.pathExistsSync(s)&&pr.readdirSync(s).length>0){let c=await ge();o.projectName=c}await It(o),_.success(W.blue(`You can reproduce this setup with the following command:
221
- ${ar(o)}`));let i=((Date.now()-e)/1e3).toFixed(2);oo(W.magenta(`Project created successfully in ${W.bold(i)} seconds!`))}catch(r){r instanceof Error?(r.name==="YError"?ao(W.red(`Invalid arguments: ${r.message}`)):(k.error(`An unexpected error occurred: ${r.message}`),k.error(r.stack)),process.exit(1)):(k.error("An unexpected error occurred."),console.error(r),process.exit(1))}}function po(e,r){let t={};if(e.database&&(t.database=e.database),e.orm&&(t.orm=e.orm),e.auth!==void 0&&(t.auth=e.auth),e.git!==void 0&&(t.git=e.git),e.install!==void 0&&(t.install=e.install),e.backend&&(t.backend=e.backend),e.runtime&&(t.runtime=e.runtime),e.frontend&&e.frontend.length>0)if(e.frontend.includes("none"))e.frontend.length>1&&(k.fatal("Cannot combine 'none' with other frontend options."),process.exit(1)),t.frontend=[];else{let p=e.frontend.filter(j=>j!=="none");p.filter(j=>j==="tanstack-router"||j==="react-router"||j==="tanstack-start"||j==="next").length>1&&(k.fatal("Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router, next"),process.exit(1)),t.frontend=p}e.api&&(t.api=e.api),e.addons&&e.addons.length>0&&(e.addons.includes("none")?(e.addons.length>1&&(k.fatal("Cannot combine 'none' with other addons."),process.exit(1)),t.addons=[]):t.addons=e.addons.filter(p=>p!=="none")),e.examples&&e.examples.length>0&&(e.examples.includes("none")?(e.examples.length>1&&(k.fatal("Cannot combine 'none' with other examples."),process.exit(1)),t.examples=[]):t.examples=e.examples.filter(p=>p!=="none")),e.packageManager&&(t.packageManager=e.packageManager),r&&(t.projectName=r),e.dbSetup&&(t.dbSetup=e.dbSetup);let a=t.database??(e.yes?g.database:void 0),n=t.orm??(e.yes?g.orm:void 0),o=t.auth??(e.yes?g.auth:void 0),s=t.dbSetup??(e.yes?g.dbSetup:void 0),i=t.examples??(e.yes?g.examples:void 0),c=t.frontend??(e.yes?g.frontend:void 0),l=t.api??(e.yes?g.api:void 0),d=t.backend??(e.yes?g.backend:void 0);if(a==="none"&&(n&&n!=="none"&&(k.fatal(`Cannot use ORM '--orm ${n}' when database is 'none'.`),process.exit(1)),t.orm="none",o===!0&&(k.fatal("Authentication requires a database. Cannot use --auth when database is 'none'."),process.exit(1)),t.auth=!1,s&&s!=="none"&&(k.fatal(`Database setup '--db-setup ${s}' requires a database. Cannot use when database is 'none'.`),process.exit(1)),t.dbSetup="none",i?.includes("todo")&&(k.fatal("The 'todo' example requires a database. Cannot use --examples todo when database is 'none'."),process.exit(1)),t.examples&&(t.examples=t.examples.filter(p=>p!=="todo"))),a==="mongodb"&&n==="drizzle"&&(k.fatal("MongoDB is only available with Prisma. Cannot use --database mongodb with --orm drizzle"),process.exit(1)),t.dbSetup&&t.dbSetup!=="none"){let p=t.dbSetup;p==="turso"?(a&&a!=="sqlite"&&(k.fatal(`Turso setup requires SQLite. Cannot use --db-setup turso with --database ${a}`),process.exit(1)),n==="prisma"&&(k.fatal("Turso setup is not compatible with Prisma. Cannot use --db-setup turso with --orm prisma"),process.exit(1)),t.database="sqlite",t.orm="drizzle"):p==="prisma-postgres"?(a&&a!=="postgres"&&(k.fatal(`Prisma PostgreSQL setup requires PostgreSQL. Cannot use --db-setup prisma-postgres with --database ${a}.`),process.exit(1)),n&&n!=="prisma"&&n!=="none"&&(k.fatal(`Prisma PostgreSQL setup requires Prisma ORM. Cannot use --db-setup prisma-postgres with --orm ${n}.`),process.exit(1)),t.database="postgres",t.orm="prisma"):p==="mongodb-atlas"?(a&&a!=="mongodb"&&(k.fatal(`MongoDB Atlas setup requires MongoDB. Cannot use --db-setup mongodb-atlas with --database ${a}.`),process.exit(1)),n&&n!=="prisma"&&n!=="none"&&(k.fatal(`MongoDB Atlas setup requires Prisma ORM. Cannot use --db-setup mongodb-atlas with --orm ${n}.`),process.exit(1)),t.database="mongodb",t.orm="prisma"):p==="neon"&&(a&&a!=="postgres"&&(k.fatal(`Neon PostgreSQL setup requires PostgreSQL. Cannot use --db-setup neon with --database ${a}.`),process.exit(1)),t.database="postgres")}let P=c?.includes("native");if(P&&l==="orpc"&&(k.fatal("oRPC API is not supported with 'native' frontend. Please use --api trpc or remove 'native' from --frontend."),process.exit(1)),P&&l!=="trpc"&&(!e.api||e.yes&&e.api!=="orpc")&&(t.api="trpc"),t.addons&&t.addons.length>0){let p=["pwa","tauri"],b=t.addons.some(A=>p.includes(A)),j=c?.some(A=>A==="tanstack-router"||A==="react-router");b&&!j&&(k.fatal("PWA and Tauri addons require tanstack-router or react-router. Cannot use these addons with your frontend selection."),process.exit(1)),t.addons.includes("husky")&&!t.addons.includes("biome")&&t.addons.push("biome"),t.addons=[...new Set(t.addons)]}return t.examples&&t.examples.length>0&&(t.examples.includes("ai")&&d==="elysia"&&(k.fatal("AI example is not compatible with Elysia backend. Cannot use --examples ai with --backend elysia"),process.exit(1)),c?.some(b=>["tanstack-router","react-router","tanstack-start","next"].includes(b))||(k.fatal("Examples require a web frontend (tanstack-router, react-router, tanstack-start, or next). Cannot use --examples with your frontend selection."),process.exit(1))),t}co().catch(e=>{k.error("Aborting installation due to unexpected error..."),e instanceof Error?(k.error(e.message),console.error(e.stack)):(k.error("An unknown error has occurred. Please open an issue on GitHub with the below:"),console.error(e)),process.exit(1)});
220
+ `)):console.log(ar(Object.values(sr)).multiline(nr))};var cr=()=>process.exit(0);process.on("SIGINT",cr);process.on("SIGTERM",cr);async function cs(){let e=Date.now();try{let t=await os(is(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","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(rr()).alias("version","v").help().alias("help","h").strict().wrap(null).parse(),a=t.projectDirectory;or();let n=ps(t,a);ns(U.magenta("Creating a new Better-T-Stack project")),!t.yes&&Object.keys(n).length>0&&(O.info(U.yellow("Using these pre-selected options:")),O.message(Fe(n)),O.message(""));let s;t.yes?(s={...y,projectName:a??y.projectName,...n},s.database==="none"&&(s.orm="none",s.auth=!1,s.dbSetup="none",s.examples=s.examples.filter(c=>c!=="todo")),O.info(U.yellow("Using these default/flag options:")),O.message(Fe(s)),O.message("")):s=await er(n);let o=rs.resolve(process.cwd(),s.projectName);if(ir.pathExistsSync(o)&&ir.readdirSync(o).length>0){let c=await ge();s.projectName=c}await Bt(s),O.success(U.blue(`You can reproduce this setup with the following command:
221
+ ${tr(s)}`));let i=((Date.now()-e)/1e3).toFixed(2);ss(U.magenta(`Project created successfully in ${U.bold(i)} seconds!`))}catch(r){r instanceof Error?(r.name==="YError"?as(U.red(`Invalid arguments: ${r.message}`)):(S.error(`An unexpected error occurred: ${r.message}`),S.error(r.stack)),process.exit(1)):(S.error("An unexpected error occurred."),console.error(r),process.exit(1))}}function ps(e,r){let t={};if(e.database&&(t.database=e.database),e.orm&&(t.orm=e.orm),e.auth!==void 0&&(t.auth=e.auth),e.git!==void 0&&(t.git=e.git),e.install!==void 0&&(t.install=e.install),e.backend&&(t.backend=e.backend),e.runtime&&(t.runtime=e.runtime),e.frontend&&e.frontend.length>0)if(e.frontend.includes("none"))e.frontend.length>1&&(S.fatal("Cannot combine 'none' with other frontend options."),process.exit(1)),t.frontend=[];else{let d=e.frontend.filter(D=>D!=="none");d.filter(D=>D==="tanstack-router"||D==="react-router"||D==="tanstack-start"||D==="next"||D==="nuxt").length>1&&(S.fatal("Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router, next, nuxt"),process.exit(1)),t.frontend=d}e.api&&(t.api=e.api),e.addons&&e.addons.length>0&&(e.addons.includes("none")?(e.addons.length>1&&(S.fatal("Cannot combine 'none' with other addons."),process.exit(1)),t.addons=[]):t.addons=e.addons.filter(d=>d!=="none")),e.examples&&e.examples.length>0&&(e.examples.includes("none")?(e.examples.length>1&&(S.fatal("Cannot combine 'none' with other examples."),process.exit(1)),t.examples=[]):t.examples=e.examples.filter(d=>d!=="none")),e.packageManager&&(t.packageManager=e.packageManager),r&&(t.projectName=r),e.dbSetup&&(t.dbSetup=e.dbSetup);let a=t.database??(e.yes?y.database:void 0),n=t.orm??(e.yes?y.orm:void 0),s=t.auth??(e.yes?y.auth:void 0),o=t.dbSetup??(e.yes?y.dbSetup:void 0),i=t.examples??(e.yes?y.examples:void 0),c=t.frontend??(e.yes?y.frontend:void 0),p=t.api??(e.yes?y.api:void 0),f=t.backend??(e.yes?y.backend:void 0);if(a==="none"&&(n&&n!=="none"&&(S.fatal(`Cannot use ORM '--orm ${n}' when database is 'none'.`),process.exit(1)),t.orm="none",s===!0&&(S.fatal("Authentication requires a database. Cannot use --auth when database is 'none'."),process.exit(1)),t.auth=!1,o&&o!=="none"&&(S.fatal(`Database setup '--db-setup ${o}' requires a database. Cannot use when database is 'none'.`),process.exit(1)),t.dbSetup="none",i?.includes("todo")&&(S.fatal("The 'todo' example requires a database. Cannot use --examples todo when database is 'none'."),process.exit(1)),t.examples&&(t.examples=t.examples.filter(d=>d!=="todo"))),a==="mongodb"&&n==="drizzle"&&(S.fatal("MongoDB is only available with Prisma. Cannot use --database mongodb with --orm drizzle"),process.exit(1)),t.dbSetup&&t.dbSetup!=="none"){let d=t.dbSetup;d==="turso"?(a&&a!=="sqlite"&&(S.fatal(`Turso setup requires SQLite. Cannot use --db-setup turso with --database ${a}`),process.exit(1)),n==="prisma"&&(S.fatal("Turso setup is not compatible with Prisma. Cannot use --db-setup turso with --orm prisma"),process.exit(1)),t.database="sqlite",t.orm="drizzle"):d==="prisma-postgres"?(a&&a!=="postgres"&&(S.fatal(`Prisma PostgreSQL setup requires PostgreSQL. Cannot use --db-setup prisma-postgres with --database ${a}.`),process.exit(1)),n&&n!=="prisma"&&n!=="none"&&(S.fatal(`Prisma PostgreSQL setup requires Prisma ORM. Cannot use --db-setup prisma-postgres with --orm ${n}.`),process.exit(1)),t.database="postgres",t.orm="prisma"):d==="mongodb-atlas"?(a&&a!=="mongodb"&&(S.fatal(`MongoDB Atlas setup requires MongoDB. Cannot use --db-setup mongodb-atlas with --database ${a}.`),process.exit(1)),n&&n!=="prisma"&&n!=="none"&&(S.fatal(`MongoDB Atlas setup requires Prisma ORM. Cannot use --db-setup mongodb-atlas with --orm ${n}.`),process.exit(1)),t.database="mongodb",t.orm="prisma"):d==="neon"&&(a&&a!=="postgres"&&(S.fatal(`Neon PostgreSQL setup requires PostgreSQL. Cannot use --db-setup neon with --database ${a}.`),process.exit(1)),t.database="postgres")}let b=c?.includes("native"),l=c?.includes("nuxt");if(l&&p==="trpc"&&(S.fatal("tRPC API is not supported with 'nuxt' frontend. Please use --api orpc or remove 'nuxt' from --frontend."),process.exit(1)),l&&p!=="orpc"&&(!e.api||e.yes&&e.api!=="trpc")&&(t.api="orpc"),t.addons&&t.addons.length>0){let d=["pwa","tauri"],k=t.addons.some(v=>d.includes(v)),D=c?.some(v=>v==="tanstack-router"||v==="react-router"||v==="nuxt"&&t.addons?.includes("tauri")&&!t.addons?.includes("pwa"));if(k&&!D){let v="";t.addons.includes("pwa")&&l?v="PWA addon is not compatible with Nuxt.":(t.addons.includes("pwa")||t.addons.includes("tauri"))&&(v="PWA and Tauri addons require tanstack-router, react-router, or Nuxt (Tauri only)."),S.fatal(`${v} Cannot use these addons with your frontend selection.`),process.exit(1)}t.addons.includes("husky")&&!t.addons.includes("biome")&&S.warn("Husky addon is recommended to be used with Biome for lint-staged configuration."),t.addons=[...new Set(t.addons)]}if(t.examples&&t.examples.length>0){t.examples.includes("ai")&&f==="elysia"&&(S.fatal("The 'ai' example is not compatible with the Elysia backend."),process.exit(1));let d=c?.some(k=>["tanstack-router","react-router","tanstack-start","next","nuxt"].includes(k));t.examples.length>0&&!d&&(S.fatal("Examples require a web frontend (tanstack-router, react-router, tanstack-start, next, or nuxt)."),process.exit(1))}return t}cs().catch(e=>{S.error("Aborting installation due to unexpected error..."),e instanceof Error?S.error(e.message):console.error(e),process.exit(1)});