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