@auth/drizzle-adapter 0.9.0 → 1.0.0
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 +59 -32
- package/index.d.ts.map +1 -1
- package/index.js +64 -37
- package/lib/mysql.d.ts +317 -296
- package/lib/mysql.d.ts.map +1 -1
- package/lib/mysql.js +134 -142
- package/lib/pg.d.ts +317 -296
- package/lib/pg.d.ts.map +1 -1
- package/lib/pg.js +128 -123
- package/lib/sqlite.d.ts +317 -296
- package/lib/sqlite.d.ts.map +1 -1
- package/lib/sqlite.js +109 -108
- package/lib/utils.d.ts +10 -21
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +1 -7
- package/package.json +7 -7
- package/src/index.ts +83 -41
- package/src/lib/mysql.ts +209 -190
- package/src/lib/pg.ts +194 -155
- package/src/lib/sqlite.ts +175 -133
- package/src/lib/utils.ts +22 -41
package/src/lib/mysql.ts
CHANGED
|
@@ -2,263 +2,282 @@ import { and, eq } from "drizzle-orm"
|
|
|
2
2
|
import {
|
|
3
3
|
int,
|
|
4
4
|
timestamp,
|
|
5
|
-
mysqlTable as defaultMySqlTableFn,
|
|
6
5
|
primaryKey,
|
|
7
6
|
varchar,
|
|
8
|
-
MySqlTableFn,
|
|
9
7
|
MySqlDatabase,
|
|
8
|
+
mysqlTable,
|
|
9
|
+
MySqlTableWithColumns,
|
|
10
|
+
TableConfig,
|
|
11
|
+
QueryResultHKT,
|
|
12
|
+
PreparedQueryHKTBase,
|
|
13
|
+
index,
|
|
10
14
|
} from "drizzle-orm/mysql-core"
|
|
11
15
|
|
|
12
|
-
import type {
|
|
16
|
+
import type {
|
|
17
|
+
Adapter,
|
|
18
|
+
AdapterUser,
|
|
19
|
+
AdapterAccount,
|
|
20
|
+
AdapterSession,
|
|
21
|
+
VerificationToken,
|
|
22
|
+
} from "@auth/core/adapters"
|
|
13
23
|
|
|
14
|
-
|
|
15
|
-
const users = mySqlTable("user", {
|
|
16
|
-
id: varchar("id", { length: 255 }).notNull().primaryKey(),
|
|
17
|
-
name: varchar("name", { length: 255 }),
|
|
18
|
-
email: varchar("email", { length: 255 }).notNull(),
|
|
19
|
-
emailVerified: timestamp("emailVerified", {
|
|
20
|
-
mode: "date",
|
|
21
|
-
fsp: 3,
|
|
22
|
-
}).defaultNow(),
|
|
23
|
-
image: varchar("image", { length: 255 }),
|
|
24
|
-
})
|
|
24
|
+
import { randomUUID } from "crypto"
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
provider: varchar("provider", { length: 255 }).notNull(),
|
|
36
|
-
providerAccountId: varchar("providerAccountId", {
|
|
37
|
-
length: 255,
|
|
38
|
-
}).notNull(),
|
|
39
|
-
refresh_token: varchar("refresh_token", { length: 255 }),
|
|
40
|
-
access_token: varchar("access_token", { length: 255 }),
|
|
41
|
-
expires_at: int("expires_at"),
|
|
42
|
-
token_type: varchar("token_type", { length: 255 }),
|
|
43
|
-
scope: varchar("scope", { length: 255 }),
|
|
44
|
-
id_token: varchar("id_token", { length: 255 }),
|
|
45
|
-
session_state: varchar("session_state", { length: 255 }),
|
|
46
|
-
},
|
|
47
|
-
(account) => ({
|
|
48
|
-
compoundKey: primaryKey(account.provider, account.providerAccountId),
|
|
49
|
-
})
|
|
50
|
-
)
|
|
26
|
+
export const mysqlUsersTable = mysqlTable("user" as string, {
|
|
27
|
+
id: varchar("id", { length: 255 })
|
|
28
|
+
.primaryKey()
|
|
29
|
+
.$defaultFn(() => randomUUID()),
|
|
30
|
+
name: varchar("name", { length: 255 }),
|
|
31
|
+
email: varchar("email", { length: 255 }).notNull().unique(),
|
|
32
|
+
emailVerified: timestamp("emailVerified", { mode: "date", fsp: 3 }),
|
|
33
|
+
image: varchar("image", { length: 255 }),
|
|
34
|
+
})
|
|
51
35
|
|
|
52
|
-
|
|
53
|
-
|
|
36
|
+
export const mysqlAccountsTable = mysqlTable(
|
|
37
|
+
"account" as string,
|
|
38
|
+
{
|
|
39
|
+
userId: varchar("userId", { length: 255 })
|
|
54
40
|
.notNull()
|
|
55
|
-
.
|
|
41
|
+
.references(() => mysqlUsersTable.id, { onDelete: "cascade" }),
|
|
42
|
+
type: varchar("type", { length: 255 }).notNull(),
|
|
43
|
+
provider: varchar("provider", { length: 255 }).notNull(),
|
|
44
|
+
providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(),
|
|
45
|
+
refresh_token: varchar("refresh_token", { length: 255 }),
|
|
46
|
+
access_token: varchar("access_token", { length: 255 }),
|
|
47
|
+
expires_at: int("expires_at"),
|
|
48
|
+
token_type: varchar("token_type", { length: 255 }),
|
|
49
|
+
scope: varchar("scope", { length: 255 }),
|
|
50
|
+
id_token: varchar("id_token", { length: 2048 }),
|
|
51
|
+
session_state: varchar("session_state", { length: 255 }),
|
|
52
|
+
},
|
|
53
|
+
(account) => ({
|
|
54
|
+
compositePk: primaryKey({
|
|
55
|
+
columns: [account.provider, account.providerAccountId],
|
|
56
|
+
}),
|
|
57
|
+
userIdIdx: index("Account_userId_index").on(account.userId),
|
|
58
|
+
})
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
export const mysqlSessionsTable = mysqlTable(
|
|
62
|
+
"session" as string,
|
|
63
|
+
{
|
|
64
|
+
id: varchar("id", { length: 255 })
|
|
65
|
+
.primaryKey()
|
|
66
|
+
.$defaultFn(() => randomUUID()),
|
|
67
|
+
sessionToken: varchar("sessionToken", { length: 255 }).notNull().unique(),
|
|
56
68
|
userId: varchar("userId", { length: 255 })
|
|
57
69
|
.notNull()
|
|
58
|
-
.references(() =>
|
|
70
|
+
.references(() => mysqlUsersTable.id, { onDelete: "cascade" }),
|
|
59
71
|
expires: timestamp("expires", { mode: "date" }).notNull(),
|
|
72
|
+
},
|
|
73
|
+
(session) => ({
|
|
74
|
+
userIdIdx: index("Session_userId_index").on(session.userId),
|
|
60
75
|
})
|
|
76
|
+
)
|
|
61
77
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return { users, accounts, sessions, verificationTokens }
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export type DefaultSchema = ReturnType<typeof createTables>
|
|
78
|
+
export const mysqlVerificationTokensTable = mysqlTable(
|
|
79
|
+
"verificationToken" as string,
|
|
80
|
+
{
|
|
81
|
+
identifier: varchar("identifier", { length: 255 }).notNull(),
|
|
82
|
+
token: varchar("token", { length: 255 }).notNull().unique(),
|
|
83
|
+
expires: timestamp("expires", { mode: "date" }).notNull(),
|
|
84
|
+
},
|
|
85
|
+
(vt) => ({
|
|
86
|
+
compositePk: primaryKey({ columns: [vt.identifier, vt.token] }),
|
|
87
|
+
})
|
|
88
|
+
)
|
|
78
89
|
|
|
79
|
-
export function
|
|
80
|
-
client:
|
|
81
|
-
|
|
90
|
+
export function MySqlDrizzleAdapter(
|
|
91
|
+
client: MySqlDatabase<QueryResultHKT, PreparedQueryHKTBase, any>,
|
|
92
|
+
schema: DefaultMySqlSchema = {
|
|
93
|
+
usersTable: mysqlUsersTable,
|
|
94
|
+
accountsTable: mysqlAccountsTable,
|
|
95
|
+
sessionsTable: mysqlSessionsTable,
|
|
96
|
+
verificationTokensTable: mysqlVerificationTokensTable,
|
|
97
|
+
}
|
|
82
98
|
): Adapter {
|
|
83
|
-
const {
|
|
84
|
-
|
|
99
|
+
const { usersTable, accountsTable, sessionsTable, verificationTokensTable } =
|
|
100
|
+
schema
|
|
85
101
|
|
|
86
102
|
return {
|
|
87
|
-
async createUser(data) {
|
|
88
|
-
const id =
|
|
103
|
+
async createUser(data: Omit<AdapterUser, "id">) {
|
|
104
|
+
const id = randomUUID()
|
|
89
105
|
|
|
90
|
-
await client.insert(
|
|
106
|
+
await client.insert(usersTable).values({ ...data, id })
|
|
91
107
|
|
|
92
|
-
return
|
|
108
|
+
return client
|
|
93
109
|
.select()
|
|
94
|
-
.from(
|
|
95
|
-
.where(eq(
|
|
110
|
+
.from(usersTable)
|
|
111
|
+
.where(eq(usersTable.id, id))
|
|
96
112
|
.then((res) => res[0])
|
|
97
113
|
},
|
|
98
|
-
async getUser(
|
|
99
|
-
|
|
100
|
-
(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
.then((res) => res[0])) ?? null
|
|
105
|
-
|
|
106
|
-
return thing
|
|
114
|
+
async getUser(userId: string) {
|
|
115
|
+
return client
|
|
116
|
+
.select()
|
|
117
|
+
.from(usersTable)
|
|
118
|
+
.where(eq(usersTable.id, userId))
|
|
119
|
+
.then((res) => (res.length > 0 ? res[0] : null))
|
|
107
120
|
},
|
|
108
|
-
async getUserByEmail(
|
|
109
|
-
|
|
110
|
-
(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
.then((res) => res[0])) ?? null
|
|
115
|
-
|
|
116
|
-
return user
|
|
121
|
+
async getUserByEmail(email: string) {
|
|
122
|
+
return client
|
|
123
|
+
.select()
|
|
124
|
+
.from(usersTable)
|
|
125
|
+
.where(eq(usersTable.email, email))
|
|
126
|
+
.then((res) => (res.length > 0 ? res[0] : null))
|
|
117
127
|
},
|
|
118
|
-
async createSession(data
|
|
119
|
-
|
|
128
|
+
async createSession(data: {
|
|
129
|
+
sessionToken: string
|
|
130
|
+
userId: string
|
|
131
|
+
expires: Date
|
|
132
|
+
}) {
|
|
133
|
+
const id = randomUUID()
|
|
120
134
|
|
|
121
|
-
|
|
135
|
+
await client.insert(sessionsTable).values({ ...data, id })
|
|
136
|
+
|
|
137
|
+
return client
|
|
122
138
|
.select()
|
|
123
|
-
.from(
|
|
124
|
-
.where(eq(
|
|
139
|
+
.from(sessionsTable)
|
|
140
|
+
.where(eq(sessionsTable.id, id))
|
|
125
141
|
.then((res) => res[0])
|
|
126
142
|
},
|
|
127
|
-
async getSessionAndUser(
|
|
128
|
-
|
|
129
|
-
(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
.then((res) => res[0])) ?? null
|
|
138
|
-
|
|
139
|
-
return sessionAndUser
|
|
143
|
+
async getSessionAndUser(sessionToken: string) {
|
|
144
|
+
return client
|
|
145
|
+
.select({
|
|
146
|
+
session: sessionsTable,
|
|
147
|
+
user: usersTable,
|
|
148
|
+
})
|
|
149
|
+
.from(sessionsTable)
|
|
150
|
+
.where(eq(sessionsTable.sessionToken, sessionToken))
|
|
151
|
+
.innerJoin(usersTable, eq(usersTable.id, sessionsTable.userId))
|
|
152
|
+
.then((res) => (res.length > 0 ? res[0] : null))
|
|
140
153
|
},
|
|
141
|
-
async updateUser(data) {
|
|
154
|
+
async updateUser(data: Partial<AdapterUser> & Pick<AdapterUser, "id">) {
|
|
142
155
|
if (!data.id) {
|
|
143
156
|
throw new Error("No user id.")
|
|
144
157
|
}
|
|
145
158
|
|
|
146
|
-
await client
|
|
159
|
+
await client
|
|
160
|
+
.update(usersTable)
|
|
161
|
+
.set(data)
|
|
162
|
+
.where(eq(usersTable.id, data.id))
|
|
147
163
|
|
|
148
|
-
|
|
164
|
+
const [result] = await client
|
|
149
165
|
.select()
|
|
150
|
-
.from(
|
|
151
|
-
.where(eq(
|
|
152
|
-
|
|
166
|
+
.from(usersTable)
|
|
167
|
+
.where(eq(usersTable.id, data.id))
|
|
168
|
+
|
|
169
|
+
if (!result) {
|
|
170
|
+
throw new Error("No user found.")
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return result
|
|
153
174
|
},
|
|
154
|
-
async updateSession(
|
|
175
|
+
async updateSession(
|
|
176
|
+
data: Partial<AdapterSession> & Pick<AdapterSession, "sessionToken">
|
|
177
|
+
) {
|
|
155
178
|
await client
|
|
156
|
-
.update(
|
|
179
|
+
.update(sessionsTable)
|
|
157
180
|
.set(data)
|
|
158
|
-
.where(eq(
|
|
181
|
+
.where(eq(sessionsTable.sessionToken, data.sessionToken))
|
|
159
182
|
|
|
160
|
-
return
|
|
183
|
+
return client
|
|
161
184
|
.select()
|
|
162
|
-
.from(
|
|
163
|
-
.where(eq(
|
|
185
|
+
.from(sessionsTable)
|
|
186
|
+
.where(eq(sessionsTable.sessionToken, data.sessionToken))
|
|
164
187
|
.then((res) => res[0])
|
|
165
188
|
},
|
|
166
|
-
async linkAccount(
|
|
167
|
-
await client.insert(
|
|
189
|
+
async linkAccount(data: AdapterAccount) {
|
|
190
|
+
await client.insert(accountsTable).values(data)
|
|
168
191
|
},
|
|
169
|
-
async getUserByAccount(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
192
|
+
async getUserByAccount(
|
|
193
|
+
account: Pick<AdapterAccount, "provider" | "providerAccountId">
|
|
194
|
+
) {
|
|
195
|
+
const result = await client
|
|
196
|
+
.select({
|
|
197
|
+
account: accountsTable,
|
|
198
|
+
user: usersTable,
|
|
199
|
+
})
|
|
200
|
+
.from(accountsTable)
|
|
201
|
+
.innerJoin(usersTable, eq(accountsTable.userId, usersTable.id))
|
|
202
|
+
.where(
|
|
203
|
+
and(
|
|
204
|
+
eq(accountsTable.provider, account.provider),
|
|
205
|
+
eq(accountsTable.providerAccountId, account.providerAccountId)
|
|
179
206
|
)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if (!dbAccount) {
|
|
184
|
-
return null
|
|
185
|
-
}
|
|
207
|
+
)
|
|
208
|
+
.then((res) => res[0])
|
|
186
209
|
|
|
187
|
-
return
|
|
210
|
+
return result?.user ?? null
|
|
188
211
|
},
|
|
189
|
-
async deleteSession(sessionToken) {
|
|
190
|
-
const session =
|
|
191
|
-
(await client
|
|
192
|
-
.select()
|
|
193
|
-
.from(sessions)
|
|
194
|
-
.where(eq(sessions.sessionToken, sessionToken))
|
|
195
|
-
.then((res) => res[0])) ?? null
|
|
196
|
-
|
|
212
|
+
async deleteSession(sessionToken: string) {
|
|
197
213
|
await client
|
|
198
|
-
.delete(
|
|
199
|
-
.where(eq(
|
|
200
|
-
|
|
201
|
-
return session
|
|
214
|
+
.delete(sessionsTable)
|
|
215
|
+
.where(eq(sessionsTable.sessionToken, sessionToken))
|
|
202
216
|
},
|
|
203
|
-
async createVerificationToken(
|
|
204
|
-
await client.insert(
|
|
217
|
+
async createVerificationToken(data: VerificationToken) {
|
|
218
|
+
await client.insert(verificationTokensTable).values(data)
|
|
205
219
|
|
|
206
|
-
return
|
|
220
|
+
return client
|
|
207
221
|
.select()
|
|
208
|
-
.from(
|
|
209
|
-
.where(eq(
|
|
222
|
+
.from(verificationTokensTable)
|
|
223
|
+
.where(eq(verificationTokensTable.identifier, data.identifier))
|
|
210
224
|
.then((res) => res[0])
|
|
211
225
|
},
|
|
212
|
-
async useVerificationToken(token) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
.
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
)
|
|
224
|
-
.then((res) => res[0])) ?? null
|
|
226
|
+
async useVerificationToken(params: { identifier: string; token: string }) {
|
|
227
|
+
const deletedToken = await client
|
|
228
|
+
.select()
|
|
229
|
+
.from(verificationTokensTable)
|
|
230
|
+
.where(
|
|
231
|
+
and(
|
|
232
|
+
eq(verificationTokensTable.identifier, params.identifier),
|
|
233
|
+
eq(verificationTokensTable.token, params.token)
|
|
234
|
+
)
|
|
235
|
+
)
|
|
236
|
+
.then((res) => (res.length > 0 ? res[0] : null))
|
|
225
237
|
|
|
238
|
+
if (deletedToken) {
|
|
226
239
|
await client
|
|
227
|
-
.delete(
|
|
240
|
+
.delete(verificationTokensTable)
|
|
228
241
|
.where(
|
|
229
242
|
and(
|
|
230
|
-
eq(
|
|
231
|
-
eq(
|
|
243
|
+
eq(verificationTokensTable.identifier, params.identifier),
|
|
244
|
+
eq(verificationTokensTable.token, params.token)
|
|
232
245
|
)
|
|
233
246
|
)
|
|
234
|
-
|
|
235
|
-
return deletedToken
|
|
236
|
-
} catch (err) {
|
|
237
|
-
throw new Error("No verification token found.")
|
|
238
247
|
}
|
|
239
|
-
},
|
|
240
|
-
async deleteUser(id) {
|
|
241
|
-
const user = await client
|
|
242
|
-
.select()
|
|
243
|
-
.from(users)
|
|
244
|
-
.where(eq(users.id, id))
|
|
245
|
-
.then((res) => res[0] ?? null)
|
|
246
248
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
249
|
+
return deletedToken
|
|
250
|
+
},
|
|
251
|
+
async deleteUser(id: string) {
|
|
252
|
+
await client.delete(usersTable).where(eq(usersTable.id, id))
|
|
250
253
|
},
|
|
251
|
-
async unlinkAccount(
|
|
254
|
+
async unlinkAccount(
|
|
255
|
+
params: Pick<AdapterAccount, "provider" | "providerAccountId">
|
|
256
|
+
) {
|
|
252
257
|
await client
|
|
253
|
-
.delete(
|
|
258
|
+
.delete(accountsTable)
|
|
254
259
|
.where(
|
|
255
260
|
and(
|
|
256
|
-
eq(
|
|
257
|
-
eq(
|
|
261
|
+
eq(accountsTable.provider, params.provider),
|
|
262
|
+
eq(accountsTable.providerAccountId, params.providerAccountId)
|
|
258
263
|
)
|
|
259
264
|
)
|
|
260
|
-
|
|
261
|
-
return undefined
|
|
262
265
|
},
|
|
263
266
|
}
|
|
264
267
|
}
|
|
268
|
+
|
|
269
|
+
export type MySqlTableFn<T extends TableConfig> = MySqlTableWithColumns<{
|
|
270
|
+
name: T["name"]
|
|
271
|
+
columns: T["columns"]
|
|
272
|
+
dialect: T["dialect"]
|
|
273
|
+
schema: string | undefined
|
|
274
|
+
}>
|
|
275
|
+
|
|
276
|
+
export type DefaultMySqlSchema = {
|
|
277
|
+
usersTable: MySqlTableFn<(typeof mysqlUsersTable)["_"]["config"]>
|
|
278
|
+
accountsTable: MySqlTableFn<(typeof mysqlAccountsTable)["_"]["config"]>
|
|
279
|
+
sessionsTable: MySqlTableFn<(typeof mysqlSessionsTable)["_"]["config"]>
|
|
280
|
+
verificationTokensTable: MySqlTableFn<
|
|
281
|
+
(typeof mysqlVerificationTokensTable)["_"]["config"]
|
|
282
|
+
>
|
|
283
|
+
}
|