create-better-t-stack 3.11.0 → 3.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as createBtsCli } from "./src-XVvJUQ_h.mjs";
2
+ import { n as createBtsCli } from "./src-Dc2OdxbP.mjs";
3
3
 
4
4
  //#region src/cli.ts
5
5
  createBtsCli().run();
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-XVvJUQ_h.mjs";
2
+ import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-Dc2OdxbP.mjs";
3
3
 
4
4
  export { builder, createBtsCli, docs, init, router, sponsors };
@@ -64,8 +64,8 @@ function getDefaultConfig() {
64
64
  const DEFAULT_CONFIG = getDefaultConfig();
65
65
  const dependencyVersionMap = {
66
66
  typescript: "^5",
67
- "better-auth": "^1.4.7",
68
- "@better-auth/expo": "^1.4.7",
67
+ "better-auth": "^1.4.9",
68
+ "@better-auth/expo": "^1.4.9",
69
69
  "@clerk/nextjs": "^6.31.5",
70
70
  "@clerk/clerk-react": "^5.45.0",
71
71
  "@clerk/tanstack-react-start": "^0.26.3",
@@ -138,13 +138,14 @@ const dependencyVersionMap = {
138
138
  "convex-svelte": "^0.0.12",
139
139
  "convex-nuxt": "0.1.5",
140
140
  "convex-vue": "^0.1.5",
141
- "@convex-dev/better-auth": "^0.10.6",
141
+ "@convex-dev/better-auth": "^0.10.9",
142
142
  "@tanstack/svelte-query": "^5.85.3",
143
143
  "@tanstack/svelte-query-devtools": "^5.85.3",
144
144
  "@tanstack/vue-query-devtools": "^5.90.2",
145
145
  "@tanstack/vue-query": "^5.90.2",
146
146
  "@tanstack/react-query-devtools": "^5.91.1",
147
147
  "@tanstack/react-query": "^5.90.12",
148
+ "@tanstack/react-router-ssr-query": "^1.142.7",
148
149
  "@tanstack/solid-query": "^5.87.4",
149
150
  "@tanstack/solid-query-devtools": "^5.87.4",
150
151
  "@tanstack/solid-router-devtools": "^1.131.44",
@@ -4171,7 +4172,10 @@ function getConvexDependencies(frontend) {
4171
4172
  web: { dependencies: ["convex"] },
4172
4173
  native: { dependencies: ["convex"] }
4173
4174
  };
4174
- if (frontend.includes("tanstack-start")) deps.web.dependencies.push("@convex-dev/react-query");
4175
+ if (frontend.includes("tanstack-start")) {
4176
+ deps.web.dependencies.push("@convex-dev/react-query");
4177
+ deps.web.dependencies.push("@tanstack/react-router-ssr-query");
4178
+ }
4175
4179
  if (frontend.includes("svelte")) deps.web.dependencies.push("convex-svelte");
4176
4180
  if (frontend.includes("nuxt")) deps.web.dependencies.push("convex-nuxt", "convex-vue");
4177
4181
  return deps;
@@ -4367,12 +4371,12 @@ async function setupAuth(config) {
4367
4371
  if (convexBackendDirExists) {
4368
4372
  await addPackageDependency({
4369
4373
  dependencies: ["better-auth", "@convex-dev/better-auth"],
4370
- customDependencies: { "better-auth": "1.4.7" },
4374
+ customDependencies: { "better-auth": "1.4.9" },
4371
4375
  projectDir: convexBackendDir
4372
4376
  });
4373
4377
  if (hasNativeForBA) await addPackageDependency({
4374
4378
  dependencies: ["@better-auth/expo"],
4375
- customDependencies: { "@better-auth/expo": "1.4.7" },
4379
+ customDependencies: { "@better-auth/expo": "1.4.9" },
4376
4380
  projectDir: convexBackendDir
4377
4381
  });
4378
4382
  }
@@ -4382,17 +4386,17 @@ async function setupAuth(config) {
4382
4386
  const hasViteReactOther = frontend.some((f) => ["tanstack-router", "react-router"].includes(f));
4383
4387
  if (hasNextJs) await addPackageDependency({
4384
4388
  dependencies: ["better-auth", "@convex-dev/better-auth"],
4385
- customDependencies: { "better-auth": "1.4.7" },
4389
+ customDependencies: { "better-auth": "1.4.9" },
4386
4390
  projectDir: clientDir
4387
4391
  });
4388
4392
  else if (hasTanStackStart) await addPackageDependency({
4389
4393
  dependencies: ["better-auth", "@convex-dev/better-auth"],
4390
- customDependencies: { "better-auth": "1.4.7" },
4394
+ customDependencies: { "better-auth": "1.4.9" },
4391
4395
  projectDir: clientDir
4392
4396
  });
4393
4397
  else if (hasViteReactOther) await addPackageDependency({
4394
4398
  dependencies: ["better-auth", "@convex-dev/better-auth"],
4395
- customDependencies: { "better-auth": "1.4.7" },
4399
+ customDependencies: { "better-auth": "1.4.9" },
4396
4400
  projectDir: clientDir
4397
4401
  });
4398
4402
  }
@@ -4406,8 +4410,8 @@ async function setupAuth(config) {
4406
4410
  "@convex-dev/better-auth"
4407
4411
  ],
4408
4412
  customDependencies: {
4409
- "better-auth": "1.4.7",
4410
- "@better-auth/expo": "1.4.7"
4413
+ "better-auth": "1.4.9",
4414
+ "@better-auth/expo": "1.4.9"
4411
4415
  },
4412
4416
  projectDir: nativeDir
4413
4417
  });
@@ -5944,7 +5948,7 @@ ${generateProjectStructure(projectName, frontend, backend, addons, isConvex, api
5944
5948
 
5945
5949
  ## Available Scripts
5946
5950
 
5947
- ${generateScriptsList(packageManagerRunCmd, database, orm, auth, hasNative, addons, backend)}
5951
+ ${generateScriptsList(packageManagerRunCmd, database, orm, auth, hasNative, addons, backend, options.dbSetup)}
5948
5952
  `;
5949
5953
  }
5950
5954
  function generateStackDescription(frontend, backend, api, isConvex) {
@@ -6099,15 +6103,13 @@ function generateDatabaseSetup(database, _auth, packageManagerRunCmd, orm, dbSet
6099
6103
  if (database === "none") return "";
6100
6104
  const isBackendSelf = backend === "self";
6101
6105
  const envPath = isBackendSelf ? "apps/web/.env" : "apps/server/.env";
6102
- const dbLocalPath = "packages/db";
6103
6106
  let setup = "## Database Setup\n\n";
6104
6107
  if (database === "sqlite") setup += `This project uses SQLite${orm === "drizzle" ? " with Drizzle ORM" : orm === "prisma" ? " with Prisma" : ` with ${orm}`}.
6105
6108
 
6106
- 1. Start the local SQLite database:
6109
+ 1. Start the local SQLite database (optional):
6107
6110
  ${dbSetup === "d1" ? "D1 local development and migrations are handled automatically by Alchemy during dev and deploy." : `\`\`\`bash
6108
- cd ${dbLocalPath} && ${packageManagerRunCmd} db:local
6109
- \`\`\`
6110
- `}
6111
+ ${packageManagerRunCmd} db:local
6112
+ \`\`\``}
6111
6113
 
6112
6114
  2. Update your \`.env\` file in the \`${isBackendSelf ? "apps/web" : "apps/server"}\` directory with the appropriate connection details if needed.
6113
6115
  `;
@@ -6140,7 +6142,7 @@ ${packageManagerRunCmd} db:push
6140
6142
  `;
6141
6143
  return setup;
6142
6144
  }
6143
- function generateScriptsList(packageManagerRunCmd, database, orm, _auth, hasNative, addons, backend) {
6145
+ function generateScriptsList(packageManagerRunCmd, database, orm, _auth, hasNative, addons, backend, dbSetup) {
6144
6146
  const isConvex = backend === "convex";
6145
6147
  const isBackendNone = backend === "none";
6146
6148
  const isBackendSelf = backend === "self";
@@ -6160,8 +6162,8 @@ function generateScriptsList(packageManagerRunCmd, database, orm, _auth, hasNati
6160
6162
  scripts += `
6161
6163
  - \`${packageManagerRunCmd} db:push\`: Push schema changes to database
6162
6164
  - \`${packageManagerRunCmd} db:studio\`: Open database studio UI`;
6163
- if (database === "sqlite" && orm === "drizzle") scripts += `
6164
- - \`cd packages/db && ${packageManagerRunCmd} db:local\`: Start the local SQLite database`;
6165
+ if (database === "sqlite" && dbSetup !== "d1") scripts += `
6166
+ - \`${packageManagerRunCmd} db:local\`: Start the local SQLite database`;
6165
6167
  }
6166
6168
  if (addons.includes("biome")) scripts += `
6167
6169
  - \`${packageManagerRunCmd} check\`: Run Biome formatting and linting`;
@@ -6348,7 +6350,7 @@ async function displayPostInstallInstructions(config) {
6348
6350
  let output = `${pc.bold("Next steps")}\n${pc.cyan("1.")} ${cdCmd}\n`;
6349
6351
  let stepCounter = 2;
6350
6352
  if (!depsInstalled) output += `${pc.cyan(`${stepCounter++}.`)} ${packageManager} install\n`;
6351
- if (database === "sqlite" && dbSetup === "none" && (serverDeploy === "alchemy" || webDeploy === "alchemy")) output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} db:local\n${pc.dim(" (starts local SQLite server for Workers compatibility)")}\n`;
6353
+ if (database === "sqlite" && dbSetup !== "d1") output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} db:local\n${pc.dim(" (optional - starts local SQLite database)")}\n`;
6352
6354
  if (isConvex) {
6353
6355
  output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev:setup\n${pc.dim(" (this will guide you through Convex project setup)")}\n`;
6354
6356
  output += `${pc.cyan(`${stepCounter++}.`)} Copy environment variables from\n${pc.white(" packages/backend/.env.local")} to ${pc.white("apps/*/.env")}\n`;
@@ -6635,7 +6637,7 @@ async function updateRootPackageJson(projectDir, options) {
6635
6637
  if (!isD1Alchemy) scripts["db:migrate"] = pmConfig.filter(dbPackageName, "db:migrate");
6636
6638
  }
6637
6639
  }
6638
- if (database === "sqlite" && dbSetup !== "d1" && orm !== "none") scripts["db:local"] = pmConfig.filter(dbPackageName, "db:local");
6640
+ if (database === "sqlite" && dbSetup !== "d1") scripts["db:local"] = pmConfig.filter(dbPackageName, "db:local");
6639
6641
  if (dbSetup === "docker") {
6640
6642
  scripts["db:start"] = pmConfig.filter(dbPackageName, "db:start");
6641
6643
  scripts["db:watch"] = pmConfig.filter(dbPackageName, "db:watch");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-better-t-stack",
3
- "version": "3.11.0",
3
+ "version": "3.11.1",
4
4
  "description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
5
5
  "keywords": [
6
6
  "better-auth",
@@ -67,7 +67,7 @@
67
67
  "prepublishOnly": "npm run build"
68
68
  },
69
69
  "dependencies": {
70
- "@better-t-stack/types": "^3.11.0",
70
+ "@better-t-stack/types": "^3.11.1",
71
71
  "@clack/prompts": "^1.0.0-alpha.8",
72
72
  "@orpc/server": "^1.13.0",
73
73
  "consola": "^3.4.2",
@@ -55,6 +55,11 @@
55
55
  "db:down": {
56
56
  "cache": false,
57
57
  "persistent": true
58
+ }{{/if}}
59
+ {{#if (and (eq database "sqlite") (ne dbSetup "d1"))}},
60
+ "db:local": {
61
+ "cache": false,
62
+ "persistent": true
58
63
  }
59
64
  {{/if}}
60
65
  }
@@ -8,10 +8,9 @@ import { convex, crossDomain } from "@convex-dev/better-auth/plugins";
8
8
  import { convex } from "@convex-dev/better-auth/plugins";
9
9
  {{/if}}
10
10
  import { components } from "./_generated/api";
11
- import { DataModel } from "./_generated/dataModel";
11
+ import type { DataModel } from "./_generated/dataModel";
12
12
  import { query } from "./_generated/server";
13
13
  import { betterAuth } from "better-auth";
14
- import { v } from "convex/values";
15
14
  import authConfig from "./auth.config";
16
15
 
17
16
  {{#if (or (includes frontend "tanstack-start") (includes frontend "next"))}}
@@ -63,8 +62,7 @@ export { createAuth };
63
62
 
64
63
  export const getCurrentUser = query({
65
64
  args: {},
66
- returns: v.any(),
67
- handler: async function (ctx) {
68
- return authComponent.getAuthUser(ctx);
65
+ handler: async (ctx) => {
66
+ return await authComponent.safeGetAuthUser(ctx);
69
67
  },
70
68
  });
@@ -1,16 +1,17 @@
1
1
  import { query } from "./_generated/server";
2
+ import { authComponent } from "./auth";
2
3
 
3
4
  export const get = query({
4
- args: {},
5
- handler: async (ctx) => {
6
- const identity = await ctx.auth.getUserIdentity();
7
- if (identity === null) {
8
- return {
9
- message: "Not authenticated",
10
- };
11
- }
12
- return {
13
- message: "This is private",
14
- };
15
- },
5
+ args: {},
6
+ handler: async (ctx) => {
7
+ const authUser = await authComponent.safeGetAuthUser(ctx);
8
+ if (!authUser) {
9
+ return {
10
+ message: "Not authenticated",
11
+ };
12
+ }
13
+ return {
14
+ message: "This is private",
15
+ };
16
+ },
16
17
  });
@@ -2,5 +2,5 @@ import { createAuthClient } from "better-auth/react";
2
2
  import { convexClient } from "@convex-dev/better-auth/client/plugins";
3
3
 
4
4
  export const authClient = createAuthClient({
5
- plugins: [convexClient()],
6
- });
5
+ plugins: [convexClient()],
6
+ });
@@ -1,4 +1,5 @@
1
1
  import { convexBetterAuthNextJs } from "@convex-dev/better-auth/nextjs";
2
+ import { isAuthError } from "@/lib/utils";
2
3
 
3
4
  export const {
4
5
  handler,
@@ -72,7 +72,7 @@ export const web = await Nextjs("web", {
72
72
  {{#if (eq auth "clerk")}}
73
73
  CLERK_SECRET_KEY: alchemy.secret.env.CLERK_SECRET_KEY,
74
74
  {{/if}}
75
- {{#if (includes examples "ai")}}
75
+ {{#if (and (includes examples "ai") (ne backend "convex"))}}
76
76
  GOOGLE_GENERATIVE_AI_API_KEY: alchemy.secret.env.GOOGLE_GENERATIVE_AI_API_KEY,
77
77
  {{/if}}
78
78
  {{#if (eq payments "polar")}}
@@ -146,7 +146,7 @@ export const web = await TanStackStart("web", {
146
146
  {{#if (eq auth "clerk")}}
147
147
  CLERK_SECRET_KEY: alchemy.secret.env.CLERK_SECRET_KEY,
148
148
  {{/if}}
149
- {{#if (includes examples "ai")}}
149
+ {{#if (and (includes examples "ai") (ne backend "convex"))}}
150
150
  GOOGLE_GENERATIVE_AI_API_KEY: alchemy.secret.env.GOOGLE_GENERATIVE_AI_API_KEY,
151
151
  {{/if}}
152
152
  {{#if (eq payments "polar")}}
@@ -1,9 +1,8 @@
1
1
  {{#if (eq backend "convex")}}
2
2
  import { createRouter as createTanStackRouter } from "@tanstack/react-router";
3
3
  import { QueryClient } from "@tanstack/react-query";
4
- import { routerWithQueryClient } from "@tanstack/react-router-with-query";
4
+ import { setupRouterSsrQueryIntegration } from "@tanstack/react-router-ssr-query";
5
5
  import { ConvexQueryClient } from "@convex-dev/react-query";
6
- import { ConvexProvider, ConvexReactClient } from "convex/react";
7
6
  import { routeTree } from "./routeTree.gen";
8
7
  import Loader from "./components/loader";
9
8
  import "./index.css";
@@ -27,21 +26,12 @@ import { orpc, queryClient } from "./utils/orpc";
27
26
 
28
27
  {{#if (eq backend "convex")}}
29
28
  export function getRouter() {
30
- const CONVEX_URL = (import.meta as any).env.VITE_CONVEX_URL!;
31
- if (!CONVEX_URL) {
32
- console.error("missing envar VITE_CONVEX_URL");
29
+ const convexUrl = (import.meta as any).env.VITE_CONVEX_URL!;
30
+ if (!convexUrl) {
31
+ throw new Error("VITE_CONVEX_URL is not set");
33
32
  }
34
- const convex = new ConvexReactClient(CONVEX_URL, {
35
- unsavedChangesWarning: false,
36
- });
37
33
 
38
- {{#if (eq auth "better-auth")}}
39
- const convexQueryClient = new ConvexQueryClient(convex, {
40
- expectAuth: true,
41
- });
42
- {{else}}
43
- const convexQueryClient = new ConvexQueryClient(convex);
44
- {{/if}}
34
+ const convexQueryClient = new ConvexQueryClient(convexUrl);
45
35
 
46
36
  const queryClient: QueryClient = new QueryClient({
47
37
  defaultOptions: {
@@ -53,21 +43,19 @@ export function getRouter() {
53
43
  });
54
44
  convexQueryClient.connect(queryClient);
55
45
 
56
- const router = routerWithQueryClient(
57
- createTanStackRouter({
58
- routeTree,
59
- defaultPreload: "intent",
60
- defaultPendingComponent: () => <Loader />,
61
- defaultNotFoundComponent: () => <div>Not Found</div>,
62
- context: { queryClient, convexClient: convex, convexQueryClient },
63
- Wrap: ({ children }) => (
64
- <ConvexProvider client={convexQueryClient.convexClient}>
65
- {children}
66
- </ConvexProvider>
67
- ),
68
- }),
46
+ const router = createTanStackRouter({
47
+ routeTree,
48
+ defaultPreload: "intent",
49
+ defaultPendingComponent: () => <Loader />,
50
+ defaultNotFoundComponent: () => <div>Not Found</div>,
51
+ context: { queryClient, convexQueryClient },
52
+ });
53
+
54
+ setupRouterSsrQueryIntegration({
55
+ router,
69
56
  queryClient,
70
- );
57
+ });
58
+
71
59
  return router;
72
60
  }
73
61
  {{else}}
@@ -17,7 +17,6 @@ import appCss from "../index.css?url";
17
17
  {{#if (eq backend "convex")}}
18
18
  import type { QueryClient } from "@tanstack/react-query";
19
19
  import type { ConvexQueryClient } from "@convex-dev/react-query";
20
- import type { ConvexReactClient } from "convex/react";
21
20
  {{else}}
22
21
  {{#if (or (eq api "trpc") (eq api "orpc"))}}
23
22
  import type { QueryClient } from "@tanstack/react-query";
@@ -49,7 +48,6 @@ const getAuth = createServerFn({ method: "GET" }).handler(async () => {
49
48
  {{#if (eq backend "convex")}}
50
49
  export interface RouterAppContext {
51
50
  queryClient: QueryClient;
52
- convexClient: ConvexReactClient;
53
51
  convexQueryClient: ConvexQueryClient;
54
52
  }
55
53
  {{else}}
@@ -122,7 +120,7 @@ function RootDocument() {
122
120
  const context = useRouteContext({ from: Route.id });
123
121
  return (
124
122
  <ClerkProvider>
125
- <ConvexProviderWithClerk client={context.convexClient} useAuth={useAuth}>
123
+ <ConvexProviderWithClerk client={context.convexQueryClient.convexClient} useAuth={useAuth}>
126
124
  <html lang="en" className="dark">
127
125
  <head>
128
126
  <HeadContent />
@@ -144,7 +142,7 @@ function RootDocument() {
144
142
  const context = useRouteContext({ from: Route.id });
145
143
  return (
146
144
  <ConvexBetterAuthProvider
147
- client={context.convexClient}
145
+ client={context.convexQueryClient.convexClient}
148
146
  authClient={authClient}
149
147
  initialToken={context.token}
150
148
  >