rhys
rhys
Explore posts from servers
BABetter Auth
Created by Oleh on 4/22/2025 in #help
Migration Guide from Clerk to Better Auth
Not yet, I suspect it's the sort of thing that's in the works
2 replies
BABetter Auth
Created by rhys on 4/21/2025 in #help
Cookies amongst multiple tenants, subdomains, and custom domains for a SaaS
Good to know that we have the same problem.
8 replies
BABetter Auth
Created by rhys on 4/21/2025 in #help
Cookies amongst multiple tenants, subdomains, and custom domains for a SaaS
async trustedOrigins (request) {
const directusAdmin = getDirectusInstance(undefined, DIRECTUS_ADMIN_TOKEN);
const allTenants = await directusAdmin.request(readItems('tenants', {
fields: ['url', 'subdomain'],
}))
const origins: string[] = [
PUBLIC_DOMAIN,
]
if (process.env.NODE_ENV === 'development') origins.push(
`https://www.${PUBLIC_COOKIE_DOMAIN}`)
const allOrigins = allTenants.reduce((acc, tenant) => {
// Handle custom domains stored in the 'url' field
if (typeof tenant.url === 'string' && tenant.url) {
// Ensure the URL is a valid origin format (https://domain.com)
try {
const parsedUrl = new URL(tenant.url);
if (parsedUrl.protocol === 'https:') {
acc.push(parsedUrl.origin);
}
} catch (e) {
console.error(`Invalid tenant URL format: ${tenant.url}`);
}
}
if (tenant.subdomain) {
acc.push(`https://${tenant.subdomain}.${PUBLIC_COOKIE_DOMAIN}`);
}
return acc;
}, origins);
if (process.env.NODE_ENV === 'development') {
console.log('Trusted Origins:', allOrigins)
}
return allOrigins;
},
plugins: [organization({

schema: {
organization: {
modelName: 'tenants',
fields: {
id: 'id',
name: 'title',
slug: 'subdomain',
logo: 'logo',
metadata: 'metadata',
createdAt: 'date_created',
},
},
invitation: {
fields: {
expiresAt: 'expires_at',
inviterId: 'inviter_id',
organizationId: 'organization_id',
teamId: 'team_id',
}
},
member: {
fields: {
organizationId: 'organization_id',
userId: 'user_id',
role: 'role',
status: 'status',
},
},
session: {
fields: {
activeOrganizationId: 'active_organization_id',
}
},
user: {
fields: {
organizationId: 'organization_id',
userId: 'user_id',
}
},
}
})]
});
async trustedOrigins (request) {
const directusAdmin = getDirectusInstance(undefined, DIRECTUS_ADMIN_TOKEN);
const allTenants = await directusAdmin.request(readItems('tenants', {
fields: ['url', 'subdomain'],
}))
const origins: string[] = [
PUBLIC_DOMAIN,
]
if (process.env.NODE_ENV === 'development') origins.push(
`https://www.${PUBLIC_COOKIE_DOMAIN}`)
const allOrigins = allTenants.reduce((acc, tenant) => {
// Handle custom domains stored in the 'url' field
if (typeof tenant.url === 'string' && tenant.url) {
// Ensure the URL is a valid origin format (https://domain.com)
try {
const parsedUrl = new URL(tenant.url);
if (parsedUrl.protocol === 'https:') {
acc.push(parsedUrl.origin);
}
} catch (e) {
console.error(`Invalid tenant URL format: ${tenant.url}`);
}
}
if (tenant.subdomain) {
acc.push(`https://${tenant.subdomain}.${PUBLIC_COOKIE_DOMAIN}`);
}
return acc;
}, origins);
if (process.env.NODE_ENV === 'development') {
console.log('Trusted Origins:', allOrigins)
}
return allOrigins;
},
plugins: [organization({

schema: {
organization: {
modelName: 'tenants',
fields: {
id: 'id',
name: 'title',
slug: 'subdomain',
logo: 'logo',
metadata: 'metadata',
createdAt: 'date_created',
},
},
invitation: {
fields: {
expiresAt: 'expires_at',
inviterId: 'inviter_id',
organizationId: 'organization_id',
teamId: 'team_id',
}
},
member: {
fields: {
organizationId: 'organization_id',
userId: 'user_id',
role: 'role',
status: 'status',
},
},
session: {
fields: {
activeOrganizationId: 'active_organization_id',
}
},
user: {
fields: {
organizationId: 'organization_id',
userId: 'user_id',
}
},
}
})]
});
8 replies
BABetter Auth
Created by rhys on 4/21/2025 in #help
Cookies amongst multiple tenants, subdomains, and custom domains for a SaaS
export const auth = betterAuth({
appName: PUBLIC_APP_NAME,
baseURL: PUBLIC_DOMAIN,
secret: DIRECTUS_SECRET,
emailAndPassword: {
enabled: true,
password: {
hash(password) {
const directus = getDirectusInstance();
return directus.request(generateHash(password))
},
verify({ hash, password}) {
const directus = getDirectusInstance();
return directus.request(verifyHash(password, hash))
},
}
},
advanced: {
database: {
generateId () { return crypto.randomUUID() },
},
crossSubDomainCookies: {
enabled: true,
domain: `.${PUBLIC_COOKIE_DOMAIN}`,
},

cookiePrefix: 'directus',
defaultCookieAttributes: {
secure: true,
httpOnly: true,
sameSite: 'none',
partitioned: true,
},
},
database: new Pool({
connectionString: DB_CONNECTION_STRING,
}),
// database: drizzleAdapter(db, {
// provider: 'pg'
// }),
user: {
modelName: 'directus_users',
fields: {
name: 'first_name',
email: 'email',
image: 'avatar',
createdAt: 'date_created',
updatedAt: 'date_updated',
emailVerified: 'email_verified',
}
},
session: {
modelName: 'directus_sessions',
fields: {
// id has to be initialised with gen_random_uuid() in the database as the default
userId: 'user',
expiresAt: 'expires',
ipAddress: 'ip',
userAgent: 'user_agent',
token: 'token',
createdAt: 'date_created',
updatedAt: 'date_updated',
}
},
verification: {
modelName: 'verification',
fields: {
createdAt: 'date_created',
updatedAt: 'date_updated',
expiresAt: 'expires_at',
value: 'value',
identifier: 'identifier',
},
},
account: {
modelName: 'account',
fields: {
accountId: 'account_id',
userId: 'user_id',
accessToken: 'access_token',
refreshToken: 'refresh_token',
idToken: 'id_token',
providerId: 'provider_id',
accessTokenExpiresAt: "access_token_expires_at",
refreshTokenExpiresAt: "refresh_token_expires_at",
scope: 'scope',
password: 'password',
createdAt: 'date_created',
updatedAt: 'date_updated',
}
},
socialProviders: {
google: {
clientId: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
mapProfileToUser: (profile) => {
return {
firstName: profile.given_name,
lastName: profile.family_name,
image: profile.picture
};
},
}
},
export const auth = betterAuth({
appName: PUBLIC_APP_NAME,
baseURL: PUBLIC_DOMAIN,
secret: DIRECTUS_SECRET,
emailAndPassword: {
enabled: true,
password: {
hash(password) {
const directus = getDirectusInstance();
return directus.request(generateHash(password))
},
verify({ hash, password}) {
const directus = getDirectusInstance();
return directus.request(verifyHash(password, hash))
},
}
},
advanced: {
database: {
generateId () { return crypto.randomUUID() },
},
crossSubDomainCookies: {
enabled: true,
domain: `.${PUBLIC_COOKIE_DOMAIN}`,
},

cookiePrefix: 'directus',
defaultCookieAttributes: {
secure: true,
httpOnly: true,
sameSite: 'none',
partitioned: true,
},
},
database: new Pool({
connectionString: DB_CONNECTION_STRING,
}),
// database: drizzleAdapter(db, {
// provider: 'pg'
// }),
user: {
modelName: 'directus_users',
fields: {
name: 'first_name',
email: 'email',
image: 'avatar',
createdAt: 'date_created',
updatedAt: 'date_updated',
emailVerified: 'email_verified',
}
},
session: {
modelName: 'directus_sessions',
fields: {
// id has to be initialised with gen_random_uuid() in the database as the default
userId: 'user',
expiresAt: 'expires',
ipAddress: 'ip',
userAgent: 'user_agent',
token: 'token',
createdAt: 'date_created',
updatedAt: 'date_updated',
}
},
verification: {
modelName: 'verification',
fields: {
createdAt: 'date_created',
updatedAt: 'date_updated',
expiresAt: 'expires_at',
value: 'value',
identifier: 'identifier',
},
},
account: {
modelName: 'account',
fields: {
accountId: 'account_id',
userId: 'user_id',
accessToken: 'access_token',
refreshToken: 'refresh_token',
idToken: 'id_token',
providerId: 'provider_id',
accessTokenExpiresAt: "access_token_expires_at",
refreshTokenExpiresAt: "refresh_token_expires_at",
scope: 'scope',
password: 'password',
createdAt: 'date_created',
updatedAt: 'date_updated',
}
},
socialProviders: {
google: {
clientId: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
mapProfileToUser: (profile) => {
return {
firstName: profile.given_name,
lastName: profile.family_name,
image: profile.picture
};
},
}
},
8 replies
BABetter Auth
Created by rhys on 4/21/2025 in #help
Cookies amongst multiple tenants, subdomains, and custom domains for a SaaS
PUBLIC_DOMAIN is https://localhost:5173 and PUBLIC_COOKIE_DOMAIN is localhost:5173
8 replies
BABetter Auth
Created by rhys on 4/21/2025 in #help
Cookies amongst multiple tenants, subdomains, and custom domains for a SaaS
req headers for sign-up via email:
POST /api/auth/sign-up/email HTTP/2
Host: peggy.localhost:5173
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0
Accept: */*
Accept-Language: en-AU,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Referer: https://peggy.localhost:5173/signin
content-type: application/json
Content-Length: 186
Origin: https://peggy.localhost:5173
DNT: 1
Connection: keep-alive
Cookie: __Host-__Secure-directus.session_token=Penk9Datqsju9A8dOYso7hGjXgOoqKkf.oc7keEUnUPZ0LTOj2lp%2FrvPe4J5YhbApI2Uhf4heQkw%3D
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Priority: u=0
Pragma: no-cache
Cache-Control: no-cache
TE: trailers
POST /api/auth/sign-up/email HTTP/2
Host: peggy.localhost:5173
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0
Accept: */*
Accept-Language: en-AU,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br, zstd
Referer: https://peggy.localhost:5173/signin
content-type: application/json
Content-Length: 186
Origin: https://peggy.localhost:5173
DNT: 1
Connection: keep-alive
Cookie: __Host-__Secure-directus.session_token=Penk9Datqsju9A8dOYso7hGjXgOoqKkf.oc7keEUnUPZ0LTOj2lp%2FrvPe4J5YhbApI2Uhf4heQkw%3D
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Priority: u=0
Pragma: no-cache
Cache-Control: no-cache
TE: trailers
response headers:
HTTP/2 200
access-control-allow-origin: *
vary: Origin
content-type: application/json
set-cookie: __Secure-directus.session_token=onz6fOWLpPbJhf2yCeh57tqIjOsTe6xM.jeemRnvxeWtSbTmnA1o%2B%2F95yTDLGrjiqbjAO6iMjRs8%3D; Max-Age=604800; Domain=.localhost:5173; Path=/; HttpOnly; Secure; SameSite=None; Partitioned
date: Mon, 21 Apr 2025 11:20:09 GMT
X-Firefox-Spdy: h2
HTTP/2 200
access-control-allow-origin: *
vary: Origin
content-type: application/json
set-cookie: __Secure-directus.session_token=onz6fOWLpPbJhf2yCeh57tqIjOsTe6xM.jeemRnvxeWtSbTmnA1o%2B%2F95yTDLGrjiqbjAO6iMjRs8%3D; Max-Age=604800; Domain=.localhost:5173; Path=/; HttpOnly; Secure; SameSite=None; Partitioned
date: Mon, 21 Apr 2025 11:20:09 GMT
X-Firefox-Spdy: h2
8 replies
BABetter Auth
Created by rhys on 4/12/2025 in #help
Output debug mode?
Hot damn! It's at the very least inserted the dummy data in the user table in the db- I get
error {"length":130,"name":"error","severity":"ERROR","code":"42703","position":"38","file":"parse_target.c","line":"1065","routine":"checkInsertTargets"}
error {"length":130,"name":"error","severity":"ERROR","code":"42703","position":"38","file":"parse_target.c","line":"1065","routine":"checkInsertTargets"}
. The account table is empty, but this is well and truly progress.
35 replies
BABetter Auth
Created by rhys on 4/12/2025 in #help
Output debug mode?
If database is an object, how do I pass the postgres pool? i.e.
database: {
generateId: false,
db: new Pool({
connectionString: DATABASE_URL
})
},
database: {
generateId: false,
db: new Pool({
connectionString: DATABASE_URL
})
},
35 replies
BABetter Auth
Created by rhys on 4/12/2025 in #help
Output debug mode?
I think the docs are just a touch out of date, generateId has shifted to database according to the intellisense
35 replies
BABetter Auth
Created by s on 4/12/2025 in #help
guys, is it possible to do with better-aauth??
12 replies
BABetter Auth
Created by rhys on 4/12/2025 in #help
Output debug mode?
Ok! That worked too. Now, it's returning 2025-04-13T00:04:21.563Z ERROR [Better Auth]: Failed to create user error: invalid input syntax for type uuid: "b7g00pstBsS5FGSuTitnYGpkIxe2RBzK". The id generated by BetterAuth likely doesn't jive with the uuid PK. I can see the generateId function that's being called as part of the create user flow is a pretty straightforward wrapper, is there any possibility that this could be extended to allow for uuid use?
35 replies
BABetter Auth
Created by rhys on 4/12/2025 in #help
Output debug mode?
Thanks so much! I'll give that a shot.
35 replies
BABetter Auth
Created by s on 4/12/2025 in #help
guys, is it possible to do with better-aauth??
As Nico says, hooks sound like they'd do the trick. Just fyi it's not great manners to ping maintainers directly- they literally just pushed a new release, and are very busy.
12 replies
BABetter Auth
Created by rhys on 4/12/2025 in #help
Output debug mode?
Nuts. Is there any way to coerce it? I don't think directus supports it being a Date.
35 replies
BABetter Auth
Created by rhys on 4/12/2025 in #help
Output debug mode?
Ahh yeah, you're one hundred percent right, looks like it is a drizzle thing. And updating to the beta has resulted in a fun new error-
bash ERROR [Better Auth]: Failed to create user TypeError [ERR_INVALID_ARG_TYPE]: The "string" argument must be of type string or an instance of Buffer or ArrayBuffer. Received an instance of Date
bash ERROR [Better Auth]: Failed to create user TypeError [ERR_INVALID_ARG_TYPE]: The "string" argument must be of type string or an instance of Buffer or ArrayBuffer. Received an instance of Date
Looks like the type is wrong for one of the columns on the users table, but the only two are date_created and date_updated, which are timestamp({ mode: 'string' }).
export const directus_users = pgTable("directus_users", {
id: uuid().primaryKey().notNull(),
first_name: varchar({ length: 50 }),
last_name: varchar({ length: 50 }),
email: varchar({ length: 128 }),
password: varchar({ length: 255 }),
location: varchar({ length: 255 }),
title: varchar({ length: 50 }),
description: text(),
tags: json(),
avatar: uuid(),
language: varchar({ length: 255 }).default(sql`NULL`),
tfa_secret: varchar({ length: 255 }),
status: varchar({ length: 16 }).default('active').notNull(),
role: uuid(),
token: varchar({ length: 255 }),
last_access: timestamp({ withTimezone: true, mode: 'string' }),
last_page: varchar({ length: 255 }),
provider: varchar({ length: 128 }).default('default').notNull(),
external_identifier: varchar({ length: 255 }),
auth_data: json(),
email_notifications: boolean().default(true),
appearance: varchar({ length: 255 }),
theme_dark: varchar({ length: 255 }),
theme_light: varchar({ length: 255 }),
theme_light_overrides: json(),
theme_dark_overrides: json(),
short_bio: text(),
biography: text(),
hero_image: uuid(),
is_group: boolean().default(false),
social_media: json(),
date_created: timestamp({ mode: 'string' }),
date_updated: timestamp({ mode: 'string' }),
email_verified: boolean().default(false).notNull(),
}, (table) => [
foreignKey({
columns: [table.hero_image],
foreignColumns: [directus_files.id],
name: "directus_users_hero_image_foreign"
}).onDelete("set null"),
foreignKey({
columns: [table.role],
foreignColumns: [directus_roles.id],
name: "directus_users_role_foreign"
}).onDelete("set null"),
unique("directus_users_email_unique").on(table.email),
unique("directus_users_token_unique").on(table.token),
unique("directus_users_external_identifier_unique").on(table.external_identifier),
]);
export const directus_users = pgTable("directus_users", {
id: uuid().primaryKey().notNull(),
first_name: varchar({ length: 50 }),
last_name: varchar({ length: 50 }),
email: varchar({ length: 128 }),
password: varchar({ length: 255 }),
location: varchar({ length: 255 }),
title: varchar({ length: 50 }),
description: text(),
tags: json(),
avatar: uuid(),
language: varchar({ length: 255 }).default(sql`NULL`),
tfa_secret: varchar({ length: 255 }),
status: varchar({ length: 16 }).default('active').notNull(),
role: uuid(),
token: varchar({ length: 255 }),
last_access: timestamp({ withTimezone: true, mode: 'string' }),
last_page: varchar({ length: 255 }),
provider: varchar({ length: 128 }).default('default').notNull(),
external_identifier: varchar({ length: 255 }),
auth_data: json(),
email_notifications: boolean().default(true),
appearance: varchar({ length: 255 }),
theme_dark: varchar({ length: 255 }),
theme_light: varchar({ length: 255 }),
theme_light_overrides: json(),
theme_dark_overrides: json(),
short_bio: text(),
biography: text(),
hero_image: uuid(),
is_group: boolean().default(false),
social_media: json(),
date_created: timestamp({ mode: 'string' }),
date_updated: timestamp({ mode: 'string' }),
email_verified: boolean().default(false).notNull(),
}, (table) => [
foreignKey({
columns: [table.hero_image],
foreignColumns: [directus_files.id],
name: "directus_users_hero_image_foreign"
}).onDelete("set null"),
foreignKey({
columns: [table.role],
foreignColumns: [directus_roles.id],
name: "directus_users_role_foreign"
}).onDelete("set null"),
unique("directus_users_email_unique").on(table.email),
unique("directus_users_token_unique").on(table.token),
unique("directus_users_external_identifier_unique").on(table.external_identifier),
]);
35 replies
BABetter Auth
Created by rhys on 4/12/2025 in #help
Output debug mode?
35 replies
BABetter Auth
Created by rhys on 4/12/2025 in #help
Output debug mode?
Of course!
export const auth = betterAuth({
appName: PUBLIC_APP_NAME,
baseURL: PUBLIC_URL,
emailAndPassword: {
enabled: true,
},
user: {
modelName: 'directus_users',
fields: {
name: 'first_name',
email: 'email',
image: 'avatar',
createdAt: 'date_created',
updatedAt: 'date_updated',
emailVerified: 'email_verified',
}
},
session: {
modelName: 'directus_sessions',
fields: {

userId: 'user',
expiresAt: 'expires',
ipAddress: 'ip',
userAgent: 'user_agent',
token: 'token',
createdAt: 'date_created',
updatedAt: 'date_updated',
}
},
verification: {
modelName: 'verification',
fields: {
createdAt: 'date_created',
updatedAt: 'date_updated',
expiresAt: 'expires_at' ,
value: 'value',
identifier: 'identifier',
},
},
database: drizzleAdapter(db, {
schema: {
verification,
directus_users,
directus_sessions,
account
},
provider: "pg", // or "pg" or "mysql"
}),
}
export const auth = betterAuth({
appName: PUBLIC_APP_NAME,
baseURL: PUBLIC_URL,
emailAndPassword: {
enabled: true,
},
user: {
modelName: 'directus_users',
fields: {
name: 'first_name',
email: 'email',
image: 'avatar',
createdAt: 'date_created',
updatedAt: 'date_updated',
emailVerified: 'email_verified',
}
},
session: {
modelName: 'directus_sessions',
fields: {

userId: 'user',
expiresAt: 'expires',
ipAddress: 'ip',
userAgent: 'user_agent',
token: 'token',
createdAt: 'date_created',
updatedAt: 'date_updated',
}
},
verification: {
modelName: 'verification',
fields: {
createdAt: 'date_created',
updatedAt: 'date_updated',
expiresAt: 'expires_at' ,
value: 'value',
identifier: 'identifier',
},
},
database: drizzleAdapter(db, {
schema: {
verification,
directus_users,
directus_sessions,
account
},
provider: "pg", // or "pg" or "mysql"
}),
}
I'm trying to get Better Auth using the existing auth tables for Directus, a headless CMS. Unfortunately, their auth isn't quite as well thought out, and they colocate their account stuff with their user table, which (amongst other things) means that they can't have multiple OAuth providers attached to the same account. So I have manually created the missing account and verification tables, and am remapping the users and sessions tables that already exist. I'm just trying to get the sign up w/ email working as a proof of concept, but I'm running into the error when I try the auth.api.signUpEmail() method.
35 replies
BABetter Auth
Created by rhys on 4/9/2025 in #help
The field "id" does not exist in the "verification" schema
You're absolutely right! Thanks so much.
21 replies
BABetter Auth
Created by rhys on 4/9/2025 in #help
The field "id" does not exist in the "verification" schema
Ahhh yeah, I can see that. I've removed that, but it's still returning the same issue.
21 replies
BABetter Auth
Created by rhys on 4/9/2025 in #help
The field "id" does not exist in the "verification" schema
// schema.ts

export const directus_users = pgTable("directus_users", {
id: uuid().primaryKey().notNull(),
first_name: varchar({ length: 50 }),
last_name: varchar({ length: 50 }),
email: varchar({ length: 128 }),
password: varchar({ length: 255 }),
location: varchar({ length: 255 }),
title: varchar({ length: 50 }),
description: text(),
tags: json(),
avatar: uuid(),
language: varchar({ length: 255 }).default(sql`NULL`),
tfa_secret: varchar({ length: 255 }),
status: varchar({ length: 16 }).default('active').notNull(),
role: uuid(),
token: varchar({ length: 255 }),
last_access: timestamp({ withTimezone: true, mode: 'string' }),
last_page: varchar({ length: 255 }),
provider: varchar({ length: 128 }).default('default').notNull(),
external_identifier: varchar({ length: 255 }),
auth_data: json(),
email_notifications: boolean().default(true),
appearance: varchar({ length: 255 }),
theme_dark: varchar({ length: 255 }),
theme_light: varchar({ length: 255 }),
theme_light_overrides: json(),
theme_dark_overrides: json(),
short_bio: text(),
biography: text(),
hero_image: uuid(),
is_group: boolean().default(false),
social_media: json(),
date_created: timestamp({ mode: 'string' }),
date_updated: timestamp({ mode: 'string' }),
}, (table) => [
foreignKey({
columns: [table.hero_image],
foreignColumns: [directus_files.id],
name: "directus_users_hero_image_foreign"
}).onDelete("set null"),
foreignKey({
columns: [table.role],
foreignColumns: [directus_roles.id],
name: "directus_users_role_foreign"
}).onDelete("set null"),
unique("directus_users_email_unique").on(table.email),
unique("directus_users_token_unique").on(table.token),
unique("directus_users_external_identifier_unique").on(table.external_identifier),
]);


export const directus_sessions = pgTable("directus_sessions", {
token: varchar({ length: 64 }).primaryKey().notNull(),
user: uuid(),
expires: timestamp({ withTimezone: true, mode: 'string' }).notNull(),
ip: varchar({ length: 255 }),
user_agent: text(),
share: uuid(),
origin: varchar({ length: 255 }),
next_token: varchar({ length: 64 }),
}, (table) => [
foreignKey({
columns: [table.share],
foreignColumns: [directus_shares.id],
name: "directus_sessions_share_foreign"
}).onDelete("cascade"),
foreignKey({
columns: [table.user],
foreignColumns: [directus_users.id],
name: "directus_sessions_user_foreign"
}).onDelete("cascade"),
]);

export const verification = pgTable("verification", {
id: text().primaryKey().notNull(),
date_created: timestamp({ mode: 'string' }),
expires_at: timestamp({ mode: 'string' }).notNull(),
value: text().notNull(),
identifier: text(),
date_updated: timestamp({ mode: 'string' }),
});

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(()=> directus_users.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()
});
// schema.ts

export const directus_users = pgTable("directus_users", {
id: uuid().primaryKey().notNull(),
first_name: varchar({ length: 50 }),
last_name: varchar({ length: 50 }),
email: varchar({ length: 128 }),
password: varchar({ length: 255 }),
location: varchar({ length: 255 }),
title: varchar({ length: 50 }),
description: text(),
tags: json(),
avatar: uuid(),
language: varchar({ length: 255 }).default(sql`NULL`),
tfa_secret: varchar({ length: 255 }),
status: varchar({ length: 16 }).default('active').notNull(),
role: uuid(),
token: varchar({ length: 255 }),
last_access: timestamp({ withTimezone: true, mode: 'string' }),
last_page: varchar({ length: 255 }),
provider: varchar({ length: 128 }).default('default').notNull(),
external_identifier: varchar({ length: 255 }),
auth_data: json(),
email_notifications: boolean().default(true),
appearance: varchar({ length: 255 }),
theme_dark: varchar({ length: 255 }),
theme_light: varchar({ length: 255 }),
theme_light_overrides: json(),
theme_dark_overrides: json(),
short_bio: text(),
biography: text(),
hero_image: uuid(),
is_group: boolean().default(false),
social_media: json(),
date_created: timestamp({ mode: 'string' }),
date_updated: timestamp({ mode: 'string' }),
}, (table) => [
foreignKey({
columns: [table.hero_image],
foreignColumns: [directus_files.id],
name: "directus_users_hero_image_foreign"
}).onDelete("set null"),
foreignKey({
columns: [table.role],
foreignColumns: [directus_roles.id],
name: "directus_users_role_foreign"
}).onDelete("set null"),
unique("directus_users_email_unique").on(table.email),
unique("directus_users_token_unique").on(table.token),
unique("directus_users_external_identifier_unique").on(table.external_identifier),
]);


export const directus_sessions = pgTable("directus_sessions", {
token: varchar({ length: 64 }).primaryKey().notNull(),
user: uuid(),
expires: timestamp({ withTimezone: true, mode: 'string' }).notNull(),
ip: varchar({ length: 255 }),
user_agent: text(),
share: uuid(),
origin: varchar({ length: 255 }),
next_token: varchar({ length: 64 }),
}, (table) => [
foreignKey({
columns: [table.share],
foreignColumns: [directus_shares.id],
name: "directus_sessions_share_foreign"
}).onDelete("cascade"),
foreignKey({
columns: [table.user],
foreignColumns: [directus_users.id],
name: "directus_sessions_user_foreign"
}).onDelete("cascade"),
]);

export const verification = pgTable("verification", {
id: text().primaryKey().notNull(),
date_created: timestamp({ mode: 'string' }),
expires_at: timestamp({ mode: 'string' }).notNull(),
value: text().notNull(),
identifier: text(),
date_updated: timestamp({ mode: 'string' }),
});

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(()=> directus_users.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()
});
21 replies