Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(adapters): Drizzle adapter #7165

Closed
wants to merge 198 commits into from
Closed

feat(adapters): Drizzle adapter #7165

wants to merge 198 commits into from

Conversation

anthonyshew
Copy link
Contributor

@anthonyshew anthonyshew commented Apr 6, 2023

☕️ Reasoning

Introducing a drizzle-orm adapter!

With drizzle's increasing popularity, it's no surprise that there's a discussion for an adapter. This PR adds it.

🧢 Checklist

  • Documentation
  • Tests
  • Ready to be merged

📌 Resources

Notes

@vercel
Copy link

vercel bot commented Apr 6, 2023

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
auth-docs ❌ Failed (Inspect) Jul 16, 2023 5:51pm
1 Ignored Deployment
Name Status Preview Comments Updated (UTC)
next-auth-docs ⬜️ Ignored (Inspect) Jul 16, 2023 5:51pm

@vercel
Copy link

vercel bot commented Apr 6, 2023

@anthonyshew is attempting to deploy a commit to the authjs Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions bot added the adapters Changes related to the core code concerning database adapters label Apr 6, 2023
@socket-security
Copy link

socket-security bot commented Apr 6, 2023

🚨 Potential security issues detected. Learn more about Socket for GitHub ↗︎

To accept the risk, merge this PR and you will not be notified again.

Issue Package Version Note Source
Potential typo squat babel-preset-preact 2.0.0
Native code @parcel/watcher 2.1.0
Native code better-sqlite3 8.4.0
Native code sharp 0.31.3
Install scripts @swc/core 1.3.56
  • Install script: postinstall
  • Source: node postinstall.js
Install scripts core-js 3.30.1
  • Install script: postinstall
  • Source: node -e "try{require('./postinstall')}catch(e){}"
Install scripts core-js-pure 3.30.1
  • Install script: postinstall
  • Source: node -e "try{require('./postinstall')}catch(e){}"
Install scripts @prisma/client 3.15.2
  • Install script: postinstall
  • Source: node scripts/postinstall.js
Install scripts @prisma/client 4.15.0
  • Install script: postinstall
  • Source: node scripts/postinstall.js
Install scripts gatsby 5.8.0-next.3
  • Install script: postinstall
  • Source: node scripts/postinstall.js
Install scripts styled-components 5.3.6
  • Install script: postinstall
  • Source: node ./postinstall.js
Protestware/Troll package styled-components 5.3.6
  • Note: This package prints a protestware console message regarding Ukraine for users with Russian language locale
Telemetry next 13.3.0
  • Note: Can be disabled by setting the environment variable NEXT_TELEMETRY_DISABLED=1

Next steps

What is a potential typo squat?

Package name is similar to other popular packages and may not be the package you want.

Use care when consuming similarly named packages and ensure that you did not intend to consume a different package. Malicious packages often publish using similar names as existing popular packages.

What's wrong with native code?

Contains native code which could be a vector to obscure malicious code, and generally decrease the likelihood of reproducible or reliable installs.

Ensure that native code bindings are expected. Consumers may consider pure JS and functionally similar alternatives to avoid the challenges and risks associated with native code bindings.

What is an install script?

Install scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.

Packages should not be running non-essential scripts during install and there are often solutions to problems people solve with install scripts that can be run at publish time instead.

What is protestware and troll packages?

This package is a joke, parody, or includes undocumented or hidden behavior unrelated to its primary function.

Consider that consuming this package my come along with functionality unrelated to its primary purpose.

What is telemetry?

This package contains telemetry which tracks you.

Most telemetry comes with settings to disable it. Consider disabling telemetry if you do not want to be tracked.

Take a deeper look at the dependency

Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support [AT] socket [DOT] dev.

Remove the package

If you happen to install a dependency that Socket reports as Known Malware you should immediately remove it and select a different dependency. For other alert types, you may may wish to investigate alternative packages or consider if there are other ways to mitigate the specific risk posed by the dependency.

Mark a package as acceptable risk

To ignore an alert, reply with a comment starting with @SocketSecurity ignore followed by a space separated list of package-name@version specifiers. e.g. @SocketSecurity ignore foo@1.0.0 bar@* or ignore all packages with @SocketSecurity ignore-all

  • @SocketSecurity ignore @swc/core@1.3.56
  • @SocketSecurity ignore core-js@3.30.1
  • @SocketSecurity ignore core-js-pure@3.30.1
  • @SocketSecurity ignore @prisma/client@3.15.2
  • @SocketSecurity ignore @prisma/client@4.15.0
  • @SocketSecurity ignore gatsby@5.8.0-next.3
  • @SocketSecurity ignore styled-components@5.3.6
  • @SocketSecurity ignore @parcel/watcher@2.1.0
  • @SocketSecurity ignore better-sqlite3@8.4.0
  • @SocketSecurity ignore sharp@0.31.3
  • @SocketSecurity ignore babel-preset-preact@2.0.0
  • @SocketSecurity ignore next@13.3.0

@github-actions github-actions bot added the dynamodb @auth/dynamodb-adapter label Apr 6, 2023
@anthonyshew anthonyshew changed the title [WIP] feat(adapters): add Drizzle adapter feat(adapters): Drizzle adapter Jul 16, 2023
@anthonyshew
Copy link
Contributor Author

anthonyshew commented Jul 17, 2023

Okay, folks, I think(?) we've got it! I've written up tests and manually tested all three SQL flavors with Docker.

One thing of note: I would recommend marking this adapter as experimental.

  • Through the course of working on this, Drizzle shipped several breaking changes that affected both the correctness and development velocity of this PR. Don't read this as a critique; rather, this would be an acknowledgement that library is still quite young (despite its popularity). The Drizzle core team is excellent and their ORM will be stable and awesome in the future - but it's important to note the downstream dependency, in my opinion.
  • Also worthy of note: The MySQL adapter most likely will not work with PlanetScale as far as I can tell. I had to find ways to cut scope and simplify this PR and dropping PlanetScale turned out to be a worthwhile tradeoff so we can ship something. This would be a great follow-up PR opportunity once we've got this adapter out in the wild and getting used!

token_type: varchar("token_type", { length: 255 }),
scope: varchar("scope", { length: 255 }),
id_token: varchar("id_token", { length: 255 }),
session_state: varchar("session_state", { length: 255 }),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied this code in my project because I wanted to start using Planetscale + Next-Auth + Drizzel. So thank you!.

Is this mysql adapter the one we should use if we want to use Planetscale? If yes, in my case I had to use for id_token and session_state a text field not a varchar because I got an error when using Google Auth.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I didn't see your previous comment here #7165 (comment)

Ignore this. I guess I'll use my custom adapter for planet scale for now. Thanks for the work!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you mind sharing your adapter? I'm also using Planetscale so this bugs me as well ... 😕

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @andresgutgon! It would be nice, maybe you have a public repo in which we can read your twist of the adapter?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied this code in my project because I wanted to start using Planetscale + Next-Auth + Drizzel. So thank you!.

Is this mysql adapter the one we should use if we want to use Planetscale? If yes, in my case I had to use for id_token and session_state a text field not a varchar because I got an error when using Google Auth.

Sharing is caring

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't even know what's that lol. So I guess no xD. What you see in the gist is what I did. Nothing else related with Drizzle + NextAuth + Planetscale

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andresgutgon prepared queries with your build are not erroring out locally. Pushing to Versel now

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain here quickly what's a prepared query and what's the benefit?

Copy link

@mschieller mschieller Jul 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A prepared statement is kinda what the name implies. Instead of generate each sql query binary on request which is the normal procedure usually when using ORMs, Drizzle can make prepared statements, where the SQL binary is made on build, and when requested by code it it can use it directly which improves performance a lot because it can reuse the binary compilation. It can also take in params if doing joins and what not, which still is much faster. See here for more https://orm.drizzle.team/docs/performance#

Copy link

@iukea1 iukea1 Jul 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so Prepared statement

When you run query to the database there're several things that happens:

  • all the configurations of the query builder got concatenated to the SQL string
  • that string and params are sent to the database driver
  • driver compiles SQL query to the binary SQL executable format and sends it to the database
  • With prepared statements you do SQL concatenation once on the Drizzle ORM side and then database driver is able to reuse precompiled binary SQL instead of parsing query all the time. It has extreme performance benefits on large SQL queries.

https://orm.drizzle.team/docs/performance

can also watch the first half of this video
https://www.youtube.com/watch?v=O9zxsSl9zgE&t=430s

.returning()
.then((res) => res[0])
},
linkAccount: async (rawAccount) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you get the following error with Github provider:

      "message": "Cannot read properties of undefined (reading 'name')",
      "stack": "TypeError: Cannot read properties of undefined (reading 'name')\n

It's because GitHub adds an extra property refresh_token_expires_in:

{
  provider: 'github',
  type: 'oauth',
  providerAccountId: '',
  access_token: '',
  expires_at: 1690073663,
  refresh_token: '',
  refresh_token_expires_in: 15897600, // <----- 
  token_type: 'bearer',
  scope: '',
  userId: '53c777ed-353a-438b-a57e-wqweqwe'
}

I think maybe it would be best (for compatibility) to add this column to the provider? Or I guess maybe point that out in the docs so people can add that column to the schema?

Also, it may be better to use bigInt (with mode number) instead of integer for the expires column(s) for flexibility. https://orm.drizzle.team/docs/column-types/pg#bigint

@mschieller
Copy link

mschieller commented Jul 24, 2023

Is there a reason to why this adapter is not using prepared statements? Hence prepared statements has a much quicker build time that standard typings, and that these auth request would be called millions of millions of time, prepared statements should be really beneficial?
And if decided not to use prepared as default, perhaps make it optional in the adapter, or would this change the decires outcome of the generality of all the adapters?

Update 30/7: After creating my own adapter and schema, I don’t find it possible to create a adapter that utilize prepared statements out-of-the-box, unless this adapter takes in a list of optional arguments that contains the prepared statements with the queries.
As well, this adapter, if it’s a custom or the one in this PR, should utilises one-to-many relationships as well (not because it would do much regarding performance, but it would be easier to create queries from the schema and since these are connected, a binder should also exist).
I created a fully functional NextAuth adapter for Drizzle+PlanetScale, which utilises the new query methodologies, optional prepared statements to be used in adapter. If any would want it, I can share my findings and code :-)

@andresgutgon
Copy link
Contributor

I created a fully functional NextAuth adapter for Drizzle+PlanetScale, which utilises the new query methodologies, optional prepared statements to be used in adapter. If any would want it, I can share my findings and code :-)

Yes please, I shared mine here but not with prepare statements. I'm curious

@mschieller
Copy link

mschieller commented Jul 30, 2023

I created a fully functional NextAuth adapter for Drizzle+PlanetScale, which utilises the new query methodologies, optional prepared statements to be used in adapter. If any would want it, I can share my findings and code :-)

Yes please, I shared mine here but not with prepare statements. I'm curious

Currently flying home from vacation, but I'll make a test-next repo tonight and post it here, so all of it can be seen 🫡

@mschieller
Copy link

I created a fully functional NextAuth adapter for Drizzle+PlanetScale, which utilises the new query methodologies, optional prepared statements to be used in adapter. If any would want it, I can share my findings and code :-)

Yes please, I shared mine here but not with prepare statements. I'm curious

Currently flying home from vacation, but I'll make a test-next repo tonight and post it here, so all of it can be seen 🫡

As promised https://github.com/mschieller/drizzle-nextauth-planetscale
Feel free to ask why, and if you see something wrong, please let me know.

be aware that typing was a bit tricky so the adapter is not typesafe yet

@zivtamary
Copy link

As promised https://github.com/mschieller/drizzle-nextauth-planetscale Feel free to ask why, and if you see something wrong, please let me know.

be aware that typing was a bit tricky so the adapter is not typesafe yet

Hey, thanks for that :) would it also work for database session strategy?

@mschieller
Copy link

As promised https://github.com/mschieller/drizzle-nextauth-planetscale Feel free to ask why, and if you see something wrong, please let me know.

be aware that typing was a bit tricky so the adapter is not typesafe yet

Hey, thanks for that :) would it also work for database session strategy?

Pretty confident it does yes, haven't tried though. Please give feedback if/when you have tried 😀

@zivtamary
Copy link

As promised https://github.com/mschieller/drizzle-nextauth-planetscale Feel free to ask why, and if you see something wrong, please let me know.

be aware that typing was a bit tricky so the adapter is not typesafe yet

Hey, thanks for that :) would it also work for database session strategy?

Pretty confident it does yes, haven't tried though. Please give feedback if/when you have tried 😀

Unfortunately getting some errors... btw I'm using Google adapter

[next-auth][error][adapter_error_linkAccount] 
https://next-auth.js.org/errors#adapter_error_linkaccount Cannot read properties of undefined (reading 'name') {
  message: "Cannot read properties of undefined (reading 'name')",
  stack: "TypeError: Cannot read properties of undefined (reading 'name')\n" +

@mschieller
Copy link

As promised https://github.com/mschieller/drizzle-nextauth-planetscale Feel free to ask why, and if you see something wrong, please let me know.

be aware that typing was a bit tricky so the adapter is not typesafe yet

Hey, thanks for that :) would it also work for database session strategy?

Pretty confident it does yes, haven't tried though. Please give feedback if/when you have tried 😀

Unfortunately getting some errors... btw I'm using Google adapter


[next-auth][error][adapter_error_linkAccount] 

https://next-auth.js.org/errors#adapter_error_linkaccount Cannot read properties of undefined (reading 'name') {

  message: "Cannot read properties of undefined (reading 'name')",

  stack: "TypeError: Cannot read properties of undefined (reading 'name')\n" +

I got the same errors my self, forgot to redo a change I had made as a test prior. Check the new update I have made to the auth schema :-)

@zivtamary

This comment was marked as off-topic.

@balazsorban44
Copy link
Member

balazsorban44 commented Aug 8, 2023

🎉 Hi folks, this is now released under @auth/drizzle-adapter! Please try it out. 🙏

Docs: https://authjs.dev/reference/adapter/drizzle

Note, it should work with both NextAuth.js and Auth.js libs.

Thanks for everyone chipping in and your patience! Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
adapters Changes related to the core code concerning database adapters
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove instanceof checks to allow for multiple drizzle-orm instances to be used