mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-10 12:27:44 +00:00
feat: add onUpdate field on db schema generation (#4241)
Fixes: https://github.com/better-auth/better-auth/issues/4187
This commit is contained in:
@@ -201,6 +201,7 @@ exports[`init > should match config 1`] = `
|
|||||||
},
|
},
|
||||||
"updatedAt": {
|
"updatedAt": {
|
||||||
"fieldName": "updatedAt",
|
"fieldName": "updatedAt",
|
||||||
|
"onUpdate": [Function],
|
||||||
"required": true,
|
"required": true,
|
||||||
"type": "date",
|
"type": "date",
|
||||||
},
|
},
|
||||||
@@ -243,6 +244,7 @@ exports[`init > should match config 1`] = `
|
|||||||
},
|
},
|
||||||
"updatedAt": {
|
"updatedAt": {
|
||||||
"fieldName": "updatedAt",
|
"fieldName": "updatedAt",
|
||||||
|
"onUpdate": [Function],
|
||||||
"required": true,
|
"required": true,
|
||||||
"type": "date",
|
"type": "date",
|
||||||
},
|
},
|
||||||
@@ -300,6 +302,7 @@ exports[`init > should match config 1`] = `
|
|||||||
"updatedAt": {
|
"updatedAt": {
|
||||||
"defaultValue": [Function],
|
"defaultValue": [Function],
|
||||||
"fieldName": "updatedAt",
|
"fieldName": "updatedAt",
|
||||||
|
"onUpdate": [Function],
|
||||||
"required": true,
|
"required": true,
|
||||||
"type": "date",
|
"type": "date",
|
||||||
},
|
},
|
||||||
@@ -328,6 +331,7 @@ exports[`init > should match config 1`] = `
|
|||||||
"updatedAt": {
|
"updatedAt": {
|
||||||
"defaultValue": [Function],
|
"defaultValue": [Function],
|
||||||
"fieldName": "updatedAt",
|
"fieldName": "updatedAt",
|
||||||
|
"onUpdate": [Function],
|
||||||
"required": false,
|
"required": false,
|
||||||
"type": "date",
|
"type": "date",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -43,6 +43,13 @@ export type FieldAttributeConfig<T extends FieldType = FieldType> = {
|
|||||||
* be used when creating a new record.
|
* be used when creating a new record.
|
||||||
*/
|
*/
|
||||||
defaultValue?: Primitive | (() => Primitive);
|
defaultValue?: Primitive | (() => Primitive);
|
||||||
|
/**
|
||||||
|
* Update value for the field
|
||||||
|
*
|
||||||
|
* Note: This will create an onUpdate trigger on the database level for supported adapters.
|
||||||
|
* It will be called when updating a record.
|
||||||
|
*/
|
||||||
|
onUpdate?: () => Primitive;
|
||||||
/**
|
/**
|
||||||
* transform the value before storing it.
|
* transform the value before storing it.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ export const getAuthTables = (
|
|||||||
type: "date",
|
type: "date",
|
||||||
required: true,
|
required: true,
|
||||||
fieldName: options.session?.fields?.updatedAt || "updatedAt",
|
fieldName: options.session?.fields?.updatedAt || "updatedAt",
|
||||||
|
onUpdate: () => new Date(),
|
||||||
},
|
},
|
||||||
ipAddress: {
|
ipAddress: {
|
||||||
type: "string",
|
type: "string",
|
||||||
@@ -161,6 +162,7 @@ export const getAuthTables = (
|
|||||||
updatedAt: {
|
updatedAt: {
|
||||||
type: "date",
|
type: "date",
|
||||||
defaultValue: () => new Date(),
|
defaultValue: () => new Date(),
|
||||||
|
onUpdate: () => new Date(),
|
||||||
required: true,
|
required: true,
|
||||||
fieldName: options.user?.fields?.updatedAt || "updatedAt",
|
fieldName: options.user?.fields?.updatedAt || "updatedAt",
|
||||||
},
|
},
|
||||||
@@ -244,6 +246,7 @@ export const getAuthTables = (
|
|||||||
type: "date",
|
type: "date",
|
||||||
required: true,
|
required: true,
|
||||||
fieldName: options.account?.fields?.updatedAt || "updatedAt",
|
fieldName: options.account?.fields?.updatedAt || "updatedAt",
|
||||||
|
onUpdate: () => new Date(),
|
||||||
},
|
},
|
||||||
...account?.fields,
|
...account?.fields,
|
||||||
},
|
},
|
||||||
@@ -277,6 +280,7 @@ export const getAuthTables = (
|
|||||||
type: "date",
|
type: "date",
|
||||||
required: false,
|
required: false,
|
||||||
defaultValue: () => new Date(),
|
defaultValue: () => new Date(),
|
||||||
|
onUpdate: () => new Date(),
|
||||||
fieldName: options.verification?.fields?.updatedAt || "updatedAt",
|
fieldName: options.verification?.fields?.updatedAt || "updatedAt",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -160,6 +160,13 @@ export const generateDrizzleSchema: SchemaGenerator = async ({
|
|||||||
type += `.default(${attr.defaultValue})`;
|
type += `.default(${attr.defaultValue})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Add .$onUpdate() for fields with onUpdate property
|
||||||
|
// Supported for all database types: PostgreSQL, MySQL, and SQLite
|
||||||
|
if (attr.onUpdate && attr.type === "date") {
|
||||||
|
if (typeof attr.onUpdate === "function") {
|
||||||
|
type += `.$onUpdate(${attr.onUpdate})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
return `${field}: ${type}${attr.required ? ".notNull()" : ""}${
|
return `${field}: ${type}${attr.required ? ".notNull()" : ""}${
|
||||||
attr.unique ? ".unique()" : ""
|
attr.unique ? ".unique()" : ""
|
||||||
}${
|
}${
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
import {
|
||||||
|
mysqlTable,
|
||||||
|
varchar,
|
||||||
|
text,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
int,
|
||||||
|
} from "drizzle-orm/mysql-core";
|
||||||
|
|
||||||
|
export const custom_user = mysqlTable("custom_user", {
|
||||||
|
id: int("id").autoincrement().primaryKey(),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
email: varchar("email", { length: 255 }).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())
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
twoFactorEnabled: boolean("two_factor_enabled").default(false),
|
||||||
|
username: varchar("username", { length: 255 }).unique(),
|
||||||
|
displayUsername: text("display_username"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_session = mysqlTable("custom_session", {
|
||||||
|
id: int("id").autoincrement().primaryKey(),
|
||||||
|
expiresAt: timestamp("expires_at").notNull(),
|
||||||
|
token: varchar("token", { length: 255 }).notNull().unique(),
|
||||||
|
createdAt: timestamp("created_at").notNull(),
|
||||||
|
updatedAt: timestamp("updated_at")
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
ipAddress: text("ip_address"),
|
||||||
|
userAgent: text("user_agent"),
|
||||||
|
userId: int("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_user.id, { onDelete: "cascade" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_account = mysqlTable("custom_account", {
|
||||||
|
id: int("id").autoincrement().primaryKey(),
|
||||||
|
accountId: text("account_id").notNull(),
|
||||||
|
providerId: text("provider_id").notNull(),
|
||||||
|
userId: int("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_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")
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_verification = mysqlTable("custom_verification", {
|
||||||
|
id: int("id").autoincrement().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())
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const twoFactor = mysqlTable("two_factor", {
|
||||||
|
id: int("id").autoincrement().primaryKey(),
|
||||||
|
secret: text("secret").notNull(),
|
||||||
|
backupCodes: text("backup_codes").notNull(),
|
||||||
|
userId: int("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_user.id, { onDelete: "cascade" }),
|
||||||
|
});
|
||||||
84
packages/cli/test/__snapshots__/auth-schema-mysql.txt
Normal file
84
packages/cli/test/__snapshots__/auth-schema-mysql.txt
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import {
|
||||||
|
mysqlTable,
|
||||||
|
varchar,
|
||||||
|
text,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
} from "drizzle-orm/mysql-core";
|
||||||
|
|
||||||
|
export const custom_user = mysqlTable("custom_user", {
|
||||||
|
id: varchar("id", { length: 36 }).primaryKey(),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
email: varchar("email", { length: 255 }).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())
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
twoFactorEnabled: boolean("two_factor_enabled").default(false),
|
||||||
|
username: varchar("username", { length: 255 }).unique(),
|
||||||
|
displayUsername: text("display_username"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_session = mysqlTable("custom_session", {
|
||||||
|
id: varchar("id", { length: 36 }).primaryKey(),
|
||||||
|
expiresAt: timestamp("expires_at").notNull(),
|
||||||
|
token: varchar("token", { length: 255 }).notNull().unique(),
|
||||||
|
createdAt: timestamp("created_at").notNull(),
|
||||||
|
updatedAt: timestamp("updated_at")
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
ipAddress: text("ip_address"),
|
||||||
|
userAgent: text("user_agent"),
|
||||||
|
userId: varchar("user_id", { length: 36 })
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_user.id, { onDelete: "cascade" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_account = mysqlTable("custom_account", {
|
||||||
|
id: varchar("id", { length: 36 }).primaryKey(),
|
||||||
|
accountId: text("account_id").notNull(),
|
||||||
|
providerId: text("provider_id").notNull(),
|
||||||
|
userId: varchar("user_id", { length: 36 })
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_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")
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_verification = mysqlTable("custom_verification", {
|
||||||
|
id: varchar("id", { length: 36 }).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())
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const twoFactor = mysqlTable("two_factor", {
|
||||||
|
id: varchar("id", { length: 36 }).primaryKey(),
|
||||||
|
secret: text("secret").notNull(),
|
||||||
|
backupCodes: text("backup_codes").notNull(),
|
||||||
|
userId: varchar("user_id", { length: 36 })
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_user.id, { onDelete: "cascade" }),
|
||||||
|
});
|
||||||
@@ -20,6 +20,7 @@ export const custom_user = pgTable("custom_user", {
|
|||||||
.notNull(),
|
.notNull(),
|
||||||
updatedAt: timestamp("updated_at")
|
updatedAt: timestamp("updated_at")
|
||||||
.$defaultFn(() => /* @__PURE__ */ new Date())
|
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
.notNull(),
|
.notNull(),
|
||||||
twoFactorEnabled: boolean("two_factor_enabled").default(false),
|
twoFactorEnabled: boolean("two_factor_enabled").default(false),
|
||||||
username: text("username").unique(),
|
username: text("username").unique(),
|
||||||
@@ -31,7 +32,9 @@ export const custom_session = pgTable("custom_session", {
|
|||||||
expiresAt: timestamp("expires_at").notNull(),
|
expiresAt: timestamp("expires_at").notNull(),
|
||||||
token: text("token").notNull().unique(),
|
token: text("token").notNull().unique(),
|
||||||
createdAt: timestamp("created_at").notNull(),
|
createdAt: timestamp("created_at").notNull(),
|
||||||
updatedAt: timestamp("updated_at").notNull(),
|
updatedAt: timestamp("updated_at")
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
ipAddress: text("ip_address"),
|
ipAddress: text("ip_address"),
|
||||||
userAgent: text("user_agent"),
|
userAgent: text("user_agent"),
|
||||||
userId: integer("user_id")
|
userId: integer("user_id")
|
||||||
@@ -54,7 +57,9 @@ export const custom_account = pgTable("custom_account", {
|
|||||||
scope: text("scope"),
|
scope: text("scope"),
|
||||||
password: text("password"),
|
password: text("password"),
|
||||||
createdAt: timestamp("created_at").notNull(),
|
createdAt: timestamp("created_at").notNull(),
|
||||||
updatedAt: timestamp("updated_at").notNull(),
|
updatedAt: timestamp("updated_at")
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const custom_verification = pgTable("custom_verification", {
|
export const custom_verification = pgTable("custom_verification", {
|
||||||
@@ -65,9 +70,9 @@ export const custom_verification = pgTable("custom_verification", {
|
|||||||
createdAt: timestamp("created_at").$defaultFn(
|
createdAt: timestamp("created_at").$defaultFn(
|
||||||
() => /* @__PURE__ */ new Date(),
|
() => /* @__PURE__ */ new Date(),
|
||||||
),
|
),
|
||||||
updatedAt: timestamp("updated_at").$defaultFn(
|
updatedAt: timestamp("updated_at")
|
||||||
() => /* @__PURE__ */ new Date(),
|
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||||
),
|
.$onUpdate(() => /* @__PURE__ */ new Date()),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const twoFactor = pgTable("two_factor", {
|
export const twoFactor = pgTable("two_factor", {
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
|
||||||
|
|
||||||
|
export const custom_user = sqliteTable("custom_user", {
|
||||||
|
id: int("id").autoincrement().primaryKey(),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
email: text("email").notNull().unique(),
|
||||||
|
emailVerified: integer("email_verified", { mode: "boolean" })
|
||||||
|
.$defaultFn(() => false)
|
||||||
|
.notNull(),
|
||||||
|
image: text("image"),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp" })
|
||||||
|
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
twoFactorEnabled: integer("two_factor_enabled", { mode: "boolean" }).default(
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
username: text("username").unique(),
|
||||||
|
displayUsername: text("display_username"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_session = sqliteTable("custom_session", {
|
||||||
|
id: int("id").autoincrement().primaryKey(),
|
||||||
|
expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
|
||||||
|
token: text("token").notNull().unique(),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
ipAddress: text("ip_address"),
|
||||||
|
userAgent: text("user_agent"),
|
||||||
|
userId: integer("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_user.id, { onDelete: "cascade" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_account = sqliteTable("custom_account", {
|
||||||
|
id: int("id").autoincrement().primaryKey(),
|
||||||
|
accountId: text("account_id").notNull(),
|
||||||
|
providerId: text("provider_id").notNull(),
|
||||||
|
userId: integer("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_user.id, { onDelete: "cascade" }),
|
||||||
|
accessToken: text("access_token"),
|
||||||
|
refreshToken: text("refresh_token"),
|
||||||
|
idToken: text("id_token"),
|
||||||
|
accessTokenExpiresAt: integer("access_token_expires_at", {
|
||||||
|
mode: "timestamp",
|
||||||
|
}),
|
||||||
|
refreshTokenExpiresAt: integer("refresh_token_expires_at", {
|
||||||
|
mode: "timestamp",
|
||||||
|
}),
|
||||||
|
scope: text("scope"),
|
||||||
|
password: text("password"),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_verification = sqliteTable("custom_verification", {
|
||||||
|
id: int("id").autoincrement().primaryKey(),
|
||||||
|
identifier: text("identifier").notNull(),
|
||||||
|
value: text("value").notNull(),
|
||||||
|
expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn(
|
||||||
|
() => /* @__PURE__ */ new Date(),
|
||||||
|
),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const twoFactor = sqliteTable("two_factor", {
|
||||||
|
id: int("id").autoincrement().primaryKey(),
|
||||||
|
secret: text("secret").notNull(),
|
||||||
|
backupCodes: text("backup_codes").notNull(),
|
||||||
|
userId: integer("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_user.id, { onDelete: "cascade" }),
|
||||||
|
});
|
||||||
84
packages/cli/test/__snapshots__/auth-schema-sqlite.txt
Normal file
84
packages/cli/test/__snapshots__/auth-schema-sqlite.txt
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
|
||||||
|
|
||||||
|
export const custom_user = sqliteTable("custom_user", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
email: text("email").notNull().unique(),
|
||||||
|
emailVerified: integer("email_verified", { mode: "boolean" })
|
||||||
|
.$defaultFn(() => false)
|
||||||
|
.notNull(),
|
||||||
|
image: text("image"),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp" })
|
||||||
|
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
twoFactorEnabled: integer("two_factor_enabled", { mode: "boolean" }).default(
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
username: text("username").unique(),
|
||||||
|
displayUsername: text("display_username"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_session = sqliteTable("custom_session", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
|
||||||
|
token: text("token").notNull().unique(),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
ipAddress: text("ip_address"),
|
||||||
|
userAgent: text("user_agent"),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_user.id, { onDelete: "cascade" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_account = sqliteTable("custom_account", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
accountId: text("account_id").notNull(),
|
||||||
|
providerId: text("provider_id").notNull(),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_user.id, { onDelete: "cascade" }),
|
||||||
|
accessToken: text("access_token"),
|
||||||
|
refreshToken: text("refresh_token"),
|
||||||
|
idToken: text("id_token"),
|
||||||
|
accessTokenExpiresAt: integer("access_token_expires_at", {
|
||||||
|
mode: "timestamp",
|
||||||
|
}),
|
||||||
|
refreshTokenExpiresAt: integer("refresh_token_expires_at", {
|
||||||
|
mode: "timestamp",
|
||||||
|
}),
|
||||||
|
scope: text("scope"),
|
||||||
|
password: text("password"),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const custom_verification = sqliteTable("custom_verification", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
identifier: text("identifier").notNull(),
|
||||||
|
value: text("value").notNull(),
|
||||||
|
expiresAt: integer("expires_at", { mode: "timestamp" }).notNull(),
|
||||||
|
createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn(
|
||||||
|
() => /* @__PURE__ */ new Date(),
|
||||||
|
),
|
||||||
|
updatedAt: integer("updated_at", { mode: "timestamp" })
|
||||||
|
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const twoFactor = sqliteTable("two_factor", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
secret: text("secret").notNull(),
|
||||||
|
backupCodes: text("backup_codes").notNull(),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => custom_user.id, { onDelete: "cascade" }),
|
||||||
|
});
|
||||||
@@ -13,6 +13,7 @@ export const custom_user = pgTable("custom_user", {
|
|||||||
.notNull(),
|
.notNull(),
|
||||||
updatedAt: timestamp("updated_at")
|
updatedAt: timestamp("updated_at")
|
||||||
.$defaultFn(() => /* @__PURE__ */ new Date())
|
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
.notNull(),
|
.notNull(),
|
||||||
twoFactorEnabled: boolean("two_factor_enabled").default(false),
|
twoFactorEnabled: boolean("two_factor_enabled").default(false),
|
||||||
username: text("username").unique(),
|
username: text("username").unique(),
|
||||||
@@ -24,7 +25,9 @@ export const custom_session = pgTable("custom_session", {
|
|||||||
expiresAt: timestamp("expires_at").notNull(),
|
expiresAt: timestamp("expires_at").notNull(),
|
||||||
token: text("token").notNull().unique(),
|
token: text("token").notNull().unique(),
|
||||||
createdAt: timestamp("created_at").notNull(),
|
createdAt: timestamp("created_at").notNull(),
|
||||||
updatedAt: timestamp("updated_at").notNull(),
|
updatedAt: timestamp("updated_at")
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
ipAddress: text("ip_address"),
|
ipAddress: text("ip_address"),
|
||||||
userAgent: text("user_agent"),
|
userAgent: text("user_agent"),
|
||||||
userId: text("user_id")
|
userId: text("user_id")
|
||||||
@@ -47,7 +50,9 @@ export const custom_account = pgTable("custom_account", {
|
|||||||
scope: text("scope"),
|
scope: text("scope"),
|
||||||
password: text("password"),
|
password: text("password"),
|
||||||
createdAt: timestamp("created_at").notNull(),
|
createdAt: timestamp("created_at").notNull(),
|
||||||
updatedAt: timestamp("updated_at").notNull(),
|
updatedAt: timestamp("updated_at")
|
||||||
|
.$onUpdate(() => /* @__PURE__ */ new Date())
|
||||||
|
.notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const custom_verification = pgTable("custom_verification", {
|
export const custom_verification = pgTable("custom_verification", {
|
||||||
@@ -58,9 +63,9 @@ export const custom_verification = pgTable("custom_verification", {
|
|||||||
createdAt: timestamp("created_at").$defaultFn(
|
createdAt: timestamp("created_at").$defaultFn(
|
||||||
() => /* @__PURE__ */ new Date(),
|
() => /* @__PURE__ */ new Date(),
|
||||||
),
|
),
|
||||||
updatedAt: timestamp("updated_at").$defaultFn(
|
updatedAt: timestamp("updated_at")
|
||||||
() => /* @__PURE__ */ new Date(),
|
.$defaultFn(() => /* @__PURE__ */ new Date())
|
||||||
),
|
.$onUpdate(() => /* @__PURE__ */ new Date()),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const twoFactor = pgTable("two_factor", {
|
export const twoFactor = pgTable("two_factor", {
|
||||||
|
|||||||
169
packages/cli/test/generate-all-db.test.ts
Normal file
169
packages/cli/test/generate-all-db.test.ts
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { generateDrizzleSchema } from "../src/generators/drizzle";
|
||||||
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||||
|
import { twoFactor, username } from "better-auth/plugins";
|
||||||
|
import type { BetterAuthOptions } from "better-auth";
|
||||||
|
|
||||||
|
describe("generate drizzle schema for all databases", async () => {
|
||||||
|
it("should generate drizzle schema for MySQL", async () => {
|
||||||
|
const schema = await generateDrizzleSchema({
|
||||||
|
file: "test.drizzle",
|
||||||
|
adapter: drizzleAdapter(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
provider: "mysql",
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
)({} as BetterAuthOptions),
|
||||||
|
options: {
|
||||||
|
database: drizzleAdapter(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
provider: "mysql",
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
plugins: [twoFactor(), username()],
|
||||||
|
user: {
|
||||||
|
modelName: "custom_user",
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
modelName: "custom_account",
|
||||||
|
},
|
||||||
|
session: {
|
||||||
|
modelName: "custom_session",
|
||||||
|
},
|
||||||
|
verification: {
|
||||||
|
modelName: "custom_verification",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(schema.code).toMatchFileSnapshot(
|
||||||
|
"./__snapshots__/auth-schema-mysql.txt",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should generate drizzle schema for SQLite", async () => {
|
||||||
|
const schema = await generateDrizzleSchema({
|
||||||
|
file: "test.drizzle",
|
||||||
|
adapter: drizzleAdapter(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
provider: "sqlite",
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
)({} as BetterAuthOptions),
|
||||||
|
options: {
|
||||||
|
database: drizzleAdapter(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
provider: "sqlite",
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
plugins: [twoFactor(), username()],
|
||||||
|
user: {
|
||||||
|
modelName: "custom_user",
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
modelName: "custom_account",
|
||||||
|
},
|
||||||
|
session: {
|
||||||
|
modelName: "custom_session",
|
||||||
|
},
|
||||||
|
verification: {
|
||||||
|
modelName: "custom_verification",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(schema.code).toMatchFileSnapshot(
|
||||||
|
"./__snapshots__/auth-schema-sqlite.txt",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should generate drizzle schema for MySQL with number id", async () => {
|
||||||
|
const schema = await generateDrizzleSchema({
|
||||||
|
file: "test.drizzle",
|
||||||
|
adapter: drizzleAdapter(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
provider: "mysql",
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
)({} as BetterAuthOptions),
|
||||||
|
options: {
|
||||||
|
database: drizzleAdapter(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
provider: "mysql",
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
plugins: [twoFactor(), username()],
|
||||||
|
advanced: {
|
||||||
|
database: {
|
||||||
|
useNumberId: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
modelName: "custom_user",
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
modelName: "custom_account",
|
||||||
|
},
|
||||||
|
session: {
|
||||||
|
modelName: "custom_session",
|
||||||
|
},
|
||||||
|
verification: {
|
||||||
|
modelName: "custom_verification",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(schema.code).toMatchFileSnapshot(
|
||||||
|
"./__snapshots__/auth-schema-mysql-number-id.txt",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should generate drizzle schema for SQLite with number id", async () => {
|
||||||
|
const schema = await generateDrizzleSchema({
|
||||||
|
file: "test.drizzle",
|
||||||
|
adapter: drizzleAdapter(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
provider: "sqlite",
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
)({} as BetterAuthOptions),
|
||||||
|
options: {
|
||||||
|
database: drizzleAdapter(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
provider: "sqlite",
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
plugins: [twoFactor(), username()],
|
||||||
|
advanced: {
|
||||||
|
database: {
|
||||||
|
useNumberId: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
user: {
|
||||||
|
modelName: "custom_user",
|
||||||
|
},
|
||||||
|
account: {
|
||||||
|
modelName: "custom_account",
|
||||||
|
},
|
||||||
|
session: {
|
||||||
|
modelName: "custom_session",
|
||||||
|
},
|
||||||
|
verification: {
|
||||||
|
modelName: "custom_verification",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(schema.code).toMatchFileSnapshot(
|
||||||
|
"./__snapshots__/auth-schema-sqlite-number-id.txt",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user