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