Skip to content

Commit 211db17

Browse files
refactor: migrate to convex + better-auth (#471)
* refactor: migrate to convex + better-auth * chore: upgrade to tailwindcss v4 --------- Co-authored-by: Tanner Linsley <tannerlinsley@gmail.com>
1 parent 171c31c commit 211db17

File tree

25 files changed

+3137
-614
lines changed

25 files changed

+3137
-614
lines changed

convex/_generated/api.d.ts

Lines changed: 2100 additions & 0 deletions
Large diffs are not rendered by default.

convex/_generated/dataModel.d.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,29 @@
88
* @module
99
*/
1010

11-
import { AnyDataModel } from "convex/server";
11+
import type {
12+
DataModelFromSchemaDefinition,
13+
DocumentByName,
14+
TableNamesInDataModel,
15+
SystemTableNames,
16+
} from "convex/server";
1217
import type { GenericId } from "convex/values";
13-
14-
/**
15-
* No `schema.ts` file found!
16-
*
17-
* This generated code has permissive types like `Doc = any` because
18-
* Convex doesn't know your schema. If you'd like more type safety, see
19-
* https://docs.convex.dev/using/schemas for instructions on how to add a
20-
* schema file.
21-
*
22-
* After you change a schema, rerun codegen with `npx convex dev`.
23-
*/
18+
import schema from "../schema.js";
2419

2520
/**
2621
* The names of all of your Convex tables.
2722
*/
28-
export type TableNames = string;
23+
export type TableNames = TableNamesInDataModel<DataModel>;
2924

3025
/**
3126
* The type of a document stored in Convex.
27+
*
28+
* @typeParam TableName - A string literal type of the table name (like "users").
3229
*/
33-
export type Doc = any;
30+
export type Doc<TableName extends TableNames> = DocumentByName<
31+
DataModel,
32+
TableName
33+
>;
3434

3535
/**
3636
* An identifier for a document in Convex.
@@ -42,8 +42,10 @@ export type Doc = any;
4242
*
4343
* IDs are just strings at runtime, but this type can be used to distinguish them from other
4444
* strings when type checking.
45+
*
46+
* @typeParam TableName - A string literal type of the table name (like "users").
4547
*/
46-
export type Id<TableName extends TableNames = TableNames> =
48+
export type Id<TableName extends TableNames | SystemTableNames> =
4749
GenericId<TableName>;
4850

4951
/**
@@ -55,4 +57,4 @@ export type Id<TableName extends TableNames = TableNames> =
5557
* This type is used to parameterize methods like `queryGeneric` and
5658
* `mutationGeneric` to make them type-safe.
5759
*/
58-
export type DataModel = AnyDataModel;
60+
export type DataModel = DataModelFromSchemaDefinition<typeof schema>;

convex/auth.config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export default {
2+
providers: [
3+
{
4+
domain: process.env.CONVEX_SITE_URL,
5+
applicationID: "convex",
6+
},
7+
],
8+
};

convex/auth.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {
2+
BetterAuth,
3+
type AuthFunctions,
4+
type PublicAuthFunctions,
5+
} from "@convex-dev/better-auth";
6+
import { api, components, internal } from "./_generated/api";
7+
import { query } from "./_generated/server";
8+
import type { Id, DataModel } from "./_generated/dataModel";
9+
10+
// Typesafe way to pass Convex functions defined in this file
11+
const authFunctions: AuthFunctions = internal.auth
12+
const publicAuthFunctions: PublicAuthFunctions = api.auth;
13+
14+
// Initialize the component
15+
export const betterAuthComponent = new BetterAuth(
16+
components.betterAuth,
17+
{
18+
authFunctions,
19+
publicAuthFunctions,
20+
}
21+
);
22+
23+
// These are required named exports
24+
export const {
25+
createUser,
26+
updateUser,
27+
deleteUser,
28+
createSession,
29+
isAuthenticated,
30+
} =
31+
betterAuthComponent.createAuthFunctions<DataModel>({
32+
// Must create a user and return the user id
33+
onCreateUser: async (ctx, user) => {
34+
return ctx.db.insert("users", {
35+
capabilities: [],
36+
});
37+
},
38+
39+
// Delete the user when they are deleted from Better Auth
40+
onDeleteUser: async (ctx, userId) => {
41+
await ctx.db.delete(userId as Id<"users">);
42+
},
43+
});
44+
45+
// Example function for getting the current user
46+
// Feel free to edit, omit, etc.
47+
export const getCurrentUser = query({
48+
args: {},
49+
handler: async (ctx) => {
50+
// Get user data from Better Auth - email, name, image, etc.
51+
const userMetadata = await betterAuthComponent.getAuthUser(ctx);
52+
if (!userMetadata) {
53+
return null;
54+
}
55+
// Get user data from your application's database
56+
// (skip this if you have no fields in your users table schema)
57+
const user = await ctx.db.get(userMetadata.userId as Id<"users">);
58+
return {
59+
...user,
60+
...userMetadata,
61+
};
62+
},
63+
});

convex/convex.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { defineApp } from 'convex/server'
22
import ossStats from '@erquhart/convex-oss-stats/convex.config'
3+
import betterAuth from '@convex-dev/better-auth/convex.config'
34

45
const app = defineApp()
56
app.use(ossStats)
7+
app.use(betterAuth)
68

79
export default app

convex/http.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import { ossStats } from './stats'
22
import { httpRouter } from 'convex/server'
33

4+
import { betterAuthComponent } from './auth'
5+
import { createAuth } from '../src/libraries/auth'
6+
47
const http = httpRouter()
58

69
ossStats.registerRoutes(http)
10+
betterAuthComponent.registerRoutes(http, createAuth)
711

812
export default http

convex/schema.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { defineSchema, defineTable } from "convex/server";
2+
import { authTables } from "@convex-dev/auth/server";
3+
import { v } from "convex/values";
4+
5+
const schema = defineSchema({
6+
...authTables,
7+
users: defineTable({
8+
capabilities: v.array(v.string()),
9+
})
10+
});
11+
12+
export default schema

package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
"linkAll": "node scripts/link.js"
1818
},
1919
"dependencies": {
20-
"@clerk/tanstack-react-start": "^0.21.7",
20+
"@auth/core": "0.37.0",
21+
"@convex-dev/auth": "^0.0.88",
22+
"@convex-dev/better-auth": "^0.7.14",
2123
"@convex-dev/react-query": "0.0.0-alpha.8",
2224
"@erquhart/convex-oss-stats": "^0.5.5",
2325
"@floating-ui/react": "^0.27.8",
@@ -50,8 +52,9 @@
5052
"airtable": "^0.12.2",
5153
"algoliasearch": "^5.23.4",
5254
"axios": "^1.6.7",
55+
"better-auth": "^1.3.7",
5356
"cmdk": "^1.1.1",
54-
"convex": "^1.17.2",
57+
"convex": "^1.25.4",
5558
"d3": "^7.9.0",
5659
"date-fns": "^2.30.0",
5760
"downshift": "^9.0.9",
@@ -76,7 +79,7 @@
7679
"tailwind-merge": "^1.14.0",
7780
"tiny-invariant": "^1.3.3",
7881
"vite-tsconfig-paths": "^5.0.1",
79-
"zod": "^3.23.8",
82+
"zod": "^4.0.17",
8083
"zustand": "^4.5.2"
8184
},
8285
"devDependencies": {

0 commit comments

Comments
 (0)