rhys
Explore posts from serversBABetter Auth
•Created by rhys on 4/24/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',
}
},
}
})]
});
6 replies
BABetter Auth
•Created by rhys on 4/24/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
};
},
}
},
6 replies
BABetter Auth
•Created by rhys on 4/24/2025 in #help
Cookies amongst multiple tenants, subdomains, and custom domains for a SaaS
6 replies
BABetter Auth
•Created by Ashwanee Kumar Gupta on 4/22/2025 in #help
redirect_uri starts with http
What's your better auth config?
5 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 we have the same problem. Hopefully there's an easy fix!
9 replies
BABetter Auth
•Created by farhan on 4/14/2025 in #help
Stripe Subscription Update Shows Error in Console but Still Works
Have you downgraded to 17.7.0?
10 replies
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
3 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',
}
},
}
})]
});
9 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
};
},
}
},
9 replies
BABetter Auth
•Created by rhys on 4/21/2025 in #help
Cookies amongst multiple tenants, subdomains, and custom domains for a SaaS
9 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:
response headers:
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
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
9 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 . The account table is empty, but this is well and truly progress.
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"}
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 intellisense35 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-
Looks like the type is wrong for one of the columns on the users table, but the only two are
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
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