@factiii/auth 0.5.3 → 0.5.4

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/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import {
2
+ __require,
2
3
  biometricVerifySchema,
3
4
  changePasswordSchema,
4
5
  checkPasswordResetSchema,
@@ -17,11 +18,265 @@ import {
17
18
  twoFaResetVerifySchema,
18
19
  twoFaVerifySchema,
19
20
  verifyEmailSchema
20
- } from "./chunk-EHI4P63M.mjs";
21
+ } from "./chunk-KUYH4DBN.mjs";
21
22
 
22
23
  // src/middleware/authGuard.ts
23
24
  import { TRPCError } from "@trpc/server";
24
25
 
26
+ // src/adapters/prismaAdapter.ts
27
+ function createPrismaAdapter(prisma) {
28
+ return {
29
+ user: {
30
+ async findByEmailInsensitive(email) {
31
+ return prisma.user.findFirst({
32
+ where: { email: { equals: email, mode: "insensitive" } }
33
+ });
34
+ },
35
+ async findByUsernameInsensitive(username) {
36
+ return prisma.user.findFirst({
37
+ where: { username: { equals: username, mode: "insensitive" } }
38
+ });
39
+ },
40
+ async findByEmailOrUsernameInsensitive(identifier) {
41
+ return prisma.user.findFirst({
42
+ where: {
43
+ OR: [
44
+ { email: { equals: identifier, mode: "insensitive" } },
45
+ { username: { equals: identifier, mode: "insensitive" } }
46
+ ]
47
+ }
48
+ });
49
+ },
50
+ async findByEmailOrOAuthId(email, oauthId) {
51
+ return prisma.user.findFirst({
52
+ where: {
53
+ OR: [
54
+ { email: { equals: email, mode: "insensitive" } },
55
+ { oauthId: { equals: oauthId } }
56
+ ]
57
+ }
58
+ });
59
+ },
60
+ async findById(id) {
61
+ return prisma.user.findUnique({ where: { id } });
62
+ },
63
+ async findActiveById(id) {
64
+ return prisma.user.findUnique({
65
+ where: { id, status: "ACTIVE" }
66
+ });
67
+ },
68
+ async create(data) {
69
+ return prisma.user.create({ data });
70
+ },
71
+ async update(id, data) {
72
+ return prisma.user.update({ where: { id }, data });
73
+ }
74
+ },
75
+ session: {
76
+ async findById(id) {
77
+ const session = await prisma.session.findUnique({
78
+ where: { id },
79
+ select: {
80
+ id: true,
81
+ userId: true,
82
+ socketId: true,
83
+ twoFaSecret: true,
84
+ browserName: true,
85
+ issuedAt: true,
86
+ lastUsed: true,
87
+ revokedAt: true,
88
+ deviceId: true,
89
+ user: { select: { status: true, verifiedHumanAt: true } }
90
+ }
91
+ });
92
+ return session;
93
+ },
94
+ async create(data) {
95
+ return prisma.session.create({ data });
96
+ },
97
+ async update(id, data) {
98
+ return prisma.session.update({ where: { id }, data });
99
+ },
100
+ async updateLastUsed(id) {
101
+ const session = await prisma.session.update({
102
+ where: { id },
103
+ data: { lastUsed: /* @__PURE__ */ new Date() },
104
+ select: {
105
+ id: true,
106
+ userId: true,
107
+ socketId: true,
108
+ twoFaSecret: true,
109
+ browserName: true,
110
+ issuedAt: true,
111
+ lastUsed: true,
112
+ revokedAt: true,
113
+ deviceId: true,
114
+ user: { select: { verifiedHumanAt: true } }
115
+ }
116
+ });
117
+ return session;
118
+ },
119
+ async revoke(id) {
120
+ await prisma.session.update({
121
+ where: { id },
122
+ data: { revokedAt: /* @__PURE__ */ new Date() }
123
+ });
124
+ },
125
+ async findActiveByUserId(userId, excludeSessionId) {
126
+ return prisma.session.findMany({
127
+ where: {
128
+ userId,
129
+ revokedAt: null,
130
+ ...excludeSessionId ? { NOT: { id: excludeSessionId } } : {}
131
+ },
132
+ select: { id: true, socketId: true, userId: true }
133
+ });
134
+ },
135
+ async revokeAllByUserId(userId, excludeSessionId) {
136
+ await prisma.session.updateMany({
137
+ where: {
138
+ userId,
139
+ revokedAt: null,
140
+ ...excludeSessionId ? { NOT: { id: excludeSessionId } } : {}
141
+ },
142
+ data: { revokedAt: /* @__PURE__ */ new Date() }
143
+ });
144
+ },
145
+ async findTwoFaSecretsByUserId(userId) {
146
+ return prisma.session.findMany({
147
+ where: { userId, twoFaSecret: { not: null } },
148
+ select: { twoFaSecret: true }
149
+ });
150
+ },
151
+ async clearTwoFaSecrets(userId, excludeSessionId) {
152
+ await prisma.session.updateMany({
153
+ where: {
154
+ userId,
155
+ ...excludeSessionId ? { NOT: { id: excludeSessionId } } : {}
156
+ },
157
+ data: { twoFaSecret: null }
158
+ });
159
+ },
160
+ async findByIdWithDevice(id, userId) {
161
+ const session = await prisma.session.findUnique({
162
+ where: { id, userId },
163
+ select: {
164
+ twoFaSecret: true,
165
+ deviceId: true,
166
+ device: { select: { pushToken: true } }
167
+ }
168
+ });
169
+ return session;
170
+ },
171
+ async revokeByDevicePushToken(userId, pushToken, excludeSessionId) {
172
+ await prisma.session.updateMany({
173
+ where: {
174
+ userId,
175
+ id: { not: excludeSessionId },
176
+ revokedAt: null,
177
+ device: { pushToken }
178
+ },
179
+ data: { revokedAt: /* @__PURE__ */ new Date() }
180
+ });
181
+ },
182
+ async clearDeviceId(userId, deviceId) {
183
+ await prisma.session.updateMany({
184
+ where: { userId, deviceId },
185
+ data: { deviceId: null }
186
+ });
187
+ }
188
+ },
189
+ otp: {
190
+ async findValidByUserAndCode(userId, code) {
191
+ return prisma.oTP.findFirst({
192
+ where: { userId, code, expiresAt: { gte: /* @__PURE__ */ new Date() } }
193
+ });
194
+ },
195
+ async create(data) {
196
+ return prisma.oTP.create({ data });
197
+ },
198
+ async delete(id) {
199
+ await prisma.oTP.delete({ where: { id } });
200
+ }
201
+ },
202
+ passwordReset: {
203
+ async findById(id) {
204
+ return prisma.passwordReset.findUnique({
205
+ where: { id },
206
+ select: { id: true, createdAt: true, userId: true }
207
+ });
208
+ },
209
+ async create(userId) {
210
+ return prisma.passwordReset.create({
211
+ data: { userId }
212
+ });
213
+ },
214
+ async delete(id) {
215
+ await prisma.passwordReset.delete({ where: { id } });
216
+ },
217
+ async deleteAllByUserId(userId) {
218
+ await prisma.passwordReset.deleteMany({ where: { userId } });
219
+ }
220
+ },
221
+ device: {
222
+ async findByTokenSessionAndUser(pushToken, sessionId, userId) {
223
+ return prisma.device.findFirst({
224
+ where: {
225
+ pushToken,
226
+ sessions: { some: { id: sessionId } },
227
+ users: { some: { id: userId } }
228
+ },
229
+ select: { id: true }
230
+ });
231
+ },
232
+ async upsertByPushToken(pushToken, sessionId, userId) {
233
+ await prisma.device.upsert({
234
+ where: { pushToken },
235
+ create: {
236
+ pushToken,
237
+ sessions: { connect: { id: sessionId } },
238
+ users: { connect: { id: userId } }
239
+ },
240
+ update: {
241
+ sessions: { connect: { id: sessionId } },
242
+ users: { connect: { id: userId } }
243
+ }
244
+ });
245
+ },
246
+ async findByUserAndToken(userId, pushToken) {
247
+ return prisma.device.findFirst({
248
+ where: { users: { some: { id: userId } }, pushToken },
249
+ select: { id: true }
250
+ });
251
+ },
252
+ async disconnectUser(deviceId, userId) {
253
+ await prisma.device.update({
254
+ where: { id: deviceId },
255
+ data: { users: { disconnect: { id: userId } } }
256
+ });
257
+ },
258
+ async hasRemainingUsers(deviceId) {
259
+ const result = await prisma.device.findUnique({
260
+ where: { id: deviceId },
261
+ select: { users: { select: { id: true }, take: 1 } }
262
+ });
263
+ return (result?.users.length ?? 0) > 0;
264
+ },
265
+ async delete(id) {
266
+ await prisma.device.delete({ where: { id } });
267
+ }
268
+ },
269
+ admin: {
270
+ async findByUserId(userId) {
271
+ return prisma.admin.findFirst({
272
+ where: { userId },
273
+ select: { ip: true }
274
+ });
275
+ }
276
+ }
277
+ };
278
+ }
279
+
25
280
  // src/adapters/email.ts
26
281
  function createNoopEmailAdapter() {
27
282
  return {
@@ -75,6 +330,291 @@ function createConsoleEmailAdapter() {
75
330
  };
76
331
  }
77
332
 
333
+ // src/adapters/drizzleAdapter.ts
334
+ function createDrizzleAdapter(db, tables) {
335
+ const {
336
+ eq,
337
+ and,
338
+ or,
339
+ isNull,
340
+ isNotNull,
341
+ gte,
342
+ ne,
343
+ sql
344
+ } = __require("drizzle-orm");
345
+ const { users, sessions, otps, passwordResets, devices, admins } = tables;
346
+ return {
347
+ user: {
348
+ async findByEmailInsensitive(email) {
349
+ const rows = await db.select().from(users).where(sql`lower(${users.email}) = lower(${email})`).limit(1);
350
+ return rows[0] ?? null;
351
+ },
352
+ async findByUsernameInsensitive(username) {
353
+ const rows = await db.select().from(users).where(sql`lower(${users.username}) = lower(${username})`).limit(1);
354
+ return rows[0] ?? null;
355
+ },
356
+ async findByEmailOrUsernameInsensitive(identifier) {
357
+ const rows = await db.select().from(users).where(
358
+ or(
359
+ sql`lower(${users.email}) = lower(${identifier})`,
360
+ sql`lower(${users.username}) = lower(${identifier})`
361
+ )
362
+ ).limit(1);
363
+ return rows[0] ?? null;
364
+ },
365
+ async findByEmailOrOAuthId(email, oauthId) {
366
+ const rows = await db.select().from(users).where(
367
+ or(
368
+ sql`lower(${users.email}) = lower(${email})`,
369
+ eq(users.oauthId, oauthId)
370
+ )
371
+ ).limit(1);
372
+ return rows[0] ?? null;
373
+ },
374
+ async findById(id) {
375
+ const rows = await db.select().from(users).where(eq(users.id, id)).limit(1);
376
+ return rows[0] ?? null;
377
+ },
378
+ async findActiveById(id) {
379
+ const rows = await db.select().from(users).where(and(eq(users.id, id), eq(users.status, "ACTIVE"))).limit(1);
380
+ return rows[0] ?? null;
381
+ },
382
+ async create(data) {
383
+ const rows = await db.insert(users).values(data).returning();
384
+ return rows[0];
385
+ },
386
+ async update(id, data) {
387
+ const rows = await db.update(users).set(data).where(eq(users.id, id)).returning();
388
+ return rows[0];
389
+ }
390
+ },
391
+ session: {
392
+ async findById(id) {
393
+ const rows = await db.select({
394
+ id: sessions.id,
395
+ userId: sessions.userId,
396
+ socketId: sessions.socketId,
397
+ twoFaSecret: sessions.twoFaSecret,
398
+ browserName: sessions.browserName,
399
+ issuedAt: sessions.issuedAt,
400
+ lastUsed: sessions.lastUsed,
401
+ revokedAt: sessions.revokedAt,
402
+ deviceId: sessions.deviceId,
403
+ user: {
404
+ status: users.status,
405
+ verifiedHumanAt: users.verifiedHumanAt
406
+ }
407
+ }).from(sessions).innerJoin(users, eq(sessions.userId, users.id)).where(eq(sessions.id, id)).limit(1);
408
+ return rows[0] ?? null;
409
+ },
410
+ async create(data) {
411
+ const rows = await db.insert(sessions).values(data).returning();
412
+ return rows[0];
413
+ },
414
+ async update(id, data) {
415
+ const rows = await db.update(sessions).set(data).where(eq(sessions.id, id)).returning();
416
+ return rows[0];
417
+ },
418
+ async updateLastUsed(id) {
419
+ await db.update(sessions).set({ lastUsed: /* @__PURE__ */ new Date() }).where(eq(sessions.id, id));
420
+ const rows = await db.select({
421
+ id: sessions.id,
422
+ userId: sessions.userId,
423
+ socketId: sessions.socketId,
424
+ twoFaSecret: sessions.twoFaSecret,
425
+ browserName: sessions.browserName,
426
+ issuedAt: sessions.issuedAt,
427
+ lastUsed: sessions.lastUsed,
428
+ revokedAt: sessions.revokedAt,
429
+ deviceId: sessions.deviceId,
430
+ user: {
431
+ verifiedHumanAt: users.verifiedHumanAt
432
+ }
433
+ }).from(sessions).innerJoin(users, eq(sessions.userId, users.id)).where(eq(sessions.id, id)).limit(1);
434
+ return rows[0];
435
+ },
436
+ async revoke(id) {
437
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(eq(sessions.id, id));
438
+ },
439
+ async findActiveByUserId(userId, excludeSessionId) {
440
+ const conditions = [eq(sessions.userId, userId), isNull(sessions.revokedAt)];
441
+ if (excludeSessionId !== void 0) {
442
+ conditions.push(ne(sessions.id, excludeSessionId));
443
+ }
444
+ return db.select({
445
+ id: sessions.id,
446
+ socketId: sessions.socketId,
447
+ userId: sessions.userId
448
+ }).from(sessions).where(and(...conditions));
449
+ },
450
+ async revokeAllByUserId(userId, excludeSessionId) {
451
+ const conditions = [eq(sessions.userId, userId), isNull(sessions.revokedAt)];
452
+ if (excludeSessionId !== void 0) {
453
+ conditions.push(ne(sessions.id, excludeSessionId));
454
+ }
455
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(and(...conditions));
456
+ },
457
+ async findTwoFaSecretsByUserId(userId) {
458
+ return db.select({ twoFaSecret: sessions.twoFaSecret }).from(sessions).where(and(eq(sessions.userId, userId), isNotNull(sessions.twoFaSecret)));
459
+ },
460
+ async clearTwoFaSecrets(userId, excludeSessionId) {
461
+ const conditions = [eq(sessions.userId, userId)];
462
+ if (excludeSessionId !== void 0) {
463
+ conditions.push(ne(sessions.id, excludeSessionId));
464
+ }
465
+ await db.update(sessions).set({ twoFaSecret: null }).where(and(...conditions));
466
+ },
467
+ async findByIdWithDevice(id, userId) {
468
+ const rows = await db.select({
469
+ twoFaSecret: sessions.twoFaSecret,
470
+ deviceId: sessions.deviceId,
471
+ device: {
472
+ pushToken: devices.pushToken
473
+ }
474
+ }).from(sessions).leftJoin(devices, eq(sessions.deviceId, devices.id)).where(and(eq(sessions.id, id), eq(sessions.userId, userId))).limit(1);
475
+ if (!rows[0]) return null;
476
+ const row = rows[0];
477
+ return {
478
+ twoFaSecret: row.twoFaSecret,
479
+ deviceId: row.deviceId,
480
+ device: row.device?.pushToken ? { pushToken: row.device.pushToken } : null
481
+ };
482
+ },
483
+ async revokeByDevicePushToken(userId, pushToken, excludeSessionId) {
484
+ const deviceRows = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
485
+ if (!deviceRows[0]) return;
486
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(
487
+ and(
488
+ eq(sessions.userId, userId),
489
+ ne(sessions.id, excludeSessionId),
490
+ isNull(sessions.revokedAt),
491
+ eq(sessions.deviceId, deviceRows[0].id)
492
+ )
493
+ );
494
+ },
495
+ async clearDeviceId(userId, deviceId) {
496
+ await db.update(sessions).set({ deviceId: null }).where(and(eq(sessions.userId, userId), eq(sessions.deviceId, deviceId)));
497
+ }
498
+ },
499
+ otp: {
500
+ async findValidByUserAndCode(userId, code) {
501
+ const rows = await db.select().from(otps).where(
502
+ and(eq(otps.userId, userId), eq(otps.code, code), gte(otps.expiresAt, /* @__PURE__ */ new Date()))
503
+ ).limit(1);
504
+ return rows[0] ?? null;
505
+ },
506
+ async create(data) {
507
+ const rows = await db.insert(otps).values(data).returning();
508
+ return rows[0];
509
+ },
510
+ async delete(id) {
511
+ await db.delete(otps).where(eq(otps.id, id));
512
+ }
513
+ },
514
+ passwordReset: {
515
+ async findById(id) {
516
+ const rows = await db.select({
517
+ id: passwordResets.id,
518
+ createdAt: passwordResets.createdAt,
519
+ userId: passwordResets.userId
520
+ }).from(passwordResets).where(eq(passwordResets.id, id)).limit(1);
521
+ return rows[0] ?? null;
522
+ },
523
+ async create(userId) {
524
+ const rows = await db.insert(passwordResets).values({ userId }).returning();
525
+ return rows[0];
526
+ },
527
+ async delete(id) {
528
+ await db.delete(passwordResets).where(eq(passwordResets.id, id));
529
+ },
530
+ async deleteAllByUserId(userId) {
531
+ await db.delete(passwordResets).where(eq(passwordResets.userId, userId));
532
+ }
533
+ },
534
+ device: {
535
+ async findByTokenSessionAndUser(pushToken, sessionId, userId) {
536
+ const rows = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
537
+ if (!rows[0]) return null;
538
+ if (tables.devicesToSessions && tables.devicesToUsers) {
539
+ const sessionLink = await db.select().from(tables.devicesToSessions).where(
540
+ and(
541
+ eq(tables.devicesToSessions.deviceId, rows[0].id),
542
+ eq(tables.devicesToSessions.sessionId, sessionId)
543
+ )
544
+ ).limit(1);
545
+ const userLink = await db.select().from(tables.devicesToUsers).where(
546
+ and(
547
+ eq(tables.devicesToUsers.deviceId, rows[0].id),
548
+ eq(tables.devicesToUsers.userId, userId)
549
+ )
550
+ ).limit(1);
551
+ if (!sessionLink[0] || !userLink[0]) return null;
552
+ }
553
+ return { id: rows[0].id };
554
+ },
555
+ async upsertByPushToken(pushToken, sessionId, userId) {
556
+ const existing = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
557
+ let deviceId;
558
+ if (existing[0]) {
559
+ deviceId = existing[0].id;
560
+ } else {
561
+ const rows = await db.insert(devices).values({ pushToken }).returning({ id: devices.id });
562
+ deviceId = rows[0].id;
563
+ }
564
+ if (tables.devicesToSessions) {
565
+ await db.insert(tables.devicesToSessions).values({ deviceId, sessionId }).onConflictDoNothing();
566
+ }
567
+ if (tables.devicesToUsers) {
568
+ await db.insert(tables.devicesToUsers).values({ deviceId, userId }).onConflictDoNothing();
569
+ }
570
+ await db.update(sessions).set({ deviceId }).where(eq(sessions.id, sessionId));
571
+ },
572
+ async findByUserAndToken(userId, pushToken) {
573
+ if (tables.devicesToUsers) {
574
+ const rows2 = await db.select({ id: devices.id }).from(devices).innerJoin(
575
+ tables.devicesToUsers,
576
+ eq(devices.id, tables.devicesToUsers.deviceId)
577
+ ).where(
578
+ and(
579
+ eq(devices.pushToken, pushToken),
580
+ eq(tables.devicesToUsers.userId, userId)
581
+ )
582
+ ).limit(1);
583
+ return rows2[0] ? { id: rows2[0].id } : null;
584
+ }
585
+ const rows = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
586
+ return rows[0] ? { id: rows[0].id } : null;
587
+ },
588
+ async disconnectUser(deviceId, userId) {
589
+ if (tables.devicesToUsers) {
590
+ await db.delete(tables.devicesToUsers).where(
591
+ and(
592
+ eq(tables.devicesToUsers.deviceId, deviceId),
593
+ eq(tables.devicesToUsers.userId, userId)
594
+ )
595
+ );
596
+ }
597
+ },
598
+ async hasRemainingUsers(deviceId) {
599
+ if (tables.devicesToUsers) {
600
+ const rows = await db.select({ userId: tables.devicesToUsers.userId }).from(tables.devicesToUsers).where(eq(tables.devicesToUsers.deviceId, deviceId)).limit(1);
601
+ return rows.length > 0;
602
+ }
603
+ return false;
604
+ },
605
+ async delete(id) {
606
+ await db.delete(devices).where(eq(devices.id, id));
607
+ }
608
+ },
609
+ admin: {
610
+ async findByUserId(userId) {
611
+ const rows = await db.select({ ip: admins.ip }).from(admins).where(eq(admins.userId, userId)).limit(1);
612
+ return rows[0] ?? null;
613
+ }
614
+ }
615
+ };
616
+ }
617
+
78
618
  // src/utilities/config.ts
79
619
  var defaultTokenSettings = {
80
620
  jwtExpiry: 30 * 24 * 60 * 60,
@@ -105,9 +645,16 @@ var defaultFeatures = {
105
645
  otpLogin: true
106
646
  };
107
647
  function createAuthConfig(config) {
648
+ if (!config.database && !config.prisma) {
649
+ throw new Error(
650
+ "@factiii/auth: Provide either a `database` adapter or a `prisma` client in config."
651
+ );
652
+ }
653
+ const database = config.database ?? createPrismaAdapter(config.prisma);
108
654
  const emailService = config.emailService ?? createNoopEmailAdapter();
109
655
  return {
110
656
  ...config,
657
+ database,
111
658
  features: { ...defaultFeatures, ...config.features },
112
659
  tokenSettings: { ...defaultTokenSettings, ...config.tokenSettings },
113
660
  cookieSettings: { ...defaultCookieSettings, ...config.cookieSettings },
@@ -225,6 +772,7 @@ function isTokenInvalidError(error) {
225
772
  function createAuthGuard(config, t) {
226
773
  const storageKeys = config.storageKeys ?? defaultStorageKeys;
227
774
  const cookieSettings = { ...defaultCookieSettings, ...config.cookieSettings };
775
+ const database = config.database ?? createPrismaAdapter(config.prisma);
228
776
  const revokeSession = async (ctx, sessionId, description, errorStack, path) => {
229
777
  clearAuthCookie(ctx.res, cookieSettings, storageKeys);
230
778
  if (config.hooks?.logError) {
@@ -261,15 +809,9 @@ ${errorStack}` : null,
261
809
  }
262
810
  if (sessionId) {
263
811
  try {
264
- await config.prisma.session.update({
265
- where: { id: sessionId },
266
- data: { revokedAt: /* @__PURE__ */ new Date() }
267
- });
812
+ await database.session.revoke(sessionId);
268
813
  if (config.hooks?.onSessionRevoked) {
269
- const session = await config.prisma.session.findUnique({
270
- where: { id: sessionId },
271
- select: { id: true, userId: true, socketId: true }
272
- });
814
+ const session = await database.session.findById(sessionId);
273
815
  if (session) {
274
816
  await config.hooks.onSessionRevoked(session.userId, session.socketId, description);
275
817
  }
@@ -294,23 +836,7 @@ ${errorStack}` : null,
294
836
  secret: config.secrets.jwt,
295
837
  ignoreExpiration: meta?.ignoreExpiration ?? false
296
838
  });
297
- const session = await config.prisma.session.findUnique({
298
- where: {
299
- id: decodedToken.id
300
- },
301
- select: {
302
- userId: true,
303
- user: {
304
- select: {
305
- status: true,
306
- verifiedHumanAt: true
307
- }
308
- },
309
- revokedAt: true,
310
- socketId: true,
311
- id: true
312
- }
313
- });
839
+ const session = await database.session.findById(decodedToken.id);
314
840
  if (!session) {
315
841
  await revokeSession(
316
842
  ctx,
@@ -364,10 +890,7 @@ ${errorStack}` : null,
364
890
  });
365
891
  }
366
892
  if (meta?.adminRequired) {
367
- const admin = await config.prisma.admin.findFirst({
368
- where: { userId: session.userId },
369
- select: { ip: true }
370
- });
893
+ const admin = await database.admin.findByUserId(session.userId);
371
894
  if (!admin || admin.ip !== ctx.ip) {
372
895
  await revokeSession(
373
896
  ctx,
@@ -622,19 +1145,14 @@ var BaseProcedureFactory = class {
622
1145
  if (this.config.hooks?.beforeRegister) {
623
1146
  await this.config.hooks.beforeRegister(typedInput);
624
1147
  }
625
- const usernameCheck = await this.config.prisma.user.findFirst({
626
- where: { username: { equals: username, mode: "insensitive" } }
627
- });
1148
+ const usernameCheck = await this.config.database.user.findByUsernameInsensitive(username);
628
1149
  if (usernameCheck) {
629
1150
  throw new TRPCError2({
630
1151
  code: "CONFLICT",
631
1152
  message: "An account already exists with that username."
632
1153
  });
633
1154
  }
634
- const emailCheck = await this.config.prisma.user.findFirst({
635
- where: { email: { equals: email, mode: "insensitive" } },
636
- select: { id: true }
637
- });
1155
+ const emailCheck = await this.config.database.user.findByEmailInsensitive(email);
638
1156
  if (emailCheck) {
639
1157
  throw new TRPCError2({
640
1158
  code: "CONFLICT",
@@ -642,30 +1160,25 @@ var BaseProcedureFactory = class {
642
1160
  });
643
1161
  }
644
1162
  const hashedPassword = await hashPassword(password);
645
- const user = await this.config.prisma.user.create({
646
- data: {
647
- username,
648
- email,
649
- password: hashedPassword,
650
- status: "ACTIVE",
651
- tag: this.config.features.biometric ? "BOT" : "HUMAN",
652
- twoFaEnabled: false,
653
- emailVerificationStatus: "UNVERIFIED",
654
- verifiedHumanAt: null
655
- }
1163
+ const user = await this.config.database.user.create({
1164
+ username,
1165
+ email,
1166
+ password: hashedPassword,
1167
+ status: "ACTIVE",
1168
+ tag: this.config.features.biometric ? "BOT" : "HUMAN",
1169
+ twoFaEnabled: false,
1170
+ emailVerificationStatus: "UNVERIFIED",
1171
+ verifiedHumanAt: null
656
1172
  });
657
1173
  if (this.config.hooks?.onUserCreated) {
658
1174
  await this.config.hooks.onUserCreated(user.id, typedInput);
659
1175
  }
660
1176
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
661
- const session = await this.config.prisma.session.create({
662
- data: {
663
- userId: user.id,
664
- browserName: detectBrowser(userAgent),
665
- socketId: null,
666
- ...extraSessionData
667
- },
668
- select: { id: true, userId: true }
1177
+ const session = await this.config.database.session.create({
1178
+ userId: user.id,
1179
+ browserName: detectBrowser(userAgent),
1180
+ socketId: null,
1181
+ ...extraSessionData
669
1182
  });
670
1183
  if (this.config.hooks?.onSessionCreated) {
671
1184
  await this.config.hooks.onSessionCreated(session.id, typedInput);
@@ -703,24 +1216,7 @@ var BaseProcedureFactory = class {
703
1216
  if (this.config.hooks?.beforeLogin) {
704
1217
  await this.config.hooks.beforeLogin(typedInput);
705
1218
  }
706
- const user = await this.config.prisma.user.findFirst({
707
- where: {
708
- OR: [
709
- { email: { equals: username, mode: "insensitive" } },
710
- { username: { equals: username, mode: "insensitive" } }
711
- ]
712
- },
713
- select: {
714
- id: true,
715
- status: true,
716
- password: true,
717
- twoFaEnabled: true,
718
- email: true,
719
- username: true,
720
- oauthProvider: true,
721
- verifiedHumanAt: true
722
- }
723
- });
1219
+ const user = await this.config.database.user.findByEmailOrUsernameInsensitive(username);
724
1220
  if (!user) {
725
1221
  throw new TRPCError2({
726
1222
  code: "FORBIDDEN",
@@ -761,10 +1257,7 @@ var BaseProcedureFactory = class {
761
1257
  };
762
1258
  }
763
1259
  let validCode = false;
764
- const secrets = await this.config.prisma.session.findMany({
765
- where: { userId: user.id, twoFaSecret: { not: null } },
766
- select: { twoFaSecret: true }
767
- });
1260
+ const secrets = await this.config.database.session.findTwoFaSecretsByUserId(user.id);
768
1261
  for (const s of secrets) {
769
1262
  if (s.twoFaSecret && await verifyTotp(code, cleanBase32String(s.twoFaSecret))) {
770
1263
  validCode = true;
@@ -772,14 +1265,13 @@ var BaseProcedureFactory = class {
772
1265
  }
773
1266
  }
774
1267
  if (!validCode) {
775
- const checkOTP = await this.config.prisma.oTP.findFirst({
776
- where: { userId: user.id, code: Number(code), expiresAt: { gte: /* @__PURE__ */ new Date() } }
777
- });
1268
+ const checkOTP = await this.config.database.otp.findValidByUserAndCode(
1269
+ user.id,
1270
+ Number(code)
1271
+ );
778
1272
  if (checkOTP) {
779
1273
  validCode = true;
780
- await this.config.prisma.oTP.delete({
781
- where: { id: checkOTP.id }
782
- });
1274
+ await this.config.database.otp.delete(checkOTP.id);
783
1275
  }
784
1276
  }
785
1277
  if (!validCode) {
@@ -790,24 +1282,11 @@ var BaseProcedureFactory = class {
790
1282
  }
791
1283
  }
792
1284
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
793
- const session = await this.config.prisma.session.create({
794
- data: {
795
- userId: user.id,
796
- browserName: detectBrowser(userAgent),
797
- socketId: null,
798
- ...extraSessionData
799
- },
800
- select: {
801
- id: true,
802
- userId: true,
803
- socketId: true,
804
- browserName: true,
805
- issuedAt: true,
806
- lastUsed: true,
807
- revokedAt: true,
808
- deviceId: true,
809
- twoFaSecret: true
810
- }
1285
+ const session = await this.config.database.session.create({
1286
+ userId: user.id,
1287
+ browserName: detectBrowser(userAgent),
1288
+ socketId: null,
1289
+ ...extraSessionData
811
1290
  });
812
1291
  if (this.config.hooks?.onUserLogin) {
813
1292
  await this.config.hooks.onUserLogin(user.id, session.id);
@@ -838,15 +1317,9 @@ var BaseProcedureFactory = class {
838
1317
  return this.authProcedure.meta({ ignoreExpiration: true }).mutation(async ({ ctx }) => {
839
1318
  const { userId, sessionId } = ctx;
840
1319
  if (sessionId) {
841
- await this.config.prisma.session.update({
842
- where: { id: sessionId },
843
- data: { revokedAt: /* @__PURE__ */ new Date() }
844
- });
1320
+ await this.config.database.session.revoke(sessionId);
845
1321
  if (userId) {
846
- await this.config.prisma.user.update({
847
- where: { id: userId },
848
- data: { isActive: false }
849
- });
1322
+ await this.config.database.user.update(userId, { isActive: false });
850
1323
  }
851
1324
  if (this.config.hooks?.afterLogout) {
852
1325
  await this.config.hooks.afterLogout(userId, sessionId, ctx.socketId);
@@ -858,15 +1331,7 @@ var BaseProcedureFactory = class {
858
1331
  }
859
1332
  refresh() {
860
1333
  return this.authProcedure.query(async ({ ctx }) => {
861
- const session = await this.config.prisma.session.update({
862
- where: { id: ctx.sessionId },
863
- data: { lastUsed: /* @__PURE__ */ new Date() },
864
- select: {
865
- id: true,
866
- userId: true,
867
- user: { select: { verifiedHumanAt: true } }
868
- }
869
- });
1334
+ const session = await this.config.database.session.updateLastUsed(ctx.sessionId);
870
1335
  if (this.config.hooks?.onRefresh) {
871
1336
  this.config.hooks.onRefresh(session.userId).catch(() => {
872
1337
  });
@@ -891,22 +1356,14 @@ var BaseProcedureFactory = class {
891
1356
  return this.authProcedure.input(endAllSessionsSchema).mutation(async ({ ctx, input }) => {
892
1357
  const { skipCurrentSession } = input;
893
1358
  const { userId, sessionId } = ctx;
894
- const sessionsToRevoke = await this.config.prisma.session.findMany({
895
- where: {
896
- userId,
897
- revokedAt: null,
898
- ...skipCurrentSession ? { NOT: { id: sessionId } } : {}
899
- },
900
- select: { socketId: true, id: true, userId: true }
901
- });
902
- await this.config.prisma.session.updateMany({
903
- where: {
904
- userId,
905
- revokedAt: null,
906
- ...skipCurrentSession ? { NOT: { id: sessionId } } : {}
907
- },
908
- data: { revokedAt: /* @__PURE__ */ new Date() }
909
- });
1359
+ const sessionsToRevoke = await this.config.database.session.findActiveByUserId(
1360
+ userId,
1361
+ skipCurrentSession ? sessionId : void 0
1362
+ );
1363
+ await this.config.database.session.revokeAllByUserId(
1364
+ userId,
1365
+ skipCurrentSession ? sessionId : void 0
1366
+ );
910
1367
  for (const session of sessionsToRevoke) {
911
1368
  if (this.config.hooks?.onSessionRevoked) {
912
1369
  await this.config.hooks.onSessionRevoked(
@@ -917,10 +1374,7 @@ var BaseProcedureFactory = class {
917
1374
  }
918
1375
  }
919
1376
  if (!skipCurrentSession) {
920
- await this.config.prisma.user.update({
921
- where: { id: userId },
922
- data: { isActive: false }
923
- });
1377
+ await this.config.database.user.update(userId, { isActive: false });
924
1378
  }
925
1379
  return { success: true, revokedCount: sessionsToRevoke.length };
926
1380
  });
@@ -935,10 +1389,7 @@ var BaseProcedureFactory = class {
935
1389
  message: "New password cannot be the same as current password"
936
1390
  });
937
1391
  }
938
- const user = await this.config.prisma.user.findUnique({
939
- where: { id: userId },
940
- select: { password: true }
941
- });
1392
+ const user = await this.config.database.user.findById(userId);
942
1393
  if (!user) {
943
1394
  throw new TRPCError2({ code: "NOT_FOUND", message: "User not found" });
944
1395
  }
@@ -956,14 +1407,8 @@ var BaseProcedureFactory = class {
956
1407
  });
957
1408
  }
958
1409
  const hashedPassword = await hashPassword(newPassword);
959
- await this.config.prisma.user.update({
960
- where: { id: userId },
961
- data: { password: hashedPassword }
962
- });
963
- await this.config.prisma.session.updateMany({
964
- where: { userId, revokedAt: null, NOT: { id: sessionId } },
965
- data: { revokedAt: /* @__PURE__ */ new Date() }
966
- });
1410
+ await this.config.database.user.update(userId, { password: hashedPassword });
1411
+ await this.config.database.session.revokeAllByUserId(userId, sessionId);
967
1412
  if (this.config.hooks?.onPasswordChanged) {
968
1413
  await this.config.hooks.onPasswordChanged(userId);
969
1414
  }
@@ -976,11 +1421,8 @@ var BaseProcedureFactory = class {
976
1421
  sendPasswordResetEmail() {
977
1422
  return this.procedure.input(requestPasswordResetSchema).mutation(async ({ input }) => {
978
1423
  const { email } = input;
979
- const user = await this.config.prisma.user.findFirst({
980
- where: { email: { equals: email, mode: "insensitive" }, status: "ACTIVE" },
981
- select: { id: true, password: true, email: true }
982
- });
983
- if (!user) {
1424
+ const user = await this.config.database.user.findByEmailInsensitive(email);
1425
+ if (!user || user.status !== "ACTIVE") {
984
1426
  return { message: "If an account exists with that email, a reset link has been sent." };
985
1427
  }
986
1428
  if (!user.password) {
@@ -989,10 +1431,8 @@ var BaseProcedureFactory = class {
989
1431
  message: "This account uses social login. Please use that method."
990
1432
  });
991
1433
  }
992
- await this.config.prisma.passwordReset.deleteMany({ where: { userId: user.id } });
993
- const passwordReset = await this.config.prisma.passwordReset.create({
994
- data: { userId: user.id }
995
- });
1434
+ await this.config.database.passwordReset.deleteAllByUserId(user.id);
1435
+ const passwordReset = await this.config.database.passwordReset.create(user.id);
996
1436
  if (this.config.emailService) {
997
1437
  await this.config.emailService.sendPasswordResetEmail(user.email, String(passwordReset.id));
998
1438
  }
@@ -1002,15 +1442,12 @@ var BaseProcedureFactory = class {
1002
1442
  checkPasswordReset() {
1003
1443
  return this.procedure.input(checkPasswordResetSchema).query(async ({ input }) => {
1004
1444
  const { token } = input;
1005
- const passwordReset = await this.config.prisma.passwordReset.findUnique({
1006
- where: { id: token },
1007
- select: { id: true, createdAt: true, userId: true }
1008
- });
1445
+ const passwordReset = await this.config.database.passwordReset.findById(token);
1009
1446
  if (!passwordReset) {
1010
1447
  throw new TRPCError2({ code: "NOT_FOUND", message: "Invalid reset token." });
1011
1448
  }
1012
1449
  if (passwordReset.createdAt.getTime() + this.config.tokenSettings.passwordResetExpiryMs < Date.now()) {
1013
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1450
+ await this.config.database.passwordReset.delete(token);
1014
1451
  throw new TRPCError2({ code: "FORBIDDEN", message: "Reset token expired." });
1015
1452
  }
1016
1453
  return { valid: true };
@@ -1019,31 +1456,23 @@ var BaseProcedureFactory = class {
1019
1456
  resetPassword() {
1020
1457
  return this.procedure.input(resetPasswordSchema).mutation(async ({ input }) => {
1021
1458
  const { token, password } = input;
1022
- const passwordReset = await this.config.prisma.passwordReset.findFirst({
1023
- where: { id: token },
1024
- select: { id: true, createdAt: true, userId: true }
1025
- });
1459
+ const passwordReset = await this.config.database.passwordReset.findById(token);
1026
1460
  if (!passwordReset) {
1027
1461
  throw new TRPCError2({ code: "NOT_FOUND", message: "Invalid reset token." });
1028
1462
  }
1029
1463
  if (passwordReset.createdAt.getTime() + this.config.tokenSettings.passwordResetExpiryMs < Date.now()) {
1030
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1464
+ await this.config.database.passwordReset.delete(token);
1031
1465
  throw new TRPCError2({ code: "FORBIDDEN", message: "Reset token expired." });
1032
1466
  }
1033
1467
  const hashedPassword = await hashPassword(password);
1034
- await this.config.prisma.user.update({
1035
- where: { id: passwordReset.userId },
1036
- data: { password: hashedPassword }
1037
- });
1038
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1039
- const sessionsToRevoke = await this.config.prisma.session.findMany({
1040
- where: { userId: passwordReset.userId, revokedAt: null },
1041
- select: { id: true, socketId: true, userId: true }
1042
- });
1043
- await this.config.prisma.session.updateMany({
1044
- where: { userId: passwordReset.userId, revokedAt: null },
1045
- data: { revokedAt: /* @__PURE__ */ new Date() }
1468
+ await this.config.database.user.update(passwordReset.userId, {
1469
+ password: hashedPassword
1046
1470
  });
1471
+ await this.config.database.passwordReset.delete(token);
1472
+ const sessionsToRevoke = await this.config.database.session.findActiveByUserId(
1473
+ passwordReset.userId
1474
+ );
1475
+ await this.config.database.session.revokeAllByUserId(passwordReset.userId);
1047
1476
  for (const session of sessionsToRevoke) {
1048
1477
  if (this.config.hooks?.onSessionRevoked) {
1049
1478
  await this.config.hooks.onSessionRevoked(
@@ -1080,9 +1509,9 @@ var BiometricProcedureFactory = class {
1080
1509
  return this.authProcedure.input(biometricVerifySchema).mutation(async ({ ctx }) => {
1081
1510
  this.checkConfig();
1082
1511
  const { userId } = ctx;
1083
- await this.config.prisma.user.update({
1084
- where: { id: userId },
1085
- data: { verifiedHumanAt: /* @__PURE__ */ new Date(), tag: "HUMAN" }
1512
+ await this.config.database.user.update(userId, {
1513
+ verifiedHumanAt: /* @__PURE__ */ new Date(),
1514
+ tag: "HUMAN"
1086
1515
  });
1087
1516
  if (this.config.hooks?.onBiometricVerified) {
1088
1517
  await this.config.hooks.onBiometricVerified(userId);
@@ -1094,10 +1523,7 @@ var BiometricProcedureFactory = class {
1094
1523
  return this.authProcedure.query(async ({ ctx }) => {
1095
1524
  this.checkConfig();
1096
1525
  const { userId } = ctx;
1097
- const user = await this.config.prisma.user.findUnique({
1098
- where: { id: userId },
1099
- select: { verifiedHumanAt: true }
1100
- });
1526
+ const user = await this.config.database.user.findById(userId);
1101
1527
  if (!user) {
1102
1528
  throw new TRPCError3({ code: "NOT_FOUND", message: "User not found" });
1103
1529
  }
@@ -1144,10 +1570,7 @@ var EmailVerificationProcedureFactory = class {
1144
1570
  return this.authProcedure.mutation(async ({ ctx }) => {
1145
1571
  this.checkConfig();
1146
1572
  const { userId } = ctx;
1147
- const user = await this.config.prisma.user.findUnique({
1148
- where: { id: userId, status: "ACTIVE" },
1149
- select: { id: true, email: true, emailVerificationStatus: true }
1150
- });
1573
+ const user = await this.config.database.user.findActiveById(userId);
1151
1574
  if (!user) {
1152
1575
  throw new TRPCError4({ code: "NOT_FOUND", message: "User not found" });
1153
1576
  }
@@ -1155,9 +1578,9 @@ var EmailVerificationProcedureFactory = class {
1155
1578
  return { message: "Email is already verified", emailSent: false };
1156
1579
  }
1157
1580
  const otp = randomUUID();
1158
- await this.config.prisma.user.update({
1159
- where: { id: userId },
1160
- data: { emailVerificationStatus: "PENDING", otpForEmailVerification: otp }
1581
+ await this.config.database.user.update(userId, {
1582
+ emailVerificationStatus: "PENDING",
1583
+ otpForEmailVerification: otp
1161
1584
  });
1162
1585
  if (this.config.emailService) {
1163
1586
  try {
@@ -1175,10 +1598,7 @@ var EmailVerificationProcedureFactory = class {
1175
1598
  this.checkConfig();
1176
1599
  const { userId } = ctx;
1177
1600
  const { code } = input;
1178
- const user = await this.config.prisma.user.findUnique({
1179
- where: { id: userId, status: "ACTIVE" },
1180
- select: { id: true, emailVerificationStatus: true, otpForEmailVerification: true }
1181
- });
1601
+ const user = await this.config.database.user.findActiveById(userId);
1182
1602
  if (!user) {
1183
1603
  throw new TRPCError4({ code: "NOT_FOUND", message: "User not found" });
1184
1604
  }
@@ -1188,9 +1608,9 @@ var EmailVerificationProcedureFactory = class {
1188
1608
  if (code !== user.otpForEmailVerification) {
1189
1609
  throw new TRPCError4({ code: "BAD_REQUEST", message: "Invalid verification code" });
1190
1610
  }
1191
- await this.config.prisma.user.update({
1192
- where: { id: userId },
1193
- data: { emailVerificationStatus: "VERIFIED", otpForEmailVerification: null }
1611
+ await this.config.database.user.update(userId, {
1612
+ emailVerificationStatus: "VERIFIED",
1613
+ otpForEmailVerification: null
1194
1614
  });
1195
1615
  if (this.config.hooks?.onEmailVerified) {
1196
1616
  await this.config.hooks.onEmailVerified(userId);
@@ -1202,10 +1622,7 @@ var EmailVerificationProcedureFactory = class {
1202
1622
  return this.authProcedure.query(async ({ ctx }) => {
1203
1623
  this.checkConfig();
1204
1624
  const { userId } = ctx;
1205
- const user = await this.config.prisma.user.findUnique({
1206
- where: { id: userId },
1207
- select: { emailVerificationStatus: true, email: true }
1208
- });
1625
+ const user = await this.config.database.user.findById(userId);
1209
1626
  if (!user) {
1210
1627
  throw new TRPCError4({ code: "NOT_FOUND", message: "User not found" });
1211
1628
  }
@@ -1259,23 +1676,7 @@ var OAuthLoginProcedureFactory = class {
1259
1676
  message: "Email not provided by OAuth provider"
1260
1677
  });
1261
1678
  }
1262
- let user = await this.config.prisma.user.findFirst({
1263
- where: {
1264
- OR: [{ email: { equals: email, mode: "insensitive" } }, { oauthId: { equals: oauthId } }]
1265
- },
1266
- select: {
1267
- id: true,
1268
- status: true,
1269
- email: true,
1270
- username: true,
1271
- password: true,
1272
- oauthProvider: true,
1273
- oauthId: true,
1274
- twoFaEnabled: true,
1275
- verifiedHumanAt: true,
1276
- emailVerificationStatus: true
1277
- }
1278
- });
1679
+ let user = await this.config.database.user.findByEmailOrOAuthId(email, oauthId);
1279
1680
  if (user?.oauthProvider && user.oauthProvider !== provider) {
1280
1681
  throw new TRPCError5({
1281
1682
  code: "BAD_REQUEST",
@@ -1290,19 +1691,17 @@ var OAuthLoginProcedureFactory = class {
1290
1691
  }
1291
1692
  if (!user) {
1292
1693
  const generateUsername = this.config.generateUsername ?? (() => `user_${Date.now()}`);
1293
- user = await this.config.prisma.user.create({
1294
- data: {
1295
- username: generateUsername(),
1296
- email,
1297
- password: null,
1298
- emailVerificationStatus: "VERIFIED",
1299
- oauthProvider: provider,
1300
- oauthId,
1301
- status: "ACTIVE",
1302
- tag: this.config.features.biometric ? "BOT" : "HUMAN",
1303
- twoFaEnabled: false,
1304
- verifiedHumanAt: null
1305
- }
1694
+ user = await this.config.database.user.create({
1695
+ username: generateUsername(),
1696
+ email,
1697
+ password: null,
1698
+ emailVerificationStatus: "VERIFIED",
1699
+ oauthProvider: provider,
1700
+ oauthId,
1701
+ status: "ACTIVE",
1702
+ tag: this.config.features.biometric ? "BOT" : "HUMAN",
1703
+ twoFaEnabled: false,
1704
+ verifiedHumanAt: null
1306
1705
  });
1307
1706
  if (this.config.hooks?.onUserCreated) {
1308
1707
  await this.config.hooks.onUserCreated(user.id, typedInput);
@@ -1318,24 +1717,11 @@ var OAuthLoginProcedureFactory = class {
1318
1717
  throw new TRPCError5({ code: "FORBIDDEN", message: "Your account has been banned." });
1319
1718
  }
1320
1719
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
1321
- const session = await this.config.prisma.session.create({
1322
- data: {
1323
- userId: user.id,
1324
- browserName: detectBrowser(userAgent),
1325
- socketId: null,
1326
- ...extraSessionData
1327
- },
1328
- select: {
1329
- id: true,
1330
- userId: true,
1331
- socketId: true,
1332
- browserName: true,
1333
- issuedAt: true,
1334
- lastUsed: true,
1335
- revokedAt: true,
1336
- deviceId: true,
1337
- twoFaSecret: true
1338
- }
1720
+ const session = await this.config.database.session.create({
1721
+ userId: user.id,
1722
+ browserName: detectBrowser(userAgent),
1723
+ socketId: null,
1724
+ ...extraSessionData
1339
1725
  });
1340
1726
  if (this.config.hooks?.onUserLogin) {
1341
1727
  await this.config.hooks.onUserLogin(user.id, session.id);
@@ -1392,10 +1778,7 @@ var TwoFaProcedureFactory = class {
1392
1778
  return this.authProcedure.mutation(async ({ ctx }) => {
1393
1779
  this.checkConfig();
1394
1780
  const { userId, sessionId } = ctx;
1395
- const user = await this.config.prisma.user.findFirst({
1396
- where: { id: userId },
1397
- select: { twoFaEnabled: true, oauthProvider: true, password: true }
1398
- });
1781
+ const user = await this.config.database.user.findById(userId);
1399
1782
  if (!user) {
1400
1783
  throw new TRPCError6({ code: "NOT_FOUND", message: "User not found." });
1401
1784
  }
@@ -1409,10 +1792,7 @@ var TwoFaProcedureFactory = class {
1409
1792
  throw new TRPCError6({ code: "BAD_REQUEST", message: "2FA already enabled." });
1410
1793
  }
1411
1794
  if (this.config.features.twoFaRequiresDevice !== false) {
1412
- const checkSession = await this.config.prisma.session.findFirst({
1413
- where: { userId, id: sessionId },
1414
- select: { deviceId: true }
1415
- });
1795
+ const checkSession = await this.config.database.session.findById(sessionId);
1416
1796
  if (!checkSession?.deviceId) {
1417
1797
  throw new TRPCError6({
1418
1798
  code: "BAD_REQUEST",
@@ -1420,23 +1800,11 @@ var TwoFaProcedureFactory = class {
1420
1800
  });
1421
1801
  }
1422
1802
  }
1423
- await this.config.prisma.session.updateMany({
1424
- where: { userId, revokedAt: null, NOT: { id: sessionId } },
1425
- data: { revokedAt: /* @__PURE__ */ new Date() }
1426
- });
1427
- await this.config.prisma.session.updateMany({
1428
- where: { userId, NOT: { id: sessionId } },
1429
- data: { twoFaSecret: null }
1430
- });
1803
+ await this.config.database.session.revokeAllByUserId(userId, sessionId);
1804
+ await this.config.database.session.clearTwoFaSecrets(userId, sessionId);
1431
1805
  const secret = generateTotpSecret();
1432
- await this.config.prisma.user.update({
1433
- where: { id: userId },
1434
- data: { twoFaEnabled: true }
1435
- });
1436
- await this.config.prisma.session.update({
1437
- where: { id: sessionId },
1438
- data: { twoFaSecret: secret }
1439
- });
1806
+ await this.config.database.user.update(userId, { twoFaEnabled: true });
1807
+ await this.config.database.session.update(sessionId, { twoFaSecret: secret });
1440
1808
  if (this.config.hooks?.onTwoFaStatusChanged) {
1441
1809
  await this.config.hooks.onTwoFaStatusChanged(userId, true);
1442
1810
  }
@@ -1448,10 +1816,7 @@ var TwoFaProcedureFactory = class {
1448
1816
  this.checkConfig();
1449
1817
  const { userId, sessionId } = ctx;
1450
1818
  const { password } = input;
1451
- const user = await this.config.prisma.user.findFirst({
1452
- where: { id: userId },
1453
- select: { password: true, status: true, oauthProvider: true }
1454
- });
1819
+ const user = await this.config.database.user.findById(userId);
1455
1820
  if (!user) {
1456
1821
  throw new TRPCError6({ code: "NOT_FOUND", message: "User not found." });
1457
1822
  }
@@ -1474,14 +1839,8 @@ var TwoFaProcedureFactory = class {
1474
1839
  if (!isMatch) {
1475
1840
  throw new TRPCError6({ code: "FORBIDDEN", message: "Incorrect password." });
1476
1841
  }
1477
- await this.config.prisma.user.update({
1478
- where: { id: userId },
1479
- data: { twoFaEnabled: false }
1480
- });
1481
- await this.config.prisma.session.update({
1482
- where: { id: sessionId },
1483
- data: { twoFaSecret: null }
1484
- });
1842
+ await this.config.database.user.update(userId, { twoFaEnabled: false });
1843
+ await this.config.database.session.update(sessionId, { twoFaSecret: null });
1485
1844
  if (this.config.hooks?.onTwoFaStatusChanged) {
1486
1845
  await this.config.hooks.onTwoFaStatusChanged(userId, false);
1487
1846
  }
@@ -1493,10 +1852,7 @@ var TwoFaProcedureFactory = class {
1493
1852
  this.checkConfig();
1494
1853
  const { userId, sessionId } = ctx;
1495
1854
  const { pushCode } = input;
1496
- const user = await this.config.prisma.user.findFirst({
1497
- where: { id: userId },
1498
- select: { twoFaEnabled: true, oauthProvider: true }
1499
- });
1855
+ const user = await this.config.database.user.findById(userId);
1500
1856
  if (user?.oauthProvider) {
1501
1857
  throw new TRPCError6({
1502
1858
  code: "FORBIDDEN",
@@ -1506,10 +1862,7 @@ var TwoFaProcedureFactory = class {
1506
1862
  if (!user?.twoFaEnabled) {
1507
1863
  throw new TRPCError6({ code: "BAD_REQUEST", message: "2FA not enabled." });
1508
1864
  }
1509
- const session = await this.config.prisma.session.findUnique({
1510
- where: { id: sessionId, userId },
1511
- select: { twoFaSecret: true, device: { select: { pushToken: true } } }
1512
- });
1865
+ const session = await this.config.database.session.findByIdWithDevice(sessionId, userId);
1513
1866
  if (!session?.device) {
1514
1867
  throw new TRPCError6({ code: "BAD_REQUEST", message: "Invalid request" });
1515
1868
  }
@@ -1521,10 +1874,7 @@ var TwoFaProcedureFactory = class {
1521
1874
  return { secret: session.twoFaSecret };
1522
1875
  }
1523
1876
  const secret = generateTotpSecret();
1524
- await this.config.prisma.session.update({
1525
- where: { id: sessionId },
1526
- data: { twoFaSecret: secret }
1527
- });
1877
+ await this.config.database.session.update(sessionId, { twoFaSecret: secret });
1528
1878
  return { secret };
1529
1879
  });
1530
1880
  }
@@ -1532,11 +1882,8 @@ var TwoFaProcedureFactory = class {
1532
1882
  return this.procedure.input(twoFaResetSchema).mutation(async ({ input }) => {
1533
1883
  this.checkConfig();
1534
1884
  const { username, password } = input;
1535
- const user = await this.config.prisma.user.findFirst({
1536
- where: { username: { equals: username, mode: "insensitive" }, twoFaEnabled: true },
1537
- select: { id: true, password: true, email: true }
1538
- });
1539
- if (!user) {
1885
+ const user = await this.config.database.user.findByUsernameInsensitive(username);
1886
+ if (!user || !user.twoFaEnabled) {
1540
1887
  throw new TRPCError6({ code: "UNAUTHORIZED", message: "Invalid credentials." });
1541
1888
  }
1542
1889
  if (!user.password) {
@@ -1551,9 +1898,7 @@ var TwoFaProcedureFactory = class {
1551
1898
  }
1552
1899
  const otp = generateOtp();
1553
1900
  const expiresAt = new Date(Date.now() + this.config.tokenSettings.otpValidityMs);
1554
- await this.config.prisma.oTP.create({
1555
- data: { userId: user.id, code: otp, expiresAt }
1556
- });
1901
+ await this.config.database.otp.create({ userId: user.id, code: otp, expiresAt });
1557
1902
  if (this.config.emailService) {
1558
1903
  await this.config.emailService.sendOTPEmail(user.email, otp);
1559
1904
  }
@@ -1564,30 +1909,17 @@ var TwoFaProcedureFactory = class {
1564
1909
  return this.procedure.input(twoFaResetVerifySchema).mutation(async ({ input }) => {
1565
1910
  this.checkConfig();
1566
1911
  const { code, username } = input;
1567
- const user = await this.config.prisma.user.findFirst({
1568
- where: { username: { equals: username, mode: "insensitive" } },
1569
- select: { id: true }
1570
- });
1912
+ const user = await this.config.database.user.findByUsernameInsensitive(username);
1571
1913
  if (!user) {
1572
1914
  throw new TRPCError6({ code: "NOT_FOUND", message: "User not found" });
1573
1915
  }
1574
- const otp = await this.config.prisma.oTP.findFirst({
1575
- where: { userId: user.id, code, expiresAt: { gte: /* @__PURE__ */ new Date() } }
1576
- });
1916
+ const otp = await this.config.database.otp.findValidByUserAndCode(user.id, code);
1577
1917
  if (!otp) {
1578
1918
  throw new TRPCError6({ code: "FORBIDDEN", message: "Invalid or expired OTP" });
1579
1919
  }
1580
- await this.config.prisma.oTP.delete({
1581
- where: { id: otp.id }
1582
- });
1583
- await this.config.prisma.user.update({
1584
- where: { id: user.id },
1585
- data: { twoFaEnabled: false }
1586
- });
1587
- await this.config.prisma.session.updateMany({
1588
- where: { userId: user.id },
1589
- data: { twoFaSecret: null }
1590
- });
1920
+ await this.config.database.otp.delete(otp.id);
1921
+ await this.config.database.user.update(user.id, { twoFaEnabled: false });
1922
+ await this.config.database.session.clearTwoFaSecrets(user.id);
1591
1923
  return { success: true, message: "2FA has been reset." };
1592
1924
  });
1593
1925
  }
@@ -1596,36 +1928,14 @@ var TwoFaProcedureFactory = class {
1596
1928
  this.checkConfig();
1597
1929
  const { userId, sessionId } = ctx;
1598
1930
  const { pushToken } = input;
1599
- await this.config.prisma.session.updateMany({
1600
- where: {
1601
- userId,
1602
- id: { not: sessionId },
1603
- revokedAt: null,
1604
- device: { pushToken }
1605
- },
1606
- data: { revokedAt: /* @__PURE__ */ new Date() }
1607
- });
1608
- const checkDevice = await this.config.prisma.device.findFirst({
1609
- where: {
1610
- pushToken,
1611
- sessions: { some: { id: sessionId } },
1612
- users: { some: { id: userId } }
1613
- },
1614
- select: { id: true }
1615
- });
1931
+ await this.config.database.session.revokeByDevicePushToken(userId, pushToken, sessionId);
1932
+ const checkDevice = await this.config.database.device.findByTokenSessionAndUser(
1933
+ pushToken,
1934
+ sessionId,
1935
+ userId
1936
+ );
1616
1937
  if (!checkDevice) {
1617
- await this.config.prisma.device.upsert({
1618
- where: { pushToken },
1619
- create: {
1620
- pushToken,
1621
- sessions: { connect: { id: sessionId } },
1622
- users: { connect: { id: userId } }
1623
- },
1624
- update: {
1625
- sessions: { connect: { id: sessionId } },
1626
- users: { connect: { id: userId } }
1627
- }
1628
- });
1938
+ await this.config.database.device.upsertByPushToken(pushToken, sessionId, userId);
1629
1939
  }
1630
1940
  return { registered: true };
1631
1941
  });
@@ -1635,30 +1945,13 @@ var TwoFaProcedureFactory = class {
1635
1945
  this.checkConfig();
1636
1946
  const { userId } = ctx;
1637
1947
  const { pushToken } = input;
1638
- const device = await this.config.prisma.device.findFirst({
1639
- where: {
1640
- users: { some: { id: userId } },
1641
- pushToken
1642
- },
1643
- select: { id: true }
1644
- });
1948
+ const device = await this.config.database.device.findByUserAndToken(userId, pushToken);
1645
1949
  if (device) {
1646
- await this.config.prisma.session.updateMany({
1647
- where: { userId, deviceId: device.id },
1648
- data: { deviceId: null }
1649
- });
1650
- await this.config.prisma.device.update({
1651
- where: { id: device.id },
1652
- data: { users: { disconnect: { id: userId } } }
1653
- });
1654
- const remainingUsers = await this.config.prisma.device.findUnique({
1655
- where: { id: device.id },
1656
- select: { users: { select: { id: true }, take: 1 } }
1657
- });
1658
- if (!remainingUsers?.users.length) {
1659
- await this.config.prisma.device.delete({
1660
- where: { id: device.id }
1661
- });
1950
+ await this.config.database.session.clearDeviceId(userId, device.id);
1951
+ await this.config.database.device.disconnectUser(device.id, userId);
1952
+ const hasUsers = await this.config.database.device.hasRemainingUsers(device.id);
1953
+ if (!hasUsers) {
1954
+ await this.config.database.device.delete(device.id);
1662
1955
  }
1663
1956
  }
1664
1957
  return { deregistered: true };
@@ -1815,8 +2108,10 @@ export {
1815
2108
  createAuthRouter,
1816
2109
  createAuthToken,
1817
2110
  createConsoleEmailAdapter,
2111
+ createDrizzleAdapter,
1818
2112
  createNoopEmailAdapter,
1819
2113
  createOAuthVerifier,
2114
+ createPrismaAdapter,
1820
2115
  decodeToken,
1821
2116
  defaultAuthConfig,
1822
2117
  defaultCookieSettings,