create-better-t-stack 2.0.10 → 2.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/templates/extras/_npmrc +1 -0
package/dist/index.js
CHANGED
|
@@ -197,7 +197,7 @@ ${y.cyan("\u2022")} Build docs site: ${`cd apps/docs && ${e} build`}
|
|
|
197
197
|
${y.yellow("WARNING:")} Database selected without an ORM. Features requiring database access (e.g., examples, auth) need manual setup.
|
|
198
198
|
`}function Na(){return`
|
|
199
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(`
|
|
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
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=`
|
|
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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.11",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
node-linker=hoisted
|