@auth/drizzle-adapter 0.9.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/index.d.ts +81 -64
- package/index.d.ts.map +1 -1
- package/index.js +86 -69
- package/lib/mysql.d.ts +477 -296
- package/lib/mysql.d.ts.map +1 -1
- package/lib/mysql.js +131 -143
- package/lib/pg.d.ts +476 -296
- package/lib/pg.d.ts.map +1 -1
- package/lib/pg.js +121 -124
- package/lib/sqlite.d.ts +476 -296
- package/lib/sqlite.d.ts.map +1 -1
- package/lib/sqlite.js +106 -107
- package/lib/utils.d.ts +10 -21
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +1 -7
- package/package.json +9 -9
- package/src/index.ts +90 -74
- package/src/lib/mysql.ts +378 -195
- package/src/lib/pg.ts +363 -162
- package/src/lib/sqlite.ts +345 -135
- package/src/lib/utils.ts +25 -43
package/src/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* <div style={{display: "flex", justifyContent: "space-between", alignItems: "center", padding: 16}}>
|
|
3
3
|
* <p style={{fontWeight: "normal"}}>Official <a href="https://orm.drizzle.team">Drizzle ORM</a> adapter for Auth.js / NextAuth.js.</p>
|
|
4
4
|
* <a href="https://orm.drizzle.team">
|
|
5
|
-
* <img style={{display: "block"}} src="/img/adapters/drizzle
|
|
5
|
+
* <img style={{display: "block"}} src="/img/adapters/drizzle.svg" width="38" />
|
|
6
6
|
* </a>
|
|
7
7
|
* </div>
|
|
8
8
|
*
|
|
@@ -16,40 +16,53 @@
|
|
|
16
16
|
* @module @auth/drizzle-adapter
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { MySqlDatabase, MySqlTableFn } from "drizzle-orm/mysql-core"
|
|
20
|
-
import { PgDatabase, PgTableFn } from "drizzle-orm/pg-core"
|
|
21
|
-
import { BaseSQLiteDatabase, SQLiteTableFn } from "drizzle-orm/sqlite-core"
|
|
22
|
-
import { mySqlDrizzleAdapter } from "./lib/mysql.js"
|
|
23
|
-
import { pgDrizzleAdapter } from "./lib/pg.js"
|
|
24
|
-
import { SQLiteDrizzleAdapter } from "./lib/sqlite.js"
|
|
25
|
-
import { SqlFlavorOptions, TableFn } from "./lib/utils.js"
|
|
26
19
|
import { is } from "drizzle-orm"
|
|
20
|
+
import { MySqlDatabase } from "drizzle-orm/mysql-core"
|
|
21
|
+
import { PgDatabase } from "drizzle-orm/pg-core"
|
|
22
|
+
import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"
|
|
23
|
+
import { DefaultMySqlSchema, MySqlDrizzleAdapter } from "./lib/mysql.js"
|
|
24
|
+
import { DefaultPostgresSchema, PostgresDrizzleAdapter } from "./lib/pg.js"
|
|
25
|
+
import { DefaultSQLiteSchema, SQLiteDrizzleAdapter } from "./lib/sqlite.js"
|
|
26
|
+
import { DefaultSchema, SqlFlavorOptions } from "./lib/utils.js"
|
|
27
27
|
|
|
28
28
|
import type { Adapter } from "@auth/core/adapters"
|
|
29
|
-
|
|
30
29
|
/**
|
|
31
|
-
* Add
|
|
30
|
+
* Create db instance and pass it to adapter. Add this adapter to your `auth.ts` Auth.js configuration object:
|
|
32
31
|
*
|
|
33
|
-
* ```ts title="
|
|
32
|
+
* ```ts title="auth.ts"
|
|
34
33
|
* import NextAuth from "next-auth"
|
|
35
|
-
* import
|
|
34
|
+
* import Google from "next-auth/providers/google"
|
|
36
35
|
* import { DrizzleAdapter } from "@auth/drizzle-adapter"
|
|
37
|
-
* import { db } from "./
|
|
36
|
+
* import { db } from "./db.ts"
|
|
38
37
|
*
|
|
39
|
-
* export
|
|
38
|
+
* export const { handlers, auth } = NextAuth({
|
|
40
39
|
* adapter: DrizzleAdapter(db),
|
|
41
40
|
* providers: [
|
|
42
|
-
*
|
|
43
|
-
* clientId: process.env.GOOGLE_CLIENT_ID,
|
|
44
|
-
* clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
45
|
-
* }),
|
|
41
|
+
* Google,
|
|
46
42
|
* ],
|
|
47
43
|
* })
|
|
48
44
|
* ```
|
|
49
45
|
*
|
|
46
|
+
* Follow the Drizzle documentation for [PostgreSQL setup](https://orm.drizzle.team/docs/get-started-postgresql), [MySQL setup](https://orm.drizzle.team/docs/get-started-mysql) and [SQLite setup](https://orm.drizzle.team/docs/get-started-sqlite).
|
|
47
|
+
*
|
|
50
48
|
* :::info
|
|
51
|
-
* If you
|
|
49
|
+
* If you want to use your own tables, you can pass them as a second argument. If you add non-nullable columns, make sure to provide a default value or rewrite functions to handle the missing values.
|
|
52
50
|
* :::
|
|
51
|
+
*
|
|
52
|
+
* ```ts title="auth.ts"
|
|
53
|
+
* import NextAuth from "next-auth"
|
|
54
|
+
* import Google from "next-auth/providers/google"
|
|
55
|
+
* import { DrizzleAdapter } from "@auth/drizzle-adapter"
|
|
56
|
+
* import { accounts, sessions, users, verificationTokens } from "./schema"
|
|
57
|
+
* import { db } from "./db.ts"
|
|
58
|
+
*
|
|
59
|
+
* export const { handlers, auth } = NextAuth({
|
|
60
|
+
* adapter: DrizzleAdapter(db, { usersTable: users, accountsTable: accounts, sessionsTable: sessions, verificationTokensTable: verificationTokens }),
|
|
61
|
+
* providers: [
|
|
62
|
+
* Google,
|
|
63
|
+
* ],
|
|
64
|
+
* })
|
|
65
|
+
* ```
|
|
53
66
|
*
|
|
54
67
|
* ## Setup
|
|
55
68
|
*
|
|
@@ -71,9 +84,10 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
71
84
|
* integer
|
|
72
85
|
* } from "drizzle-orm/pg-core"
|
|
73
86
|
* import type { AdapterAccount } from '@auth/core/adapters'
|
|
87
|
+
* import { randomUUID } from "crypto"
|
|
74
88
|
*
|
|
75
89
|
* export const users = pgTable("user", {
|
|
76
|
-
* id: text("id").
|
|
90
|
+
* id: text("id").primaryKey().$defaultFn(() => randomUUID()),
|
|
77
91
|
* name: text("name"),
|
|
78
92
|
* email: text("email").notNull(),
|
|
79
93
|
* emailVerified: timestamp("emailVerified", { mode: "date" }),
|
|
@@ -86,7 +100,7 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
86
100
|
* userId: text("userId")
|
|
87
101
|
* .notNull()
|
|
88
102
|
* .references(() => users.id, { onDelete: "cascade" }),
|
|
89
|
-
* type: text("type")
|
|
103
|
+
* type: text("type").notNull(),
|
|
90
104
|
* provider: text("provider").notNull(),
|
|
91
105
|
* providerAccountId: text("providerAccountId").notNull(),
|
|
92
106
|
* refresh_token: text("refresh_token"),
|
|
@@ -103,7 +117,7 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
103
117
|
* )
|
|
104
118
|
*
|
|
105
119
|
* export const sessions = pgTable("session", {
|
|
106
|
-
* sessionToken: text("sessionToken").
|
|
120
|
+
* sessionToken: text("sessionToken").primaryKey(),
|
|
107
121
|
* userId: text("userId")
|
|
108
122
|
* .notNull()
|
|
109
123
|
* .references(() => users.id, { onDelete: "cascade" }),
|
|
@@ -125,6 +139,8 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
125
139
|
*
|
|
126
140
|
* ### MySQL
|
|
127
141
|
*
|
|
142
|
+
* In MySQL, there's no `returning` clause, so in the `createUser` function, we first insert a new user and then search by `email` to get the user's data. To make the search faster, we suggest adding an index to the `email` column.
|
|
143
|
+
*
|
|
128
144
|
* ```ts title="schema.ts"
|
|
129
145
|
* import {
|
|
130
146
|
* int,
|
|
@@ -136,39 +152,39 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
136
152
|
* import type { AdapterAccount } from "@auth/core/adapters"
|
|
137
153
|
*
|
|
138
154
|
* export const users = mysqlTable("user", {
|
|
139
|
-
* id: varchar("id", { length: 255 }).
|
|
155
|
+
* id: varchar("id", { length: 255 }).primaryKey().$defaultFn(() => randomUUID()),
|
|
140
156
|
* name: varchar("name", { length: 255 }),
|
|
141
157
|
* email: varchar("email", { length: 255 }).notNull(),
|
|
142
|
-
*
|
|
158
|
+
* emailVerified: timestamp("emailVerified", { mode: "date", fsp: 3 }),
|
|
143
159
|
* image: varchar("image", { length: 255 }),
|
|
144
160
|
* })
|
|
145
161
|
*
|
|
146
162
|
* export const accounts = mysqlTable(
|
|
147
163
|
* "account",
|
|
148
164
|
* {
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
165
|
+
* userId: varchar("userId", { length: 255 })
|
|
166
|
+
* .notNull()
|
|
167
|
+
* .references(() => users.id, { onDelete: "cascade" }),
|
|
168
|
+
* type: varchar("type", { length: 255 }).notNull(),
|
|
153
169
|
* provider: varchar("provider", { length: 255 }).notNull(),
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
*
|
|
170
|
+
* providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(),
|
|
171
|
+
* refresh_token: varchar("refresh_token", { length: 255 }),
|
|
172
|
+
* access_token: varchar("access_token", { length: 255 }),
|
|
173
|
+
* expires_at: int("expires_at"),
|
|
174
|
+
* token_type: varchar("token_type", { length: 255 }),
|
|
175
|
+
* scope: varchar("scope", { length: 255 }),
|
|
176
|
+
* id_token: varchar("id_token", { length: 2048 }),
|
|
177
|
+
* session_state: varchar("session_state", { length: 255 }),
|
|
178
|
+
* },
|
|
179
|
+
* (account) => ({
|
|
180
|
+
* compoundKey: primaryKey({
|
|
181
|
+
columns: [account.provider, account.providerAccountId],
|
|
182
|
+
})
|
|
183
|
+
* })
|
|
168
184
|
* )
|
|
169
185
|
*
|
|
170
186
|
* export const sessions = mysqlTable("session", {
|
|
171
|
-
* sessionToken: varchar("sessionToken", { length: 255 }).
|
|
187
|
+
* sessionToken: varchar("sessionToken", { length: 255 }).primaryKey(),
|
|
172
188
|
* userId: varchar("userId", { length: 255 })
|
|
173
189
|
* .notNull()
|
|
174
190
|
* .references(() => users.id, { onDelete: "cascade" }),
|
|
@@ -176,15 +192,15 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
176
192
|
* })
|
|
177
193
|
*
|
|
178
194
|
* export const verificationTokens = mysqlTable(
|
|
179
|
-
*
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
195
|
+
* "verificationToken",
|
|
196
|
+
* {
|
|
197
|
+
* identifier: varchar("identifier", { length: 255 }).notNull(),
|
|
198
|
+
* token: varchar("token", { length: 255 }).notNull(),
|
|
199
|
+
* expires: timestamp("expires", { mode: "date" }).notNull(),
|
|
200
|
+
* },
|
|
201
|
+
* (vt) => ({
|
|
202
|
+
* compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
|
|
203
|
+
* })
|
|
188
204
|
* )
|
|
189
205
|
* ```
|
|
190
206
|
*
|
|
@@ -195,7 +211,7 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
195
211
|
* import type { AdapterAccount } from "@auth/core/adapters"
|
|
196
212
|
*
|
|
197
213
|
* export const users = sqliteTable("user", {
|
|
198
|
-
* id: text("id").
|
|
214
|
+
* id: text("id").primaryKey().$defaultFn(() => randomUUID()),
|
|
199
215
|
* name: text("name"),
|
|
200
216
|
* email: text("email").notNull(),
|
|
201
217
|
* emailVerified: integer("emailVerified", { mode: "timestamp_ms" }),
|
|
@@ -208,7 +224,7 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
208
224
|
* userId: text("userId")
|
|
209
225
|
* .notNull()
|
|
210
226
|
* .references(() => users.id, { onDelete: "cascade" }),
|
|
211
|
-
* type: text("type")
|
|
227
|
+
* type: text("type").notNull(),
|
|
212
228
|
* provider: text("provider").notNull(),
|
|
213
229
|
* providerAccountId: text("providerAccountId").notNull(),
|
|
214
230
|
* refresh_token: text("refresh_token"),
|
|
@@ -222,49 +238,49 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
222
238
|
* (account) => ({
|
|
223
239
|
* compoundKey: primaryKey({
|
|
224
240
|
columns: [account.provider, account.providerAccountId],
|
|
225
|
-
})
|
|
241
|
+
})
|
|
226
242
|
* })
|
|
227
243
|
* )
|
|
228
244
|
*
|
|
229
245
|
* export const sessions = sqliteTable("session", {
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
246
|
+
* sessionToken: text("sessionToken").primaryKey(),
|
|
247
|
+
* userId: text("userId")
|
|
248
|
+
* .notNull()
|
|
249
|
+
* .references(() => users.id, { onDelete: "cascade" }),
|
|
250
|
+
* expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
|
|
235
251
|
* })
|
|
236
252
|
*
|
|
237
253
|
* export const verificationTokens = sqliteTable(
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
254
|
+
* "verificationToken",
|
|
255
|
+
* {
|
|
256
|
+
* identifier: text("identifier").notNull(),
|
|
257
|
+
* token: text("token").notNull(),
|
|
258
|
+
* expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
|
|
259
|
+
* },
|
|
260
|
+
* (vt) => ({
|
|
261
|
+
* compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
|
|
262
|
+
* })
|
|
247
263
|
* )
|
|
248
264
|
* ```
|
|
249
265
|
*
|
|
250
266
|
* ## Migrating your database
|
|
251
267
|
* With your schema now described in your code, you'll need to migrate your database to your schema.
|
|
252
268
|
*
|
|
253
|
-
* For full documentation on how to run migrations with Drizzle, [visit the Drizzle documentation](https://orm.drizzle.team/kit-docs/overview#running-migrations).
|
|
269
|
+
* For full documentation on how to run migrations with Drizzle, [visit the Drizzle documentation](https://orm.drizzle.team/kit-docs/overview#running-migrations) or check how to apply changes directly to the database with [push command](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push).
|
|
254
270
|
*
|
|
255
271
|
* ---
|
|
256
272
|
*
|
|
257
273
|
**/
|
|
258
274
|
export function DrizzleAdapter<SqlFlavor extends SqlFlavorOptions>(
|
|
259
275
|
db: SqlFlavor,
|
|
260
|
-
|
|
276
|
+
schema?: DefaultSchema<SqlFlavor>
|
|
261
277
|
): Adapter {
|
|
262
278
|
if (is(db, MySqlDatabase)) {
|
|
263
|
-
return
|
|
279
|
+
return MySqlDrizzleAdapter(db, schema as DefaultMySqlSchema)
|
|
264
280
|
} else if (is(db, PgDatabase)) {
|
|
265
|
-
return
|
|
281
|
+
return PostgresDrizzleAdapter(db, schema as DefaultPostgresSchema)
|
|
266
282
|
} else if (is(db, BaseSQLiteDatabase)) {
|
|
267
|
-
return SQLiteDrizzleAdapter(db,
|
|
283
|
+
return SQLiteDrizzleAdapter(db, schema as DefaultSQLiteSchema)
|
|
268
284
|
}
|
|
269
285
|
|
|
270
286
|
throw new Error(
|