Drizzle ORM support #7005
Replies: 9 comments 25 replies
-
Hello! I've seen a few public repositories have their custom adapter for working with the PlanetScale driver, but I think it is a great idea to add official Drizzle ORM support into NextAuth.js/Auth.js. I am willing to look into this and try to write an adapter that works with the supported databases. What do you think? Should I open a new issue? |
Beta Was this translation helpful? Give feedback.
-
+1 for Drizzle |
Beta Was this translation helpful? Give feedback.
-
I've read the note saying that feature requests are converted to discussions, and I decided to send updates and respond to any questions here, such that we can keep everything related to this topic in one place. I'll follow up with a pull request once I've made enough progress. Let me know if you have any suggestions on how I should proceed! |
Beta Was this translation helpful? Give feedback.
-
I'm having errors while trying to sign in with google, it says
I think someone else mentioned this on another issue but it hasn't been solved yet |
Beta Was this translation helpful? Give feedback.
-
follow up, the user seems to be created in the DB after signing in, however the error log shows and there's no redirect to main page |
Beta Was this translation helpful? Give feedback.
-
update 2: // ...
id_token: varchar('id_token', { length: 2555 }) the column is now 10x bigger so it should continue working |
Beta Was this translation helpful? Give feedback.
-
Anyone having issues with adding extra columns to the user model and then getting drizzle to save/retrieve that data? According to the docs it should be as simple as adding a new column to the schema and return the data from the profile() option. https://authjs.dev/guides/basics/role-based-access-control#with-database It should then be available in the user object in the session callback. Yet nothing happens when you return something from the profile function, nor is the property on the user in the session callback. Works fine with prisma. |
Beta Was this translation helpful? Give feedback.
-
Hello, I've been trying to do some sane customisation to the defaults and it's proven very annoying to do. Things I can't stand:
I'm thinking of:
I'd appreciate if someone explained to me the use of the I would like to create a solution that other people can use, but I feel as if NextAuth makes it impossible to provide a clean solution. In any case, if anyone managed to do it or have any thoughts, I'd appreciate your input. |
Beta Was this translation helpful? Give feedback.
-
An example of a custom drizzle adapter using queries api and also having relations for the user object. (roles and permissions) import type { Adapter } from "@auth/core/adapters";
import { and, eq } from "drizzle-orm";
import type { db } from "@acme/db";
import { schema } from "@acme/db";
export function mySqlDrizzleAdapter(client: typeof db): Adapter {
const { users, accounts, sessions, verificationTokens } = schema;
return {
async createUser(data) {
const id = crypto.randomUUID();
const name = data?.name ?? data.email?.split("@")[0];
console.log(name, data);
await client.insert(users).values({ ...data, name, id });
const user = await client.query.users.findFirst({
where: (user) => eq(user.id, id),
with: {
roles: true,
},
});
return user!;
},
async getUser(data) {
const thing =
(await client.query.users.findFirst({
where: (user) => eq(user.id, data),
with: {
roles: true,
},
})) ?? null;
return thing;
},
async getUserByEmail(data) {
const user =
(await client.query.users.findFirst({
where: (user) => eq(user.email, data),
with: {
roles: true,
},
})) ?? null;
return user;
},
async createSession(data) {
await client.insert(sessions).values(data);
const session = await client.query.sessions.findFirst({
where: (session) => eq(session.sessionToken, data.sessionToken),
});
return session!;
},
async getSessionAndUser(data) {
let sessionAndUser = null;
const res = await client.query.sessions.findFirst({
where: (session) => eq(session.sessionToken, data),
with: {
user: {
with: {
roles: true,
},
},
},
});
if (res) {
const { user, ...rest } = res;
sessionAndUser = { session: rest, user };
}
return sessionAndUser;
},
async updateUser(data) {
if (!data.id) {
throw new Error("No user id.");
}
await client.update(users).set(data).where(eq(users.id, data.id));
const user = await client.query.users.findFirst({
where: (user) => eq(user.id, data.id),
with: {
roles: true,
},
});
return user!;
},
async updateSession(data) {
await client
.update(sessions)
.set(data)
.where(eq(sessions.sessionToken, data.sessionToken));
return await client.query.sessions.findFirst({
where: (session) => eq(session.sessionToken, data.sessionToken),
});
},
async linkAccount(rawAccount) {
await client.insert(accounts).values(rawAccount);
},
async getUserByAccount(account) {
const dbAccount =
(await client.query.accounts.findFirst({
where: (acc) =>
and(
eq(acc.providerAccountId, account.providerAccountId),
eq(acc.provider, account.provider),
),
with: {
user: {
with: {
roles: true,
},
},
},
})) ?? null;
if (!dbAccount) {
return null;
}
return dbAccount.user;
},
async deleteSession(sessionToken) {
const session =
client.query.sessions.findFirst({
where: (session) => eq(session.sessionToken, sessionToken),
}) ?? null;
await client
.delete(sessions)
.where(eq(sessions.sessionToken, sessionToken));
return session;
},
async createVerificationToken(token) {
await client.insert(verificationTokens).values(token);
return await client
.select()
.from(verificationTokens)
.where(eq(verificationTokens.identifier, token.identifier))
.then((res) => res[0]);
},
async useVerificationToken(token) {
try {
const deletedToken =
(await client
.select()
.from(verificationTokens)
.where(
and(
eq(verificationTokens.identifier, token.identifier),
eq(verificationTokens.token, token.token),
),
)
.then((res) => res[0])) ?? null;
await client
.delete(verificationTokens)
.where(
and(
eq(verificationTokens.identifier, token.identifier),
eq(verificationTokens.token, token.token),
),
);
return deletedToken;
} catch (err) {
throw new Error("No verification token found.");
}
},
async deleteUser(id) {
const user = await client.query.users.findFirst({
where: (user) => eq(user.id, id),
with: {
roles: true,
},
});
await client.delete(users).where(eq(users.id, id));
return user;
},
async unlinkAccount(account) {
await client
.delete(accounts)
.where(
and(
eq(accounts.providerAccountId, account.providerAccountId),
eq(accounts.provider, account.provider),
),
);
return undefined;
},
};
} |
Beta Was this translation helpful? Give feedback.
-
It would be amazing to support Drizzle, it's gaining good support and has a fantastic DX. https://github.com/drizzle-team/drizzle-orm
Beta Was this translation helpful? Give feedback.
All reactions