@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/lib/sqlite.js
CHANGED
|
@@ -1,82 +1,93 @@
|
|
|
1
1
|
import { eq, and } from "drizzle-orm";
|
|
2
|
-
import { integer,
|
|
3
|
-
import {
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
export
|
|
46
|
-
|
|
2
|
+
import { integer, text, primaryKey, sqliteTable, index, } from "drizzle-orm/sqlite-core";
|
|
3
|
+
import { randomUUID } from "crypto";
|
|
4
|
+
export const sqliteUsersTable = sqliteTable("user", {
|
|
5
|
+
id: text("id")
|
|
6
|
+
.primaryKey()
|
|
7
|
+
.$defaultFn(() => randomUUID()),
|
|
8
|
+
name: text("name"),
|
|
9
|
+
email: text("email").notNull().unique(),
|
|
10
|
+
emailVerified: integer("emailVerified", { mode: "timestamp_ms" }),
|
|
11
|
+
image: text("image"),
|
|
12
|
+
});
|
|
13
|
+
export const sqliteAccountsTable = sqliteTable("account", {
|
|
14
|
+
userId: text("userId")
|
|
15
|
+
.notNull()
|
|
16
|
+
.references(() => sqliteUsersTable.id, { onDelete: "cascade" }),
|
|
17
|
+
type: text("type").notNull(),
|
|
18
|
+
provider: text("provider").notNull(),
|
|
19
|
+
providerAccountId: text("providerAccountId").notNull(),
|
|
20
|
+
refresh_token: text("refresh_token"),
|
|
21
|
+
access_token: text("access_token"),
|
|
22
|
+
expires_at: integer("expires_at"),
|
|
23
|
+
token_type: text("token_type"),
|
|
24
|
+
scope: text("scope"),
|
|
25
|
+
id_token: text("id_token"),
|
|
26
|
+
session_state: text("session_state"),
|
|
27
|
+
}, (account) => ({
|
|
28
|
+
userIdIdx: index("Account_userId_index").on(account.userId),
|
|
29
|
+
compositePk: primaryKey({
|
|
30
|
+
columns: [account.provider, account.providerAccountId],
|
|
31
|
+
}),
|
|
32
|
+
}));
|
|
33
|
+
export const sqliteSessionsTable = sqliteTable("session", {
|
|
34
|
+
id: text("id")
|
|
35
|
+
.primaryKey()
|
|
36
|
+
.$defaultFn(() => randomUUID()),
|
|
37
|
+
sessionToken: text("sessionToken").notNull().unique(),
|
|
38
|
+
userId: text("userId")
|
|
39
|
+
.notNull()
|
|
40
|
+
.references(() => sqliteUsersTable.id, { onDelete: "cascade" }),
|
|
41
|
+
expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
|
|
42
|
+
}, (table) => ({
|
|
43
|
+
userIdIdx: index("Session_userId_index").on(table.userId),
|
|
44
|
+
}));
|
|
45
|
+
export const sqliteVerificationTokensTable = sqliteTable("verificationToken", {
|
|
46
|
+
identifier: text("identifier").notNull(),
|
|
47
|
+
token: text("token").notNull().unique(),
|
|
48
|
+
expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
|
|
49
|
+
}, (vt) => ({
|
|
50
|
+
compositePk: primaryKey({ columns: [vt.identifier, vt.token] }),
|
|
51
|
+
}));
|
|
52
|
+
export function SQLiteDrizzleAdapter(client, schema = {
|
|
53
|
+
usersTable: sqliteUsersTable,
|
|
54
|
+
accountsTable: sqliteAccountsTable,
|
|
55
|
+
sessionsTable: sqliteSessionsTable,
|
|
56
|
+
verificationTokensTable: sqliteVerificationTokensTable,
|
|
57
|
+
}) {
|
|
58
|
+
const { usersTable, accountsTable, sessionsTable, verificationTokensTable } = schema;
|
|
47
59
|
return {
|
|
48
60
|
async createUser(data) {
|
|
49
|
-
return
|
|
50
|
-
.insert(users)
|
|
51
|
-
.values({ ...data, id: crypto.randomUUID() })
|
|
52
|
-
.returning()
|
|
53
|
-
.get();
|
|
61
|
+
return client.insert(usersTable).values(data).returning().get();
|
|
54
62
|
},
|
|
55
|
-
async getUser(
|
|
63
|
+
async getUser(userId) {
|
|
56
64
|
const result = await client
|
|
57
65
|
.select()
|
|
58
|
-
.from(
|
|
59
|
-
.where(eq(
|
|
66
|
+
.from(usersTable)
|
|
67
|
+
.where(eq(usersTable.id, userId))
|
|
60
68
|
.get();
|
|
61
69
|
return result ?? null;
|
|
62
70
|
},
|
|
63
|
-
async getUserByEmail(
|
|
71
|
+
async getUserByEmail(email) {
|
|
64
72
|
const result = await client
|
|
65
73
|
.select()
|
|
66
|
-
.from(
|
|
67
|
-
.where(eq(
|
|
74
|
+
.from(usersTable)
|
|
75
|
+
.where(eq(usersTable.email, email))
|
|
68
76
|
.get();
|
|
69
77
|
return result ?? null;
|
|
70
78
|
},
|
|
71
|
-
createSession(data) {
|
|
72
|
-
return client.insert(
|
|
79
|
+
async createSession(data) {
|
|
80
|
+
return await client.insert(sessionsTable).values(data).returning().get();
|
|
73
81
|
},
|
|
74
|
-
async getSessionAndUser(
|
|
82
|
+
async getSessionAndUser(sessionToken) {
|
|
75
83
|
const result = await client
|
|
76
|
-
.select({
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
.select({
|
|
85
|
+
session: sessionsTable,
|
|
86
|
+
user: usersTable,
|
|
87
|
+
})
|
|
88
|
+
.from(sessionsTable)
|
|
89
|
+
.where(eq(sessionsTable.sessionToken, sessionToken))
|
|
90
|
+
.innerJoin(usersTable, eq(usersTable.id, sessionsTable.userId))
|
|
80
91
|
.get();
|
|
81
92
|
return result ?? null;
|
|
82
93
|
},
|
|
@@ -85,78 +96,68 @@ export function SQLiteDrizzleAdapter(client, tableFn = defaultSqliteTableFn) {
|
|
|
85
96
|
throw new Error("No user id.");
|
|
86
97
|
}
|
|
87
98
|
const result = await client
|
|
88
|
-
.update(
|
|
99
|
+
.update(usersTable)
|
|
89
100
|
.set(data)
|
|
90
|
-
.where(eq(
|
|
101
|
+
.where(eq(usersTable.id, data.id))
|
|
91
102
|
.returning()
|
|
92
103
|
.get();
|
|
93
|
-
|
|
104
|
+
if (!result) {
|
|
105
|
+
throw new Error("User not found.");
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
94
108
|
},
|
|
95
109
|
async updateSession(data) {
|
|
96
110
|
const result = await client
|
|
97
|
-
.update(
|
|
111
|
+
.update(sessionsTable)
|
|
98
112
|
.set(data)
|
|
99
|
-
.where(eq(
|
|
113
|
+
.where(eq(sessionsTable.sessionToken, data.sessionToken))
|
|
100
114
|
.returning()
|
|
101
115
|
.get();
|
|
102
116
|
return result ?? null;
|
|
103
117
|
},
|
|
104
|
-
async linkAccount(
|
|
105
|
-
|
|
118
|
+
async linkAccount(data) {
|
|
119
|
+
await client.insert(accountsTable).values(data).run();
|
|
106
120
|
},
|
|
107
121
|
async getUserByAccount(account) {
|
|
108
|
-
const
|
|
109
|
-
.select(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
122
|
+
const result = await client
|
|
123
|
+
.select({
|
|
124
|
+
account: accountsTable,
|
|
125
|
+
user: usersTable,
|
|
126
|
+
})
|
|
127
|
+
.from(accountsTable)
|
|
128
|
+
.innerJoin(usersTable, eq(accountsTable.userId, usersTable.id))
|
|
129
|
+
.where(and(eq(accountsTable.provider, account.provider), eq(accountsTable.providerAccountId, account.providerAccountId)))
|
|
113
130
|
.get();
|
|
114
|
-
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
return Promise.resolve(results).then((results) => results.user);
|
|
131
|
+
return result?.user ?? null;
|
|
118
132
|
},
|
|
119
133
|
async deleteSession(sessionToken) {
|
|
120
|
-
|
|
121
|
-
.delete(
|
|
122
|
-
.where(eq(
|
|
134
|
+
await client
|
|
135
|
+
.delete(sessionsTable)
|
|
136
|
+
.where(eq(sessionsTable.sessionToken, sessionToken))
|
|
137
|
+
.run();
|
|
138
|
+
},
|
|
139
|
+
async createVerificationToken(data) {
|
|
140
|
+
return await client
|
|
141
|
+
.insert(verificationTokensTable)
|
|
142
|
+
.values(data)
|
|
123
143
|
.returning()
|
|
124
144
|
.get();
|
|
125
|
-
return result ?? null;
|
|
126
145
|
},
|
|
127
|
-
async
|
|
146
|
+
async useVerificationToken(params) {
|
|
128
147
|
const result = await client
|
|
129
|
-
.
|
|
130
|
-
.
|
|
148
|
+
.delete(verificationTokensTable)
|
|
149
|
+
.where(and(eq(verificationTokensTable.identifier, params.identifier), eq(verificationTokensTable.token, params.token)))
|
|
131
150
|
.returning()
|
|
132
151
|
.get();
|
|
133
152
|
return result ?? null;
|
|
134
153
|
},
|
|
135
|
-
async useVerificationToken(token) {
|
|
136
|
-
try {
|
|
137
|
-
const result = await client
|
|
138
|
-
.delete(verificationTokens)
|
|
139
|
-
.where(and(eq(verificationTokens.identifier, token.identifier), eq(verificationTokens.token, token.token)))
|
|
140
|
-
.returning()
|
|
141
|
-
.get();
|
|
142
|
-
return result ?? null;
|
|
143
|
-
}
|
|
144
|
-
catch (err) {
|
|
145
|
-
throw new Error("No verification token found.");
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
154
|
async deleteUser(id) {
|
|
149
|
-
|
|
150
|
-
.delete(users)
|
|
151
|
-
.where(eq(users.id, id))
|
|
152
|
-
.returning()
|
|
153
|
-
.get();
|
|
154
|
-
return result ?? null;
|
|
155
|
+
await client.delete(usersTable).where(eq(usersTable.id, id)).run();
|
|
155
156
|
},
|
|
156
|
-
async unlinkAccount(
|
|
157
|
+
async unlinkAccount(params) {
|
|
157
158
|
await client
|
|
158
|
-
.delete(
|
|
159
|
-
.where(and(eq(
|
|
159
|
+
.delete(accountsTable)
|
|
160
|
+
.where(and(eq(accountsTable.provider, params.provider), eq(accountsTable.providerAccountId, params.providerAccountId)))
|
|
160
161
|
.run();
|
|
161
162
|
},
|
|
162
163
|
};
|
package/lib/utils.d.ts
CHANGED
|
@@ -1,26 +1,15 @@
|
|
|
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
|
-
import type {
|
|
5
|
-
import type {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export type
|
|
13
|
-
export
|
|
14
|
-
mysql: MySqlSchema & Record<string, AnyMySqlTable>;
|
|
15
|
-
pg: PgSchema & Record<string, AnyPgTable>;
|
|
16
|
-
sqlite: SQLiteSchema & Record<string, AnySQLiteTable>;
|
|
17
|
-
}
|
|
18
|
-
export type SqlFlavorOptions = AnyMySqlDatabase | AnyPgDatabase | AnySQLiteDatabase;
|
|
19
|
-
export type ClientFlavors<Flavor> = Flavor extends AnyMySqlDatabase ? MinimumSchema["mysql"] : Flavor extends AnyPgDatabase ? MinimumSchema["pg"] : Flavor extends AnySQLiteDatabase ? MinimumSchema["sqlite"] : never;
|
|
20
|
-
export type TableFn<Flavor> = Flavor extends AnyMySqlDatabase ? MySqlTableFn : Flavor extends AnyPgDatabase ? PgTableFn : Flavor extends AnySQLiteDatabase ? SQLiteTableFn : AnySQLiteTable;
|
|
21
|
-
type NonNullableProps<T> = {
|
|
22
|
-
[P in keyof T]: null extends T[P] ? never : P;
|
|
23
|
-
}[keyof T];
|
|
24
|
-
export declare function stripUndefined<T>(obj: T): Pick<T, NonNullableProps<T>>;
|
|
4
|
+
import type { QueryResultHKT as MySQLQueryResultHKT, PreparedQueryHKTBase } from "drizzle-orm/mysql-core";
|
|
5
|
+
import type { QueryResultHKT as PostgresQueryResultHKT } from "drizzle-orm/pg-core";
|
|
6
|
+
import { DefaultSQLiteSchema } from "./sqlite";
|
|
7
|
+
import { DefaultPostgresSchema } from "./pg";
|
|
8
|
+
import { DefaultMySqlSchema } from "./mysql";
|
|
9
|
+
type AnyPostgresDatabase = PgDatabase<PostgresQueryResultHKT, any>;
|
|
10
|
+
type AnyMySqlDatabase = MySqlDatabase<MySQLQueryResultHKT, PreparedQueryHKTBase, any>;
|
|
11
|
+
type AnySQLiteDatabase = BaseSQLiteDatabase<"sync" | "async", any, any>;
|
|
12
|
+
export type SqlFlavorOptions = AnyPostgresDatabase | AnyMySqlDatabase | AnySQLiteDatabase;
|
|
13
|
+
export type DefaultSchema<Flavor> = Flavor extends AnyMySqlDatabase ? DefaultMySqlSchema : Flavor extends AnyPostgresDatabase ? DefaultPostgresSchema : Flavor extends AnySQLiteDatabase ? DefaultSQLiteSchema : never;
|
|
25
14
|
export {};
|
|
26
15
|
//# sourceMappingURL=utils.d.ts.map
|
package/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,KAAK,EACV,cAAc,IAAI,mBAAmB,EACrC,oBAAoB,EACrB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,cAAc,IAAI,sBAAsB,EAAE,MAAM,qBAAqB,CAAA;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,MAAM,CAAA;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAE5C,KAAK,mBAAmB,GAAG,UAAU,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAA;AAClE,KAAK,gBAAgB,GAAG,aAAa,CACnC,mBAAmB,EACnB,oBAAoB,EACpB,GAAG,CACJ,CAAA;AACD,KAAK,iBAAiB,GAAG,kBAAkB,CAAC,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;AAEvE,MAAM,MAAM,gBAAgB,GACxB,mBAAmB,GACnB,gBAAgB,GAChB,iBAAiB,CAAA;AAErB,MAAM,MAAM,aAAa,CAAC,MAAM,IAAI,MAAM,SAAS,gBAAgB,GAC/D,kBAAkB,GAClB,MAAM,SAAS,mBAAmB,GAChC,qBAAqB,GACrB,MAAM,SAAS,iBAAiB,GAC9B,mBAAmB,GACnB,KAAK,CAAA"}
|
package/lib/utils.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auth/drizzle-adapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Drizzle adapter for Auth.js.",
|
|
5
5
|
"homepage": "https://authjs.dev",
|
|
6
6
|
"repository": "https://github.com/nextauthjs/next-auth",
|
|
@@ -19,7 +19,8 @@
|
|
|
19
19
|
"exports": {
|
|
20
20
|
".": {
|
|
21
21
|
"types": "./index.d.ts",
|
|
22
|
-
"import": "./index.js"
|
|
22
|
+
"import": "./index.js",
|
|
23
|
+
"require": "./index.js"
|
|
23
24
|
}
|
|
24
25
|
},
|
|
25
26
|
"license": "ISC",
|
|
@@ -36,16 +37,15 @@
|
|
|
36
37
|
"access": "public"
|
|
37
38
|
},
|
|
38
39
|
"dependencies": {
|
|
39
|
-
"@auth/core": "0.
|
|
40
|
+
"@auth/core": "0.30.0"
|
|
40
41
|
},
|
|
41
42
|
"devDependencies": {
|
|
42
|
-
"@libsql/client": "0.4.0-pre.5",
|
|
43
43
|
"@types/better-sqlite3": "^7.6.4",
|
|
44
44
|
"@types/uuid": "^8.3.3",
|
|
45
45
|
"better-sqlite3": "^8.6.0",
|
|
46
|
-
"drizzle-kit": "^0.20.
|
|
47
|
-
"drizzle-orm": "^0.
|
|
48
|
-
"mysql2": "^3.
|
|
46
|
+
"drizzle-kit": "^0.20.14",
|
|
47
|
+
"drizzle-orm": "^0.30.5",
|
|
48
|
+
"mysql2": "^3.9.4",
|
|
49
49
|
"postgres": "^3.3.4",
|
|
50
50
|
"tsx": "^4.7.0"
|
|
51
51
|
},
|
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,69 @@
|
|
|
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
29
|
|
|
30
|
+
export {
|
|
31
|
+
postgresUsersTable,
|
|
32
|
+
postgresAccountsTable,
|
|
33
|
+
postgresSessionsTable,
|
|
34
|
+
postgresVerificationTokensTable,
|
|
35
|
+
} from "./lib/pg.js"
|
|
36
|
+
export {
|
|
37
|
+
sqliteUsersTable,
|
|
38
|
+
sqliteAccountsTable,
|
|
39
|
+
sqliteSessionsTable,
|
|
40
|
+
sqliteVerificationTokensTable,
|
|
41
|
+
} from "./lib/sqlite.js"
|
|
42
|
+
export {
|
|
43
|
+
mysqlUsersTable,
|
|
44
|
+
mysqlAccountsTable,
|
|
45
|
+
mysqlSessionsTable,
|
|
46
|
+
mysqlVerificationTokensTable,
|
|
47
|
+
} from "./lib/mysql.js"
|
|
30
48
|
/**
|
|
31
|
-
* Add
|
|
49
|
+
* Add this adapter to your `auth.ts` Auth.js configuration object:
|
|
32
50
|
*
|
|
33
|
-
* ```ts title="
|
|
51
|
+
* ```ts title="auth.ts"
|
|
34
52
|
* import NextAuth from "next-auth"
|
|
35
|
-
* import
|
|
53
|
+
* import Google from "next-auth/providers/google"
|
|
36
54
|
* import { DrizzleAdapter } from "@auth/drizzle-adapter"
|
|
37
55
|
* import { db } from "./schema"
|
|
38
56
|
*
|
|
39
|
-
* export
|
|
57
|
+
* export const { handlers, auth } = NextAuth({
|
|
40
58
|
* adapter: DrizzleAdapter(db),
|
|
41
59
|
* providers: [
|
|
42
|
-
*
|
|
43
|
-
* clientId: process.env.GOOGLE_CLIENT_ID,
|
|
44
|
-
* clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
45
|
-
* }),
|
|
60
|
+
* Google,
|
|
46
61
|
* ],
|
|
47
62
|
* })
|
|
48
63
|
* ```
|
|
49
64
|
*
|
|
50
65
|
* :::info
|
|
51
|
-
* If you
|
|
66
|
+
* If you want to use your own tables, you can pass them as a second argument
|
|
52
67
|
* :::
|
|
68
|
+
*
|
|
69
|
+
* ```ts title="auth.ts"
|
|
70
|
+
* import NextAuth from "next-auth"
|
|
71
|
+
* import Google from "next-auth/providers/google"
|
|
72
|
+
* import { DrizzleAdapter } from "@auth/drizzle-adapter"
|
|
73
|
+
* import { db, accounts, sessions, users, verificationTokens } from "./schema"
|
|
74
|
+
*
|
|
75
|
+
* export const { handlers, auth } = NextAuth({
|
|
76
|
+
* adapter: DrizzleAdapter(db, { usersTable: users, accountsTable: accounts, sessionsTable: sessions, verificationTokensTable: verificationTokens }),
|
|
77
|
+
* providers: [
|
|
78
|
+
* Google,
|
|
79
|
+
* ],
|
|
80
|
+
* })
|
|
81
|
+
* ```
|
|
53
82
|
*
|
|
54
83
|
* ## Setup
|
|
55
84
|
*
|
|
@@ -71,11 +100,12 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
71
100
|
* integer
|
|
72
101
|
* } from "drizzle-orm/pg-core"
|
|
73
102
|
* import type { AdapterAccount } from '@auth/core/adapters'
|
|
103
|
+
* import { randomUUID } from "crypto"
|
|
74
104
|
*
|
|
75
105
|
* export const users = pgTable("user", {
|
|
76
|
-
* id: text("id").
|
|
106
|
+
* id: text("id").primaryKey().$defaultFn(() => randomUUID()),
|
|
77
107
|
* name: text("name"),
|
|
78
|
-
* email: text("email").notNull(),
|
|
108
|
+
* email: text("email").notNull().unique(),
|
|
79
109
|
* emailVerified: timestamp("emailVerified", { mode: "date" }),
|
|
80
110
|
* image: text("image"),
|
|
81
111
|
* })
|
|
@@ -86,7 +116,7 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
86
116
|
* userId: text("userId")
|
|
87
117
|
* .notNull()
|
|
88
118
|
* .references(() => users.id, { onDelete: "cascade" }),
|
|
89
|
-
* type: text("type")
|
|
119
|
+
* type: text("type").notNull(),
|
|
90
120
|
* provider: text("provider").notNull(),
|
|
91
121
|
* providerAccountId: text("providerAccountId").notNull(),
|
|
92
122
|
* refresh_token: text("refresh_token"),
|
|
@@ -98,23 +128,27 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
98
128
|
* session_state: text("session_state"),
|
|
99
129
|
* },
|
|
100
130
|
* (account) => ({
|
|
131
|
+
* userIdIdx: index().on(account.userId),
|
|
101
132
|
* compoundKey: primaryKey({ columns: [account.provider, account.providerAccountId] }),
|
|
102
133
|
* })
|
|
103
134
|
* )
|
|
104
135
|
*
|
|
105
136
|
* export const sessions = pgTable("session", {
|
|
106
|
-
*
|
|
137
|
+
* id: text("id").primaryKey().$defaultFn(() => randomUUID()),
|
|
138
|
+
* sessionToken: text("sessionToken").notNull().unique(),
|
|
107
139
|
* userId: text("userId")
|
|
108
140
|
* .notNull()
|
|
109
141
|
* .references(() => users.id, { onDelete: "cascade" }),
|
|
110
142
|
* expires: timestamp("expires", { mode: "date" }).notNull(),
|
|
111
|
-
* })
|
|
143
|
+
* }, (session) => ({
|
|
144
|
+
* userIdIdx: index().on(session.userId)
|
|
145
|
+
* }))
|
|
112
146
|
*
|
|
113
147
|
* export const verificationTokens = pgTable(
|
|
114
148
|
* "verificationToken",
|
|
115
149
|
* {
|
|
116
150
|
* identifier: text("identifier").notNull(),
|
|
117
|
-
* token: text("token").notNull(),
|
|
151
|
+
* token: text("token").notNull().unique(),
|
|
118
152
|
* expires: timestamp("expires", { mode: "date" }).notNull(),
|
|
119
153
|
* },
|
|
120
154
|
* (vt) => ({
|
|
@@ -136,10 +170,10 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
136
170
|
* import type { AdapterAccount } from "@auth/core/adapters"
|
|
137
171
|
*
|
|
138
172
|
* export const users = mysqlTable("user", {
|
|
139
|
-
* id: varchar("id", { length: 255 }).
|
|
173
|
+
* id: varchar("id", { length: 255 }).primaryKey().$defaultFn(() => randomUUID()),
|
|
140
174
|
* name: varchar("name", { length: 255 }),
|
|
141
|
-
* email: varchar("email", { length: 255 }).notNull(),
|
|
142
|
-
*
|
|
175
|
+
* email: varchar("email", { length: 255 }).notNull().unique(),
|
|
176
|
+
* emailVerified: timestamp("emailVerified", { mode: "date", fsp: 3 }),
|
|
143
177
|
* image: varchar("image", { length: 255 }),
|
|
144
178
|
* })
|
|
145
179
|
*
|
|
@@ -149,8 +183,8 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
149
183
|
* userId: varchar("userId", { length: 255 })
|
|
150
184
|
* .notNull()
|
|
151
185
|
* .references(() => users.id, { onDelete: "cascade" }),
|
|
152
|
-
* type: varchar("type", { length: 255 })
|
|
153
|
-
*
|
|
186
|
+
* type: varchar("type", { length: 255 }).notNull(),
|
|
187
|
+
* provider: varchar("provider", { length: 255 }).notNull(),
|
|
154
188
|
* providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(),
|
|
155
189
|
* refresh_token: varchar("refresh_token", { length: 255 }),
|
|
156
190
|
* access_token: varchar("access_token", { length: 255 }),
|
|
@@ -164,22 +198,26 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
164
198
|
* compoundKey: primaryKey({
|
|
165
199
|
columns: [account.provider, account.providerAccountId],
|
|
166
200
|
}),
|
|
201
|
+
userIdIdx: index('Account_userId_index').on(account.userId)
|
|
167
202
|
* })
|
|
168
203
|
* )
|
|
169
204
|
*
|
|
170
205
|
* export const sessions = mysqlTable("session", {
|
|
171
|
-
*
|
|
206
|
+
* id: varchar("id", { length: 255 }).primaryKey().$defaultFn(() => randomUUID()),
|
|
207
|
+
* sessionToken: varchar("sessionToken", { length: 255 }).notNull().unique(),
|
|
172
208
|
* userId: varchar("userId", { length: 255 })
|
|
173
209
|
* .notNull()
|
|
174
210
|
* .references(() => users.id, { onDelete: "cascade" }),
|
|
175
211
|
* expires: timestamp("expires", { mode: "date" }).notNull(),
|
|
176
|
-
* })
|
|
212
|
+
* }, (session) => ({
|
|
213
|
+
* userIdIdx: index('Session_userId_index').on(session.userId)
|
|
214
|
+
* }))
|
|
177
215
|
*
|
|
178
216
|
* export const verificationTokens = mysqlTable(
|
|
179
217
|
* "verificationToken",
|
|
180
218
|
* {
|
|
181
219
|
* identifier: varchar("identifier", { length: 255 }).notNull(),
|
|
182
|
-
* token: varchar("token", { length: 255 }).notNull(),
|
|
220
|
+
* token: varchar("token", { length: 255 }).notNull().unique(),
|
|
183
221
|
* expires: timestamp("expires", { mode: "date" }).notNull(),
|
|
184
222
|
* },
|
|
185
223
|
* (vt) => ({
|
|
@@ -195,9 +233,9 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
195
233
|
* import type { AdapterAccount } from "@auth/core/adapters"
|
|
196
234
|
*
|
|
197
235
|
* export const users = sqliteTable("user", {
|
|
198
|
-
* id: text("id").
|
|
236
|
+
* id: text("id").primaryKey().$defaultFn(() => randomUUID()),
|
|
199
237
|
* name: text("name"),
|
|
200
|
-
* email: text("email").notNull(),
|
|
238
|
+
* email: text("email").notNull().unique(),
|
|
201
239
|
* emailVerified: integer("emailVerified", { mode: "timestamp_ms" }),
|
|
202
240
|
* image: text("image"),
|
|
203
241
|
* })
|
|
@@ -208,7 +246,7 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
208
246
|
* userId: text("userId")
|
|
209
247
|
* .notNull()
|
|
210
248
|
* .references(() => users.id, { onDelete: "cascade" }),
|
|
211
|
-
* type: text("type")
|
|
249
|
+
* type: text("type").notNull(),
|
|
212
250
|
* provider: text("provider").notNull(),
|
|
213
251
|
* providerAccountId: text("providerAccountId").notNull(),
|
|
214
252
|
* refresh_token: text("refresh_token"),
|
|
@@ -223,22 +261,26 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
223
261
|
* compoundKey: primaryKey({
|
|
224
262
|
columns: [account.provider, account.providerAccountId],
|
|
225
263
|
}),
|
|
264
|
+
userIdIdx: index('Account_userId_index').on(account.userId)
|
|
226
265
|
* })
|
|
227
266
|
* )
|
|
228
267
|
*
|
|
229
268
|
* export const sessions = sqliteTable("session", {
|
|
230
|
-
*
|
|
269
|
+
* id: text("id").primaryKey().$defaultFn(() => randomUUID())
|
|
270
|
+
* sessionToken: text("sessionToken").notNull().unique(),
|
|
231
271
|
* userId: text("userId")
|
|
232
272
|
* .notNull()
|
|
233
273
|
* .references(() => users.id, { onDelete: "cascade" }),
|
|
234
274
|
* expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
|
|
235
|
-
* })
|
|
275
|
+
* }, (table) => ({
|
|
276
|
+
* userIdIdx: index('Session_userId_index').on(table.userId)
|
|
277
|
+
* }))
|
|
236
278
|
*
|
|
237
279
|
* export const verificationTokens = sqliteTable(
|
|
238
280
|
* "verificationToken",
|
|
239
281
|
* {
|
|
240
282
|
* identifier: text("identifier").notNull(),
|
|
241
|
-
* token: text("token").notNull(),
|
|
283
|
+
* token: text("token").notNull().unique(),
|
|
242
284
|
* expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
|
|
243
285
|
* },
|
|
244
286
|
* (vt) => ({
|
|
@@ -257,14 +299,14 @@ import type { Adapter } from "@auth/core/adapters"
|
|
|
257
299
|
**/
|
|
258
300
|
export function DrizzleAdapter<SqlFlavor extends SqlFlavorOptions>(
|
|
259
301
|
db: SqlFlavor,
|
|
260
|
-
|
|
302
|
+
schema?: DefaultSchema<SqlFlavor>
|
|
261
303
|
): Adapter {
|
|
262
304
|
if (is(db, MySqlDatabase)) {
|
|
263
|
-
return
|
|
305
|
+
return MySqlDrizzleAdapter(db, schema as DefaultMySqlSchema)
|
|
264
306
|
} else if (is(db, PgDatabase)) {
|
|
265
|
-
return
|
|
307
|
+
return PostgresDrizzleAdapter(db, schema as DefaultPostgresSchema)
|
|
266
308
|
} else if (is(db, BaseSQLiteDatabase)) {
|
|
267
|
-
return SQLiteDrizzleAdapter(db,
|
|
309
|
+
return SQLiteDrizzleAdapter(db, schema as DefaultSQLiteSchema)
|
|
268
310
|
}
|
|
269
311
|
|
|
270
312
|
throw new Error(
|