Skip to content

Commit b6be85e

Browse files
fix(cli): align better auth mongo and convex templates
1 parent 5569d1c commit b6be85e

19 files changed

Lines changed: 246 additions & 107 deletions

File tree

apps/cli/test/auth.test.ts

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,43 @@ describe("Authentication Configurations", () => {
7878
});
7979

8080
expectSuccess(result);
81+
expect(result.projectDir).toBeDefined();
82+
const projectDir = result.projectDir as string;
83+
const authPackageJson = await fs.readJson(
84+
path.join(projectDir, "packages/auth/package.json"),
85+
);
86+
expect(authPackageJson.dependencies.mongodb).toBe("^7.2.0");
87+
88+
const dbIndex = await fs.readFile(path.join(projectDir, "packages/db/src/index.ts"), "utf8");
89+
expect(dbIndex).toContain("await mongoose.connect(env.DATABASE_URL);");
90+
expect(dbIndex).toContain("mongoose.connection.getClient().db()");
91+
expect(dbIndex).not.toContain(".catch(");
92+
expect(dbIndex).not.toContain("myDB");
93+
94+
const todosRoute = await fs.readFile(
95+
path.join(projectDir, "apps/web/src/routes/todos.tsx"),
96+
"utf8",
97+
);
98+
expect(todosRoute).toContain("type TodoId = string");
99+
expect(todosRoute).toContain("const handleToggleTodo = (id: TodoId");
100+
expect(todosRoute).toContain("const handleDeleteTodo = (id: TodoId");
101+
102+
const todoRouter = await fs.readFile(
103+
path.join(projectDir, "packages/api/src/routers/todo.ts"),
104+
"utf8",
105+
);
106+
expect(todoRouter).toContain('import "@better-auth-mongodb/db";');
107+
expect(todoRouter).toContain("id: todo.id.toString()");
108+
109+
const authModels = await fs.readFile(
110+
path.join(projectDir, "packages/db/src/models/auth.model.ts"),
111+
"utf8",
112+
);
113+
expect(authModels).toContain("const { ObjectId } = Schema.Types");
114+
expect(authModels).toContain("_id: { type: ObjectId, auto: true }");
115+
expect(authModels).toContain('userId: { type: ObjectId, ref: "User", required: true }');
116+
expect(authModels).toContain("sessionSchema.index({ userId: 1 })");
117+
expect(authModels).toContain("verificationSchema.index({ identifier: 1 })");
81118
});
82119

83120
it("should add nextCookies plugin for Next.js self backend", async () => {
@@ -187,6 +224,50 @@ describe("Authentication Configurations", () => {
187224
});
188225

189226
expectSuccess(result);
227+
if (!result.projectDir) {
228+
throw new Error("Expected projectDir to be defined");
229+
}
230+
231+
const packageJson = await fs.readJson(path.join(result.projectDir, "package.json"));
232+
const backendPackageJson = await fs.readJson(
233+
path.join(result.projectDir, "packages/backend/package.json"),
234+
);
235+
const webPackageJson = await fs.readJson(
236+
path.join(result.projectDir, "apps/web/package.json"),
237+
);
238+
const authFile = await fs.readFile(
239+
path.join(result.projectDir, "packages/backend/convex/auth.ts"),
240+
"utf8",
241+
);
242+
const httpFile = await fs.readFile(
243+
path.join(result.projectDir, "packages/backend/convex/http.ts"),
244+
"utf8",
245+
);
246+
const authClientFile = await fs.readFile(
247+
path.join(result.projectDir, "apps/web/src/lib/auth-client.ts"),
248+
"utf8",
249+
);
250+
const convexTsconfig = await fs.readFile(
251+
path.join(result.projectDir, "packages/backend/convex/tsconfig.json"),
252+
"utf8",
253+
);
254+
const convexEnvFile = await fs.readFile(
255+
path.join(result.projectDir, "packages/backend/.env.local"),
256+
"utf8",
257+
);
258+
259+
expect(packageJson.workspaces.catalog["better-auth"]).toBe("~1.6.9");
260+
expect(packageJson.workspaces.catalog["@convex-dev/better-auth"]).toBe("^0.12.2");
261+
expect(backendPackageJson.dependencies["better-auth"]).toBe("catalog:");
262+
expect(webPackageJson.dependencies["better-auth"]).toBe("catalog:");
263+
expect(authFile).toContain("baseURL: process.env.CONVEX_SITE_URL");
264+
expect(httpFile).toContain("authComponent.registerRoutes(http, createAuth, { cors: true })");
265+
expect(authClientFile).toContain("plugins: [convexClient(), crossDomainClient()]");
266+
expect(convexTsconfig).toContain('"types": ["node"]');
267+
expect(convexEnvFile).toContain(
268+
"# npx convex env set CONVEX_SITE_URL https://<YOUR_CONVEX_SITE_URL>",
269+
);
270+
expect(convexEnvFile).toContain("# CONVEX_SITE_URL=");
190271
});
191272

192273
it("should scaffold react-router with Convex Better Auth wiring", async () => {
@@ -227,7 +308,7 @@ describe("Authentication Configurations", () => {
227308

228309
expect(rootFile).toContain("ConvexBetterAuthProvider");
229310
expect(rootFile).toContain('import { authClient } from "@/lib/auth-client";');
230-
expect(authClientFile).toContain("crossDomainClient(), convexClient()");
311+
expect(authClientFile).toContain("convexClient(), crossDomainClient()");
231312
expect(dashboardFile).toContain("Authenticated");
232313
expect(dashboardFile).toContain("Unauthenticated");
233314
});

packages/template-generator/src/processors/auth-deps.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import type { ProjectConfig } from "@better-t-stack/types";
22

33
import type { VirtualFileSystem } from "../core/virtual-fs";
4-
import { addPackageDependency } from "../utils/add-deps";
4+
import { addPackageDependency, type AvailableDependencies } from "../utils/add-deps";
55

6-
const CONVEX_BETTER_AUTH_VERSION = "1.6.9";
6+
// Intentional: @convex-dev/better-auth currently documents a pinned Better Auth range.
7+
const CONVEX_BETTER_AUTH_VERSION = "~1.6.9";
78

89
export function processAuthDeps(vfs: VirtualFileSystem, config: ProjectConfig): void {
910
const { auth, backend } = config;
@@ -124,7 +125,7 @@ function processConvexAuthDeps(vfs: VirtualFileSystem, config: ProjectConfig): v
124125
}
125126

126127
function processStandardAuthDeps(vfs: VirtualFileSystem, config: ProjectConfig): void {
127-
const { auth, backend, frontend } = config;
128+
const { auth, backend, frontend, orm } = config;
128129
const authPath = "packages/auth/package.json";
129130
const apiPath = "packages/api/package.json";
130131
const webPath = "apps/web/package.json";
@@ -202,7 +203,11 @@ function processStandardAuthDeps(vfs: VirtualFileSystem, config: ProjectConfig):
202203
}
203204
} else if (auth === "better-auth") {
204205
if (authExists) {
205-
addPackageDependency({ vfs, packagePath: authPath, dependencies: ["better-auth"] });
206+
const authDependencies: AvailableDependencies[] = ["better-auth"];
207+
if (orm === "mongoose") {
208+
authDependencies.push("mongodb");
209+
}
210+
addPackageDependency({ vfs, packagePath: authPath, dependencies: authDependencies });
206211
if (hasNative) {
207212
addPackageDependency({ vfs, packagePath: authPath, dependencies: ["@better-auth/expo"] });
208213
}

packages/template-generator/src/processors/db-deps.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,18 @@ function processPrismaDeps(
3333
const { database, dbSetup } = config;
3434

3535
if (database === "mongodb") {
36+
// Intentional: Prisma ORM v7 does not support MongoDB yet, so MongoDB stays on v6.
3637
addPackageDependency({
3738
vfs,
3839
packagePath: dbPkgPath,
39-
customDependencies: { "@prisma/client": "6.19.0" },
40-
customDevDependencies: { prisma: "6.19.0" },
40+
customDependencies: { "@prisma/client": "6.19.3" },
41+
customDevDependencies: { prisma: "6.19.3" },
4142
});
4243
if (webExists) {
4344
addPackageDependency({
4445
vfs,
4546
packagePath: webPkgPath,
46-
customDependencies: { "@prisma/client": "6.19.0" },
47+
customDependencies: { "@prisma/client": "6.19.3" },
4748
});
4849
}
4950
return;

packages/template-generator/src/processors/env-vars.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ function buildConvexBackendVars(
259259
auth: ProjectConfig["auth"],
260260
examples: ProjectConfig["examples"],
261261
): EnvVariable[] {
262+
const hasReactRouter = frontend.includes("react-router");
263+
const hasTanStackRouter = frontend.includes("tanstack-router");
262264
const hasNextJs = frontend.includes("next");
263265
const hasNative =
264266
frontend.includes("native-bare") ||
@@ -294,6 +296,15 @@ function buildConvexBackendVars(
294296
}
295297

296298
if (auth === "better-auth") {
299+
if (hasReactRouter || hasTanStackRouter) {
300+
vars.push({
301+
key: "CONVEX_SITE_URL",
302+
value: "",
303+
condition: true,
304+
comment: "Same as CONVEX_URL but ends in .site",
305+
});
306+
}
307+
297308
if (hasNative) {
298309
vars.push({
299310
key: "EXPO_PUBLIC_CONVEX_SITE_URL",
@@ -336,6 +347,8 @@ function buildConvexCommentBlocks(
336347
auth: ProjectConfig["auth"],
337348
examples: ProjectConfig["examples"],
338349
): string {
350+
const needsConvexSiteUrl =
351+
frontend.includes("react-router") || frontend.includes("tanstack-router");
339352
const hasNative =
340353
frontend.includes("native-bare") ||
341354
frontend.includes("native-uniwind") ||
@@ -370,7 +383,7 @@ function buildConvexCommentBlocks(
370383
if (auth === "better-auth") {
371384
commentBlocks += `# Set Convex environment variables
372385
# npx convex env set BETTER_AUTH_SECRET=$(openssl rand -base64 32)
373-
${hasWeb || hasNative ? `# npx convex env set SITE_URL ${defaultSiteUrl}\n` : ""}`;
386+
${needsConvexSiteUrl ? "# npx convex env set CONVEX_SITE_URL https://<YOUR_CONVEX_SITE_URL>\n" : ""}${hasWeb || hasNative ? `# npx convex env set SITE_URL ${defaultSiteUrl}\n` : ""}`;
374387
}
375388

376389
return commentBlocks;

0 commit comments

Comments
 (0)