@holeauth/adapter-drizzle 0.0.1-alpha.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Robert Kratz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # @holeauth/adapter-drizzle
2
+
3
+ Drizzle factory adapters for holeauth core — Postgres, MySQL, SQLite.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pnpm add @holeauth/adapter-drizzle drizzle-orm
9
+ ```
10
+
11
+ ## Usage (Postgres)
12
+
13
+ ```ts
14
+ // db/schema.ts
15
+ import { pgTable, text, timestamp } from 'drizzle-orm/pg-core';
16
+ import { createHoleauthTables } from '@holeauth/adapter-drizzle/pg';
17
+
18
+ export const users = pgTable('users', {
19
+ id: text('id').primaryKey(),
20
+ email: text('email').notNull().unique(),
21
+ name: text('name'),
22
+ image: text('image'),
23
+ emailVerified: timestamp('email_verified', { withTimezone: true, mode: 'date' }),
24
+ passwordHash: text('password_hash'),
25
+ });
26
+
27
+ export const holeauth = createHoleauthTables({ usersTable: users });
28
+ ```
29
+
30
+ ```ts
31
+ // lib/auth.ts
32
+ import { drizzle } from 'drizzle-orm/node-postgres';
33
+ import { createHoleauthAdapters } from '@holeauth/adapter-drizzle/pg';
34
+ import { users, holeauth } from '@/db/schema';
35
+
36
+ const db = drizzle(process.env.DATABASE_URL!);
37
+ const adapters = createHoleauthAdapters({ db, tables: holeauth.tables });
38
+ ```
39
+
40
+ ## Subpath exports
41
+
42
+ - `@holeauth/adapter-drizzle/pg`
43
+ - `@holeauth/adapter-drizzle/mysql`
44
+ - `@holeauth/adapter-drizzle/sqlite`
45
+
46
+ ## Notes
47
+
48
+ - `usersTable` is caller-owned; `id` column drives cascade-delete FKs.
49
+ - No migrations shipped. Use `drizzle-kit push` or generate migrations yourself.
50
+ - `transaction.run` wraps `db.transaction` — multi-step writes become atomic.
package/dist/index.cjs ADDED
@@ -0,0 +1,4 @@
1
+ 'use strict';
2
+
3
+ //# sourceMappingURL=index.cjs.map
4
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,285 @@
1
+ 'use strict';
2
+
3
+ var mysqlCore = require('drizzle-orm/mysql-core');
4
+ var drizzleOrm = require('drizzle-orm');
5
+
6
+ // src/mysql/index.ts
7
+ function createHoleauthTables(opts) {
8
+ const { usersTable, prefix = "holeauth_" } = opts;
9
+ const p = (s) => `${prefix}${s}`;
10
+ const sessions = mysqlCore.mysqlTable(
11
+ p("session"),
12
+ {
13
+ id: mysqlCore.varchar("id", { length: 191 }).primaryKey(),
14
+ userId: mysqlCore.varchar("user_id", { length: 191 }).notNull().references(() => usersTable.id, { onDelete: "cascade" }),
15
+ familyId: mysqlCore.varchar("family_id", { length: 191 }).notNull(),
16
+ refreshTokenHash: mysqlCore.varchar("refresh_token_hash", { length: 191 }).notNull(),
17
+ expiresAt: mysqlCore.timestamp("expires_at", { fsp: 3 }).notNull(),
18
+ createdAt: mysqlCore.timestamp("created_at", { fsp: 3 }).notNull().defaultNow(),
19
+ revokedAt: mysqlCore.timestamp("revoked_at", { fsp: 3 }),
20
+ userAgent: mysqlCore.text("user_agent"),
21
+ ip: mysqlCore.varchar("ip", { length: 64 })
22
+ },
23
+ (t) => ({
24
+ familyIdx: mysqlCore.index(`${p("session")}_family_idx`).on(t.familyId),
25
+ hashIdx: mysqlCore.uniqueIndex(`${p("session")}_hash_idx`).on(t.refreshTokenHash),
26
+ userIdx: mysqlCore.index(`${p("session")}_user_idx`).on(t.userId)
27
+ })
28
+ );
29
+ const accounts = mysqlCore.mysqlTable(
30
+ p("account"),
31
+ {
32
+ id: mysqlCore.varchar("id", { length: 191 }).primaryKey(),
33
+ userId: mysqlCore.varchar("user_id", { length: 191 }).notNull().references(() => usersTable.id, { onDelete: "cascade" }),
34
+ provider: mysqlCore.varchar("provider", { length: 191 }).notNull(),
35
+ providerAccountId: mysqlCore.varchar("provider_account_id", { length: 191 }).notNull(),
36
+ email: mysqlCore.varchar("email", { length: 320 }),
37
+ accessToken: mysqlCore.text("access_token"),
38
+ refreshToken: mysqlCore.text("refresh_token"),
39
+ expiresAt: mysqlCore.timestamp("expires_at", { fsp: 3 }),
40
+ tokenType: mysqlCore.varchar("token_type", { length: 64 }),
41
+ scope: mysqlCore.text("scope"),
42
+ idToken: mysqlCore.text("id_token")
43
+ },
44
+ (t) => ({
45
+ providerIdx: mysqlCore.uniqueIndex(`${p("account")}_provider_idx`).on(t.provider, t.providerAccountId),
46
+ userIdx: mysqlCore.index(`${p("account")}_user_idx`).on(t.userId)
47
+ })
48
+ );
49
+ const verificationTokens = mysqlCore.mysqlTable(
50
+ p("verification_token"),
51
+ {
52
+ identifier: mysqlCore.varchar("identifier", { length: 320 }).notNull(),
53
+ token: mysqlCore.varchar("token", { length: 191 }).notNull(),
54
+ expiresAt: mysqlCore.timestamp("expires_at", { fsp: 3 }).notNull()
55
+ },
56
+ (t) => ({ pk: mysqlCore.primaryKey({ columns: [t.identifier, t.token] }) })
57
+ );
58
+ const auditLog = mysqlCore.mysqlTable(
59
+ p("audit_log"),
60
+ {
61
+ id: mysqlCore.varchar("id", { length: 191 }).primaryKey(),
62
+ type: mysqlCore.varchar("type", { length: 64 }).notNull(),
63
+ userId: mysqlCore.varchar("user_id", { length: 191 }).references(() => usersTable.id, { onDelete: "set null" }),
64
+ sessionId: mysqlCore.varchar("session_id", { length: 191 }),
65
+ at: mysqlCore.timestamp("at", { fsp: 3 }).notNull().defaultNow(),
66
+ ip: mysqlCore.varchar("ip", { length: 64 }),
67
+ userAgent: mysqlCore.text("user_agent"),
68
+ data: mysqlCore.json("data")
69
+ },
70
+ (t) => ({
71
+ typeIdx: mysqlCore.index(`${p("audit_log")}_type_idx`).on(t.type),
72
+ userIdx: mysqlCore.index(`${p("audit_log")}_user_idx`).on(t.userId)
73
+ })
74
+ );
75
+ const sessionsRelations = drizzleOrm.relations(sessions, ({ one }) => ({
76
+ user: one(usersTable, { fields: [sessions.userId], references: [usersTable.id] })
77
+ }));
78
+ const accountsRelations = drizzleOrm.relations(accounts, ({ one }) => ({
79
+ user: one(usersTable, { fields: [accounts.userId], references: [usersTable.id] })
80
+ }));
81
+ const auditLogRelations = drizzleOrm.relations(auditLog, ({ one }) => ({
82
+ user: one(usersTable, { fields: [auditLog.userId], references: [usersTable.id] })
83
+ }));
84
+ return {
85
+ tables: { users: usersTable, sessions, accounts, verificationTokens, auditLog },
86
+ relations: { sessionsRelations, accountsRelations, auditLogRelations }
87
+ };
88
+ }
89
+ function createHoleauthAdapters(opts) {
90
+ const { db, tables, userEmailColumn = "email", generateId = () => crypto.randomUUID() } = opts;
91
+ const { users, sessions, accounts, verificationTokens, auditLog } = tables;
92
+ const emailCol = users[userEmailColumn];
93
+ if (!emailCol) {
94
+ throw new Error(`[holeauth] usersTable missing "${userEmailColumn}" column.`);
95
+ }
96
+ const one = (rows) => rows[0];
97
+ const userRowToAdapter = (r) => ({
98
+ id: String(r.id),
99
+ email: String(r[userEmailColumn] ?? ""),
100
+ emailVerified: r.emailVerified ?? null,
101
+ name: r.name ?? null,
102
+ image: r.image ?? null,
103
+ passwordHash: r.passwordHash ?? null
104
+ });
105
+ const user = {
106
+ async getUserById(id) {
107
+ const rows = await db.select().from(users).where(drizzleOrm.eq(users.id, id)).limit(1);
108
+ const row = one(rows);
109
+ return row ? userRowToAdapter(row) : null;
110
+ },
111
+ async getUserByEmail(email) {
112
+ const rows = await db.select().from(users).where(drizzleOrm.eq(emailCol, email)).limit(1);
113
+ const row = one(rows);
114
+ return row ? userRowToAdapter(row) : null;
115
+ },
116
+ async createUser(data) {
117
+ const id = generateId();
118
+ await db.insert(users).values({
119
+ id,
120
+ [userEmailColumn]: data.email,
121
+ emailVerified: data.emailVerified ?? null,
122
+ name: data.name ?? null,
123
+ image: data.image ?? null,
124
+ passwordHash: data.passwordHash ?? null
125
+ });
126
+ const rows = await db.select().from(users).where(drizzleOrm.eq(users.id, id)).limit(1);
127
+ return userRowToAdapter(rows[0]);
128
+ },
129
+ async updateUser(id, patch) {
130
+ const toSet = { ...patch };
131
+ if ("email" in toSet) {
132
+ toSet[userEmailColumn] = toSet.email;
133
+ if (userEmailColumn !== "email") delete toSet.email;
134
+ }
135
+ await db.update(users).set(toSet).where(drizzleOrm.eq(users.id, id));
136
+ const rows = await db.select().from(users).where(drizzleOrm.eq(users.id, id)).limit(1);
137
+ const row = one(rows);
138
+ if (!row) throw new Error(`User ${id} not found`);
139
+ return userRowToAdapter(row);
140
+ },
141
+ async deleteUser(id) {
142
+ await db.delete(users).where(drizzleOrm.eq(users.id, id));
143
+ }
144
+ };
145
+ const sessionRowToAdapter = (r) => ({
146
+ id: String(r.id),
147
+ userId: String(r.userId),
148
+ familyId: String(r.familyId),
149
+ refreshTokenHash: String(r.refreshTokenHash),
150
+ expiresAt: r.expiresAt,
151
+ createdAt: r.createdAt,
152
+ revokedAt: r.revokedAt ?? null,
153
+ userAgent: r.userAgent ?? null,
154
+ ip: r.ip ?? null
155
+ });
156
+ const session = {
157
+ async createSession(data) {
158
+ await db.insert(sessions).values(data);
159
+ const rows = await db.select().from(sessions).where(drizzleOrm.eq(sessions.id, data.id)).limit(1);
160
+ return sessionRowToAdapter(rows[0]);
161
+ },
162
+ async getSession(id) {
163
+ const rows = await db.select().from(sessions).where(drizzleOrm.eq(sessions.id, id)).limit(1);
164
+ return rows[0] ? sessionRowToAdapter(rows[0]) : null;
165
+ },
166
+ async getByRefreshHash(hash) {
167
+ const rows = await db.select().from(sessions).where(drizzleOrm.eq(sessions.refreshTokenHash, hash)).limit(1);
168
+ return rows[0] ? sessionRowToAdapter(rows[0]) : null;
169
+ },
170
+ async findByFamily(familyId) {
171
+ const rows = await db.select().from(sessions).where(drizzleOrm.eq(sessions.familyId, familyId));
172
+ return rows.map(sessionRowToAdapter);
173
+ },
174
+ async deleteSession(id) {
175
+ await db.delete(sessions).where(drizzleOrm.eq(sessions.id, id));
176
+ },
177
+ async rotateRefresh(id, newHash, expiresAt) {
178
+ await db.update(sessions).set({ refreshTokenHash: newHash, expiresAt }).where(drizzleOrm.eq(sessions.id, id));
179
+ const rows = await db.select().from(sessions).where(drizzleOrm.eq(sessions.id, id)).limit(1);
180
+ const row = one(rows);
181
+ if (!row) throw new Error(`Session ${id} not found`);
182
+ return sessionRowToAdapter(row);
183
+ },
184
+ async revokeFamily(familyId) {
185
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(drizzleOrm.and(drizzleOrm.eq(sessions.familyId, familyId), drizzleOrm.sql`${sessions.revokedAt} IS NULL`));
186
+ },
187
+ async revokeUser(userId) {
188
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(drizzleOrm.and(drizzleOrm.eq(sessions.userId, userId), drizzleOrm.sql`${sessions.revokedAt} IS NULL`));
189
+ }
190
+ };
191
+ const accountRowToAdapter = (r) => ({
192
+ id: String(r.id),
193
+ userId: String(r.userId),
194
+ provider: String(r.provider),
195
+ providerAccountId: String(r.providerAccountId),
196
+ email: r.email ?? null,
197
+ accessToken: r.accessToken ?? null,
198
+ refreshToken: r.refreshToken ?? null,
199
+ expiresAt: r.expiresAt ?? null,
200
+ tokenType: r.tokenType ?? null,
201
+ scope: r.scope ?? null,
202
+ idToken: r.idToken ?? null
203
+ });
204
+ const account = {
205
+ async linkAccount(data) {
206
+ const id = generateId();
207
+ await db.insert(accounts).values({ id, ...data });
208
+ const rows = await db.select().from(accounts).where(drizzleOrm.eq(accounts.id, id)).limit(1);
209
+ return accountRowToAdapter(rows[0]);
210
+ },
211
+ async getAccountByProvider(provider, providerAccountId) {
212
+ const rows = await db.select().from(accounts).where(drizzleOrm.and(drizzleOrm.eq(accounts.provider, provider), drizzleOrm.eq(accounts.providerAccountId, providerAccountId))).limit(1);
213
+ return rows[0] ? accountRowToAdapter(rows[0]) : null;
214
+ },
215
+ async getByProviderEmail(provider, email) {
216
+ const rows = await db.select().from(accounts).where(drizzleOrm.and(drizzleOrm.eq(accounts.provider, provider), drizzleOrm.eq(accounts.email, email))).limit(1);
217
+ return rows[0] ? accountRowToAdapter(rows[0]) : null;
218
+ },
219
+ async listByUser(userId) {
220
+ const rows = await db.select().from(accounts).where(drizzleOrm.eq(accounts.userId, userId));
221
+ return rows.map(accountRowToAdapter);
222
+ },
223
+ async unlinkAccount(id) {
224
+ await db.delete(accounts).where(drizzleOrm.eq(accounts.id, id));
225
+ }
226
+ };
227
+ const vtRowToAdapter = (r) => ({
228
+ identifier: String(r.identifier),
229
+ token: String(r.token),
230
+ expiresAt: r.expiresAt
231
+ });
232
+ const verificationToken = {
233
+ async create(data) {
234
+ await db.insert(verificationTokens).values(data);
235
+ return vtRowToAdapter(data);
236
+ },
237
+ async consume(identifier, token) {
238
+ const rows = await db.select().from(verificationTokens).where(drizzleOrm.and(drizzleOrm.eq(verificationTokens.identifier, identifier), drizzleOrm.eq(verificationTokens.token, token))).limit(1);
239
+ const row = rows[0];
240
+ if (!row) return null;
241
+ await db.delete(verificationTokens).where(drizzleOrm.and(drizzleOrm.eq(verificationTokens.identifier, identifier), drizzleOrm.eq(verificationTokens.token, token)));
242
+ const rec = vtRowToAdapter(row);
243
+ return rec.expiresAt.getTime() < Date.now() ? null : rec;
244
+ },
245
+ async purgeExpired() {
246
+ const existing = await db.select({ identifier: verificationTokens.identifier }).from(verificationTokens).where(drizzleOrm.sql`${verificationTokens.expiresAt} < NOW()`);
247
+ await db.delete(verificationTokens).where(drizzleOrm.sql`${verificationTokens.expiresAt} < NOW()`);
248
+ return existing.length;
249
+ }
250
+ };
251
+ const auditRowToAdapter = (r) => ({
252
+ id: String(r.id),
253
+ type: String(r.type),
254
+ userId: r.userId ?? null,
255
+ sessionId: r.sessionId ?? null,
256
+ at: r.at,
257
+ ip: r.ip ?? null,
258
+ userAgent: r.userAgent ?? null,
259
+ data: r.data ?? null
260
+ });
261
+ const auditLogAdapter = {
262
+ async record(event) {
263
+ await db.insert(auditLog).values({ id: event.id ?? generateId(), ...event });
264
+ },
265
+ async list(filter) {
266
+ const conds = [];
267
+ if (filter.userId) conds.push(drizzleOrm.eq(auditLog.userId, filter.userId));
268
+ if (filter.type) conds.push(drizzleOrm.eq(auditLog.type, filter.type));
269
+ const q = db.select().from(auditLog);
270
+ const rows = conds.length ? await q.where(drizzleOrm.and(...conds)).limit(filter.limit ?? 100) : await q.limit(filter.limit ?? 100);
271
+ return rows.map(auditRowToAdapter);
272
+ }
273
+ };
274
+ const transaction = {
275
+ async run(fn) {
276
+ return db.transaction(async () => fn());
277
+ }
278
+ };
279
+ return { user, session, account, verificationToken, auditLog: auditLogAdapter, transaction };
280
+ }
281
+
282
+ exports.createHoleauthAdapters = createHoleauthAdapters;
283
+ exports.createHoleauthTables = createHoleauthTables;
284
+ //# sourceMappingURL=index.cjs.map
285
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/mysql/index.ts"],"names":["mysqlTable","varchar","timestamp","text","index","uniqueIndex","primaryKey","json","relations","eq","and","sql"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\n mysqlTable,\n varchar,\n text,\n timestamp,\n json,\n index,\n uniqueIndex,\n primaryKey,\n type MySqlTableWithColumns,\n} from 'drizzle-orm/mysql-core';\nimport { relations, eq, and, sql } from 'drizzle-orm';\nimport type {\n AdapterUser,\n AdapterSession,\n AdapterAccount,\n AdapterVerificationToken,\n AdapterAuditEvent,\n UserAdapter,\n SessionAdapter,\n AccountAdapter,\n VerificationTokenAdapter,\n AuditLogAdapter,\n TransactionAdapter,\n} from '@holeauth/core/adapters';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type MysqlUsersTable = MySqlTableWithColumns<any> & { id: any };\n\nexport interface CreateHoleauthTablesOptions<U extends MysqlUsersTable> {\n usersTable: U;\n prefix?: string;\n}\n\nexport function createHoleauthTables<U extends MysqlUsersTable>(\n opts: CreateHoleauthTablesOptions<U>,\n) {\n const { usersTable, prefix = 'holeauth_' } = opts;\n const p = (s: string) => `${prefix}${s}`;\n\n const sessions = mysqlTable(\n p('session'),\n {\n id: varchar('id', { length: 191 }).primaryKey(),\n userId: varchar('user_id', { length: 191 })\n .notNull()\n .references(() => usersTable.id, { onDelete: 'cascade' }),\n familyId: varchar('family_id', { length: 191 }).notNull(),\n refreshTokenHash: varchar('refresh_token_hash', { length: 191 }).notNull(),\n expiresAt: timestamp('expires_at', { fsp: 3 }).notNull(),\n createdAt: timestamp('created_at', { fsp: 3 }).notNull().defaultNow(),\n revokedAt: timestamp('revoked_at', { fsp: 3 }),\n userAgent: text('user_agent'),\n ip: varchar('ip', { length: 64 }),\n },\n (t) => ({\n familyIdx: index(`${p('session')}_family_idx`).on(t.familyId),\n hashIdx: uniqueIndex(`${p('session')}_hash_idx`).on(t.refreshTokenHash),\n userIdx: index(`${p('session')}_user_idx`).on(t.userId),\n }),\n );\n\n const accounts = mysqlTable(\n p('account'),\n {\n id: varchar('id', { length: 191 }).primaryKey(),\n userId: varchar('user_id', { length: 191 })\n .notNull()\n .references(() => usersTable.id, { onDelete: 'cascade' }),\n provider: varchar('provider', { length: 191 }).notNull(),\n providerAccountId: varchar('provider_account_id', { length: 191 }).notNull(),\n email: varchar('email', { length: 320 }),\n accessToken: text('access_token'),\n refreshToken: text('refresh_token'),\n expiresAt: timestamp('expires_at', { fsp: 3 }),\n tokenType: varchar('token_type', { length: 64 }),\n scope: text('scope'),\n idToken: text('id_token'),\n },\n (t) => ({\n providerIdx: uniqueIndex(`${p('account')}_provider_idx`).on(t.provider, t.providerAccountId),\n userIdx: index(`${p('account')}_user_idx`).on(t.userId),\n }),\n );\n\n const verificationTokens = mysqlTable(\n p('verification_token'),\n {\n identifier: varchar('identifier', { length: 320 }).notNull(),\n token: varchar('token', { length: 191 }).notNull(),\n expiresAt: timestamp('expires_at', { fsp: 3 }).notNull(),\n },\n (t) => ({ pk: primaryKey({ columns: [t.identifier, t.token] }) }),\n );\n\n const auditLog = mysqlTable(\n p('audit_log'),\n {\n id: varchar('id', { length: 191 }).primaryKey(),\n type: varchar('type', { length: 64 }).notNull(),\n userId: varchar('user_id', { length: 191 }).references(() => usersTable.id, { onDelete: 'set null' }),\n sessionId: varchar('session_id', { length: 191 }),\n at: timestamp('at', { fsp: 3 }).notNull().defaultNow(),\n ip: varchar('ip', { length: 64 }),\n userAgent: text('user_agent'),\n data: json('data'),\n },\n (t) => ({\n typeIdx: index(`${p('audit_log')}_type_idx`).on(t.type),\n userIdx: index(`${p('audit_log')}_user_idx`).on(t.userId),\n }),\n );\n\n const sessionsRelations = relations(sessions, ({ one }) => ({\n user: one(usersTable, { fields: [sessions.userId], references: [usersTable.id] }),\n }));\n const accountsRelations = relations(accounts, ({ one }) => ({\n user: one(usersTable, { fields: [accounts.userId], references: [usersTable.id] }),\n }));\n const auditLogRelations = relations(auditLog, ({ one }) => ({\n user: one(usersTable, { fields: [auditLog.userId], references: [usersTable.id] }),\n }));\n\n return {\n tables: { users: usersTable, sessions, accounts, verificationTokens, auditLog },\n relations: { sessionsRelations, accountsRelations, auditLogRelations },\n };\n}\n\ntype HoleauthTables<U extends MysqlUsersTable> = ReturnType<\n typeof createHoleauthTables<U>\n>['tables'];\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type MysqlDb = any;\n\nexport interface CreateHoleauthAdaptersOptions<U extends MysqlUsersTable> {\n db: MysqlDb;\n tables: HoleauthTables<U>;\n userEmailColumn?: string;\n generateId?: () => string;\n}\n\nexport interface HoleauthAdapterBundle {\n user: UserAdapter;\n session: SessionAdapter;\n account: AccountAdapter;\n verificationToken: VerificationTokenAdapter;\n auditLog: AuditLogAdapter;\n transaction: TransactionAdapter;\n}\n\nexport function createHoleauthAdapters<U extends MysqlUsersTable>(\n opts: CreateHoleauthAdaptersOptions<U>,\n): HoleauthAdapterBundle {\n const { db, tables, userEmailColumn = 'email', generateId = () => crypto.randomUUID() } = opts;\n const { users, sessions, accounts, verificationTokens, auditLog } = tables;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const emailCol = (users as any)[userEmailColumn];\n if (!emailCol) {\n throw new Error(`[holeauth] usersTable missing \"${userEmailColumn}\" column.`);\n }\n\n const one = <T>(rows: T[]): T | undefined => rows[0];\n\n const userRowToAdapter = (r: Record<string, unknown>): AdapterUser => ({\n id: String(r.id),\n email: String(r[userEmailColumn] ?? ''),\n emailVerified: (r.emailVerified as Date | null | undefined) ?? null,\n name: (r.name as string | null | undefined) ?? null,\n image: (r.image as string | null | undefined) ?? null,\n passwordHash: (r.passwordHash as string | null | undefined) ?? null,\n });\n\n const user: UserAdapter = {\n async getUserById(id) {\n const rows = await db.select().from(users).where(eq(users.id, id)).limit(1);\n const row = one(rows);\n return row ? userRowToAdapter(row as Record<string, unknown>) : null;\n },\n async getUserByEmail(email) {\n const rows = await db.select().from(users).where(eq(emailCol, email)).limit(1);\n const row = one(rows);\n return row ? userRowToAdapter(row as Record<string, unknown>) : null;\n },\n async createUser(data) {\n const id = generateId();\n await db.insert(users).values({\n id,\n [userEmailColumn]: data.email,\n emailVerified: data.emailVerified ?? null,\n name: data.name ?? null,\n image: data.image ?? null,\n passwordHash: data.passwordHash ?? null,\n });\n const rows = await db.select().from(users).where(eq(users.id, id)).limit(1);\n return userRowToAdapter(rows[0] as Record<string, unknown>);\n },\n async updateUser(id, patch) {\n const toSet: Record<string, unknown> = { ...patch };\n if ('email' in toSet) {\n toSet[userEmailColumn] = toSet.email;\n if (userEmailColumn !== 'email') delete toSet.email;\n }\n await db.update(users).set(toSet).where(eq(users.id, id));\n const rows = await db.select().from(users).where(eq(users.id, id)).limit(1);\n const row = one(rows);\n if (!row) throw new Error(`User ${id} not found`);\n return userRowToAdapter(row as Record<string, unknown>);\n },\n async deleteUser(id) {\n await db.delete(users).where(eq(users.id, id));\n },\n };\n\n const sessionRowToAdapter = (r: Record<string, unknown>): AdapterSession => ({\n id: String(r.id),\n userId: String(r.userId),\n familyId: String(r.familyId),\n refreshTokenHash: String(r.refreshTokenHash),\n expiresAt: r.expiresAt as Date,\n createdAt: r.createdAt as Date | undefined,\n revokedAt: (r.revokedAt as Date | null | undefined) ?? null,\n userAgent: (r.userAgent as string | null | undefined) ?? null,\n ip: (r.ip as string | null | undefined) ?? null,\n });\n\n const session: SessionAdapter = {\n async createSession(data) {\n await db.insert(sessions).values(data);\n const rows = await db.select().from(sessions).where(eq(sessions.id, data.id)).limit(1);\n return sessionRowToAdapter(rows[0] as Record<string, unknown>);\n },\n async getSession(id) {\n const rows = await db.select().from(sessions).where(eq(sessions.id, id)).limit(1);\n return rows[0] ? sessionRowToAdapter(rows[0] as Record<string, unknown>) : null;\n },\n async getByRefreshHash(hash) {\n const rows = await db.select().from(sessions).where(eq(sessions.refreshTokenHash, hash)).limit(1);\n return rows[0] ? sessionRowToAdapter(rows[0] as Record<string, unknown>) : null;\n },\n async findByFamily(familyId) {\n const rows = await db.select().from(sessions).where(eq(sessions.familyId, familyId));\n return (rows as Record<string, unknown>[]).map(sessionRowToAdapter);\n },\n async deleteSession(id) {\n await db.delete(sessions).where(eq(sessions.id, id));\n },\n async rotateRefresh(id, newHash, expiresAt) {\n await db.update(sessions).set({ refreshTokenHash: newHash, expiresAt }).where(eq(sessions.id, id));\n const rows = await db.select().from(sessions).where(eq(sessions.id, id)).limit(1);\n const row = one(rows);\n if (!row) throw new Error(`Session ${id} not found`);\n return sessionRowToAdapter(row as Record<string, unknown>);\n },\n async revokeFamily(familyId) {\n await db\n .update(sessions)\n .set({ revokedAt: new Date() })\n .where(and(eq(sessions.familyId, familyId), sql`${sessions.revokedAt} IS NULL`));\n },\n async revokeUser(userId) {\n await db\n .update(sessions)\n .set({ revokedAt: new Date() })\n .where(and(eq(sessions.userId, userId), sql`${sessions.revokedAt} IS NULL`));\n },\n };\n\n const accountRowToAdapter = (r: Record<string, unknown>): AdapterAccount => ({\n id: String(r.id),\n userId: String(r.userId),\n provider: String(r.provider),\n providerAccountId: String(r.providerAccountId),\n email: (r.email as string | null | undefined) ?? null,\n accessToken: (r.accessToken as string | null | undefined) ?? null,\n refreshToken: (r.refreshToken as string | null | undefined) ?? null,\n expiresAt: (r.expiresAt as Date | null | undefined) ?? null,\n tokenType: (r.tokenType as string | null | undefined) ?? null,\n scope: (r.scope as string | null | undefined) ?? null,\n idToken: (r.idToken as string | null | undefined) ?? null,\n });\n\n const account: AccountAdapter = {\n async linkAccount(data) {\n const id = generateId();\n await db.insert(accounts).values({ id, ...data });\n const rows = await db.select().from(accounts).where(eq(accounts.id, id)).limit(1);\n return accountRowToAdapter(rows[0] as Record<string, unknown>);\n },\n async getAccountByProvider(provider, providerAccountId) {\n const rows = await db\n .select()\n .from(accounts)\n .where(and(eq(accounts.provider, provider), eq(accounts.providerAccountId, providerAccountId)))\n .limit(1);\n return rows[0] ? accountRowToAdapter(rows[0] as Record<string, unknown>) : null;\n },\n async getByProviderEmail(provider, email) {\n const rows = await db\n .select()\n .from(accounts)\n .where(and(eq(accounts.provider, provider), eq(accounts.email, email)))\n .limit(1);\n return rows[0] ? accountRowToAdapter(rows[0] as Record<string, unknown>) : null;\n },\n async listByUser(userId) {\n const rows = await db.select().from(accounts).where(eq(accounts.userId, userId));\n return (rows as Record<string, unknown>[]).map(accountRowToAdapter);\n },\n async unlinkAccount(id) {\n await db.delete(accounts).where(eq(accounts.id, id));\n },\n };\n\n const vtRowToAdapter = (r: Record<string, unknown>): AdapterVerificationToken => ({\n identifier: String(r.identifier),\n token: String(r.token),\n expiresAt: r.expiresAt as Date,\n });\n\n const verificationToken: VerificationTokenAdapter = {\n async create(data) {\n await db.insert(verificationTokens).values(data);\n return vtRowToAdapter(data as unknown as Record<string, unknown>);\n },\n async consume(identifier, token) {\n const rows = await db\n .select()\n .from(verificationTokens)\n .where(and(eq(verificationTokens.identifier, identifier), eq(verificationTokens.token, token)))\n .limit(1);\n const row = rows[0];\n if (!row) return null;\n await db\n .delete(verificationTokens)\n .where(and(eq(verificationTokens.identifier, identifier), eq(verificationTokens.token, token)));\n const rec = vtRowToAdapter(row as Record<string, unknown>);\n return rec.expiresAt.getTime() < Date.now() ? null : rec;\n },\n async purgeExpired() {\n const existing = await db\n .select({ identifier: verificationTokens.identifier })\n .from(verificationTokens)\n .where(sql`${verificationTokens.expiresAt} < NOW()`);\n await db.delete(verificationTokens).where(sql`${verificationTokens.expiresAt} < NOW()`);\n return (existing as unknown[]).length;\n },\n };\n\n const auditRowToAdapter = (r: Record<string, unknown>): AdapterAuditEvent => ({\n id: String(r.id),\n type: String(r.type),\n userId: (r.userId as string | null | undefined) ?? null,\n sessionId: (r.sessionId as string | null | undefined) ?? null,\n at: r.at as Date | undefined,\n ip: (r.ip as string | null | undefined) ?? null,\n userAgent: (r.userAgent as string | null | undefined) ?? null,\n data: (r.data as Record<string, unknown> | null | undefined) ?? null,\n });\n\n const auditLogAdapter: AuditLogAdapter = {\n async record(event) {\n await db.insert(auditLog).values({ id: event.id ?? generateId(), ...event });\n },\n async list(filter) {\n const conds = [];\n if (filter.userId) conds.push(eq(auditLog.userId, filter.userId));\n if (filter.type) conds.push(eq(auditLog.type, filter.type));\n const q = db.select().from(auditLog);\n const rows = conds.length\n ? await q.where(and(...conds)).limit(filter.limit ?? 100)\n : await q.limit(filter.limit ?? 100);\n return (rows as Record<string, unknown>[]).map(auditRowToAdapter);\n },\n };\n\n const transaction: TransactionAdapter = {\n async run(fn) {\n return db.transaction(async () => fn());\n },\n };\n\n return { user, session, account, verificationToken, auditLog: auditLogAdapter, transaction };\n}\n"]}