create-t3-app
Version:
Create web application with the t3 stack
63 lines (59 loc) • 30.2 kB
JavaScript
import nt from"path";import{execa as Nt}from"execa";import st from"fs-extra";import*as f from"@clack/prompts";import oe from"chalk";import{Command as St}from"commander";import fe from"path";import{fileURLToPath as lt}from"url";var ct=lt(import.meta.url),pt=fe.dirname(ct),c=fe.join(pt,"../"),ue=` ___ ___ ___ __ _____ ___ _____ ____ __ ___ ___
/ __| _ \\ __| / \\_ _| __| |_ _|__ / / \\ | _ \\ _ \\
| (__| / _| / /\\ \\| | | _| | | |_ \\ / /\\ \\| _/ _/
\\___|_|_\\___|_/\u203E\u203E\\_\\_| |___| |_| |___/ /_/\u203E\u203E\\_\\_| |_|
`,F="my-t3-app",Z="create-t3-app";import mt from"node:crypto";import N from"path";import ee from"fs-extra";var ge=({projectDir:e,packages:i,databaseProvider:o,scopedAppName:t})=>{let n=i?.nextAuth.inUse,s=i?.prisma.inUse,a=i?.drizzle.inUse,r=s===!0||a===!0,p=o==="planetscale",g=dt(!!n,!!s,!!a,o,t),m="";if(r?p?n?m="with-auth-db-planetscale.js":m="with-db-planetscale.js":n?m="with-auth-db.js":m="with-db.js":n&&(m="with-auth.js"),m!==""){let K=N.join(c,"template/extras/src/env",m),Y=N.join(e,"src/env.js");ee.copyFileSync(K,Y)}let x=N.join(e,".env"),h=N.join(e,".env.example"),w=ft+g,R=Buffer.from(mt.getRandomValues(new Uint8Array(32))).toString("base64"),H=g.replace('AUTH_SECRET=""',`AUTH_SECRET="${R}" # Generated by create-t3-app.`);ee.writeFileSync(x,H,"utf-8"),ee.writeFileSync(h,w,"utf-8")},dt=(e,i,o,t,n)=>{let s=`
# When adding additional environment variables, the schema in "/src/env.js"
# should be updated accordingly.
`.trim().concat(`
`);return e&&(s+=`
# Next Auth
# You can generate a new secret on the command line with:
# npx auth secret
# https://next-auth.js.org/configuration/options#secret
AUTH_SECRET=""
# Next Auth Discord Provider
AUTH_DISCORD_ID=""
AUTH_DISCORD_SECRET=""
`),i&&(s+=`
# Prisma
# https://www.prisma.io/docs/reference/database-reference/connection-urls#env
`),o&&(s+=`
# Drizzle
`),(i||o)&&(t==="planetscale"?o?s+=`# Get the Database URL from the "prisma" dropdown selector in PlanetScale.
# Change the query params at the end of the URL to "?ssl={"rejectUnauthorized":true}"
DATABASE_URL='mysql://YOUR_MYSQL_URL_HERE?ssl={"rejectUnauthorized":true}'`:s=`# Get the Database URL from the "prisma" dropdown selector in PlanetScale.
DATABASE_URL='mysql://YOUR_MYSQL_URL_HERE?sslaccept=strict'`:t==="mysql"?s+=`DATABASE_URL="mysql://root:password@localhost:3306/${n}"`:t==="postgres"?s+=`DATABASE_URL="postgresql://postgres:password@localhost:5432/${n}"`:t==="sqlite"&&(s+='DATABASE_URL="file:./db.sqlite"'),s+=`
`),!e&&!i&&(s+=`
# Example:
# SERVERVAR="foo"
# NEXT_PUBLIC_CLIENTVAR="bar"
`),s},ft=`
# Since the ".env" file is gitignored, you can use the ".env.example" file to
# build a new ".env" file when you clone the repo. Keep this file up-to-date
# when you add new variables to \`.env\`.
# This file will be committed to version control, so make sure not to have any
# secrets in it. If you are cloning this repo, create a copy of this file named
# ".env" and populate it with your secrets.
`.trim().concat(`
`);import _ from"path";import te from"fs-extra";import ye from"path";import be from"fs-extra";import ut from"sort-package-json";var he={"next-auth":"5.0.0-beta.25","@auth/prisma-adapter":"^2.7.2","@auth/drizzle-adapter":"^1.7.2",prisma:"^6.5.0","@prisma/client":"^6.5.0","@prisma/adapter-planetscale":"^6.5.0","drizzle-kit":"^0.30.5","drizzle-orm":"^0.41.0",mysql2:"^3.11.0","@planetscale/database":"^1.19.0",postgres:"^3.4.4","@libsql/client":"^0.14.0",tailwindcss:"^4.0.15",postcss:"^8.5.3","@tailwindcss/postcss":"^4.0.15","@trpc/client":"^11.0.0","@trpc/server":"^11.0.0","@trpc/react-query":"^11.0.0","@trpc/next":"^11.0.0","@tanstack/react-query":"^5.69.0",superjson:"^2.2.1","server-only":"^0.0.1","@biomejs/biome":"1.9.4",prettier:"^3.5.3","@eslint/eslintrc":"^3.3.1","prettier-plugin-tailwindcss":"^0.6.11",eslint:"^9.23.0","eslint-config-next":"^15.2.3","eslint-plugin-drizzle":"^0.2.3","typescript-eslint":"^8.27.0"};var u=e=>{let{dependencies:i,devMode:o,projectDir:t}=e,n=be.readJSONSync(ye.join(t,"package.json"));i.forEach(a=>{let r=he[a];o&&n.devDependencies?n.devDependencies[a]=r:n.dependencies&&(n.dependencies[a]=r)});let s=ut(n);be.writeJSONSync(ye.join(t,"package.json"),s,{spaces:2})};var xe=({projectDir:e,packages:i})=>{let o=i?.prisma.inUse,t=i?.drizzle.inUse,n=["next-auth"];o&&n.push("@auth/prisma-adapter"),t&&n.push("@auth/drizzle-adapter"),u({projectDir:e,dependencies:n,devMode:!1});let s=_.join(c,"template/extras"),a="src/app/api/auth/[...nextauth]/route.ts",r=_.join(s,a),p=_.join(e,a),g=_.join(s,"src/server/auth/config",o?"with-prisma.ts":t?"with-drizzle.ts":"base.ts"),m=_.join(e,"src/server/auth/config.ts"),x=_.join(s,"src/server/auth/index.ts"),h=_.join(e,"src/server/auth/index.ts");te.copySync(r,p),te.copySync(g,m),te.copySync(x,h)};import C from"path";import G from"fs-extra";import gt from"path";import we from"fs-extra";import ht from"sort-package-json";var v=e=>{let{scripts:i,projectDir:o}=e,t=gt.join(o,"package.json"),n=we.readJSONSync(t);n.scripts={...n.scripts,...i};let s=ht(n);we.writeJSONSync(t,s,{spaces:2})};var ve=({projectDir:e,packages:i,databaseProvider:o})=>{u({projectDir:e,dependencies:["prisma"],devMode:!0}),u({projectDir:e,dependencies:["@prisma/client"],devMode:!1}),o==="planetscale"&&u({projectDir:e,dependencies:["@prisma/adapter-planetscale","@planetscale/database"],devMode:!1});let t=C.join(c,"template/extras"),n=C.join(t,"prisma/schema",`${i?.nextAuth.inUse?"with-auth":"base"}${o==="planetscale"?"-planetscale":""}.prisma`),s=G.readFileSync(n,"utf-8");o!=="sqlite"&&(s=s.replace('provider = "sqlite"',`provider = "${{mysql:"mysql",postgres:"postgresql",planetscale:"mysql"}[o]}"`),["mysql","planetscale"].includes(o)&&(s=s.replace("// @db.Text","@db.Text")));let a=C.join(e,"prisma/schema.prisma");G.mkdirSync(C.dirname(a),{recursive:!0}),G.writeFileSync(a,s);let r=C.join(t,o==="planetscale"?"src/server/db/db-prisma-planetscale.ts":"src/server/db/db-prisma.ts"),p=C.join(e,"src/server/db.ts");v({projectDir:e,scripts:{postinstall:"prisma generate","db:push":"prisma db push","db:studio":"prisma studio","db:generate":"prisma migrate dev","db:migrate":"prisma migrate deploy"}}),G.copySync(r,p)};import U from"path";import Pe from"fs-extra";var Se=({projectDir:e})=>{u({projectDir:e,dependencies:["tailwindcss","postcss","@tailwindcss/postcss"],devMode:!0});let i=U.join(c,"template/extras"),o=U.join(i,"config/postcss.config.js"),t=U.join(e,"postcss.config.js"),n=U.join(i,"src/styles/globals.css"),s=U.join(e,"src/styles/globals.css");Pe.copySync(o,t),Pe.copySync(n,s)};import d from"path";import yt from"fs-extra";var _e=({projectDir:e,packages:i,appRouter:o})=>{u({projectDir:e,dependencies:["@tanstack/react-query","superjson","@trpc/server","@trpc/client","@trpc/react-query"],devMode:!1});let t=i?.nextAuth.inUse,n=i?.prisma.inUse,s=i?.drizzle.inUse,a=n===!0||s===!0,r=d.join(c,"template/extras"),m=o?"src/app/api/trpc/[trpc]/route.ts":"src/pages/api/trpc/[trpc].ts",x=d.join(r,m),h=d.join(e,m),w=t&&a?"with-auth-db.ts":t?"with-auth.ts":a?"with-db.ts":"base.ts",R=d.join(r,"src/server/api",o?"trpc-app":"trpc-pages",w),H=d.join(e,"src/server/api/trpc.ts"),K=d.join(r,"src/server/api/root.ts"),Y=d.join(e,"src/server/api/root.ts"),ot=t&&n?"with-auth-prisma.ts":t&&s?"with-auth-drizzle.ts":t?"with-auth.ts":n?"with-prisma.ts":s?"with-drizzle.ts":"base.ts",at=d.join(r,"src/server/api/routers/post",ot),rt=d.join(e,"src/server/api/routers/post.ts"),Q=[[x,h],[R,H],[K,Y],[at,rt]];if(o){u({dependencies:["server-only"],devMode:!1,projectDir:e});let z=d.join(r,"src/trpc");Q.push([d.join(z,"server.ts"),d.join(e,"src/trpc/server.ts")],[d.join(z,"react.tsx"),d.join(e,"src/trpc/react.tsx")],[d.join(r,"src/app/_components",i?.tailwind.inUse?"post-tw.tsx":"post.tsx"),d.join(e,"src/app/_components/post.tsx")],[d.join(r,"src/trpc/query-client.ts"),d.join(e,"src/trpc/query-client.ts")])}else{u({dependencies:["@trpc/next"],devMode:!1,projectDir:e});let z=d.join(r,"src/utils/api.ts"),X=d.join(e,"src/utils/api.ts");Q.push([z,X])}Q.forEach(([z,X])=>{yt.copySync(z,X)})};import ie from"path";import bt from"fs-extra";var ke=({projectDir:e})=>{u({projectDir:e,dependencies:["@biomejs/biome"],devMode:!0});let i=ie.join(c,"template/extras"),o=ie.join(i,"config/biome.jsonc"),t=ie.join(e,"biome.jsonc");bt.copySync(o,t),v({projectDir:e,scripts:{"check:unsafe":"biome check --write --unsafe .","check:write":"biome check --write .",check:"biome check ."}})};import ne from"fs";import Ae from"path";import Ie from"path";var L=e=>(e.length>1&&e.endsWith("/")&&(e=e.slice(0,-1)),e);var q=e=>{let o=L(e).split("/"),t=o[o.length-1];if(t==="."){let a=Ie.resolve(process.cwd());t=Ie.basename(a)}let n=o.findIndex(a=>a.startsWith("@"));o.findIndex(a=>a.startsWith("@"))!==-1&&(t=o.slice(n).join("/"));let s=o.filter(a=>!a.startsWith("@")).join("/");return[t,s]};var xt=e=>e.replace(/[^a-zA-Z0-9_.-]/g,"_").toLowerCase(),je=({projectDir:e,databaseProvider:i,projectName:o})=>{let t=Ae.join(c,`template/extras/start-database/${i}.sh`),n=ne.readFileSync(t,"utf-8"),s=Ae.join(e,"start-database.sh"),[a]=o==="."?q(e):[o],r=xt(a);ne.writeFileSync(s,n.replaceAll("project1",r)),ne.chmodSync(s,"755")};import P from"path";import k from"fs-extra";var ze=({projectDir:e,packages:i,scopedAppName:o,databaseProvider:t})=>{u({projectDir:e,dependencies:["drizzle-kit"],devMode:!0}),u({projectDir:e,dependencies:["drizzle-orm",{planetscale:"@planetscale/database",mysql:"mysql2",postgres:"postgres",sqlite:"@libsql/client"}[t]],devMode:!1});let n=P.join(c,"template/extras"),s=P.join(n,`config/drizzle-config-${t==="planetscale"?"mysql":t}.ts`),a=P.join(e,"drizzle.config.ts"),r=P.join(n,"src/server/db/schema-drizzle",i?.nextAuth.inUse?`with-auth-${t}.ts`:`base-${t}.ts`),p=P.join(e,"src/server/db/schema.ts"),g=k.readFileSync(r,"utf-8");g=g.replace("project1_${name}",`${o}_\${name}`);let m=k.readFileSync(s,"utf-8");m=m.replace("project1_*",`${o}_*`);let x=P.join(n,`src/server/db/index-drizzle/with-${t}.ts`),h=P.join(e,"src/server/db/index.ts");v({projectDir:e,scripts:{"db:push":"drizzle-kit push","db:studio":"drizzle-kit studio","db:generate":"drizzle-kit generate","db:migrate":"drizzle-kit migrate"}}),k.copySync(s,a),k.mkdirSync(P.dirname(p),{recursive:!0}),k.writeFileSync(p,g),k.writeFileSync(a,m),k.copySync(x,h)};import S from"path";import se from"fs-extra";var y=()=>{let e=process.env.npm_config_user_agent;return e?e.startsWith("yarn")?"yarn":e.startsWith("pnpm")?"pnpm":e.startsWith("bun")?"bun":"npm":"npm"};var Ce=({projectDir:e,packages:i})=>{let o=["prettier","eslint","eslint-config-next","typescript-eslint","@eslint/eslintrc"];i?.tailwind.inUse&&o.push("prettier-plugin-tailwindcss"),i?.drizzle.inUse&&o.push("eslint-plugin-drizzle"),u({projectDir:e,dependencies:o,devMode:!0});let t=S.join(c,"template/extras"),n;i?.tailwind.inUse?n=S.join(t,"config/_tailwind.prettier.config.js"):n=S.join(t,"config/_prettier.config.js");let s=S.join(e,"prettier.config.js");if(se.copySync(n,s),y()==="pnpm"){let m=S.join(t,"pnpm/_npmrc");se.copySync(m,S.join(e,".npmrc"))}v({projectDir:e,scripts:{lint:"next lint","lint:fix":"next lint --fix",check:"next lint && tsc --noEmit","format:write":'prettier --write "**/*.{ts,tsx,js,jsx,mdx}" --cache',"format:check":'prettier --check "**/*.{ts,tsx,js,jsx,mdx}" --cache'}});let r=!!i?.drizzle?.inUse,p=S.join(t,r?"config/_eslint.drizzle.js":"config/_eslint.base.js"),g=S.join(e,"eslint.config.js");se.copySync(p,g)};var V=["mysql","postgres","sqlite","planetscale"],Te=(e,i)=>({nextAuth:{inUse:e.includes("nextAuth"),installer:xe},prisma:{inUse:e.includes("prisma"),installer:ve},drizzle:{inUse:e.includes("drizzle"),installer:ze},tailwind:{inUse:e.includes("tailwind"),installer:Se},trpc:{inUse:e.includes("trpc"),installer:_e},dbContainer:{inUse:["mysql","postgres"].includes(i),installer:je},envVariables:{inUse:!0,installer:ge},eslint:{inUse:e.includes("eslint"),installer:Ce},biome:{inUse:e.includes("biome"),installer:ke}});import wt from"path";import vt from"fs-extra";var T=()=>{let e=wt.join(c,"package.json");return vt.readJSONSync(e).version??"1.0.0"};var E=class extends Error{constructor(i){super(i)}};import B from"chalk";var l={error(...e){console.log(B.red(...e))},warn(...e){console.log(B.yellow(...e))},info(...e){console.log(B.cyan(...e))},success(...e){console.log(B.green(...e))}};var Pt=/^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/,Re=e=>{let i=L(e),o=i.split("/"),t=o.findIndex(s=>s.startsWith("@")),n=o[o.length-1];if(o.findIndex(s=>s.startsWith("@"))!==-1&&(n=o.slice(t).join("/")),!(i==="."||Pt.test(n??"")))return"App name must consist of only lowercase alphanumeric characters, '-', and '_'"};var Ue=e=>{if(e.startsWith(".")||e.startsWith("/"))return"Import alias can't start with '.' or '/'"};var I={appName:F,packages:["nextAuth","prisma","tailwind","trpc","eslint"],flags:{noGit:!1,noInstall:!1,default:!1,CI:!1,tailwind:!1,trpc:!1,prisma:!1,drizzle:!1,nextAuth:!1,importAlias:"~/",appRouter:!1,dbProvider:"sqlite",eslint:!1,biome:!1},databaseProvider:"sqlite"},Ee=async()=>{let e=I,i=new St().name(Z).description("A CLI for creating web applications with the t3 stack").argument("[dir]","The name of the application, as well as the name of the directory to create").option("--noGit","Explicitly tell the CLI to not initialize a new git repo in the project",!1).option("--noInstall","Explicitly tell the CLI to not run the package manager's install command",!1).option("-y, --default","Bypass the CLI and use all default options to bootstrap a new t3-app",!1).option("--CI","Boolean value if we're running in CI",!1).option("--tailwind [boolean]","Experimental: Boolean value if we should install Tailwind CSS. Must be used in conjunction with `--CI`.",t=>!!t&&t!=="false").option("--nextAuth [boolean]","Experimental: Boolean value if we should install NextAuth.js. Must be used in conjunction with `--CI`.",t=>!!t&&t!=="false").option("--prisma [boolean]","Experimental: Boolean value if we should install Prisma. Must be used in conjunction with `--CI`.",t=>!!t&&t!=="false").option("--drizzle [boolean]","Experimental: Boolean value if we should install Drizzle. Must be used in conjunction with `--CI`.",t=>!!t&&t!=="false").option("--trpc [boolean]","Experimental: Boolean value if we should install tRPC. Must be used in conjunction with `--CI`.",t=>!!t&&t!=="false").option("-i, --import-alias","Explicitly tell the CLI to use a custom import alias",I.flags.importAlias).option("--dbProvider [provider]",`Choose a database provider to use. Possible values: ${V.join(", ")}`,I.flags.dbProvider).option("--appRouter [boolean]","Explicitly tell the CLI to use the new Next.js app router",t=>!!t&&t!=="false").option("--eslint [boolean]","Experimental: Boolean value if we should install eslint and prettier. Must be used in conjunction with `--CI`.",t=>!!t&&t!=="false").option("--biome [boolean]","Experimental: Boolean value if we should install biome. Must be used in conjunction with `--CI`.",t=>!!t&&t!=="false").version(T(),"-v, --version","Display the version number").addHelpText("afterAll",`
The t3 stack was inspired by ${oe.hex("#E8DCFF").bold("@t3dotgg")} and has been used to build awesome fullstack applications like ${oe.hex("#E24A8D").underline("https://ping.gg")}
`).parse(process.argv);process.env.npm_config_user_agent?.startsWith("yarn/3")&&l.warn(` WARNING: It looks like you are using Yarn 3. This is currently not supported,
and likely to result in a crash. Please run create-t3-app with another
package manager such as pnpm, npm, or Yarn Classic.
See: https://github.com/t3-oss/create-t3-app/issues/57`);let o=i.args[0];if(o&&(e.appName=o),e.flags=i.opts(),e.flags.CI)return e.packages=[],e.flags.trpc&&e.packages.push("trpc"),e.flags.tailwind&&e.packages.push("tailwind"),e.flags.prisma&&e.packages.push("prisma"),e.flags.drizzle&&e.packages.push("drizzle"),e.flags.nextAuth&&e.packages.push("nextAuth"),e.flags.eslint&&e.packages.push("eslint"),e.flags.biome&&e.packages.push("biome"),e.flags.prisma&&e.flags.drizzle&&(l.warn("Incompatible combination Prisma + Drizzle. Exiting."),process.exit(0)),e.flags.biome&&e.flags.eslint&&(l.warn("Incompatible combination Biome + ESLint. Exiting."),process.exit(0)),V.includes(e.flags.dbProvider)===!1&&(l.warn(`Incompatible database provided. Use: ${V.join(", ")}. Exiting.`),process.exit(0)),e.databaseProvider=e.packages.includes("drizzle")||e.packages.includes("prisma")?e.flags.dbProvider:"sqlite",e;if(e.flags.default)return e;try{if(process.env.TERM_PROGRAM?.toLowerCase().includes("mintty"))throw l.warn(` WARNING: It looks like you are using MinTTY, which is non-interactive. This is most likely because you are
using Git Bash. If that's that case, please use Git Bash from another terminal, such as Windows Terminal. Alternatively, you
can provide the arguments from the CLI directly: https://create.t3.gg/en/installation#experimental-usage to skip the prompts.`),new E("Non-interactive environment");let t=y(),n=await f.group({...!o&&{name:()=>f.text({message:"What will your project be called?",defaultValue:o,validate:Re})},language:()=>f.select({message:"Will you be using TypeScript or JavaScript?",options:[{value:"typescript",label:"TypeScript"},{value:"javascript",label:"JavaScript"}],initialValue:"typescript"}),_:({results:a})=>a.language==="javascript"?f.note(oe.redBright("Wrong answer, using TypeScript instead")):void 0,styling:()=>f.confirm({message:"Will you be using Tailwind CSS for styling?"}),trpc:()=>f.confirm({message:"Would you like to use tRPC?"}),authentication:()=>f.select({message:"What authentication provider would you like to use?",options:[{value:"none",label:"None"},{value:"next-auth",label:"NextAuth.js"}],initialValue:"none"}),database:()=>f.select({message:"What database ORM would you like to use?",options:[{value:"none",label:"None"},{value:"prisma",label:"Prisma"},{value:"drizzle",label:"Drizzle"}],initialValue:"none"}),appRouter:()=>f.confirm({message:"Would you like to use Next.js App Router?",initialValue:!0}),databaseProvider:({results:a})=>{if(a.database!=="none")return f.select({message:"What database provider would you like to use?",options:[{value:"sqlite",label:"SQLite (LibSQL)"},{value:"mysql",label:"MySQL"},{value:"postgres",label:"PostgreSQL"},{value:"planetscale",label:"PlanetScale"}],initialValue:"sqlite"})},linter:()=>f.select({message:"Would you like to use ESLint and Prettier or Biome for linting and formatting?",options:[{value:"eslint",label:"ESLint/Prettier"},{value:"biome",label:"Biome"}],initialValue:"eslint"}),...!e.flags.noGit&&{git:()=>f.confirm({message:"Should we initialize a Git repository and stage the changes?",initialValue:!I.flags.noGit})},...!e.flags.noInstall&&{install:()=>f.confirm({message:`Should we run '${t}`+(t==="yarn"?"'?":" install' for you?"),initialValue:!I.flags.noInstall})},importAlias:()=>f.text({message:"What import alias would you like to use?",defaultValue:I.flags.importAlias,placeholder:I.flags.importAlias,validate:Ue})},{onCancel(){process.exit(1)}}),s=[];return n.styling&&s.push("tailwind"),n.trpc&&s.push("trpc"),n.authentication==="next-auth"&&s.push("nextAuth"),n.database==="prisma"&&s.push("prisma"),n.database==="drizzle"&&s.push("drizzle"),n.linter==="eslint"&&s.push("eslint"),n.linter==="biome"&&s.push("biome"),{appName:n.name??e.appName,packages:s,databaseProvider:n.databaseProvider||"sqlite",flags:{...e.flags,appRouter:n.appRouter??e.flags.appRouter,noGit:!n.git||e.flags.noGit,noInstall:!n.install||e.flags.noInstall,importAlias:n.importAlias??e.flags.importAlias}}}catch(t){if(t instanceof E)l.warn(`
${Z} needs an interactive terminal to provide options`),await f.confirm({message:"Continue scaffolding a default T3 app?",initialValue:!0})||(l.info("Exiting..."),process.exit(0)),l.info(`Bootstrapping a default T3 app in ./${e.appName}`);else throw t}return e};import Le from"fs";import M from"path";import De from"chalk";import _t from"ora";var Me=e=>{let{packages:i}=e;l.info("Adding boilerplate...");for(let[o,t]of Object.entries(i))if(t.inUse){let n=_t(`Boilerplating ${o}...`).start();t.installer(e),n.succeed(De.green(`Successfully setup boilerplate for ${De.green.bold(o)}`))}l.info("")};import ae from"path";import*as j from"@clack/prompts";import A from"chalk";import D from"fs-extra";import kt from"ora";var Oe=async({projectName:e,projectDir:i,pkgManager:o,noInstall:t})=>{let n=ae.join(c,"template/base");t?l.info(""):l.info(`
Using: ${A.cyan.bold(o)}
`);let s=kt(`Scaffolding in: ${i}...
`).start();if(D.existsSync(i))if(D.readdirSync(i).length===0)e!=="."&&s.info(`${A.cyan.bold(e)} exists but is empty, continuing...
`);else{s.stopAndPersist();let r=await j.select({message:`${A.redBright.bold("Warning:")} ${A.cyan.bold(e)} already exists and isn't empty. How would you like to proceed?`,options:[{label:"Abort installation (recommended)",value:"abort"},{label:"Clear the directory and continue installation",value:"clear"},{label:"Continue installation and overwrite conflicting files",value:"overwrite"}],initialValue:"abort"});(j.isCancel(r)||r==="abort")&&(s.fail("Aborting installation..."),process.exit(1));let p=await j.confirm({message:`Are you sure you want to ${r==="clear"?"clear the directory":"overwrite conflicting files"}?`,initialValue:!1});(j.isCancel(p)||!p)&&(s.fail("Aborting installation..."),process.exit(1)),r==="clear"&&(s.info(`Emptying ${A.cyan.bold(e)} and creating t3 app..
`),D.emptyDirSync(i))}s.start(),D.copySync(n,i),D.renameSync(ae.join(i,"_gitignore"),ae.join(i,".gitignore"));let a=e==="."?"App":A.cyan.bold(e);s.succeed(`${a} ${A.green("scaffolded successfully!")}
`)};import b from"path";import W from"fs-extra";var $e=({projectDir:e,packages:i})=>{let o=b.join(c,"template/extras/src/pages/_app"),t=i.tailwind.inUse,n=i.trpc.inUse,s=i.nextAuth.inUse,a="base.tsx";n&&t&&s?a="with-auth-trpc-tw.tsx":n&&!t&&s?a="with-auth-trpc.tsx":n&&t?a="with-trpc-tw.tsx":n&&!t?a="with-trpc.tsx":!n&&t?a="with-tw.tsx":s&&t?a="with-auth-tw.tsx":s&&!t&&(a="with-auth.tsx");let r=b.join(o,a),p=b.join(e,"src/pages/_app.tsx");W.copySync(r,p)},Fe=({projectDir:e,packages:i})=>{let o=b.join(c,"template/extras/src/app/layout"),t=i.tailwind.inUse,n=i.trpc.inUse,s="base.tsx";n&&t?s="with-trpc-tw.tsx":n&&!t?s="with-trpc.tsx":!n&&t&&(s="with-tw.tsx");let a=b.join(o,s),r=b.join(e,"src/app/layout.tsx");W.copySync(a,r)},Ne=({projectDir:e,packages:i})=>{let o=b.join(c,"template/extras/src/pages/index"),t=i.trpc.inUse,n=i.tailwind.inUse,s=i.nextAuth.inUse,a="base.tsx";t&&n&&s?a="with-auth-trpc-tw.tsx":t&&!n&&s?a="with-auth-trpc.tsx":t&&n?a="with-trpc-tw.tsx":t&&!n?a="with-trpc.tsx":!t&&n&&(a="with-tw.tsx");let r=b.join(o,a),p=b.join(e,"src/pages/index.tsx");W.copySync(r,p)},Ge=({projectDir:e,packages:i})=>{let o=b.join(c,"template/extras/src/app/page"),t=i.trpc.inUse,n=i.tailwind.inUse,s=i.nextAuth.inUse,a="base.tsx";t&&n&&s?a="with-auth-trpc-tw.tsx":t&&!n&&s?a="with-auth-trpc.tsx":t&&n?a="with-trpc-tw.tsx":t&&!n?a="with-trpc.tsx":!t&&n&&(a="with-tw.tsx");let r=b.join(o,a),p=b.join(e,"src/app/page.tsx");W.copySync(r,p)};var qe=async({projectName:e,scopedAppName:i,packages:o,noInstall:t,appRouter:n,databaseProvider:s})=>{let a=y(),r=M.resolve(process.cwd(),e);if(await Oe({projectName:e,projectDir:r,pkgManager:a,scopedAppName:i,noInstall:t,appRouter:n,databaseProvider:s}),Me({projectName:e,scopedAppName:i,projectDir:r,pkgManager:a,packages:o,noInstall:t,appRouter:n,databaseProvider:s}),n?(Le.copyFileSync(M.join(c,"template/extras/config/next-config-appdir.js"),M.join(r,"next.config.js")),Fe({projectDir:r,packages:o}),Ge({projectDir:r,packages:o})):($e({projectDir:r,packages:o}),Ne({projectDir:r,packages:o})),!o.tailwind.inUse){let p=M.join(c,"template/extras/src/index.module.css"),g=M.join(r,"src",n?"app":"pages","index.module.css");Le.copyFileSync(p,g)}return r};import{execSync as ce}from"child_process";import re from"path";import*as le from"@clack/prompts";import O from"chalk";import{execa as $}from"execa";import Ve from"fs-extra";import It from"ora";var At=e=>{try{return ce("git --version",{cwd:e}),!0}catch{return!1}},pe=e=>Ve.existsSync(re.join(e,".git")),me=async e=>{try{return await $("git",["rev-parse","--is-inside-work-tree"],{cwd:e,stdout:"ignore"}),!0}catch{return!1}},jt=()=>{let i=ce("git --version").toString().trim().split(" ")[2],o=i?.split(".")[0],t=i?.split(".")[1];return{major:Number(o),minor:Number(t)}},zt=()=>ce("git config --global init.defaultBranch || echo main").toString().trim(),Be=async e=>{if(l.info("Initializing Git..."),!At(e)){l.warn("Git is not installed. Skipping Git initialization.");return}let i=It(`Creating a new git repo...
`).start(),o=pe(e),t=await me(e),n=re.parse(e).name;if(t&&o){if(i.stop(),!await le.confirm({message:`${O.redBright.bold("Warning:")} Git is already initialized in "${n}". Initializing a new git repository would delete the previous history. Would you like to continue anyways?`,initialValue:!1})){i.info("Skipping Git initialization.");return}Ve.removeSync(re.join(e,".git"))}else if(t&&!o&&(i.stop(),!await le.confirm({message:`${O.redBright.bold("Warning:")} "${n}" is already in a git worktree. Would you still like to initialize a new git repository in this directory?`,initialValue:!1}))){i.info("Skipping Git initialization.");return}try{let s=zt(),{major:a,minor:r}=jt();a<2||a==2&&r<28?(await $("git",["init"],{cwd:e}),await $("git",["symbolic-ref","HEAD",`refs/heads/${s}`],{cwd:e})):await $("git",["init",`--initial-branch=${s}`],{cwd:e}),await $("git",["add","."],{cwd:e}),i.succeed(`${O.green("Successfully initialized and staged")} ${O.green.bold("git")}
`)}catch{i.fail(`${O.bold.red("Failed:")} could not initialize git. Update git to the latest version!
`)}};var We=async({projectName:e=F,packages:i,noInstall:o,projectDir:t,databaseProvider:n})=>{let s=y();l.info("Next steps:"),e!=="."&&l.info(` cd ${e}`),o&&(s==="yarn"?l.info(` ${s}`):l.info(` ${s} install`)),["postgres","mysql"].includes(n)&&l.info(" Start up a database, if needed using './start-database.sh'"),(i?.prisma.inUse||i?.drizzle.inUse)&&(["npm","bun"].includes(s)?l.info(` ${s} run db:push`):l.info(` ${s} db:push`)),i?.nextAuth.inUse&&l.info(" Fill in your .env with necessary values. See https://create.t3.gg/en/usage/first-steps for more info."),["npm","bun"].includes(s)?l.info(` ${s} run dev`):l.info(` ${s} dev`),!await me(t)&&!pe(t)&&l.info(" git init"),l.info(' git commit -m "initial commit"')};import J from"fs";import Ct from"path";function Je(e,i,o){J.readdirSync(e).forEach(n=>{let s=Ct.join(e,n);if(J.statSync(s).isDirectory())Je(s,i,o);else{let r=J.readFileSync(s,"utf8").replace(new RegExp(i,"g"),o);J.writeFileSync(s,r,"utf8")}})}var He=(e,i)=>{let o=i.replace(/\*/g,"").replace(/[^/]$/,"$&/");Je(e,"~/",o)};import Tt from"gradient-string";var Rt={blue:"#add7ff",cyan:"#89ddff",green:"#5de4c7",magenta:"#fae4fc",red:"#d0679d",yellow:"#fffac2"},Ke=()=>{let e=Tt(Object.values(Rt)),i=y();(i==="yarn"||i==="pnpm")&&console.log(""),console.log(e.multiline(ue))};import Ut from"chalk";import{execa as Ye}from"execa";import Et from"ora";var Qe=async({pkgManager:e,projectDir:i,eslint:o,biome:t})=>{l.info(`Formatting project with ${o?"eslint":"biome"}...`);let n=Et(`Running format command
`).start();o?await Ye(e,["run","format:write"],{cwd:i}):t&&await Ye(e,["run","check:unsafe"],{cwd:i}),n.succeed(`${Ut.green("Successfully formatted project")}`)};import Dt from"chalk";import{execa as Xe}from"execa";import Ze from"ora";var de=async(e,i,o)=>{let{onDataHandle:t,args:n=["install"],stdout:s="pipe"}=o,a=Ze(`Running ${i} install...`).start(),r=Xe(i,n,{cwd:e,stdout:s});return await new Promise((p,g)=>{t&&r.stdout?.on("data",t(a)),r.on("error",m=>g(m)),r.on("close",()=>p())}),a},Mt=async(e,i)=>{switch(e){case"npm":return await Xe(e,["install"],{cwd:i,stderr:"inherit"}),null;case"pnpm":return de(i,e,{onDataHandle:o=>t=>{let n=t.toString();n.includes("Progress")&&(o.text=n.includes("|")?n.split(" | ")[1]??"":n)}});case"yarn":return de(i,e,{onDataHandle:o=>t=>{o.text=t.toString()}});case"bun":return de(i,e,{stdout:"ignore"})}},et=async({projectDir:e})=>{l.info("Installing dependencies...");let i=y();(await Mt(i,e)??Ze()).succeed(Dt.green(`Successfully installed dependencies!
`))};import{execSync as Ot}from"child_process";import $t from"https";var tt=e=>{let i=T();i.includes("beta")?(l.warn(" You are using a beta version of create-t3-app."),l.warn(" Please report any bugs you encounter.")):i.includes("next")?(l.warn(" You are running create-t3-app with the @next tag which is no longer maintained."),l.warn(" Please run the CLI with @latest instead.")):i!==e&&(l.warn(" You are using an outdated version of create-t3-app."),l.warn(" Your version:",i+".","Latest version in the npm registry:",e),l.warn(" Please run the CLI with @latest to get the latest updates.")),console.log("")};function Ft(){return new Promise((e,i)=>{$t.get("https://registry.npmjs.org/-/package/create-t3-app/dist-tags",o=>{if(o.statusCode===200){let t="";o.on("data",n=>t+=n),o.on("end",()=>{e(JSON.parse(t).latest)})}else i()}).on("error",()=>{i()})})}var it=()=>Ft().catch(()=>{try{return Ot("npm view create-t3-app version").toString().trim()}catch{return null}});var Gt=async()=>{let e=await it(),i=y();Ke(),e&&tt(e);let{appName:o,packages:t,flags:{noGit:n,noInstall:s,importAlias:a,appRouter:r},databaseProvider:p}=await Ee(),g=Te(t,p),[m,x]=q(o),h=await qe({projectName:x,scopedAppName:m,packages:g,databaseProvider:p,importAlias:a,noInstall:s,appRouter:r}),w=st.readJSONSync(nt.join(h,"package.json"));if(w.name=m,w.ct3aMetadata={initVersion:T()},i!=="bun"){let{stdout:R}=await Nt(i,["-v"],{cwd:h});w.packageManager=`${i}@${R.trim()}`}st.writeJSONSync(nt.join(h,"package.json"),w,{spaces:2}),a!=="~/"&&He(h,a),s||(await et({projectDir:h}),await Qe({pkgManager:i,projectDir:h,eslint:t.includes("eslint"),biome:t.includes("biome")})),n||await Be(h),await We({projectName:x,packages:g,appRouter:r,noInstall:s,projectDir:h,databaseProvider:p}),process.exit(0)};Gt().catch(e=>{l.error("Aborting installation..."),e instanceof Error?l.error(e):(l.error("An unknown error has occurred. Please open an issue on github with the below:"),console.log(e)),process.exit(1)});