create-better-t-stack 2.8.2 → 2.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import e from"node:path";import{cancel as t,confirm as n,group as r,intro as i,isCancel as a,log as o,multiselect as s,outro as c,password as l,select as u,spinner as d,text as f}from"@clack/prompts";import p,{consola as m}from"consola";import h from"fs-extra";import g from"picocolors";import _ from"yargs";import{hideBin as v}from"yargs/helpers";import{fileURLToPath as y}from"node:url";import{$ as b,execa as x}from"execa";import S from"node:os";import{globby as C}from"globby";import w from"handlebars";import T from"gradient-string";const E=()=>{let e=process.env.npm_config_user_agent;return e?.startsWith(`pnpm`)?`pnpm`:e?.startsWith(`bun`)?`bun`:`npm`},D=y(import.meta.url),O=e.dirname(D),k=e.join(O,`../`),A={projectName:`my-better-t-app`,projectDir:e.resolve(process.cwd(),`my-better-t-app`),relativePath:`my-better-t-app`,frontend:[`tanstack-router`],database:`sqlite`,orm:`drizzle`,auth:!0,addons:[],examples:[],git:!0,packageManager:E(),install:!0,dbSetup:`none`,backend:`hono`,runtime:`bun`,api:`trpc`},j={"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.7.0`,prisma:`^6.7.0`,mongoose:`^8.14.0`,"vite-plugin-pwa":`^0.21.2`,"@vite-pwa/assets-generator":`^0.2.6`,"@tauri-apps/cli":`^2.4.0`,"@biomejs/biome":`1.9.4`,husky:`^9.1.7`,"lint-staged":`^15.5.0`,"@hono/node-server":`^1.14.0`,tsx:`^4.19.2`,"@types/node":`^22.13.11`,"@types/bun":`^1.2.6`,"@elysiajs/node":`^1.2.6`,"@elysiajs/cors":`^1.2.0`,"@elysiajs/trpc":`^1.1.0`,elysia:`^1.2.25`,"@hono/trpc-server":`^0.3.4`,hono:`^4.7.6`,cors:`^2.8.5`,express:`^5.1.0`,"@types/express":`^5.0.1`,"@types/cors":`^2.8.17`,turbo:`^2.4.2`,ai:`^4.2.8`,"@ai-sdk/google":`^1.2.3`,"@ai-sdk/vue":`^1.2.8`,"@ai-sdk/svelte":`^2.1.9`,"@prisma/extension-accelerate":`^1.3.0`,"@orpc/server":`^1.1.1`,"@orpc/client":`^1.1.1`,"@orpc/react-query":`^1.1.1`,"@orpc/solid-query":`^1.1.1`,"@orpc/vue-query":`^1.1.1`,"@orpc/svelte-query":`^1.1.1`,"@trpc/tanstack-react-query":`^11.0.0`,"@trpc/server":`^11.0.0`,"@trpc/client":`^11.0.0`,convex:`^1.23.0`,"@convex-dev/react-query":`^0.0.0-alpha.8`,"convex-svelte":`^0.0.11`,"@tanstack/svelte-query":`^5.74.4`,"@tanstack/react-query-devtools":`^5.69.0`,"@tanstack/react-query":`^5.69.0`,"@tanstack/solid-query":`^5.75.0`,"@tanstack/solid-query-devtools":`^5.75.0`},M=async t=>{let{dependencies:n=[],devDependencies:r=[],projectDir:i}=t,a=e.join(i,`package.json`),o=await h.readJson(a);o.dependencies||={},o.devDependencies||={};for(let e of n){let t=j[e];t?o.dependencies[e]=t:console.warn(`Warning: Dependency ${e} not found in version map.`)}for(let e of r){let t=j[e];t?o.devDependencies[e]=t:console.warn(`Warning: Dev dependency ${e} not found in version map.`)}await h.writeJson(a,o,{spaces:2})};function N(e,t){switch(e){case`pnpm`:return`pnpm dlx ${t}`;case`bun`:return`bunx ${t}`;default:return`npx ${t}`}}async function ee(t){let{projectName:n,packageManager:r,projectDir:i}=t,a=d();try{a.start(`Setting up Starlight docs...`);let t=[`docs`,`--template`,`starlight`,`--no-install`,`--add`,`tailwind`,`--no-git`,`--skip-houston`],n=t.join(` `),o=`create-astro@latest ${n}`,s=N(r,o);await x(s,{cwd:e.join(i,`apps`),env:{CI:`true`},shell:!0}),a.stop(`Starlight docs setup successfully!`)}catch(e){a.stop(g.red(`Failed to set up Starlight docs`)),e instanceof Error&&p.error(g.red(e.message))}}async function te(t){let{projectName:n,packageManager:r,frontend:i,projectDir:a}=t,o=d(),s=e.join(a,`apps/web`);if(await h.pathExists(s))try{o.start(`Setting up Tauri desktop app support...`),await M({devDependencies:[`@tauri-apps/cli`],projectDir:s});let t=e.join(s,`package.json`);if(await h.pathExists(t)){let e=await h.readJson(t);e.scripts={...e.scripts,tauri:`tauri`,"desktop:dev":`tauri dev`,"desktop:build":`tauri build`},await h.writeJson(t,e,{spaces:2})}let n=i.includes(`tanstack-router`),c=i.includes(`react-router`),l=i.includes(`nuxt`),u=i.includes(`svelte`),d=i.includes(`solid`),f=c||u?`http://localhost:5173`:`http://localhost:3001`,p=l?`../.output/public`:u?`../build`:`../dist`,m=[`init`,`--app-name=${e.basename(a)}`,`--window-title=${e.basename(a)}`,`--frontend-dist=${p}`,`--dev-url=${f}`,`--before-dev-command=\"${r} run dev\"`,`--before-build-command=\"${r} run build\"`],g=m.join(` `),_=`@tauri-apps/cli@latest ${g}`,v=N(r,_);await x(v,{cwd:s,env:{CI:`true`},shell:!0}),o.stop(`Tauri desktop app support configured successfully!`)}catch(e){o.stop(g.red(`Failed to set up Tauri`)),e instanceof Error&&m.error(g.red(e.message))}}async function ne(e){let{projectName:t,addons:n,frontend:r,projectDir:i}=e,a=r.includes(`react-router`)||r.includes(`tanstack-router`),o=r.includes(`nuxt`),s=r.includes(`svelte`),c=r.includes(`solid`);n.includes(`turborepo`)&&await M({devDependencies:[`turbo`],projectDir:i}),n.includes(`pwa`)&&(a||c)&&await oe(i,r),n.includes(`tauri`)&&(a||o||s||c)&&await te(e),n.includes(`biome`)&&await ie(i),n.includes(`husky`)&&await ae(i),n.includes(`starlight`)&&await ee(e)}function re(t,n){return n.some(e=>[`react-router`,`tanstack-router`,`nuxt`,`svelte`,`solid`].includes(e)),e.join(t,`apps/web`)}async function ie(t){await M({devDependencies:[`@biomejs/biome`],projectDir:t});let n=e.join(t,`package.json`);if(await h.pathExists(n)){let e=await h.readJson(n);e.scripts={...e.scripts,check:`biome check --write .`},await h.writeJson(n,e,{spaces:2})}}async function ae(t){await M({devDependencies:[`husky`,`lint-staged`],projectDir:t});let n=e.join(t,`package.json`);if(await h.pathExists(n)){let e=await h.readJson(n);e.scripts={...e.scripts,prepare:`husky`},e[`lint-staged`]={"*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}":[`biome check --write .`]},await h.writeJson(n,e,{spaces:2})}}async function oe(t,n){let r=n.some(e=>[`react-router`,`tanstack-router`,`solid`].includes(e));if(!r)return;let i=re(t,n);if(!await h.pathExists(i))return;await M({dependencies:[`vite-plugin-pwa`],devDependencies:[`@vite-pwa/assets-generator`],projectDir:i});let a=e.join(i,`package.json`);if(await h.pathExists(a)){let e=await h.readJson(a);e.scripts={...e.scripts,"generate-pwa-assets":`pwa-assets-generator`},await h.writeJson(a,e,{spaces:2})}}async function se(t){let{api:n,projectName:r,frontend:i,backend:a,packageManager:o,projectDir:s}=t,c=a===`convex`,l=e.join(s,`apps/web`),u=e.join(s,`apps/native`),d=await h.pathExists(l),f=await h.pathExists(u),p=i.some(e=>[`tanstack-router`,`react-router`,`tanstack-start`,`next`].includes(e)),m=i.includes(`nuxt`),g=i.includes(`svelte`),_=i.includes(`solid`);if(!c&&n!==`none`){let r=e.join(s,`apps/server`),i=await h.pathExists(r);i&&(n===`orpc`?await M({dependencies:[`@orpc/server`,`@orpc/client`],projectDir:r}):n===`trpc`&&(await M({dependencies:[`@trpc/server`,`@trpc/client`],projectDir:r}),t.backend===`hono`?await M({dependencies:[`@hono/trpc-server`],projectDir:r}):t.backend===`elysia`&&await M({dependencies:[`@elysiajs/trpc`],projectDir:r}))),d&&(p?n===`orpc`?await M({dependencies:[`@orpc/react-query`,`@orpc/client`,`@orpc/server`],projectDir:l}):n===`trpc`&&await M({dependencies:[`@trpc/tanstack-react-query`,`@trpc/client`,`@trpc/server`],projectDir:l}):m?n===`orpc`&&await M({dependencies:[`@orpc/vue-query`,`@orpc/client`,`@orpc/server`],projectDir:l}):g?n===`orpc`&&await M({dependencies:[`@orpc/svelte-query`,`@orpc/client`,`@orpc/server`,`@tanstack/svelte-query`],projectDir:l}):_&&n===`orpc`&&await M({dependencies:[`@orpc/solid-query`,`@orpc/client`,`@orpc/server`,`@tanstack/solid-query`],projectDir:l})),f&&(n===`trpc`?await M({dependencies:[`@trpc/tanstack-react-query`,`@trpc/client`,`@trpc/server`],projectDir:u}):n===`orpc`&&await M({dependencies:[`@orpc/react-query`,`@orpc/client`,`@orpc/server`],projectDir:u}))}let v=[`react-router`,`tanstack-router`,`tanstack-start`,`next`,`native`],y=i.includes(`solid`),b=i.some(e=>v.includes(e));if(b&&!c){let t=[`@tanstack/react-query`],n=[`@tanstack/react-query-devtools`],r=i.some(e=>e!==`native`&&v.includes(e)),a=i.includes(`native`);if(r&&d){let r=e.join(l,`package.json`);if(await h.pathExists(r))try{await M({dependencies:t,devDependencies:n,projectDir:l})}catch{}}if(a&&f){let n=e.join(u,`package.json`);if(await h.pathExists(n))try{await M({dependencies:t,projectDir:u})}catch{}}}if(y&&!c){let t=[`@tanstack/solid-query`],n=[`@tanstack/solid-query-devtools`];if(d){let r=e.join(l,`package.json`);if(await h.pathExists(r))try{await M({dependencies:t,devDependencies:n,projectDir:l})}catch{}}}if(c){if(d){let t=e.join(l,`package.json`);if(await h.pathExists(t))try{let e=[`convex`];i.includes(`tanstack-start`)&&e.push(`@convex-dev/react-query`),g&&e.push(`convex-svelte`),await M({dependencies:e,projectDir:l})}catch{}}if(f){let t=e.join(u,`package.json`);if(await h.pathExists(t))try{await M({dependencies:[`convex`],projectDir:u})}catch{}}let t=`@${r}/backend`,n=o===`npm`?`*`:`workspace:*`,a=async(e,t,n)=>{try{let r=await h.readJson(e);r.dependencies||={},r.dependencies[t]!==n&&(r.dependencies[t]=n,await h.writeJson(e,r,{spaces:2}))}catch{}};if(d){let r=e.join(l,`package.json`);await h.pathExists(r)&&await a(r,t,n)}if(f){let r=e.join(u,`package.json`);await h.pathExists(r)&&await a(r,t,n)}}}async function ce(t){let{projectName:n,auth:r,frontend:i,backend:a,projectDir:o}=t;if(a===`convex`||!r)return;let s=e.join(o,`apps/server`),c=e.join(o,`apps/web`),l=e.join(o,`apps/native`),u=await h.pathExists(c),d=await h.pathExists(l),f=await h.pathExists(s);try{f&&await M({dependencies:[`better-auth`],projectDir:s});let e=i.some(e=>[`react-router`,`tanstack-router`,`tanstack-start`,`next`,`nuxt`,`svelte`].includes(e));e&&u&&await M({dependencies:[`better-auth`],projectDir:c}),i.includes(`native`)&&d&&(await M({dependencies:[`better-auth`,`@better-auth/expo`],projectDir:l}),f&&await M({dependencies:[`@better-auth/expo`],projectDir:s}))}catch(e){p.error(g.red(`Failed to configure authentication dependencies`)),e instanceof Error&&p.error(g.red(e.message))}}function le(e=32){let t=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`,n=``,r=t.length;for(let i=0;i<e;i++)n+=t.charAt(Math.floor(Math.random()*r));return n}async function ue(t){let{projectName:n,backend:r,runtime:i,api:a,projectDir:o}=t;if(r===`convex`)return;let s=r,c=e.join(o,`apps/server`),l=[],u=[];s===`hono`?(l.push(`hono`),a===`trpc`&&l.push(`@hono/trpc-server`),i===`node`&&(l.push(`@hono/node-server`),u.push(`tsx`,`@types/node`))):s===`elysia`?(l.push(`elysia`,`@elysiajs/cors`),a===`trpc`&&l.push(`@elysiajs/trpc`),i===`node`&&(l.push(`@elysiajs/node`),u.push(`tsx`,`@types/node`))):s===`express`&&(l.push(`express`,`cors`),u.push(`@types/express`,`@types/cors`),i===`node`&&u.push(`tsx`,`@types/node`)),i===`bun`&&u.push(`@types/bun`),(l.length>0||u.length>0)&&await M({dependencies:l,devDependencies:u,projectDir:c})}async function de(t,n){let r=e.join(t,`README.md`),i=fe(n);try{await h.writeFile(r,i)}catch(e){p.error(`Failed to create README.md file:`,e)}}function fe(e){let{projectName:t,packageManager:n,database:r,auth:i,addons:a=[],orm:o=`drizzle`,runtime:s=`bun`,frontend:c=[`tanstack-router`],backend:l=`hono`,api:u=`trpc`}=e,d=l===`convex`,f=c.includes(`react-router`),p=c.includes(`tanstack-router`),m=c.includes(`native`),h=c.includes(`next`),g=c.includes(`tanstack-start`),_=c.includes(`svelte`),v=c.includes(`solid`),y=c.includes(`nuxt`),b=n===`npm`?`npm run`:n,x=`3001`;return(f||_)&&(x=`5173`),`# ${t}
|
|
2
|
+
import e from"node:path";import{cancel as t,confirm as n,group as r,intro as i,isCancel as a,log as o,multiselect as s,outro as c,password as l,select as u,spinner as d,text as f}from"@clack/prompts";import p,{consola as m}from"consola";import h from"fs-extra";import g from"picocolors";import _ from"yargs";import{hideBin as v}from"yargs/helpers";import{fileURLToPath as y}from"node:url";import{$ as b,execa as x}from"execa";import S from"node:os";import{globby as C}from"globby";import w from"handlebars";import T from"gradient-string";const E=()=>{let e=process.env.npm_config_user_agent;return e?.startsWith(`pnpm`)?`pnpm`:e?.startsWith(`bun`)?`bun`:`npm`},D=y(import.meta.url),O=e.dirname(D),k=e.join(O,`../`),A={projectName:`my-better-t-app`,projectDir:e.resolve(process.cwd(),`my-better-t-app`),relativePath:`my-better-t-app`,frontend:[`tanstack-router`],database:`sqlite`,orm:`drizzle`,auth:!0,addons:[],examples:[],git:!0,packageManager:E(),install:!0,dbSetup:`none`,backend:`hono`,runtime:`bun`,api:`trpc`},j={"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.7.0`,prisma:`^6.7.0`,mongoose:`^8.14.0`,"vite-plugin-pwa":`^0.21.2`,"@vite-pwa/assets-generator":`^0.2.6`,"@tauri-apps/cli":`^2.4.0`,"@biomejs/biome":`1.9.4`,husky:`^9.1.7`,"lint-staged":`^15.5.0`,"@hono/node-server":`^1.14.0`,tsx:`^4.19.2`,"@types/node":`^22.13.11`,"@types/bun":`^1.2.6`,"@elysiajs/node":`^1.2.6`,"@elysiajs/cors":`^1.2.0`,"@elysiajs/trpc":`^1.1.0`,elysia:`^1.2.25`,"@hono/trpc-server":`^0.3.4`,hono:`^4.7.6`,cors:`^2.8.5`,express:`^5.1.0`,"@types/express":`^5.0.1`,"@types/cors":`^2.8.17`,turbo:`^2.4.2`,ai:`^4.2.8`,"@ai-sdk/google":`^1.2.3`,"@ai-sdk/vue":`^1.2.8`,"@ai-sdk/svelte":`^2.1.9`,"@prisma/extension-accelerate":`^1.3.0`,"@orpc/server":`^1.2.0`,"@orpc/client":`^1.2.0`,"@orpc/react-query":`^1.2.0`,"@orpc/solid-query":`^1.2.0`,"@orpc/vue-query":`^1.2.0`,"@orpc/svelte-query":`^1.2.0`,"@trpc/tanstack-react-query":`^11.0.0`,"@trpc/server":`^11.0.0`,"@trpc/client":`^11.0.0`,convex:`^1.23.0`,"@convex-dev/react-query":`^0.0.0-alpha.8`,"convex-svelte":`^0.0.11`,"@tanstack/svelte-query":`^5.74.4`,"@tanstack/react-query-devtools":`^5.69.0`,"@tanstack/react-query":`^5.69.0`,"@tanstack/solid-query":`^5.75.0`,"@tanstack/solid-query-devtools":`^5.75.0`},M=async t=>{let{dependencies:n=[],devDependencies:r=[],projectDir:i}=t,a=e.join(i,`package.json`),o=await h.readJson(a);o.dependencies||={},o.devDependencies||={};for(let e of n){let t=j[e];t?o.dependencies[e]=t:console.warn(`Warning: Dependency ${e} not found in version map.`)}for(let e of r){let t=j[e];t?o.devDependencies[e]=t:console.warn(`Warning: Dev dependency ${e} not found in version map.`)}await h.writeJson(a,o,{spaces:2})};function N(e,t){switch(e){case`pnpm`:return`pnpm dlx ${t}`;case`bun`:return`bunx ${t}`;default:return`npx ${t}`}}async function ee(t){let{projectName:n,packageManager:r,projectDir:i}=t,a=d();try{a.start(`Setting up Starlight docs...`);let t=[`docs`,`--template`,`starlight`,`--no-install`,`--add`,`tailwind`,`--no-git`,`--skip-houston`],n=t.join(` `),o=`create-astro@latest ${n}`,s=N(r,o);await x(s,{cwd:e.join(i,`apps`),env:{CI:`true`},shell:!0}),a.stop(`Starlight docs setup successfully!`)}catch(e){a.stop(g.red(`Failed to set up Starlight docs`)),e instanceof Error&&p.error(g.red(e.message))}}async function te(t){let{projectName:n,packageManager:r,frontend:i,projectDir:a}=t,o=d(),s=e.join(a,`apps/web`);if(await h.pathExists(s))try{o.start(`Setting up Tauri desktop app support...`),await M({devDependencies:[`@tauri-apps/cli`],projectDir:s});let t=e.join(s,`package.json`);if(await h.pathExists(t)){let e=await h.readJson(t);e.scripts={...e.scripts,tauri:`tauri`,"desktop:dev":`tauri dev`,"desktop:build":`tauri build`},await h.writeJson(t,e,{spaces:2})}let n=i.includes(`tanstack-router`),c=i.includes(`react-router`),l=i.includes(`nuxt`),u=i.includes(`svelte`),d=i.includes(`solid`),f=c||u?`http://localhost:5173`:`http://localhost:3001`,p=l?`../.output/public`:u?`../build`:`../dist`,m=[`init`,`--app-name=${e.basename(a)}`,`--window-title=${e.basename(a)}`,`--frontend-dist=${p}`,`--dev-url=${f}`,`--before-dev-command=\"${r} run dev\"`,`--before-build-command=\"${r} run build\"`],g=m.join(` `),_=`@tauri-apps/cli@latest ${g}`,v=N(r,_);await x(v,{cwd:s,env:{CI:`true`},shell:!0}),o.stop(`Tauri desktop app support configured successfully!`)}catch(e){o.stop(g.red(`Failed to set up Tauri`)),e instanceof Error&&m.error(g.red(e.message))}}async function ne(e){let{projectName:t,addons:n,frontend:r,projectDir:i}=e,a=r.includes(`react-router`)||r.includes(`tanstack-router`),o=r.includes(`nuxt`),s=r.includes(`svelte`),c=r.includes(`solid`);n.includes(`turborepo`)&&await M({devDependencies:[`turbo`],projectDir:i}),n.includes(`pwa`)&&(a||c)&&await oe(i,r),n.includes(`tauri`)&&(a||o||s||c)&&await te(e),n.includes(`biome`)&&await ie(i),n.includes(`husky`)&&await ae(i),n.includes(`starlight`)&&await ee(e)}function re(t,n){return n.some(e=>[`react-router`,`tanstack-router`,`nuxt`,`svelte`,`solid`].includes(e)),e.join(t,`apps/web`)}async function ie(t){await M({devDependencies:[`@biomejs/biome`],projectDir:t});let n=e.join(t,`package.json`);if(await h.pathExists(n)){let e=await h.readJson(n);e.scripts={...e.scripts,check:`biome check --write .`},await h.writeJson(n,e,{spaces:2})}}async function ae(t){await M({devDependencies:[`husky`,`lint-staged`],projectDir:t});let n=e.join(t,`package.json`);if(await h.pathExists(n)){let e=await h.readJson(n);e.scripts={...e.scripts,prepare:`husky`},e[`lint-staged`]={"*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}":[`biome check --write .`]},await h.writeJson(n,e,{spaces:2})}}async function oe(t,n){let r=n.some(e=>[`react-router`,`tanstack-router`,`solid`].includes(e));if(!r)return;let i=re(t,n);if(!await h.pathExists(i))return;await M({dependencies:[`vite-plugin-pwa`],devDependencies:[`@vite-pwa/assets-generator`],projectDir:i});let a=e.join(i,`package.json`);if(await h.pathExists(a)){let e=await h.readJson(a);e.scripts={...e.scripts,"generate-pwa-assets":`pwa-assets-generator`},await h.writeJson(a,e,{spaces:2})}}async function se(t){let{api:n,projectName:r,frontend:i,backend:a,packageManager:o,projectDir:s}=t,c=a===`convex`,l=e.join(s,`apps/web`),u=e.join(s,`apps/native`),d=await h.pathExists(l),f=await h.pathExists(u),p=i.some(e=>[`tanstack-router`,`react-router`,`tanstack-start`,`next`].includes(e)),m=i.includes(`nuxt`),g=i.includes(`svelte`),_=i.includes(`solid`);if(!c&&n!==`none`){let r=e.join(s,`apps/server`),i=await h.pathExists(r);i&&(n===`orpc`?await M({dependencies:[`@orpc/server`,`@orpc/client`],projectDir:r}):n===`trpc`&&(await M({dependencies:[`@trpc/server`,`@trpc/client`],projectDir:r}),t.backend===`hono`?await M({dependencies:[`@hono/trpc-server`],projectDir:r}):t.backend===`elysia`&&await M({dependencies:[`@elysiajs/trpc`],projectDir:r}))),d&&(p?n===`orpc`?await M({dependencies:[`@orpc/react-query`,`@orpc/client`,`@orpc/server`],projectDir:l}):n===`trpc`&&await M({dependencies:[`@trpc/tanstack-react-query`,`@trpc/client`,`@trpc/server`],projectDir:l}):m?n===`orpc`&&await M({dependencies:[`@orpc/vue-query`,`@orpc/client`,`@orpc/server`],projectDir:l}):g?n===`orpc`&&await M({dependencies:[`@orpc/svelte-query`,`@orpc/client`,`@orpc/server`,`@tanstack/svelte-query`],projectDir:l}):_&&n===`orpc`&&await M({dependencies:[`@orpc/solid-query`,`@orpc/client`,`@orpc/server`,`@tanstack/solid-query`],projectDir:l})),f&&(n===`trpc`?await M({dependencies:[`@trpc/tanstack-react-query`,`@trpc/client`,`@trpc/server`],projectDir:u}):n===`orpc`&&await M({dependencies:[`@orpc/react-query`,`@orpc/client`,`@orpc/server`],projectDir:u}))}let v=[`react-router`,`tanstack-router`,`tanstack-start`,`next`,`native`],y=i.includes(`solid`),b=i.some(e=>v.includes(e));if(b&&!c){let t=[`@tanstack/react-query`],n=[`@tanstack/react-query-devtools`],r=i.some(e=>e!==`native`&&v.includes(e)),a=i.includes(`native`);if(r&&d){let r=e.join(l,`package.json`);if(await h.pathExists(r))try{await M({dependencies:t,devDependencies:n,projectDir:l})}catch{}}if(a&&f){let n=e.join(u,`package.json`);if(await h.pathExists(n))try{await M({dependencies:t,projectDir:u})}catch{}}}if(y&&!c){let t=[`@tanstack/solid-query`],n=[`@tanstack/solid-query-devtools`];if(d){let r=e.join(l,`package.json`);if(await h.pathExists(r))try{await M({dependencies:t,devDependencies:n,projectDir:l})}catch{}}}if(c){if(d){let t=e.join(l,`package.json`);if(await h.pathExists(t))try{let e=[`convex`];i.includes(`tanstack-start`)&&e.push(`@convex-dev/react-query`),g&&e.push(`convex-svelte`),await M({dependencies:e,projectDir:l})}catch{}}if(f){let t=e.join(u,`package.json`);if(await h.pathExists(t))try{await M({dependencies:[`convex`],projectDir:u})}catch{}}let t=`@${r}/backend`,n=o===`npm`?`*`:`workspace:*`,a=async(e,t,n)=>{try{let r=await h.readJson(e);r.dependencies||={},r.dependencies[t]!==n&&(r.dependencies[t]=n,await h.writeJson(e,r,{spaces:2}))}catch{}};if(d){let r=e.join(l,`package.json`);await h.pathExists(r)&&await a(r,t,n)}if(f){let r=e.join(u,`package.json`);await h.pathExists(r)&&await a(r,t,n)}}}async function ce(t){let{projectName:n,auth:r,frontend:i,backend:a,projectDir:o}=t;if(a===`convex`||!r)return;let s=e.join(o,`apps/server`),c=e.join(o,`apps/web`),l=e.join(o,`apps/native`),u=await h.pathExists(c),d=await h.pathExists(l),f=await h.pathExists(s);try{f&&await M({dependencies:[`better-auth`],projectDir:s});let e=i.some(e=>[`react-router`,`tanstack-router`,`tanstack-start`,`next`,`nuxt`,`svelte`].includes(e));e&&u&&await M({dependencies:[`better-auth`],projectDir:c}),i.includes(`native`)&&d&&(await M({dependencies:[`better-auth`,`@better-auth/expo`],projectDir:l}),f&&await M({dependencies:[`@better-auth/expo`],projectDir:s}))}catch(e){p.error(g.red(`Failed to configure authentication dependencies`)),e instanceof Error&&p.error(g.red(e.message))}}function le(e=32){let t=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`,n=``,r=t.length;for(let i=0;i<e;i++)n+=t.charAt(Math.floor(Math.random()*r));return n}async function ue(t){let{projectName:n,backend:r,runtime:i,api:a,projectDir:o}=t;if(r===`convex`)return;let s=r,c=e.join(o,`apps/server`),l=[],u=[];s===`hono`?(l.push(`hono`),a===`trpc`&&l.push(`@hono/trpc-server`),i===`node`&&(l.push(`@hono/node-server`),u.push(`tsx`,`@types/node`))):s===`elysia`?(l.push(`elysia`,`@elysiajs/cors`),a===`trpc`&&l.push(`@elysiajs/trpc`),i===`node`&&(l.push(`@elysiajs/node`),u.push(`tsx`,`@types/node`))):s===`express`&&(l.push(`express`,`cors`),u.push(`@types/express`,`@types/cors`),i===`node`&&u.push(`tsx`,`@types/node`)),i===`bun`&&u.push(`@types/bun`),(l.length>0||u.length>0)&&await M({dependencies:l,devDependencies:u,projectDir:c})}async function de(t,n){let r=e.join(t,`README.md`),i=fe(n);try{await h.writeFile(r,i)}catch(e){p.error(`Failed to create README.md file:`,e)}}function fe(e){let{projectName:t,packageManager:n,database:r,auth:i,addons:a=[],orm:o=`drizzle`,runtime:s=`bun`,frontend:c=[`tanstack-router`],backend:l=`hono`,api:u=`trpc`}=e,d=l===`convex`,f=c.includes(`react-router`),p=c.includes(`tanstack-router`),m=c.includes(`native`),h=c.includes(`next`),g=c.includes(`tanstack-start`),_=c.includes(`svelte`),v=c.includes(`solid`),y=c.includes(`nuxt`),b=n===`npm`?`npm run`:n,x=`3001`;return(f||_)&&(x=`5173`),`# ${t}
|
|
3
3
|
|
|
4
4
|
This project was created with [Better-T-Stack](https://github.com/AmanVarshney01/create-better-t-stack), a modern TypeScript stack that combines ${p?`React, TanStack Router`:f?`React, React Router`:h?`Next.js`:g?`React, TanStack Start`:_?`SvelteKit`:y?`Nuxt`:v?`SolidJS`:``}, ${l[0].toUpperCase()+l.slice(1)}${d?``:`, ${u.toUpperCase()}`}, and more.
|
|
5
5
|
|
package/package.json
CHANGED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { createFileRoute } from "@tanstack/solid-router";
|
|
2
|
-
import { Loader2, Trash2 } from "lucide-solid";
|
|
3
|
-
import { createSignal, For, Show } from "solid-js";
|
|
4
|
-
import { orpc } from "@/utils/orpc";
|
|
5
|
-
import { useQuery, useMutation } from "@tanstack/solid-query";
|
|
6
|
-
|
|
7
|
-
export const Route = createFileRoute("/todos")({
|
|
8
|
-
component: TodosRoute,
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
function TodosRoute() {
|
|
12
|
-
const [newTodoText, setNewTodoText] = createSignal("");
|
|
13
|
-
|
|
14
|
-
const todos = useQuery(() => orpc.todo.getAll.queryOptions());
|
|
15
|
-
|
|
16
|
-
const createMutation = useMutation(() =>
|
|
17
|
-
orpc.todo.create.mutationOptions({
|
|
18
|
-
onSuccess: () => {
|
|
19
|
-
todos.refetch();
|
|
20
|
-
setNewTodoText("");
|
|
21
|
-
},
|
|
22
|
-
}),
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
const toggleMutation = useMutation(() =>
|
|
26
|
-
orpc.todo.toggle.mutationOptions({
|
|
27
|
-
onSuccess: () => todos.refetch(),
|
|
28
|
-
}),
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
const deleteMutation = useMutation(() =>
|
|
32
|
-
orpc.todo.delete.mutationOptions({
|
|
33
|
-
onSuccess: () => todos.refetch(),
|
|
34
|
-
}),
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
const handleAddTodo = (e: Event) => {
|
|
38
|
-
e.preventDefault();
|
|
39
|
-
if (newTodoText().trim()) {
|
|
40
|
-
createMutation.mutate({ text: newTodoText() });
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const handleToggleTodo = (id: number, completed: boolean) => {
|
|
45
|
-
toggleMutation.mutate({ id, completed: !completed });
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const handleDeleteTodo = (id: number) => {
|
|
49
|
-
deleteMutation.mutate({ id });
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
return (
|
|
53
|
-
<div class="mx-auto w-full max-w-md py-10">
|
|
54
|
-
<div class="rounded-lg border p-6 shadow-sm">
|
|
55
|
-
<div class="mb-4">
|
|
56
|
-
<h2 class="text-xl font-semibold">Todo List</h2>
|
|
57
|
-
<p class="text-sm">Manage your tasks efficiently</p>
|
|
58
|
-
</div>
|
|
59
|
-
<div>
|
|
60
|
-
<form
|
|
61
|
-
onSubmit={handleAddTodo}
|
|
62
|
-
class="mb-6 flex items-center space-x-2"
|
|
63
|
-
>
|
|
64
|
-
<input
|
|
65
|
-
type="text"
|
|
66
|
-
value={newTodoText()}
|
|
67
|
-
onInput={(e) => setNewTodoText(e.currentTarget.value)}
|
|
68
|
-
placeholder="Add a new task..."
|
|
69
|
-
disabled={createMutation.isPending}
|
|
70
|
-
class="w-full rounded-md border p-2 text-sm"
|
|
71
|
-
/>
|
|
72
|
-
<button
|
|
73
|
-
type="submit"
|
|
74
|
-
disabled={createMutation.isPending || !newTodoText().trim()}
|
|
75
|
-
class="rounded-md bg-blue-600 px-4 py-2 text-sm text-white disabled:opacity-50"
|
|
76
|
-
>
|
|
77
|
-
<Show when={createMutation.isPending} fallback="Add">
|
|
78
|
-
<Loader2 class="h-4 w-4 animate-spin" />
|
|
79
|
-
</Show>
|
|
80
|
-
</button>
|
|
81
|
-
</form>
|
|
82
|
-
|
|
83
|
-
<Show when={todos.isLoading}>
|
|
84
|
-
<div class="flex justify-center py-4">
|
|
85
|
-
<Loader2 class="h-6 w-6 animate-spin" />
|
|
86
|
-
</div>
|
|
87
|
-
</Show>
|
|
88
|
-
|
|
89
|
-
<Show when={!todos.isLoading && todos.data?.length === 0}>
|
|
90
|
-
<p class="py-4 text-center">No todos yet. Add one above!</p>
|
|
91
|
-
</Show>
|
|
92
|
-
|
|
93
|
-
<Show when={!todos.isLoading}>
|
|
94
|
-
<ul class="space-y-2">
|
|
95
|
-
<For each={todos.data}>
|
|
96
|
-
{(todo) => (
|
|
97
|
-
<li class="flex items-center justify-between rounded-md border p-2">
|
|
98
|
-
<div class="flex items-center space-x-2">
|
|
99
|
-
<input
|
|
100
|
-
type="checkbox"
|
|
101
|
-
checked={todo.completed}
|
|
102
|
-
onChange={() =>
|
|
103
|
-
handleToggleTodo(todo.id, todo.completed)
|
|
104
|
-
}
|
|
105
|
-
id={`todo-${todo.id}`}
|
|
106
|
-
class="h-4 w-4"
|
|
107
|
-
/>
|
|
108
|
-
<label
|
|
109
|
-
for={`todo-${todo.id}`}
|
|
110
|
-
class={todo.completed ? "line-through" : ""}
|
|
111
|
-
>
|
|
112
|
-
{todo.text}
|
|
113
|
-
</label>
|
|
114
|
-
</div>
|
|
115
|
-
<button
|
|
116
|
-
type="button"
|
|
117
|
-
onClick={() => handleDeleteTodo(todo.id)}
|
|
118
|
-
aria-label="Delete todo"
|
|
119
|
-
class="ml-2 rounded-md p-1"
|
|
120
|
-
>
|
|
121
|
-
<Trash2 class="h-4 w-4" />
|
|
122
|
-
</button>
|
|
123
|
-
</li>
|
|
124
|
-
)}
|
|
125
|
-
</For>
|
|
126
|
-
</ul>
|
|
127
|
-
</Show>
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
</div>
|
|
131
|
-
);
|
|
132
|
-
}
|