Drizzle and NextAuth (trying to leave Supabase)
Unanswered
Pacific herring posted this in #help-forum
Pacific herringOP
Okay (hello @B33fb0n3 ) I have my all app build with Supabase. But I wanna something very "modular" so being stuck on Supabase isnt a good idea, that why I wnana switch with a default postgres database, so I need an ORM and NextAuth. Well lets try Drizzle (Prisma sound good too but many people say that Drizzle is more future proof). Firstly, Ive setup my Drizzle schema. I have 3 files inside
- index.ts
- auth.ts
- public.ts
My idea is to have a seperate schema only for auth table (like Supabase does and allows me to keep seperate sensible data like password etc...). So the index.ts file only concatenate the two schema like this :
Ive setup my "db" like this (ive previously try to setup with Neon but got TS error without any fancy stuff just the official docs ahah) :
@/db/schema/ :- index.ts
- auth.ts
- public.ts
My idea is to have a seperate schema only for auth table (like Supabase does and allows me to keep seperate sensible data like password etc...). So the index.ts file only concatenate the two schema like this :
import * as authSchema from '@/db/schema/auth'
import * as publicSchema from '@/db/schema/public'
const schema = {
...authSchema,
...publicSchema,
}
export default schema;Ive setup my "db" like this (ive previously try to setup with Neon but got TS error without any fancy stuff just the official docs ahah) :
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
import schema from '@/db/schema'
const connectionString = String(process.env.DATABASE_URL)
const client = postgres(connectionString)
export const db = drizzle(client, { schema });33 Replies
what's inside your authSchema and what kind of errors do you get? Where does "String" coming from? How does your "publicSchema" look like right now?
Pacific herringOP
Well right now the schema seems to work, the first problem is with my "users" table when I use the serial function for generating a random uuid, but I have this error when try to push change inside db :
There is my auth schema :
error: type "serial" does not existThere is my auth schema :
import {
timestamp,
text,
primaryKey,
integer,
pgSchema,
serial
} from "drizzle-orm/pg-core"
import type { AdapterAccount } from '@auth/core/adapters'
export const authSchema = pgSchema("auth")
export const users = authSchema.table("users", {
id: serial("id").primaryKey(),
email: text("email").notNull(),
email_verified: timestamp("email_verified", { mode: "date" }),
password: text("password"),
last_sign_in: timestamp("last_sign_in", { mode: "date" }),
create_at: timestamp("create_at", { mode: "date" }),
update_at: timestamp("update_at", { mode: "date" }),
})
export const accounts = authSchema.table("account", {
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
type: text("type").$type<AdapterAccount["type"]>().notNull(),
provider: text("provider").notNull(),
providerAccountId: text("providerAccountId").notNull(),
refresh_token: text("refresh_token"),
access_token: text("access_token"),
expires_at: integer("expires_at"),
token_type: text("token_type"),
scope: text("scope"),
id_token: text("id_token"),
session_state: text("session_state"),
},
(account) => ({
compoundKey: primaryKey({ columns: [account.provider, account.providerAccountId] }),
})
)
export const sessions = authSchema.table("session", {
sessionToken: text("sessionToken").notNull().primaryKey(),
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
expires: timestamp("expires", { mode: "date" }).notNull(),
})
export const verificationTokens = authSchema.table("verificationToken", {
identifier: text("identifier").notNull(),
token: text("token").notNull(),
expires: timestamp("expires", { mode: "date" }).notNull(),
},
(vt) => ({
compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
})
)@Pacific herring import {
timestamp,
text,
primaryKey,
integer,
pgSchema,
serial
} from "drizzle-orm/pg-core"
import type { AdapterAccount } from '@auth/core/adapters'
export const authSchema = pgSchema("auth")
export const users = authSchema.table("users", {
id: serial("id").primaryKey(),
email: text("email").notNull(),
email_verified: timestamp("email_verified", { mode: "date" }),
password: text("password"),
last_sign_in: timestamp("last_sign_in", { mode: "date" }),
create_at: timestamp("create_at", { mode: "date" }),
update_at: timestamp("update_at", { mode: "date" }),
})
export const accounts = authSchema.table("account", {
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
type: text("type").$type<AdapterAccount["type"]>().notNull(),
provider: text("provider").notNull(),
providerAccountId: text("providerAccountId").notNull(),
refresh_token: text("refresh_token"),
access_token: text("access_token"),
expires_at: integer("expires_at"),
token_type: text("token_type"),
scope: text("scope"),
id_token: text("id_token"),
session_state: text("session_state"),
},
(account) => ({
compoundKey: primaryKey({ columns: [account.provider, account.providerAccountId] }),
})
)
export const sessions = authSchema.table("session", {
sessionToken: text("sessionToken").notNull().primaryKey(),
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
expires: timestamp("expires", { mode: "date" }).notNull(),
})
export const verificationTokens = authSchema.table("verificationToken", {
identifier: text("identifier").notNull(),
token: text("token").notNull(),
expires: timestamp("expires", { mode: "date" }).notNull(),
},
(vt) => ({
compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
})
)
For me this seems like the table schema is beeing "confused" with the postgres serial type, which is normally just a number which increases, not a uuid. If you would like to use a uuid, use the uuid constraint. You can do it like that:
id: uuid("id").defaultRandom().primaryKey().notNull()@B33fb0n3 For me this seems like the table schema is beeing "confused" with the postgres serial type, which is normally just a number which increases, not a uuid. If you would like to use a uuid, use the uuid constraint. You can do it like that:
postgresql
id: uuid("id").defaultRandom().primaryKey().notNull()
Pacific herringOP
Im getting this error after :
error: column "id" cannot be cast automatically to type uuid
error: column "id" cannot be cast automatically to type uuid
do you have data inside the table that needs the id column?
@B33fb0n3 do you have data inside the table that needs the id column?
Pacific herringOP
Well probably something Ive just create new database in Neon for a fresh start and it seems to work
yes
Pacific herringOP
Okay now I can try to setup the NextAuth with it
sometimes its the best to just create a new database, model all your tables, relations, foreignkeys, primarykeys, ... and after you done that, you can push the schema
Pacific herringOP
When I do this :
Ive got an ts error in adapter :
And the docs say if u have multiple schemas, u should add inside DrizzleAdapter the schema like this I guess :
But I got another error in schema :
export const authOptions: NextAuthOptions = {
adapter: DrizzleAdapter(db),Ive got an ts error in adapter :
Type 'import("/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/@auth/core/adapters").Adapter' is not assignable to type 'import("/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next-auth/adapters").Adapter'.
Types of property 'createUser' are incompatible.
Type '((user: AdapterUser) => Awaitable<AdapterUser>) | undefined' is not assignable to type '((user: Omit<AdapterUser, "id">) => Awaitable<AdapterUser>) | undefined'.
Type '(user: AdapterUser) => Awaitable<AdapterUser>' is not assignable to type '(user: Omit<AdapterUser, "id">) => Awaitable<AdapterUser>'.
Types of parameters 'user' and 'user' are incompatible.
Property 'id' is missing in type 'Omit<AdapterUser, "id">' but required in type 'AdapterUser'.ts(2322)
adapters.d.ts(174, 5): 'id' is declared here.
types.d.ts(106, 5): The expected type comes from property 'adapter' which is declared here on type 'AuthOptions'And the docs say if u have multiple schemas, u should add inside DrizzleAdapter the schema like this I guess :
adapter: DrizzleAdapter(db, { schema }),But I got another error in schema :
Object literal may only specify known properties, and 'schema' does not exist in type 'PgTableFn<undefined>'.can I see your imports please?
@B33fb0n3 can I see your imports please?
Pacific herringOP
Sure, there is my auth.ts :
And
//...
import { db } from "@/db";
import schema from "@/db/schema";
export const authOptions: NextAuthOptions = {
adapter: DrizzleAdapter(db, { schema }),
secret: process.env.NEXTAUTH_SECRET,
// ...And
@/db/index.ts :import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
import schema from '@/db/schema'
const connectionString = String(process.env.DATABASE_URL)
const client = postgres(connectionString)
export const db = drizzle(client, { schema });@Pacific herring Sure, there is my auth.ts :
//...
import { db } from "@/db";
import schema from "@/db/schema";
export const authOptions: NextAuthOptions = {
adapter: DrizzleAdapter(db, { schema }),
secret: process.env.NEXTAUTH_SECRET,
// ...
And `@/db/index.ts` :
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
import schema from '@/db/schema'
const connectionString = String(process.env.DATABASE_URL)
const client = postgres(connectionString)
export const db = drizzle(client, { schema });
it seems like your
DrizzleAdapter isn't imported yet. It seems like thats another problem@B33fb0n3 it seems like your DrizzleAdapter isn't imported yet. It seems like thats another problem
Pacific herringOP
Ohh sry I didnt add it in my preview code but is imported (my bad)
There is my import :
import { NextAuthOptions } from "next-auth";
import { DrizzleAdapter } from "@auth/drizzle-adapter"
import { compare } from "bcrypt";
// Providers
import CredentialsProvider from "next-auth/providers/credentials";
import GithubProvider from "next-auth/providers/github";
import { db } from "@/db";
import schema from "@/db/schema";Ive got the same error with the default example from AuthJS :
export default NextAuth({
adapter: DrizzleAdapter(db),
providers: [
GithubProvider({
clientId: process.env.NEXTAUTH_GITHUB_ID as string,
clientSecret: process.env.NEXTAUTH_GITHUB_SECRET as string,
}),
],
})@Pacific herring Okay (hello <@301376057326567425> ) I have my all app build with Supabase. But I wanna something very "modular" so being stuck on Supabase isnt a good idea, that why I wnana switch with a default postgres database, so I need an ORM and NextAuth. Well lets try Drizzle (Prisma sound good too but many people say that Drizzle is more future proof). Firstly, Ive setup my Drizzle schema. I have 3 files inside `@/db/schema/` :
- index.ts
- auth.ts
- public.ts
My idea is to have a seperate schema only for auth table (like Supabase does and allows me to keep seperate sensible data like password etc...). So the index.ts file only concatenate the two schema like this :
import * as authSchema from '@/db/schema/auth'
import * as publicSchema from '@/db/schema/public'
const schema = {
...authSchema,
...publicSchema,
}
export default schema;
Ive setup my "db" like this (ive previously try to setup with Neon but got TS error without any fancy stuff just the official docs ahah) :
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
import schema from '@/db/schema'
const connectionString = String(process.env.DATABASE_URL)
const client = postgres(connectionString)
export const db = drizzle(client, { schema });
what drizzle version are you using? 0.29.4 has a ts bug https://github.com/drizzle-team/drizzle-orm/issues/1945 which seems related to your issue. use 0.29.3
yes then use "0.29.3" without the ^
Pacific herringOP
Dumby question, but how can I update the change ?
go to
package.json, change "^0.29.4" to "0.29.3", run npm install again@joulev go to `package.json`, change `"^0.29.4"` to `"0.29.3"`, run `npm install` again
Pacific herringOP
Well still having same problem, its propably due to my schema because the error is this :
Type 'import("/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/@auth/core/adapters").Adapter' is not assignable to type 'import("/Users/loup/Projects/DEV/Recomend/recomend-web-app/node_modules/next-auth/adapters").Adapter'.
Types of property 'createUser' are incompatible.
Type '((user: AdapterUser) => Awaitable<AdapterUser>) | undefined' is not assignable to type '((user: Omit<AdapterUser, "id">) => Awaitable<AdapterUser>) | undefined'.
Type '(user: AdapterUser) => Awaitable<AdapterUser>' is not assignable to type '(user: Omit<AdapterUser, "id">) => Awaitable<AdapterUser>'.
Types of parameters 'user' and 'user' are incompatible.
Property 'id' is missing in type 'Omit<AdapterUser, "id">' but required in type 'AdapterUser'.ts(2322)
adapters.d.ts(174, 5): 'id' is declared here.
types.d.ts(106, 5): The expected type comes from property 'adapter' which is declared here on type 'AuthOptions'okay I guess I found, I have a custom table "user" in public schema, but I was thinking that the adapter use table "users" but no, in the adapter I can see this :
So there is a conflict between my custom table user and the user one for auth
export function createTables(pgTable: PgTableFn) {
const users = pgTable("user", {
id: text("id").notNull().primaryKey(),
name: text("name"),
email: text("email").notNull(),
emailVerified: timestamp("emailVerified", { mode: "date" }),
image: text("image"),
})So there is a conflict between my custom table user and the user one for auth
I guess we cant custom the target table from
DrizzleAdapter@joulev oh this error is a bug in your code then, which i have no comments
Pacific herringOP
Yeah but using the DrizzleAdapter dont allows me to use custom table for auth. I just wanna separate auth schema from public shema because I dont wanna user can have access to the password variable from the users table from auth
Pacific herringOP
Well heaven with a custom adapter I still getting the same issue from
adapteranyway I just gonna put a ts-ignore for this
new problem during sign up a user, I cant get back the inserted row ?
Pacific herringOP
okay we only have an array as return value, that quite frustating
Pacific herringOP
I try to extend my Next Auth session with all user data, but where can I get the type from schema ?
With prisma :
import { user as PrismaUser } from "@prisma/client";
declare module "next-auth" {
interface User extends PrismaUser {}
interface Session {
user: User;
}
}
But how to achieve this with Drizzle ?
import { user as PrismaUser } from "@prisma/client";
declare module "next-auth" {
interface User extends PrismaUser {}
interface Session {
user: User;
}
}
But how to achieve this with Drizzle ?