Better auth
2. Drizzle
Cài đặt drizzle
Cài đặt drizzle
pnpm add drizzle-ormCài đặt kit
pnpm add -D drizzle-kitCài đặt neon DB driver
pnpm add @neondatabase/serverlesscài đặt môi trường
pnpm add dotenvCài đặt Neon
- Đăng ký tài khoản neon
- Lấy URL và cập nhật
.env
postgres://username:password@ep-cool-darkness-123456.us-east-2.aws.neon.tech/neondb- Bổ sung vào file
.env
DATABASE_URL=NEON_DATABASE_CONNECTION_STRING- Tạo file
src/db/drizzle.ts
import { config } from "dotenv";
import { drizzle } from 'drizzle-orm/neon-http';
config({ path: ".env" }); // or .env.local
export const db = drizzle(process.env.DATABASE_URL!);- Tạo schema
import { integer, text, boolean, pgTable } from "drizzle-orm/pg-core";
export const todo = pgTable("todo", {
id: integer("id").primaryKey(),
text: text("text").notNull(),
done: boolean("done").default(false).notNull(),
});- Tạo file cấu hình
nằm ngang hàng file .env
import { config } from 'dotenv';
import { defineConfig } from "drizzle-kit";
config({ path: '.env' });
export default defineConfig({
schema: "./src/db/schema.ts",
out: "./migrations",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL!,
},
});- Chạy khởi tạo
npx @better-auth/cli generatechọn yes để khởi tạo schema
√ Do you want to generate the schema to ./auth-schema.ts? ... yes 2025-08-10T10:02:15.493Z SUCCESS [Better Auth]: 🚀 Schema was generated successfully!
- Thay thế nội dung file schema
Cập nhật lại file db/schema và xoá file đã tạo ở trên
import {
pgTable,
text,
timestamp,
boolean,
integer,
} from "drizzle-orm/pg-core";
export const user = pgTable("user", {
id: text("id").primaryKey(),
name: text("name").notNull(),
email: text("email").notNull().unique(),
emailVerified: boolean("email_verified")
.$defaultFn(() => false)
.notNull(),
image: text("image"),
createdAt: timestamp("created_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
updatedAt: timestamp("updated_at")
.$defaultFn(() => /* @__PURE__ */ new Date())
.notNull(),
});
export const session = pgTable("session", {
id: text("id").primaryKey(),
expiresAt: timestamp("expires_at").notNull(),
token: text("token").notNull().unique(),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
ipAddress: text("ip_address"),
userAgent: text("user_agent"),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
});
export const account = pgTable("account", {
id: text("id").primaryKey(),
accountId: text("account_id").notNull(),
providerId: text("provider_id").notNull(),
userId: text("user_id")
.notNull()
.references(() => user.id, { onDelete: "cascade" }),
accessToken: text("access_token"),
refreshToken: text("refresh_token"),
idToken: text("id_token"),
accessTokenExpiresAt: timestamp("access_token_expires_at"),
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
scope: text("scope"),
password: text("password"),
createdAt: timestamp("created_at").notNull(),
updatedAt: timestamp("updated_at").notNull(),
});
export const verification = pgTable("verification", {
id: text("id").primaryKey(),
identifier: text("identifier").notNull(),
value: text("value").notNull(),
expiresAt: timestamp("expires_at").notNull(),
createdAt: timestamp("created_at").$defaultFn(
() => /* @__PURE__ */ new Date(),
),
updatedAt: timestamp("updated_at").$defaultFn(
() => /* @__PURE__ */ new Date(),
),
});- Tạo bảng table trên neon
npx drizzle-kit pushVào neon và kiểm tra xem 4 bảng mới tạo ra