@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/lib/pg.js CHANGED
@@ -1,165 +1,170 @@
1
1
  import { and, eq } from "drizzle-orm";
2
- import { timestamp, pgTable as defaultPgTableFn, text, primaryKey, integer, } from "drizzle-orm/pg-core";
3
- import { stripUndefined } from "./utils.js";
4
- export function createTables(pgTable) {
5
- const users = pgTable("user", {
6
- id: text("id").notNull().primaryKey(),
7
- name: text("name"),
8
- email: text("email").notNull(),
9
- emailVerified: timestamp("emailVerified", { mode: "date" }),
10
- image: text("image"),
11
- });
12
- const accounts = pgTable("account", {
13
- userId: text("userId")
14
- .notNull()
15
- .references(() => users.id, { onDelete: "cascade" }),
16
- type: text("type").$type().notNull(),
17
- provider: text("provider").notNull(),
18
- providerAccountId: text("providerAccountId").notNull(),
19
- refresh_token: text("refresh_token"),
20
- access_token: text("access_token"),
21
- expires_at: integer("expires_at"),
22
- token_type: text("token_type"),
23
- scope: text("scope"),
24
- id_token: text("id_token"),
25
- session_state: text("session_state"),
26
- }, (account) => ({
27
- compoundKey: primaryKey(account.provider, account.providerAccountId),
28
- }));
29
- const sessions = pgTable("session", {
30
- sessionToken: text("sessionToken").notNull().primaryKey(),
31
- userId: text("userId")
32
- .notNull()
33
- .references(() => users.id, { onDelete: "cascade" }),
34
- expires: timestamp("expires", { mode: "date" }).notNull(),
35
- });
36
- const verificationTokens = pgTable("verificationToken", {
37
- identifier: text("identifier").notNull(),
38
- token: text("token").notNull(),
39
- expires: timestamp("expires", { mode: "date" }).notNull(),
40
- }, (vt) => ({
41
- compoundKey: primaryKey(vt.identifier, vt.token),
42
- }));
43
- return { users, accounts, sessions, verificationTokens };
44
- }
45
- export function pgDrizzleAdapter(client, tableFn = defaultPgTableFn) {
46
- const { users, accounts, sessions, verificationTokens } = createTables(tableFn);
2
+ import { timestamp, text, primaryKey, integer, pgTable, index, } from "drizzle-orm/pg-core";
3
+ import { randomUUID } from "crypto";
4
+ export const postgresUsersTable = pgTable("user", {
5
+ id: text("id")
6
+ .primaryKey()
7
+ .$defaultFn(() => randomUUID()),
8
+ name: text("name"),
9
+ email: text("email").notNull().unique(),
10
+ emailVerified: timestamp("emailVerified", { mode: "date" }),
11
+ image: text("image"),
12
+ });
13
+ export const postgresAccountsTable = pgTable("account", {
14
+ userId: text("userId")
15
+ .notNull()
16
+ .references(() => postgresUsersTable.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
+ }, (table) => {
28
+ return {
29
+ userIdIdx: index().on(table.userId),
30
+ compositePk: primaryKey({
31
+ columns: [table.provider, table.providerAccountId],
32
+ }),
33
+ };
34
+ });
35
+ export const postgresSessionsTable = pgTable("session", {
36
+ id: text("id")
37
+ .primaryKey()
38
+ .$defaultFn(() => randomUUID()),
39
+ sessionToken: text("sessionToken").notNull().unique(),
40
+ userId: text("userId")
41
+ .notNull()
42
+ .references(() => postgresUsersTable.id, { onDelete: "cascade" }),
43
+ expires: timestamp("expires", { mode: "date" }).notNull(),
44
+ }, (table) => {
45
+ return {
46
+ userIdIdx: index().on(table.userId),
47
+ };
48
+ });
49
+ export const postgresVerificationTokensTable = pgTable("verificationToken", {
50
+ identifier: text("identifier").notNull(),
51
+ token: text("token").notNull().unique(),
52
+ expires: timestamp("expires", { mode: "date" }).notNull(),
53
+ }, (table) => {
54
+ return {
55
+ compositePk: primaryKey({ columns: [table.identifier, table.token] }),
56
+ };
57
+ });
58
+ export function PostgresDrizzleAdapter(client, schema = {
59
+ usersTable: postgresUsersTable,
60
+ accountsTable: postgresAccountsTable,
61
+ sessionsTable: postgresSessionsTable,
62
+ verificationTokensTable: postgresVerificationTokensTable,
63
+ }) {
64
+ const { usersTable, accountsTable, sessionsTable, verificationTokensTable } = schema;
47
65
  return {
48
66
  async createUser(data) {
49
- return await client
50
- .insert(users)
51
- .values({ ...data, id: crypto.randomUUID() })
67
+ return client
68
+ .insert(usersTable)
69
+ .values(data)
52
70
  .returning()
53
- .then((res) => res[0] ?? null);
71
+ .then((res) => res[0]);
54
72
  },
55
- async getUser(data) {
56
- return await client
73
+ async getUser(userId) {
74
+ return client
57
75
  .select()
58
- .from(users)
59
- .where(eq(users.id, data))
60
- .then((res) => res[0] ?? null);
76
+ .from(usersTable)
77
+ .where(eq(usersTable.id, userId))
78
+ .then((res) => (res.length > 0 ? res[0] : null));
61
79
  },
62
- async getUserByEmail(data) {
63
- return await client
80
+ async getUserByEmail(email) {
81
+ return client
64
82
  .select()
65
- .from(users)
66
- .where(eq(users.email, data))
67
- .then((res) => res[0] ?? null);
83
+ .from(usersTable)
84
+ .where(eq(usersTable.email, email))
85
+ .then((res) => (res.length > 0 ? res[0] : null));
68
86
  },
69
87
  async createSession(data) {
70
- return await client
71
- .insert(sessions)
88
+ return client
89
+ .insert(sessionsTable)
72
90
  .values(data)
73
91
  .returning()
74
92
  .then((res) => res[0]);
75
93
  },
76
- async getSessionAndUser(data) {
77
- return await client
94
+ async getSessionAndUser(sessionToken) {
95
+ return client
78
96
  .select({
79
- session: sessions,
80
- user: users,
97
+ session: sessionsTable,
98
+ user: usersTable,
81
99
  })
82
- .from(sessions)
83
- .where(eq(sessions.sessionToken, data))
84
- .innerJoin(users, eq(users.id, sessions.userId))
85
- .then((res) => res[0] ?? null);
100
+ .from(sessionsTable)
101
+ .where(eq(sessionsTable.sessionToken, sessionToken))
102
+ .innerJoin(usersTable, eq(usersTable.id, sessionsTable.userId))
103
+ .then((res) => (res.length > 0 ? res[0] : null));
86
104
  },
87
105
  async updateUser(data) {
88
106
  if (!data.id) {
89
107
  throw new Error("No user id.");
90
108
  }
91
- return await client
92
- .update(users)
109
+ const [result] = await client
110
+ .update(usersTable)
93
111
  .set(data)
94
- .where(eq(users.id, data.id))
95
- .returning()
96
- .then((res) => res[0]);
112
+ .where(eq(usersTable.id, data.id))
113
+ .returning();
114
+ if (!result) {
115
+ throw new Error("No user found.");
116
+ }
117
+ return result;
97
118
  },
98
119
  async updateSession(data) {
99
- return await client
100
- .update(sessions)
120
+ return client
121
+ .update(sessionsTable)
101
122
  .set(data)
102
- .where(eq(sessions.sessionToken, data.sessionToken))
123
+ .where(eq(sessionsTable.sessionToken, data.sessionToken))
103
124
  .returning()
104
125
  .then((res) => res[0]);
105
126
  },
106
- async linkAccount(rawAccount) {
107
- return stripUndefined(await client
108
- .insert(accounts)
109
- .values(rawAccount)
110
- .returning()
111
- .then((res) => res[0]));
127
+ async linkAccount(data) {
128
+ await client.insert(accountsTable).values(data);
112
129
  },
113
130
  async getUserByAccount(account) {
114
- const dbAccount = (await client
115
- .select()
116
- .from(accounts)
117
- .where(and(eq(accounts.providerAccountId, account.providerAccountId), eq(accounts.provider, account.provider)))
118
- .leftJoin(users, eq(accounts.userId, users.id))
119
- .then((res) => res[0])) ?? null;
120
- return dbAccount?.user ?? null;
131
+ const result = await client
132
+ .select({
133
+ account: accountsTable,
134
+ user: usersTable,
135
+ })
136
+ .from(accountsTable)
137
+ .innerJoin(usersTable, eq(accountsTable.userId, usersTable.id))
138
+ .where(and(eq(accountsTable.provider, account.provider), eq(accountsTable.providerAccountId, account.providerAccountId)))
139
+ .then((res) => res[0]);
140
+ return result?.user ?? null;
121
141
  },
122
142
  async deleteSession(sessionToken) {
123
- const session = await client
124
- .delete(sessions)
125
- .where(eq(sessions.sessionToken, sessionToken))
126
- .returning()
127
- .then((res) => res[0] ?? null);
128
- return session;
143
+ await client
144
+ .delete(sessionsTable)
145
+ .where(eq(sessionsTable.sessionToken, sessionToken));
129
146
  },
130
- async createVerificationToken(token) {
131
- return await client
132
- .insert(verificationTokens)
133
- .values(token)
147
+ async createVerificationToken(data) {
148
+ return client
149
+ .insert(verificationTokensTable)
150
+ .values(data)
134
151
  .returning()
135
152
  .then((res) => res[0]);
136
153
  },
137
- async useVerificationToken(token) {
138
- try {
139
- return await client
140
- .delete(verificationTokens)
141
- .where(and(eq(verificationTokens.identifier, token.identifier), eq(verificationTokens.token, token.token)))
142
- .returning()
143
- .then((res) => res[0] ?? null);
144
- }
145
- catch (err) {
146
- throw new Error("No verification token found.");
147
- }
154
+ async useVerificationToken(params) {
155
+ return client
156
+ .delete(verificationTokensTable)
157
+ .where(and(eq(verificationTokensTable.identifier, params.identifier), eq(verificationTokensTable.token, params.token)))
158
+ .returning()
159
+ .then((res) => (res.length > 0 ? res[0] : null));
148
160
  },
149
161
  async deleteUser(id) {
150
- await client
151
- .delete(users)
152
- .where(eq(users.id, id))
153
- .returning()
154
- .then((res) => res[0] ?? null);
162
+ await client.delete(usersTable).where(eq(usersTable.id, id));
155
163
  },
156
- async unlinkAccount(account) {
157
- const { type, provider, providerAccountId, userId } = await client
158
- .delete(accounts)
159
- .where(and(eq(accounts.providerAccountId, account.providerAccountId), eq(accounts.provider, account.provider)))
160
- .returning()
161
- .then((res) => res[0] ?? null);
162
- return { provider, type, providerAccountId, userId };
164
+ async unlinkAccount(params) {
165
+ await client
166
+ .delete(accountsTable)
167
+ .where(and(eq(accountsTable.provider, params.provider), eq(accountsTable.providerAccountId, params.providerAccountId)));
163
168
  },
164
169
  };
165
170
  }