@factiii/auth 0.5.2 → 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",
@@ -756,14 +1252,12 @@ var BaseProcedureFactory = class {
756
1252
  if (!code) {
757
1253
  return {
758
1254
  success: false,
759
- requires2FA: true
1255
+ requires2FA: true,
1256
+ userId: user.id
760
1257
  };
761
1258
  }
762
1259
  let validCode = false;
763
- const secrets = await this.config.prisma.session.findMany({
764
- where: { userId: user.id, twoFaSecret: { not: null } },
765
- select: { twoFaSecret: true }
766
- });
1260
+ const secrets = await this.config.database.session.findTwoFaSecretsByUserId(user.id);
767
1261
  for (const s of secrets) {
768
1262
  if (s.twoFaSecret && await verifyTotp(code, cleanBase32String(s.twoFaSecret))) {
769
1263
  validCode = true;
@@ -771,14 +1265,13 @@ var BaseProcedureFactory = class {
771
1265
  }
772
1266
  }
773
1267
  if (!validCode) {
774
- const checkOTP = await this.config.prisma.oTP.findFirst({
775
- where: { userId: user.id, code: Number(code), expiresAt: { gte: /* @__PURE__ */ new Date() } }
776
- });
1268
+ const checkOTP = await this.config.database.otp.findValidByUserAndCode(
1269
+ user.id,
1270
+ Number(code)
1271
+ );
777
1272
  if (checkOTP) {
778
1273
  validCode = true;
779
- await this.config.prisma.oTP.delete({
780
- where: { id: checkOTP.id }
781
- });
1274
+ await this.config.database.otp.delete(checkOTP.id);
782
1275
  }
783
1276
  }
784
1277
  if (!validCode) {
@@ -789,24 +1282,11 @@ var BaseProcedureFactory = class {
789
1282
  }
790
1283
  }
791
1284
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
792
- const session = await this.config.prisma.session.create({
793
- data: {
794
- userId: user.id,
795
- browserName: detectBrowser(userAgent),
796
- socketId: null,
797
- ...extraSessionData
798
- },
799
- select: {
800
- id: true,
801
- userId: true,
802
- socketId: true,
803
- browserName: true,
804
- issuedAt: true,
805
- lastUsed: true,
806
- revokedAt: true,
807
- deviceId: true,
808
- twoFaSecret: true
809
- }
1285
+ const session = await this.config.database.session.create({
1286
+ userId: user.id,
1287
+ browserName: detectBrowser(userAgent),
1288
+ socketId: null,
1289
+ ...extraSessionData
810
1290
  });
811
1291
  if (this.config.hooks?.onUserLogin) {
812
1292
  await this.config.hooks.onUserLogin(user.id, session.id);
@@ -837,15 +1317,9 @@ var BaseProcedureFactory = class {
837
1317
  return this.authProcedure.meta({ ignoreExpiration: true }).mutation(async ({ ctx }) => {
838
1318
  const { userId, sessionId } = ctx;
839
1319
  if (sessionId) {
840
- await this.config.prisma.session.update({
841
- where: { id: sessionId },
842
- data: { revokedAt: /* @__PURE__ */ new Date() }
843
- });
1320
+ await this.config.database.session.revoke(sessionId);
844
1321
  if (userId) {
845
- await this.config.prisma.user.update({
846
- where: { id: userId },
847
- data: { isActive: false }
848
- });
1322
+ await this.config.database.user.update(userId, { isActive: false });
849
1323
  }
850
1324
  if (this.config.hooks?.afterLogout) {
851
1325
  await this.config.hooks.afterLogout(userId, sessionId, ctx.socketId);
@@ -857,15 +1331,7 @@ var BaseProcedureFactory = class {
857
1331
  }
858
1332
  refresh() {
859
1333
  return this.authProcedure.query(async ({ ctx }) => {
860
- const session = await this.config.prisma.session.update({
861
- where: { id: ctx.sessionId },
862
- data: { lastUsed: /* @__PURE__ */ new Date() },
863
- select: {
864
- id: true,
865
- userId: true,
866
- user: { select: { verifiedHumanAt: true } }
867
- }
868
- });
1334
+ const session = await this.config.database.session.updateLastUsed(ctx.sessionId);
869
1335
  if (this.config.hooks?.onRefresh) {
870
1336
  this.config.hooks.onRefresh(session.userId).catch(() => {
871
1337
  });
@@ -890,22 +1356,14 @@ var BaseProcedureFactory = class {
890
1356
  return this.authProcedure.input(endAllSessionsSchema).mutation(async ({ ctx, input }) => {
891
1357
  const { skipCurrentSession } = input;
892
1358
  const { userId, sessionId } = ctx;
893
- const sessionsToRevoke = await this.config.prisma.session.findMany({
894
- where: {
895
- userId,
896
- revokedAt: null,
897
- ...skipCurrentSession ? { NOT: { id: sessionId } } : {}
898
- },
899
- select: { socketId: true, id: true, userId: true }
900
- });
901
- await this.config.prisma.session.updateMany({
902
- where: {
903
- userId,
904
- revokedAt: null,
905
- ...skipCurrentSession ? { NOT: { id: sessionId } } : {}
906
- },
907
- data: { revokedAt: /* @__PURE__ */ new Date() }
908
- });
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
+ );
909
1367
  for (const session of sessionsToRevoke) {
910
1368
  if (this.config.hooks?.onSessionRevoked) {
911
1369
  await this.config.hooks.onSessionRevoked(
@@ -916,10 +1374,7 @@ var BaseProcedureFactory = class {
916
1374
  }
917
1375
  }
918
1376
  if (!skipCurrentSession) {
919
- await this.config.prisma.user.update({
920
- where: { id: userId },
921
- data: { isActive: false }
922
- });
1377
+ await this.config.database.user.update(userId, { isActive: false });
923
1378
  }
924
1379
  return { success: true, revokedCount: sessionsToRevoke.length };
925
1380
  });
@@ -934,10 +1389,7 @@ var BaseProcedureFactory = class {
934
1389
  message: "New password cannot be the same as current password"
935
1390
  });
936
1391
  }
937
- const user = await this.config.prisma.user.findUnique({
938
- where: { id: userId },
939
- select: { password: true }
940
- });
1392
+ const user = await this.config.database.user.findById(userId);
941
1393
  if (!user) {
942
1394
  throw new TRPCError2({ code: "NOT_FOUND", message: "User not found" });
943
1395
  }
@@ -955,14 +1407,8 @@ var BaseProcedureFactory = class {
955
1407
  });
956
1408
  }
957
1409
  const hashedPassword = await hashPassword(newPassword);
958
- await this.config.prisma.user.update({
959
- where: { id: userId },
960
- data: { password: hashedPassword }
961
- });
962
- await this.config.prisma.session.updateMany({
963
- where: { userId, revokedAt: null, NOT: { id: sessionId } },
964
- data: { revokedAt: /* @__PURE__ */ new Date() }
965
- });
1410
+ await this.config.database.user.update(userId, { password: hashedPassword });
1411
+ await this.config.database.session.revokeAllByUserId(userId, sessionId);
966
1412
  if (this.config.hooks?.onPasswordChanged) {
967
1413
  await this.config.hooks.onPasswordChanged(userId);
968
1414
  }
@@ -975,11 +1421,8 @@ var BaseProcedureFactory = class {
975
1421
  sendPasswordResetEmail() {
976
1422
  return this.procedure.input(requestPasswordResetSchema).mutation(async ({ input }) => {
977
1423
  const { email } = input;
978
- const user = await this.config.prisma.user.findFirst({
979
- where: { email: { equals: email, mode: "insensitive" }, status: "ACTIVE" },
980
- select: { id: true, password: true, email: true }
981
- });
982
- if (!user) {
1424
+ const user = await this.config.database.user.findByEmailInsensitive(email);
1425
+ if (!user || user.status !== "ACTIVE") {
983
1426
  return { message: "If an account exists with that email, a reset link has been sent." };
984
1427
  }
985
1428
  if (!user.password) {
@@ -988,10 +1431,8 @@ var BaseProcedureFactory = class {
988
1431
  message: "This account uses social login. Please use that method."
989
1432
  });
990
1433
  }
991
- await this.config.prisma.passwordReset.deleteMany({ where: { userId: user.id } });
992
- const passwordReset = await this.config.prisma.passwordReset.create({
993
- data: { userId: user.id }
994
- });
1434
+ await this.config.database.passwordReset.deleteAllByUserId(user.id);
1435
+ const passwordReset = await this.config.database.passwordReset.create(user.id);
995
1436
  if (this.config.emailService) {
996
1437
  await this.config.emailService.sendPasswordResetEmail(user.email, String(passwordReset.id));
997
1438
  }
@@ -1001,15 +1442,12 @@ var BaseProcedureFactory = class {
1001
1442
  checkPasswordReset() {
1002
1443
  return this.procedure.input(checkPasswordResetSchema).query(async ({ input }) => {
1003
1444
  const { token } = input;
1004
- const passwordReset = await this.config.prisma.passwordReset.findUnique({
1005
- where: { id: token },
1006
- select: { id: true, createdAt: true, userId: true }
1007
- });
1445
+ const passwordReset = await this.config.database.passwordReset.findById(token);
1008
1446
  if (!passwordReset) {
1009
1447
  throw new TRPCError2({ code: "NOT_FOUND", message: "Invalid reset token." });
1010
1448
  }
1011
1449
  if (passwordReset.createdAt.getTime() + this.config.tokenSettings.passwordResetExpiryMs < Date.now()) {
1012
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1450
+ await this.config.database.passwordReset.delete(token);
1013
1451
  throw new TRPCError2({ code: "FORBIDDEN", message: "Reset token expired." });
1014
1452
  }
1015
1453
  return { valid: true };
@@ -1018,31 +1456,23 @@ var BaseProcedureFactory = class {
1018
1456
  resetPassword() {
1019
1457
  return this.procedure.input(resetPasswordSchema).mutation(async ({ input }) => {
1020
1458
  const { token, password } = input;
1021
- const passwordReset = await this.config.prisma.passwordReset.findFirst({
1022
- where: { id: token },
1023
- select: { id: true, createdAt: true, userId: true }
1024
- });
1459
+ const passwordReset = await this.config.database.passwordReset.findById(token);
1025
1460
  if (!passwordReset) {
1026
1461
  throw new TRPCError2({ code: "NOT_FOUND", message: "Invalid reset token." });
1027
1462
  }
1028
1463
  if (passwordReset.createdAt.getTime() + this.config.tokenSettings.passwordResetExpiryMs < Date.now()) {
1029
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1464
+ await this.config.database.passwordReset.delete(token);
1030
1465
  throw new TRPCError2({ code: "FORBIDDEN", message: "Reset token expired." });
1031
1466
  }
1032
1467
  const hashedPassword = await hashPassword(password);
1033
- await this.config.prisma.user.update({
1034
- where: { id: passwordReset.userId },
1035
- data: { password: hashedPassword }
1036
- });
1037
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1038
- const sessionsToRevoke = await this.config.prisma.session.findMany({
1039
- where: { userId: passwordReset.userId, revokedAt: null },
1040
- select: { id: true, socketId: true, userId: true }
1041
- });
1042
- await this.config.prisma.session.updateMany({
1043
- where: { userId: passwordReset.userId, revokedAt: null },
1044
- data: { revokedAt: /* @__PURE__ */ new Date() }
1468
+ await this.config.database.user.update(passwordReset.userId, {
1469
+ password: hashedPassword
1045
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);
1046
1476
  for (const session of sessionsToRevoke) {
1047
1477
  if (this.config.hooks?.onSessionRevoked) {
1048
1478
  await this.config.hooks.onSessionRevoked(
@@ -1079,9 +1509,9 @@ var BiometricProcedureFactory = class {
1079
1509
  return this.authProcedure.input(biometricVerifySchema).mutation(async ({ ctx }) => {
1080
1510
  this.checkConfig();
1081
1511
  const { userId } = ctx;
1082
- await this.config.prisma.user.update({
1083
- where: { id: userId },
1084
- data: { verifiedHumanAt: /* @__PURE__ */ new Date(), tag: "HUMAN" }
1512
+ await this.config.database.user.update(userId, {
1513
+ verifiedHumanAt: /* @__PURE__ */ new Date(),
1514
+ tag: "HUMAN"
1085
1515
  });
1086
1516
  if (this.config.hooks?.onBiometricVerified) {
1087
1517
  await this.config.hooks.onBiometricVerified(userId);
@@ -1093,10 +1523,7 @@ var BiometricProcedureFactory = class {
1093
1523
  return this.authProcedure.query(async ({ ctx }) => {
1094
1524
  this.checkConfig();
1095
1525
  const { userId } = ctx;
1096
- const user = await this.config.prisma.user.findUnique({
1097
- where: { id: userId },
1098
- select: { verifiedHumanAt: true }
1099
- });
1526
+ const user = await this.config.database.user.findById(userId);
1100
1527
  if (!user) {
1101
1528
  throw new TRPCError3({ code: "NOT_FOUND", message: "User not found" });
1102
1529
  }
@@ -1143,10 +1570,7 @@ var EmailVerificationProcedureFactory = class {
1143
1570
  return this.authProcedure.mutation(async ({ ctx }) => {
1144
1571
  this.checkConfig();
1145
1572
  const { userId } = ctx;
1146
- const user = await this.config.prisma.user.findUnique({
1147
- where: { id: userId, status: "ACTIVE" },
1148
- select: { id: true, email: true, emailVerificationStatus: true }
1149
- });
1573
+ const user = await this.config.database.user.findActiveById(userId);
1150
1574
  if (!user) {
1151
1575
  throw new TRPCError4({ code: "NOT_FOUND", message: "User not found" });
1152
1576
  }
@@ -1154,9 +1578,9 @@ var EmailVerificationProcedureFactory = class {
1154
1578
  return { message: "Email is already verified", emailSent: false };
1155
1579
  }
1156
1580
  const otp = randomUUID();
1157
- await this.config.prisma.user.update({
1158
- where: { id: userId },
1159
- data: { emailVerificationStatus: "PENDING", otpForEmailVerification: otp }
1581
+ await this.config.database.user.update(userId, {
1582
+ emailVerificationStatus: "PENDING",
1583
+ otpForEmailVerification: otp
1160
1584
  });
1161
1585
  if (this.config.emailService) {
1162
1586
  try {
@@ -1174,10 +1598,7 @@ var EmailVerificationProcedureFactory = class {
1174
1598
  this.checkConfig();
1175
1599
  const { userId } = ctx;
1176
1600
  const { code } = input;
1177
- const user = await this.config.prisma.user.findUnique({
1178
- where: { id: userId, status: "ACTIVE" },
1179
- select: { id: true, emailVerificationStatus: true, otpForEmailVerification: true }
1180
- });
1601
+ const user = await this.config.database.user.findActiveById(userId);
1181
1602
  if (!user) {
1182
1603
  throw new TRPCError4({ code: "NOT_FOUND", message: "User not found" });
1183
1604
  }
@@ -1187,9 +1608,9 @@ var EmailVerificationProcedureFactory = class {
1187
1608
  if (code !== user.otpForEmailVerification) {
1188
1609
  throw new TRPCError4({ code: "BAD_REQUEST", message: "Invalid verification code" });
1189
1610
  }
1190
- await this.config.prisma.user.update({
1191
- where: { id: userId },
1192
- data: { emailVerificationStatus: "VERIFIED", otpForEmailVerification: null }
1611
+ await this.config.database.user.update(userId, {
1612
+ emailVerificationStatus: "VERIFIED",
1613
+ otpForEmailVerification: null
1193
1614
  });
1194
1615
  if (this.config.hooks?.onEmailVerified) {
1195
1616
  await this.config.hooks.onEmailVerified(userId);
@@ -1201,10 +1622,7 @@ var EmailVerificationProcedureFactory = class {
1201
1622
  return this.authProcedure.query(async ({ ctx }) => {
1202
1623
  this.checkConfig();
1203
1624
  const { userId } = ctx;
1204
- const user = await this.config.prisma.user.findUnique({
1205
- where: { id: userId },
1206
- select: { emailVerificationStatus: true, email: true }
1207
- });
1625
+ const user = await this.config.database.user.findById(userId);
1208
1626
  if (!user) {
1209
1627
  throw new TRPCError4({ code: "NOT_FOUND", message: "User not found" });
1210
1628
  }
@@ -1258,23 +1676,7 @@ var OAuthLoginProcedureFactory = class {
1258
1676
  message: "Email not provided by OAuth provider"
1259
1677
  });
1260
1678
  }
1261
- let user = await this.config.prisma.user.findFirst({
1262
- where: {
1263
- OR: [{ email: { equals: email, mode: "insensitive" } }, { oauthId: { equals: oauthId } }]
1264
- },
1265
- select: {
1266
- id: true,
1267
- status: true,
1268
- email: true,
1269
- username: true,
1270
- password: true,
1271
- oauthProvider: true,
1272
- oauthId: true,
1273
- twoFaEnabled: true,
1274
- verifiedHumanAt: true,
1275
- emailVerificationStatus: true
1276
- }
1277
- });
1679
+ let user = await this.config.database.user.findByEmailOrOAuthId(email, oauthId);
1278
1680
  if (user?.oauthProvider && user.oauthProvider !== provider) {
1279
1681
  throw new TRPCError5({
1280
1682
  code: "BAD_REQUEST",
@@ -1289,19 +1691,17 @@ var OAuthLoginProcedureFactory = class {
1289
1691
  }
1290
1692
  if (!user) {
1291
1693
  const generateUsername = this.config.generateUsername ?? (() => `user_${Date.now()}`);
1292
- user = await this.config.prisma.user.create({
1293
- data: {
1294
- username: generateUsername(),
1295
- email,
1296
- password: null,
1297
- emailVerificationStatus: "VERIFIED",
1298
- oauthProvider: provider,
1299
- oauthId,
1300
- status: "ACTIVE",
1301
- tag: this.config.features.biometric ? "BOT" : "HUMAN",
1302
- twoFaEnabled: false,
1303
- verifiedHumanAt: null
1304
- }
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
1305
1705
  });
1306
1706
  if (this.config.hooks?.onUserCreated) {
1307
1707
  await this.config.hooks.onUserCreated(user.id, typedInput);
@@ -1317,24 +1717,11 @@ var OAuthLoginProcedureFactory = class {
1317
1717
  throw new TRPCError5({ code: "FORBIDDEN", message: "Your account has been banned." });
1318
1718
  }
1319
1719
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
1320
- const session = await this.config.prisma.session.create({
1321
- data: {
1322
- userId: user.id,
1323
- browserName: detectBrowser(userAgent),
1324
- socketId: null,
1325
- ...extraSessionData
1326
- },
1327
- select: {
1328
- id: true,
1329
- userId: true,
1330
- socketId: true,
1331
- browserName: true,
1332
- issuedAt: true,
1333
- lastUsed: true,
1334
- revokedAt: true,
1335
- deviceId: true,
1336
- twoFaSecret: true
1337
- }
1720
+ const session = await this.config.database.session.create({
1721
+ userId: user.id,
1722
+ browserName: detectBrowser(userAgent),
1723
+ socketId: null,
1724
+ ...extraSessionData
1338
1725
  });
1339
1726
  if (this.config.hooks?.onUserLogin) {
1340
1727
  await this.config.hooks.onUserLogin(user.id, session.id);
@@ -1391,10 +1778,7 @@ var TwoFaProcedureFactory = class {
1391
1778
  return this.authProcedure.mutation(async ({ ctx }) => {
1392
1779
  this.checkConfig();
1393
1780
  const { userId, sessionId } = ctx;
1394
- const user = await this.config.prisma.user.findFirst({
1395
- where: { id: userId },
1396
- select: { twoFaEnabled: true, oauthProvider: true, password: true }
1397
- });
1781
+ const user = await this.config.database.user.findById(userId);
1398
1782
  if (!user) {
1399
1783
  throw new TRPCError6({ code: "NOT_FOUND", message: "User not found." });
1400
1784
  }
@@ -1408,10 +1792,7 @@ var TwoFaProcedureFactory = class {
1408
1792
  throw new TRPCError6({ code: "BAD_REQUEST", message: "2FA already enabled." });
1409
1793
  }
1410
1794
  if (this.config.features.twoFaRequiresDevice !== false) {
1411
- const checkSession = await this.config.prisma.session.findFirst({
1412
- where: { userId, id: sessionId },
1413
- select: { deviceId: true }
1414
- });
1795
+ const checkSession = await this.config.database.session.findById(sessionId);
1415
1796
  if (!checkSession?.deviceId) {
1416
1797
  throw new TRPCError6({
1417
1798
  code: "BAD_REQUEST",
@@ -1419,23 +1800,11 @@ var TwoFaProcedureFactory = class {
1419
1800
  });
1420
1801
  }
1421
1802
  }
1422
- await this.config.prisma.session.updateMany({
1423
- where: { userId, revokedAt: null, NOT: { id: sessionId } },
1424
- data: { revokedAt: /* @__PURE__ */ new Date() }
1425
- });
1426
- await this.config.prisma.session.updateMany({
1427
- where: { userId, NOT: { id: sessionId } },
1428
- data: { twoFaSecret: null }
1429
- });
1803
+ await this.config.database.session.revokeAllByUserId(userId, sessionId);
1804
+ await this.config.database.session.clearTwoFaSecrets(userId, sessionId);
1430
1805
  const secret = generateTotpSecret();
1431
- await this.config.prisma.user.update({
1432
- where: { id: userId },
1433
- data: { twoFaEnabled: true }
1434
- });
1435
- await this.config.prisma.session.update({
1436
- where: { id: sessionId },
1437
- data: { twoFaSecret: secret }
1438
- });
1806
+ await this.config.database.user.update(userId, { twoFaEnabled: true });
1807
+ await this.config.database.session.update(sessionId, { twoFaSecret: secret });
1439
1808
  if (this.config.hooks?.onTwoFaStatusChanged) {
1440
1809
  await this.config.hooks.onTwoFaStatusChanged(userId, true);
1441
1810
  }
@@ -1447,10 +1816,7 @@ var TwoFaProcedureFactory = class {
1447
1816
  this.checkConfig();
1448
1817
  const { userId, sessionId } = ctx;
1449
1818
  const { password } = input;
1450
- const user = await this.config.prisma.user.findFirst({
1451
- where: { id: userId },
1452
- select: { password: true, status: true, oauthProvider: true }
1453
- });
1819
+ const user = await this.config.database.user.findById(userId);
1454
1820
  if (!user) {
1455
1821
  throw new TRPCError6({ code: "NOT_FOUND", message: "User not found." });
1456
1822
  }
@@ -1473,14 +1839,8 @@ var TwoFaProcedureFactory = class {
1473
1839
  if (!isMatch) {
1474
1840
  throw new TRPCError6({ code: "FORBIDDEN", message: "Incorrect password." });
1475
1841
  }
1476
- await this.config.prisma.user.update({
1477
- where: { id: userId },
1478
- data: { twoFaEnabled: false }
1479
- });
1480
- await this.config.prisma.session.update({
1481
- where: { id: sessionId },
1482
- data: { twoFaSecret: null }
1483
- });
1842
+ await this.config.database.user.update(userId, { twoFaEnabled: false });
1843
+ await this.config.database.session.update(sessionId, { twoFaSecret: null });
1484
1844
  if (this.config.hooks?.onTwoFaStatusChanged) {
1485
1845
  await this.config.hooks.onTwoFaStatusChanged(userId, false);
1486
1846
  }
@@ -1492,10 +1852,7 @@ var TwoFaProcedureFactory = class {
1492
1852
  this.checkConfig();
1493
1853
  const { userId, sessionId } = ctx;
1494
1854
  const { pushCode } = input;
1495
- const user = await this.config.prisma.user.findFirst({
1496
- where: { id: userId },
1497
- select: { twoFaEnabled: true, oauthProvider: true }
1498
- });
1855
+ const user = await this.config.database.user.findById(userId);
1499
1856
  if (user?.oauthProvider) {
1500
1857
  throw new TRPCError6({
1501
1858
  code: "FORBIDDEN",
@@ -1505,10 +1862,7 @@ var TwoFaProcedureFactory = class {
1505
1862
  if (!user?.twoFaEnabled) {
1506
1863
  throw new TRPCError6({ code: "BAD_REQUEST", message: "2FA not enabled." });
1507
1864
  }
1508
- const session = await this.config.prisma.session.findUnique({
1509
- where: { id: sessionId, userId },
1510
- select: { twoFaSecret: true, device: { select: { pushToken: true } } }
1511
- });
1865
+ const session = await this.config.database.session.findByIdWithDevice(sessionId, userId);
1512
1866
  if (!session?.device) {
1513
1867
  throw new TRPCError6({ code: "BAD_REQUEST", message: "Invalid request" });
1514
1868
  }
@@ -1520,10 +1874,7 @@ var TwoFaProcedureFactory = class {
1520
1874
  return { secret: session.twoFaSecret };
1521
1875
  }
1522
1876
  const secret = generateTotpSecret();
1523
- await this.config.prisma.session.update({
1524
- where: { id: sessionId },
1525
- data: { twoFaSecret: secret }
1526
- });
1877
+ await this.config.database.session.update(sessionId, { twoFaSecret: secret });
1527
1878
  return { secret };
1528
1879
  });
1529
1880
  }
@@ -1531,11 +1882,8 @@ var TwoFaProcedureFactory = class {
1531
1882
  return this.procedure.input(twoFaResetSchema).mutation(async ({ input }) => {
1532
1883
  this.checkConfig();
1533
1884
  const { username, password } = input;
1534
- const user = await this.config.prisma.user.findFirst({
1535
- where: { username: { equals: username, mode: "insensitive" }, twoFaEnabled: true },
1536
- select: { id: true, password: true, email: true }
1537
- });
1538
- if (!user) {
1885
+ const user = await this.config.database.user.findByUsernameInsensitive(username);
1886
+ if (!user || !user.twoFaEnabled) {
1539
1887
  throw new TRPCError6({ code: "UNAUTHORIZED", message: "Invalid credentials." });
1540
1888
  }
1541
1889
  if (!user.password) {
@@ -1550,9 +1898,7 @@ var TwoFaProcedureFactory = class {
1550
1898
  }
1551
1899
  const otp = generateOtp();
1552
1900
  const expiresAt = new Date(Date.now() + this.config.tokenSettings.otpValidityMs);
1553
- await this.config.prisma.oTP.create({
1554
- data: { userId: user.id, code: otp, expiresAt }
1555
- });
1901
+ await this.config.database.otp.create({ userId: user.id, code: otp, expiresAt });
1556
1902
  if (this.config.emailService) {
1557
1903
  await this.config.emailService.sendOTPEmail(user.email, otp);
1558
1904
  }
@@ -1563,30 +1909,17 @@ var TwoFaProcedureFactory = class {
1563
1909
  return this.procedure.input(twoFaResetVerifySchema).mutation(async ({ input }) => {
1564
1910
  this.checkConfig();
1565
1911
  const { code, username } = input;
1566
- const user = await this.config.prisma.user.findFirst({
1567
- where: { username: { equals: username, mode: "insensitive" } },
1568
- select: { id: true }
1569
- });
1912
+ const user = await this.config.database.user.findByUsernameInsensitive(username);
1570
1913
  if (!user) {
1571
1914
  throw new TRPCError6({ code: "NOT_FOUND", message: "User not found" });
1572
1915
  }
1573
- const otp = await this.config.prisma.oTP.findFirst({
1574
- where: { userId: user.id, code, expiresAt: { gte: /* @__PURE__ */ new Date() } }
1575
- });
1916
+ const otp = await this.config.database.otp.findValidByUserAndCode(user.id, code);
1576
1917
  if (!otp) {
1577
1918
  throw new TRPCError6({ code: "FORBIDDEN", message: "Invalid or expired OTP" });
1578
1919
  }
1579
- await this.config.prisma.oTP.delete({
1580
- where: { id: otp.id }
1581
- });
1582
- await this.config.prisma.user.update({
1583
- where: { id: user.id },
1584
- data: { twoFaEnabled: false }
1585
- });
1586
- await this.config.prisma.session.updateMany({
1587
- where: { userId: user.id },
1588
- data: { twoFaSecret: null }
1589
- });
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);
1590
1923
  return { success: true, message: "2FA has been reset." };
1591
1924
  });
1592
1925
  }
@@ -1595,36 +1928,14 @@ var TwoFaProcedureFactory = class {
1595
1928
  this.checkConfig();
1596
1929
  const { userId, sessionId } = ctx;
1597
1930
  const { pushToken } = input;
1598
- await this.config.prisma.session.updateMany({
1599
- where: {
1600
- userId,
1601
- id: { not: sessionId },
1602
- revokedAt: null,
1603
- device: { pushToken }
1604
- },
1605
- data: { revokedAt: /* @__PURE__ */ new Date() }
1606
- });
1607
- const checkDevice = await this.config.prisma.device.findFirst({
1608
- where: {
1609
- pushToken,
1610
- sessions: { some: { id: sessionId } },
1611
- users: { some: { id: userId } }
1612
- },
1613
- select: { id: true }
1614
- });
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
+ );
1615
1937
  if (!checkDevice) {
1616
- await this.config.prisma.device.upsert({
1617
- where: { pushToken },
1618
- create: {
1619
- pushToken,
1620
- sessions: { connect: { id: sessionId } },
1621
- users: { connect: { id: userId } }
1622
- },
1623
- update: {
1624
- sessions: { connect: { id: sessionId } },
1625
- users: { connect: { id: userId } }
1626
- }
1627
- });
1938
+ await this.config.database.device.upsertByPushToken(pushToken, sessionId, userId);
1628
1939
  }
1629
1940
  return { registered: true };
1630
1941
  });
@@ -1634,30 +1945,13 @@ var TwoFaProcedureFactory = class {
1634
1945
  this.checkConfig();
1635
1946
  const { userId } = ctx;
1636
1947
  const { pushToken } = input;
1637
- const device = await this.config.prisma.device.findFirst({
1638
- where: {
1639
- users: { some: { id: userId } },
1640
- pushToken
1641
- },
1642
- select: { id: true }
1643
- });
1948
+ const device = await this.config.database.device.findByUserAndToken(userId, pushToken);
1644
1949
  if (device) {
1645
- await this.config.prisma.session.updateMany({
1646
- where: { userId, deviceId: device.id },
1647
- data: { deviceId: null }
1648
- });
1649
- await this.config.prisma.device.update({
1650
- where: { id: device.id },
1651
- data: { users: { disconnect: { id: userId } } }
1652
- });
1653
- const remainingUsers = await this.config.prisma.device.findUnique({
1654
- where: { id: device.id },
1655
- select: { users: { select: { id: true }, take: 1 } }
1656
- });
1657
- if (!remainingUsers?.users.length) {
1658
- await this.config.prisma.device.delete({
1659
- where: { id: device.id }
1660
- });
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);
1661
1955
  }
1662
1956
  }
1663
1957
  return { deregistered: true };
@@ -1814,8 +2108,10 @@ export {
1814
2108
  createAuthRouter,
1815
2109
  createAuthToken,
1816
2110
  createConsoleEmailAdapter,
2111
+ createDrizzleAdapter,
1817
2112
  createNoopEmailAdapter,
1818
2113
  createOAuthVerifier,
2114
+ createPrismaAdapter,
1819
2115
  decodeToken,
1820
2116
  defaultAuthConfig,
1821
2117
  defaultCookieSettings,