@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.js CHANGED
@@ -42,8 +42,10 @@ __export(index_exports, {
42
42
  createAuthRouter: () => createAuthRouter,
43
43
  createAuthToken: () => createAuthToken,
44
44
  createConsoleEmailAdapter: () => createConsoleEmailAdapter,
45
+ createDrizzleAdapter: () => createDrizzleAdapter,
45
46
  createNoopEmailAdapter: () => createNoopEmailAdapter,
46
47
  createOAuthVerifier: () => createOAuthVerifier,
48
+ createPrismaAdapter: () => createPrismaAdapter,
47
49
  decodeToken: () => decodeToken,
48
50
  defaultAuthConfig: () => defaultAuthConfig,
49
51
  defaultCookieSettings: () => defaultCookieSettings,
@@ -78,6 +80,260 @@ module.exports = __toCommonJS(index_exports);
78
80
  // src/middleware/authGuard.ts
79
81
  var import_server = require("@trpc/server");
80
82
 
83
+ // src/adapters/prismaAdapter.ts
84
+ function createPrismaAdapter(prisma) {
85
+ return {
86
+ user: {
87
+ async findByEmailInsensitive(email) {
88
+ return prisma.user.findFirst({
89
+ where: { email: { equals: email, mode: "insensitive" } }
90
+ });
91
+ },
92
+ async findByUsernameInsensitive(username) {
93
+ return prisma.user.findFirst({
94
+ where: { username: { equals: username, mode: "insensitive" } }
95
+ });
96
+ },
97
+ async findByEmailOrUsernameInsensitive(identifier) {
98
+ return prisma.user.findFirst({
99
+ where: {
100
+ OR: [
101
+ { email: { equals: identifier, mode: "insensitive" } },
102
+ { username: { equals: identifier, mode: "insensitive" } }
103
+ ]
104
+ }
105
+ });
106
+ },
107
+ async findByEmailOrOAuthId(email, oauthId) {
108
+ return prisma.user.findFirst({
109
+ where: {
110
+ OR: [
111
+ { email: { equals: email, mode: "insensitive" } },
112
+ { oauthId: { equals: oauthId } }
113
+ ]
114
+ }
115
+ });
116
+ },
117
+ async findById(id) {
118
+ return prisma.user.findUnique({ where: { id } });
119
+ },
120
+ async findActiveById(id) {
121
+ return prisma.user.findUnique({
122
+ where: { id, status: "ACTIVE" }
123
+ });
124
+ },
125
+ async create(data) {
126
+ return prisma.user.create({ data });
127
+ },
128
+ async update(id, data) {
129
+ return prisma.user.update({ where: { id }, data });
130
+ }
131
+ },
132
+ session: {
133
+ async findById(id) {
134
+ const session = await prisma.session.findUnique({
135
+ where: { id },
136
+ select: {
137
+ id: true,
138
+ userId: true,
139
+ socketId: true,
140
+ twoFaSecret: true,
141
+ browserName: true,
142
+ issuedAt: true,
143
+ lastUsed: true,
144
+ revokedAt: true,
145
+ deviceId: true,
146
+ user: { select: { status: true, verifiedHumanAt: true } }
147
+ }
148
+ });
149
+ return session;
150
+ },
151
+ async create(data) {
152
+ return prisma.session.create({ data });
153
+ },
154
+ async update(id, data) {
155
+ return prisma.session.update({ where: { id }, data });
156
+ },
157
+ async updateLastUsed(id) {
158
+ const session = await prisma.session.update({
159
+ where: { id },
160
+ data: { lastUsed: /* @__PURE__ */ new Date() },
161
+ select: {
162
+ id: true,
163
+ userId: true,
164
+ socketId: true,
165
+ twoFaSecret: true,
166
+ browserName: true,
167
+ issuedAt: true,
168
+ lastUsed: true,
169
+ revokedAt: true,
170
+ deviceId: true,
171
+ user: { select: { verifiedHumanAt: true } }
172
+ }
173
+ });
174
+ return session;
175
+ },
176
+ async revoke(id) {
177
+ await prisma.session.update({
178
+ where: { id },
179
+ data: { revokedAt: /* @__PURE__ */ new Date() }
180
+ });
181
+ },
182
+ async findActiveByUserId(userId, excludeSessionId) {
183
+ return prisma.session.findMany({
184
+ where: {
185
+ userId,
186
+ revokedAt: null,
187
+ ...excludeSessionId ? { NOT: { id: excludeSessionId } } : {}
188
+ },
189
+ select: { id: true, socketId: true, userId: true }
190
+ });
191
+ },
192
+ async revokeAllByUserId(userId, excludeSessionId) {
193
+ await prisma.session.updateMany({
194
+ where: {
195
+ userId,
196
+ revokedAt: null,
197
+ ...excludeSessionId ? { NOT: { id: excludeSessionId } } : {}
198
+ },
199
+ data: { revokedAt: /* @__PURE__ */ new Date() }
200
+ });
201
+ },
202
+ async findTwoFaSecretsByUserId(userId) {
203
+ return prisma.session.findMany({
204
+ where: { userId, twoFaSecret: { not: null } },
205
+ select: { twoFaSecret: true }
206
+ });
207
+ },
208
+ async clearTwoFaSecrets(userId, excludeSessionId) {
209
+ await prisma.session.updateMany({
210
+ where: {
211
+ userId,
212
+ ...excludeSessionId ? { NOT: { id: excludeSessionId } } : {}
213
+ },
214
+ data: { twoFaSecret: null }
215
+ });
216
+ },
217
+ async findByIdWithDevice(id, userId) {
218
+ const session = await prisma.session.findUnique({
219
+ where: { id, userId },
220
+ select: {
221
+ twoFaSecret: true,
222
+ deviceId: true,
223
+ device: { select: { pushToken: true } }
224
+ }
225
+ });
226
+ return session;
227
+ },
228
+ async revokeByDevicePushToken(userId, pushToken, excludeSessionId) {
229
+ await prisma.session.updateMany({
230
+ where: {
231
+ userId,
232
+ id: { not: excludeSessionId },
233
+ revokedAt: null,
234
+ device: { pushToken }
235
+ },
236
+ data: { revokedAt: /* @__PURE__ */ new Date() }
237
+ });
238
+ },
239
+ async clearDeviceId(userId, deviceId) {
240
+ await prisma.session.updateMany({
241
+ where: { userId, deviceId },
242
+ data: { deviceId: null }
243
+ });
244
+ }
245
+ },
246
+ otp: {
247
+ async findValidByUserAndCode(userId, code) {
248
+ return prisma.oTP.findFirst({
249
+ where: { userId, code, expiresAt: { gte: /* @__PURE__ */ new Date() } }
250
+ });
251
+ },
252
+ async create(data) {
253
+ return prisma.oTP.create({ data });
254
+ },
255
+ async delete(id) {
256
+ await prisma.oTP.delete({ where: { id } });
257
+ }
258
+ },
259
+ passwordReset: {
260
+ async findById(id) {
261
+ return prisma.passwordReset.findUnique({
262
+ where: { id },
263
+ select: { id: true, createdAt: true, userId: true }
264
+ });
265
+ },
266
+ async create(userId) {
267
+ return prisma.passwordReset.create({
268
+ data: { userId }
269
+ });
270
+ },
271
+ async delete(id) {
272
+ await prisma.passwordReset.delete({ where: { id } });
273
+ },
274
+ async deleteAllByUserId(userId) {
275
+ await prisma.passwordReset.deleteMany({ where: { userId } });
276
+ }
277
+ },
278
+ device: {
279
+ async findByTokenSessionAndUser(pushToken, sessionId, userId) {
280
+ return prisma.device.findFirst({
281
+ where: {
282
+ pushToken,
283
+ sessions: { some: { id: sessionId } },
284
+ users: { some: { id: userId } }
285
+ },
286
+ select: { id: true }
287
+ });
288
+ },
289
+ async upsertByPushToken(pushToken, sessionId, userId) {
290
+ await prisma.device.upsert({
291
+ where: { pushToken },
292
+ create: {
293
+ pushToken,
294
+ sessions: { connect: { id: sessionId } },
295
+ users: { connect: { id: userId } }
296
+ },
297
+ update: {
298
+ sessions: { connect: { id: sessionId } },
299
+ users: { connect: { id: userId } }
300
+ }
301
+ });
302
+ },
303
+ async findByUserAndToken(userId, pushToken) {
304
+ return prisma.device.findFirst({
305
+ where: { users: { some: { id: userId } }, pushToken },
306
+ select: { id: true }
307
+ });
308
+ },
309
+ async disconnectUser(deviceId, userId) {
310
+ await prisma.device.update({
311
+ where: { id: deviceId },
312
+ data: { users: { disconnect: { id: userId } } }
313
+ });
314
+ },
315
+ async hasRemainingUsers(deviceId) {
316
+ const result = await prisma.device.findUnique({
317
+ where: { id: deviceId },
318
+ select: { users: { select: { id: true }, take: 1 } }
319
+ });
320
+ return (result?.users.length ?? 0) > 0;
321
+ },
322
+ async delete(id) {
323
+ await prisma.device.delete({ where: { id } });
324
+ }
325
+ },
326
+ admin: {
327
+ async findByUserId(userId) {
328
+ return prisma.admin.findFirst({
329
+ where: { userId },
330
+ select: { ip: true }
331
+ });
332
+ }
333
+ }
334
+ };
335
+ }
336
+
81
337
  // src/adapters/email.ts
82
338
  function createNoopEmailAdapter() {
83
339
  return {
@@ -131,6 +387,291 @@ function createConsoleEmailAdapter() {
131
387
  };
132
388
  }
133
389
 
390
+ // src/adapters/drizzleAdapter.ts
391
+ function createDrizzleAdapter(db, tables) {
392
+ const {
393
+ eq,
394
+ and,
395
+ or,
396
+ isNull,
397
+ isNotNull,
398
+ gte,
399
+ ne,
400
+ sql
401
+ } = require("drizzle-orm");
402
+ const { users, sessions, otps, passwordResets, devices, admins } = tables;
403
+ return {
404
+ user: {
405
+ async findByEmailInsensitive(email) {
406
+ const rows = await db.select().from(users).where(sql`lower(${users.email}) = lower(${email})`).limit(1);
407
+ return rows[0] ?? null;
408
+ },
409
+ async findByUsernameInsensitive(username) {
410
+ const rows = await db.select().from(users).where(sql`lower(${users.username}) = lower(${username})`).limit(1);
411
+ return rows[0] ?? null;
412
+ },
413
+ async findByEmailOrUsernameInsensitive(identifier) {
414
+ const rows = await db.select().from(users).where(
415
+ or(
416
+ sql`lower(${users.email}) = lower(${identifier})`,
417
+ sql`lower(${users.username}) = lower(${identifier})`
418
+ )
419
+ ).limit(1);
420
+ return rows[0] ?? null;
421
+ },
422
+ async findByEmailOrOAuthId(email, oauthId) {
423
+ const rows = await db.select().from(users).where(
424
+ or(
425
+ sql`lower(${users.email}) = lower(${email})`,
426
+ eq(users.oauthId, oauthId)
427
+ )
428
+ ).limit(1);
429
+ return rows[0] ?? null;
430
+ },
431
+ async findById(id) {
432
+ const rows = await db.select().from(users).where(eq(users.id, id)).limit(1);
433
+ return rows[0] ?? null;
434
+ },
435
+ async findActiveById(id) {
436
+ const rows = await db.select().from(users).where(and(eq(users.id, id), eq(users.status, "ACTIVE"))).limit(1);
437
+ return rows[0] ?? null;
438
+ },
439
+ async create(data) {
440
+ const rows = await db.insert(users).values(data).returning();
441
+ return rows[0];
442
+ },
443
+ async update(id, data) {
444
+ const rows = await db.update(users).set(data).where(eq(users.id, id)).returning();
445
+ return rows[0];
446
+ }
447
+ },
448
+ session: {
449
+ async findById(id) {
450
+ const rows = await db.select({
451
+ id: sessions.id,
452
+ userId: sessions.userId,
453
+ socketId: sessions.socketId,
454
+ twoFaSecret: sessions.twoFaSecret,
455
+ browserName: sessions.browserName,
456
+ issuedAt: sessions.issuedAt,
457
+ lastUsed: sessions.lastUsed,
458
+ revokedAt: sessions.revokedAt,
459
+ deviceId: sessions.deviceId,
460
+ user: {
461
+ status: users.status,
462
+ verifiedHumanAt: users.verifiedHumanAt
463
+ }
464
+ }).from(sessions).innerJoin(users, eq(sessions.userId, users.id)).where(eq(sessions.id, id)).limit(1);
465
+ return rows[0] ?? null;
466
+ },
467
+ async create(data) {
468
+ const rows = await db.insert(sessions).values(data).returning();
469
+ return rows[0];
470
+ },
471
+ async update(id, data) {
472
+ const rows = await db.update(sessions).set(data).where(eq(sessions.id, id)).returning();
473
+ return rows[0];
474
+ },
475
+ async updateLastUsed(id) {
476
+ await db.update(sessions).set({ lastUsed: /* @__PURE__ */ new Date() }).where(eq(sessions.id, id));
477
+ const rows = await db.select({
478
+ id: sessions.id,
479
+ userId: sessions.userId,
480
+ socketId: sessions.socketId,
481
+ twoFaSecret: sessions.twoFaSecret,
482
+ browserName: sessions.browserName,
483
+ issuedAt: sessions.issuedAt,
484
+ lastUsed: sessions.lastUsed,
485
+ revokedAt: sessions.revokedAt,
486
+ deviceId: sessions.deviceId,
487
+ user: {
488
+ verifiedHumanAt: users.verifiedHumanAt
489
+ }
490
+ }).from(sessions).innerJoin(users, eq(sessions.userId, users.id)).where(eq(sessions.id, id)).limit(1);
491
+ return rows[0];
492
+ },
493
+ async revoke(id) {
494
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(eq(sessions.id, id));
495
+ },
496
+ async findActiveByUserId(userId, excludeSessionId) {
497
+ const conditions = [eq(sessions.userId, userId), isNull(sessions.revokedAt)];
498
+ if (excludeSessionId !== void 0) {
499
+ conditions.push(ne(sessions.id, excludeSessionId));
500
+ }
501
+ return db.select({
502
+ id: sessions.id,
503
+ socketId: sessions.socketId,
504
+ userId: sessions.userId
505
+ }).from(sessions).where(and(...conditions));
506
+ },
507
+ async revokeAllByUserId(userId, excludeSessionId) {
508
+ const conditions = [eq(sessions.userId, userId), isNull(sessions.revokedAt)];
509
+ if (excludeSessionId !== void 0) {
510
+ conditions.push(ne(sessions.id, excludeSessionId));
511
+ }
512
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(and(...conditions));
513
+ },
514
+ async findTwoFaSecretsByUserId(userId) {
515
+ return db.select({ twoFaSecret: sessions.twoFaSecret }).from(sessions).where(and(eq(sessions.userId, userId), isNotNull(sessions.twoFaSecret)));
516
+ },
517
+ async clearTwoFaSecrets(userId, excludeSessionId) {
518
+ const conditions = [eq(sessions.userId, userId)];
519
+ if (excludeSessionId !== void 0) {
520
+ conditions.push(ne(sessions.id, excludeSessionId));
521
+ }
522
+ await db.update(sessions).set({ twoFaSecret: null }).where(and(...conditions));
523
+ },
524
+ async findByIdWithDevice(id, userId) {
525
+ const rows = await db.select({
526
+ twoFaSecret: sessions.twoFaSecret,
527
+ deviceId: sessions.deviceId,
528
+ device: {
529
+ pushToken: devices.pushToken
530
+ }
531
+ }).from(sessions).leftJoin(devices, eq(sessions.deviceId, devices.id)).where(and(eq(sessions.id, id), eq(sessions.userId, userId))).limit(1);
532
+ if (!rows[0]) return null;
533
+ const row = rows[0];
534
+ return {
535
+ twoFaSecret: row.twoFaSecret,
536
+ deviceId: row.deviceId,
537
+ device: row.device?.pushToken ? { pushToken: row.device.pushToken } : null
538
+ };
539
+ },
540
+ async revokeByDevicePushToken(userId, pushToken, excludeSessionId) {
541
+ const deviceRows = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
542
+ if (!deviceRows[0]) return;
543
+ await db.update(sessions).set({ revokedAt: /* @__PURE__ */ new Date() }).where(
544
+ and(
545
+ eq(sessions.userId, userId),
546
+ ne(sessions.id, excludeSessionId),
547
+ isNull(sessions.revokedAt),
548
+ eq(sessions.deviceId, deviceRows[0].id)
549
+ )
550
+ );
551
+ },
552
+ async clearDeviceId(userId, deviceId) {
553
+ await db.update(sessions).set({ deviceId: null }).where(and(eq(sessions.userId, userId), eq(sessions.deviceId, deviceId)));
554
+ }
555
+ },
556
+ otp: {
557
+ async findValidByUserAndCode(userId, code) {
558
+ const rows = await db.select().from(otps).where(
559
+ and(eq(otps.userId, userId), eq(otps.code, code), gte(otps.expiresAt, /* @__PURE__ */ new Date()))
560
+ ).limit(1);
561
+ return rows[0] ?? null;
562
+ },
563
+ async create(data) {
564
+ const rows = await db.insert(otps).values(data).returning();
565
+ return rows[0];
566
+ },
567
+ async delete(id) {
568
+ await db.delete(otps).where(eq(otps.id, id));
569
+ }
570
+ },
571
+ passwordReset: {
572
+ async findById(id) {
573
+ const rows = await db.select({
574
+ id: passwordResets.id,
575
+ createdAt: passwordResets.createdAt,
576
+ userId: passwordResets.userId
577
+ }).from(passwordResets).where(eq(passwordResets.id, id)).limit(1);
578
+ return rows[0] ?? null;
579
+ },
580
+ async create(userId) {
581
+ const rows = await db.insert(passwordResets).values({ userId }).returning();
582
+ return rows[0];
583
+ },
584
+ async delete(id) {
585
+ await db.delete(passwordResets).where(eq(passwordResets.id, id));
586
+ },
587
+ async deleteAllByUserId(userId) {
588
+ await db.delete(passwordResets).where(eq(passwordResets.userId, userId));
589
+ }
590
+ },
591
+ device: {
592
+ async findByTokenSessionAndUser(pushToken, sessionId, userId) {
593
+ const rows = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
594
+ if (!rows[0]) return null;
595
+ if (tables.devicesToSessions && tables.devicesToUsers) {
596
+ const sessionLink = await db.select().from(tables.devicesToSessions).where(
597
+ and(
598
+ eq(tables.devicesToSessions.deviceId, rows[0].id),
599
+ eq(tables.devicesToSessions.sessionId, sessionId)
600
+ )
601
+ ).limit(1);
602
+ const userLink = await db.select().from(tables.devicesToUsers).where(
603
+ and(
604
+ eq(tables.devicesToUsers.deviceId, rows[0].id),
605
+ eq(tables.devicesToUsers.userId, userId)
606
+ )
607
+ ).limit(1);
608
+ if (!sessionLink[0] || !userLink[0]) return null;
609
+ }
610
+ return { id: rows[0].id };
611
+ },
612
+ async upsertByPushToken(pushToken, sessionId, userId) {
613
+ const existing = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
614
+ let deviceId;
615
+ if (existing[0]) {
616
+ deviceId = existing[0].id;
617
+ } else {
618
+ const rows = await db.insert(devices).values({ pushToken }).returning({ id: devices.id });
619
+ deviceId = rows[0].id;
620
+ }
621
+ if (tables.devicesToSessions) {
622
+ await db.insert(tables.devicesToSessions).values({ deviceId, sessionId }).onConflictDoNothing();
623
+ }
624
+ if (tables.devicesToUsers) {
625
+ await db.insert(tables.devicesToUsers).values({ deviceId, userId }).onConflictDoNothing();
626
+ }
627
+ await db.update(sessions).set({ deviceId }).where(eq(sessions.id, sessionId));
628
+ },
629
+ async findByUserAndToken(userId, pushToken) {
630
+ if (tables.devicesToUsers) {
631
+ const rows2 = await db.select({ id: devices.id }).from(devices).innerJoin(
632
+ tables.devicesToUsers,
633
+ eq(devices.id, tables.devicesToUsers.deviceId)
634
+ ).where(
635
+ and(
636
+ eq(devices.pushToken, pushToken),
637
+ eq(tables.devicesToUsers.userId, userId)
638
+ )
639
+ ).limit(1);
640
+ return rows2[0] ? { id: rows2[0].id } : null;
641
+ }
642
+ const rows = await db.select({ id: devices.id }).from(devices).where(eq(devices.pushToken, pushToken)).limit(1);
643
+ return rows[0] ? { id: rows[0].id } : null;
644
+ },
645
+ async disconnectUser(deviceId, userId) {
646
+ if (tables.devicesToUsers) {
647
+ await db.delete(tables.devicesToUsers).where(
648
+ and(
649
+ eq(tables.devicesToUsers.deviceId, deviceId),
650
+ eq(tables.devicesToUsers.userId, userId)
651
+ )
652
+ );
653
+ }
654
+ },
655
+ async hasRemainingUsers(deviceId) {
656
+ if (tables.devicesToUsers) {
657
+ const rows = await db.select({ userId: tables.devicesToUsers.userId }).from(tables.devicesToUsers).where(eq(tables.devicesToUsers.deviceId, deviceId)).limit(1);
658
+ return rows.length > 0;
659
+ }
660
+ return false;
661
+ },
662
+ async delete(id) {
663
+ await db.delete(devices).where(eq(devices.id, id));
664
+ }
665
+ },
666
+ admin: {
667
+ async findByUserId(userId) {
668
+ const rows = await db.select({ ip: admins.ip }).from(admins).where(eq(admins.userId, userId)).limit(1);
669
+ return rows[0] ?? null;
670
+ }
671
+ }
672
+ };
673
+ }
674
+
134
675
  // src/utilities/config.ts
135
676
  var defaultTokenSettings = {
136
677
  jwtExpiry: 30 * 24 * 60 * 60,
@@ -161,9 +702,16 @@ var defaultFeatures = {
161
702
  otpLogin: true
162
703
  };
163
704
  function createAuthConfig(config) {
705
+ if (!config.database && !config.prisma) {
706
+ throw new Error(
707
+ "@factiii/auth: Provide either a `database` adapter or a `prisma` client in config."
708
+ );
709
+ }
710
+ const database = config.database ?? createPrismaAdapter(config.prisma);
164
711
  const emailService = config.emailService ?? createNoopEmailAdapter();
165
712
  return {
166
713
  ...config,
714
+ database,
167
715
  features: { ...defaultFeatures, ...config.features },
168
716
  tokenSettings: { ...defaultTokenSettings, ...config.tokenSettings },
169
717
  cookieSettings: { ...defaultCookieSettings, ...config.cookieSettings },
@@ -281,6 +829,7 @@ function isTokenInvalidError(error) {
281
829
  function createAuthGuard(config, t) {
282
830
  const storageKeys = config.storageKeys ?? defaultStorageKeys;
283
831
  const cookieSettings = { ...defaultCookieSettings, ...config.cookieSettings };
832
+ const database = config.database ?? createPrismaAdapter(config.prisma);
284
833
  const revokeSession = async (ctx, sessionId, description, errorStack, path) => {
285
834
  clearAuthCookie(ctx.res, cookieSettings, storageKeys);
286
835
  if (config.hooks?.logError) {
@@ -317,15 +866,9 @@ ${errorStack}` : null,
317
866
  }
318
867
  if (sessionId) {
319
868
  try {
320
- await config.prisma.session.update({
321
- where: { id: sessionId },
322
- data: { revokedAt: /* @__PURE__ */ new Date() }
323
- });
869
+ await database.session.revoke(sessionId);
324
870
  if (config.hooks?.onSessionRevoked) {
325
- const session = await config.prisma.session.findUnique({
326
- where: { id: sessionId },
327
- select: { id: true, userId: true, socketId: true }
328
- });
871
+ const session = await database.session.findById(sessionId);
329
872
  if (session) {
330
873
  await config.hooks.onSessionRevoked(session.userId, session.socketId, description);
331
874
  }
@@ -350,23 +893,7 @@ ${errorStack}` : null,
350
893
  secret: config.secrets.jwt,
351
894
  ignoreExpiration: meta?.ignoreExpiration ?? false
352
895
  });
353
- const session = await config.prisma.session.findUnique({
354
- where: {
355
- id: decodedToken.id
356
- },
357
- select: {
358
- userId: true,
359
- user: {
360
- select: {
361
- status: true,
362
- verifiedHumanAt: true
363
- }
364
- },
365
- revokedAt: true,
366
- socketId: true,
367
- id: true
368
- }
369
- });
896
+ const session = await database.session.findById(decodedToken.id);
370
897
  if (!session) {
371
898
  await revokeSession(
372
899
  ctx,
@@ -420,10 +947,7 @@ ${errorStack}` : null,
420
947
  });
421
948
  }
422
949
  if (meta?.adminRequired) {
423
- const admin = await config.prisma.admin.findFirst({
424
- where: { userId: session.userId },
425
- select: { ip: true }
426
- });
950
+ const admin = await database.admin.findByUserId(session.userId);
427
951
  if (!admin || admin.ip !== ctx.ip) {
428
952
  await revokeSession(
429
953
  ctx,
@@ -756,19 +1280,14 @@ var BaseProcedureFactory = class {
756
1280
  if (this.config.hooks?.beforeRegister) {
757
1281
  await this.config.hooks.beforeRegister(typedInput);
758
1282
  }
759
- const usernameCheck = await this.config.prisma.user.findFirst({
760
- where: { username: { equals: username, mode: "insensitive" } }
761
- });
1283
+ const usernameCheck = await this.config.database.user.findByUsernameInsensitive(username);
762
1284
  if (usernameCheck) {
763
1285
  throw new import_server2.TRPCError({
764
1286
  code: "CONFLICT",
765
1287
  message: "An account already exists with that username."
766
1288
  });
767
1289
  }
768
- const emailCheck = await this.config.prisma.user.findFirst({
769
- where: { email: { equals: email, mode: "insensitive" } },
770
- select: { id: true }
771
- });
1290
+ const emailCheck = await this.config.database.user.findByEmailInsensitive(email);
772
1291
  if (emailCheck) {
773
1292
  throw new import_server2.TRPCError({
774
1293
  code: "CONFLICT",
@@ -776,30 +1295,25 @@ var BaseProcedureFactory = class {
776
1295
  });
777
1296
  }
778
1297
  const hashedPassword = await hashPassword(password);
779
- const user = await this.config.prisma.user.create({
780
- data: {
781
- username,
782
- email,
783
- password: hashedPassword,
784
- status: "ACTIVE",
785
- tag: this.config.features.biometric ? "BOT" : "HUMAN",
786
- twoFaEnabled: false,
787
- emailVerificationStatus: "UNVERIFIED",
788
- verifiedHumanAt: null
789
- }
1298
+ const user = await this.config.database.user.create({
1299
+ username,
1300
+ email,
1301
+ password: hashedPassword,
1302
+ status: "ACTIVE",
1303
+ tag: this.config.features.biometric ? "BOT" : "HUMAN",
1304
+ twoFaEnabled: false,
1305
+ emailVerificationStatus: "UNVERIFIED",
1306
+ verifiedHumanAt: null
790
1307
  });
791
1308
  if (this.config.hooks?.onUserCreated) {
792
1309
  await this.config.hooks.onUserCreated(user.id, typedInput);
793
1310
  }
794
1311
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
795
- const session = await this.config.prisma.session.create({
796
- data: {
797
- userId: user.id,
798
- browserName: detectBrowser(userAgent),
799
- socketId: null,
800
- ...extraSessionData
801
- },
802
- select: { id: true, userId: true }
1312
+ const session = await this.config.database.session.create({
1313
+ userId: user.id,
1314
+ browserName: detectBrowser(userAgent),
1315
+ socketId: null,
1316
+ ...extraSessionData
803
1317
  });
804
1318
  if (this.config.hooks?.onSessionCreated) {
805
1319
  await this.config.hooks.onSessionCreated(session.id, typedInput);
@@ -837,24 +1351,7 @@ var BaseProcedureFactory = class {
837
1351
  if (this.config.hooks?.beforeLogin) {
838
1352
  await this.config.hooks.beforeLogin(typedInput);
839
1353
  }
840
- const user = await this.config.prisma.user.findFirst({
841
- where: {
842
- OR: [
843
- { email: { equals: username, mode: "insensitive" } },
844
- { username: { equals: username, mode: "insensitive" } }
845
- ]
846
- },
847
- select: {
848
- id: true,
849
- status: true,
850
- password: true,
851
- twoFaEnabled: true,
852
- email: true,
853
- username: true,
854
- oauthProvider: true,
855
- verifiedHumanAt: true
856
- }
857
- });
1354
+ const user = await this.config.database.user.findByEmailOrUsernameInsensitive(username);
858
1355
  if (!user) {
859
1356
  throw new import_server2.TRPCError({
860
1357
  code: "FORBIDDEN",
@@ -895,10 +1392,7 @@ var BaseProcedureFactory = class {
895
1392
  };
896
1393
  }
897
1394
  let validCode = false;
898
- const secrets = await this.config.prisma.session.findMany({
899
- where: { userId: user.id, twoFaSecret: { not: null } },
900
- select: { twoFaSecret: true }
901
- });
1395
+ const secrets = await this.config.database.session.findTwoFaSecretsByUserId(user.id);
902
1396
  for (const s of secrets) {
903
1397
  if (s.twoFaSecret && await verifyTotp(code, cleanBase32String(s.twoFaSecret))) {
904
1398
  validCode = true;
@@ -906,14 +1400,13 @@ var BaseProcedureFactory = class {
906
1400
  }
907
1401
  }
908
1402
  if (!validCode) {
909
- const checkOTP = await this.config.prisma.oTP.findFirst({
910
- where: { userId: user.id, code: Number(code), expiresAt: { gte: /* @__PURE__ */ new Date() } }
911
- });
1403
+ const checkOTP = await this.config.database.otp.findValidByUserAndCode(
1404
+ user.id,
1405
+ Number(code)
1406
+ );
912
1407
  if (checkOTP) {
913
1408
  validCode = true;
914
- await this.config.prisma.oTP.delete({
915
- where: { id: checkOTP.id }
916
- });
1409
+ await this.config.database.otp.delete(checkOTP.id);
917
1410
  }
918
1411
  }
919
1412
  if (!validCode) {
@@ -924,24 +1417,11 @@ var BaseProcedureFactory = class {
924
1417
  }
925
1418
  }
926
1419
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
927
- const session = await this.config.prisma.session.create({
928
- data: {
929
- userId: user.id,
930
- browserName: detectBrowser(userAgent),
931
- socketId: null,
932
- ...extraSessionData
933
- },
934
- select: {
935
- id: true,
936
- userId: true,
937
- socketId: true,
938
- browserName: true,
939
- issuedAt: true,
940
- lastUsed: true,
941
- revokedAt: true,
942
- deviceId: true,
943
- twoFaSecret: true
944
- }
1420
+ const session = await this.config.database.session.create({
1421
+ userId: user.id,
1422
+ browserName: detectBrowser(userAgent),
1423
+ socketId: null,
1424
+ ...extraSessionData
945
1425
  });
946
1426
  if (this.config.hooks?.onUserLogin) {
947
1427
  await this.config.hooks.onUserLogin(user.id, session.id);
@@ -972,15 +1452,9 @@ var BaseProcedureFactory = class {
972
1452
  return this.authProcedure.meta({ ignoreExpiration: true }).mutation(async ({ ctx }) => {
973
1453
  const { userId, sessionId } = ctx;
974
1454
  if (sessionId) {
975
- await this.config.prisma.session.update({
976
- where: { id: sessionId },
977
- data: { revokedAt: /* @__PURE__ */ new Date() }
978
- });
1455
+ await this.config.database.session.revoke(sessionId);
979
1456
  if (userId) {
980
- await this.config.prisma.user.update({
981
- where: { id: userId },
982
- data: { isActive: false }
983
- });
1457
+ await this.config.database.user.update(userId, { isActive: false });
984
1458
  }
985
1459
  if (this.config.hooks?.afterLogout) {
986
1460
  await this.config.hooks.afterLogout(userId, sessionId, ctx.socketId);
@@ -992,15 +1466,7 @@ var BaseProcedureFactory = class {
992
1466
  }
993
1467
  refresh() {
994
1468
  return this.authProcedure.query(async ({ ctx }) => {
995
- const session = await this.config.prisma.session.update({
996
- where: { id: ctx.sessionId },
997
- data: { lastUsed: /* @__PURE__ */ new Date() },
998
- select: {
999
- id: true,
1000
- userId: true,
1001
- user: { select: { verifiedHumanAt: true } }
1002
- }
1003
- });
1469
+ const session = await this.config.database.session.updateLastUsed(ctx.sessionId);
1004
1470
  if (this.config.hooks?.onRefresh) {
1005
1471
  this.config.hooks.onRefresh(session.userId).catch(() => {
1006
1472
  });
@@ -1025,22 +1491,14 @@ var BaseProcedureFactory = class {
1025
1491
  return this.authProcedure.input(endAllSessionsSchema).mutation(async ({ ctx, input }) => {
1026
1492
  const { skipCurrentSession } = input;
1027
1493
  const { userId, sessionId } = ctx;
1028
- const sessionsToRevoke = await this.config.prisma.session.findMany({
1029
- where: {
1030
- userId,
1031
- revokedAt: null,
1032
- ...skipCurrentSession ? { NOT: { id: sessionId } } : {}
1033
- },
1034
- select: { socketId: true, id: true, userId: true }
1035
- });
1036
- await this.config.prisma.session.updateMany({
1037
- where: {
1038
- userId,
1039
- revokedAt: null,
1040
- ...skipCurrentSession ? { NOT: { id: sessionId } } : {}
1041
- },
1042
- data: { revokedAt: /* @__PURE__ */ new Date() }
1043
- });
1494
+ const sessionsToRevoke = await this.config.database.session.findActiveByUserId(
1495
+ userId,
1496
+ skipCurrentSession ? sessionId : void 0
1497
+ );
1498
+ await this.config.database.session.revokeAllByUserId(
1499
+ userId,
1500
+ skipCurrentSession ? sessionId : void 0
1501
+ );
1044
1502
  for (const session of sessionsToRevoke) {
1045
1503
  if (this.config.hooks?.onSessionRevoked) {
1046
1504
  await this.config.hooks.onSessionRevoked(
@@ -1051,10 +1509,7 @@ var BaseProcedureFactory = class {
1051
1509
  }
1052
1510
  }
1053
1511
  if (!skipCurrentSession) {
1054
- await this.config.prisma.user.update({
1055
- where: { id: userId },
1056
- data: { isActive: false }
1057
- });
1512
+ await this.config.database.user.update(userId, { isActive: false });
1058
1513
  }
1059
1514
  return { success: true, revokedCount: sessionsToRevoke.length };
1060
1515
  });
@@ -1069,10 +1524,7 @@ var BaseProcedureFactory = class {
1069
1524
  message: "New password cannot be the same as current password"
1070
1525
  });
1071
1526
  }
1072
- const user = await this.config.prisma.user.findUnique({
1073
- where: { id: userId },
1074
- select: { password: true }
1075
- });
1527
+ const user = await this.config.database.user.findById(userId);
1076
1528
  if (!user) {
1077
1529
  throw new import_server2.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1078
1530
  }
@@ -1090,14 +1542,8 @@ var BaseProcedureFactory = class {
1090
1542
  });
1091
1543
  }
1092
1544
  const hashedPassword = await hashPassword(newPassword);
1093
- await this.config.prisma.user.update({
1094
- where: { id: userId },
1095
- data: { password: hashedPassword }
1096
- });
1097
- await this.config.prisma.session.updateMany({
1098
- where: { userId, revokedAt: null, NOT: { id: sessionId } },
1099
- data: { revokedAt: /* @__PURE__ */ new Date() }
1100
- });
1545
+ await this.config.database.user.update(userId, { password: hashedPassword });
1546
+ await this.config.database.session.revokeAllByUserId(userId, sessionId);
1101
1547
  if (this.config.hooks?.onPasswordChanged) {
1102
1548
  await this.config.hooks.onPasswordChanged(userId);
1103
1549
  }
@@ -1110,11 +1556,8 @@ var BaseProcedureFactory = class {
1110
1556
  sendPasswordResetEmail() {
1111
1557
  return this.procedure.input(requestPasswordResetSchema).mutation(async ({ input }) => {
1112
1558
  const { email } = input;
1113
- const user = await this.config.prisma.user.findFirst({
1114
- where: { email: { equals: email, mode: "insensitive" }, status: "ACTIVE" },
1115
- select: { id: true, password: true, email: true }
1116
- });
1117
- if (!user) {
1559
+ const user = await this.config.database.user.findByEmailInsensitive(email);
1560
+ if (!user || user.status !== "ACTIVE") {
1118
1561
  return { message: "If an account exists with that email, a reset link has been sent." };
1119
1562
  }
1120
1563
  if (!user.password) {
@@ -1123,10 +1566,8 @@ var BaseProcedureFactory = class {
1123
1566
  message: "This account uses social login. Please use that method."
1124
1567
  });
1125
1568
  }
1126
- await this.config.prisma.passwordReset.deleteMany({ where: { userId: user.id } });
1127
- const passwordReset = await this.config.prisma.passwordReset.create({
1128
- data: { userId: user.id }
1129
- });
1569
+ await this.config.database.passwordReset.deleteAllByUserId(user.id);
1570
+ const passwordReset = await this.config.database.passwordReset.create(user.id);
1130
1571
  if (this.config.emailService) {
1131
1572
  await this.config.emailService.sendPasswordResetEmail(user.email, String(passwordReset.id));
1132
1573
  }
@@ -1136,15 +1577,12 @@ var BaseProcedureFactory = class {
1136
1577
  checkPasswordReset() {
1137
1578
  return this.procedure.input(checkPasswordResetSchema).query(async ({ input }) => {
1138
1579
  const { token } = input;
1139
- const passwordReset = await this.config.prisma.passwordReset.findUnique({
1140
- where: { id: token },
1141
- select: { id: true, createdAt: true, userId: true }
1142
- });
1580
+ const passwordReset = await this.config.database.passwordReset.findById(token);
1143
1581
  if (!passwordReset) {
1144
1582
  throw new import_server2.TRPCError({ code: "NOT_FOUND", message: "Invalid reset token." });
1145
1583
  }
1146
1584
  if (passwordReset.createdAt.getTime() + this.config.tokenSettings.passwordResetExpiryMs < Date.now()) {
1147
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1585
+ await this.config.database.passwordReset.delete(token);
1148
1586
  throw new import_server2.TRPCError({ code: "FORBIDDEN", message: "Reset token expired." });
1149
1587
  }
1150
1588
  return { valid: true };
@@ -1153,31 +1591,23 @@ var BaseProcedureFactory = class {
1153
1591
  resetPassword() {
1154
1592
  return this.procedure.input(resetPasswordSchema).mutation(async ({ input }) => {
1155
1593
  const { token, password } = input;
1156
- const passwordReset = await this.config.prisma.passwordReset.findFirst({
1157
- where: { id: token },
1158
- select: { id: true, createdAt: true, userId: true }
1159
- });
1594
+ const passwordReset = await this.config.database.passwordReset.findById(token);
1160
1595
  if (!passwordReset) {
1161
1596
  throw new import_server2.TRPCError({ code: "NOT_FOUND", message: "Invalid reset token." });
1162
1597
  }
1163
1598
  if (passwordReset.createdAt.getTime() + this.config.tokenSettings.passwordResetExpiryMs < Date.now()) {
1164
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1599
+ await this.config.database.passwordReset.delete(token);
1165
1600
  throw new import_server2.TRPCError({ code: "FORBIDDEN", message: "Reset token expired." });
1166
1601
  }
1167
1602
  const hashedPassword = await hashPassword(password);
1168
- await this.config.prisma.user.update({
1169
- where: { id: passwordReset.userId },
1170
- data: { password: hashedPassword }
1171
- });
1172
- await this.config.prisma.passwordReset.delete({ where: { id: token } });
1173
- const sessionsToRevoke = await this.config.prisma.session.findMany({
1174
- where: { userId: passwordReset.userId, revokedAt: null },
1175
- select: { id: true, socketId: true, userId: true }
1176
- });
1177
- await this.config.prisma.session.updateMany({
1178
- where: { userId: passwordReset.userId, revokedAt: null },
1179
- data: { revokedAt: /* @__PURE__ */ new Date() }
1603
+ await this.config.database.user.update(passwordReset.userId, {
1604
+ password: hashedPassword
1180
1605
  });
1606
+ await this.config.database.passwordReset.delete(token);
1607
+ const sessionsToRevoke = await this.config.database.session.findActiveByUserId(
1608
+ passwordReset.userId
1609
+ );
1610
+ await this.config.database.session.revokeAllByUserId(passwordReset.userId);
1181
1611
  for (const session of sessionsToRevoke) {
1182
1612
  if (this.config.hooks?.onSessionRevoked) {
1183
1613
  await this.config.hooks.onSessionRevoked(
@@ -1214,9 +1644,9 @@ var BiometricProcedureFactory = class {
1214
1644
  return this.authProcedure.input(biometricVerifySchema).mutation(async ({ ctx }) => {
1215
1645
  this.checkConfig();
1216
1646
  const { userId } = ctx;
1217
- await this.config.prisma.user.update({
1218
- where: { id: userId },
1219
- data: { verifiedHumanAt: /* @__PURE__ */ new Date(), tag: "HUMAN" }
1647
+ await this.config.database.user.update(userId, {
1648
+ verifiedHumanAt: /* @__PURE__ */ new Date(),
1649
+ tag: "HUMAN"
1220
1650
  });
1221
1651
  if (this.config.hooks?.onBiometricVerified) {
1222
1652
  await this.config.hooks.onBiometricVerified(userId);
@@ -1228,10 +1658,7 @@ var BiometricProcedureFactory = class {
1228
1658
  return this.authProcedure.query(async ({ ctx }) => {
1229
1659
  this.checkConfig();
1230
1660
  const { userId } = ctx;
1231
- const user = await this.config.prisma.user.findUnique({
1232
- where: { id: userId },
1233
- select: { verifiedHumanAt: true }
1234
- });
1661
+ const user = await this.config.database.user.findById(userId);
1235
1662
  if (!user) {
1236
1663
  throw new import_server3.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1237
1664
  }
@@ -1278,10 +1705,7 @@ var EmailVerificationProcedureFactory = class {
1278
1705
  return this.authProcedure.mutation(async ({ ctx }) => {
1279
1706
  this.checkConfig();
1280
1707
  const { userId } = ctx;
1281
- const user = await this.config.prisma.user.findUnique({
1282
- where: { id: userId, status: "ACTIVE" },
1283
- select: { id: true, email: true, emailVerificationStatus: true }
1284
- });
1708
+ const user = await this.config.database.user.findActiveById(userId);
1285
1709
  if (!user) {
1286
1710
  throw new import_server4.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1287
1711
  }
@@ -1289,9 +1713,9 @@ var EmailVerificationProcedureFactory = class {
1289
1713
  return { message: "Email is already verified", emailSent: false };
1290
1714
  }
1291
1715
  const otp = (0, import_node_crypto.randomUUID)();
1292
- await this.config.prisma.user.update({
1293
- where: { id: userId },
1294
- data: { emailVerificationStatus: "PENDING", otpForEmailVerification: otp }
1716
+ await this.config.database.user.update(userId, {
1717
+ emailVerificationStatus: "PENDING",
1718
+ otpForEmailVerification: otp
1295
1719
  });
1296
1720
  if (this.config.emailService) {
1297
1721
  try {
@@ -1309,10 +1733,7 @@ var EmailVerificationProcedureFactory = class {
1309
1733
  this.checkConfig();
1310
1734
  const { userId } = ctx;
1311
1735
  const { code } = input;
1312
- const user = await this.config.prisma.user.findUnique({
1313
- where: { id: userId, status: "ACTIVE" },
1314
- select: { id: true, emailVerificationStatus: true, otpForEmailVerification: true }
1315
- });
1736
+ const user = await this.config.database.user.findActiveById(userId);
1316
1737
  if (!user) {
1317
1738
  throw new import_server4.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1318
1739
  }
@@ -1322,9 +1743,9 @@ var EmailVerificationProcedureFactory = class {
1322
1743
  if (code !== user.otpForEmailVerification) {
1323
1744
  throw new import_server4.TRPCError({ code: "BAD_REQUEST", message: "Invalid verification code" });
1324
1745
  }
1325
- await this.config.prisma.user.update({
1326
- where: { id: userId },
1327
- data: { emailVerificationStatus: "VERIFIED", otpForEmailVerification: null }
1746
+ await this.config.database.user.update(userId, {
1747
+ emailVerificationStatus: "VERIFIED",
1748
+ otpForEmailVerification: null
1328
1749
  });
1329
1750
  if (this.config.hooks?.onEmailVerified) {
1330
1751
  await this.config.hooks.onEmailVerified(userId);
@@ -1336,10 +1757,7 @@ var EmailVerificationProcedureFactory = class {
1336
1757
  return this.authProcedure.query(async ({ ctx }) => {
1337
1758
  this.checkConfig();
1338
1759
  const { userId } = ctx;
1339
- const user = await this.config.prisma.user.findUnique({
1340
- where: { id: userId },
1341
- select: { emailVerificationStatus: true, email: true }
1342
- });
1760
+ const user = await this.config.database.user.findById(userId);
1343
1761
  if (!user) {
1344
1762
  throw new import_server4.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1345
1763
  }
@@ -1393,23 +1811,7 @@ var OAuthLoginProcedureFactory = class {
1393
1811
  message: "Email not provided by OAuth provider"
1394
1812
  });
1395
1813
  }
1396
- let user = await this.config.prisma.user.findFirst({
1397
- where: {
1398
- OR: [{ email: { equals: email, mode: "insensitive" } }, { oauthId: { equals: oauthId } }]
1399
- },
1400
- select: {
1401
- id: true,
1402
- status: true,
1403
- email: true,
1404
- username: true,
1405
- password: true,
1406
- oauthProvider: true,
1407
- oauthId: true,
1408
- twoFaEnabled: true,
1409
- verifiedHumanAt: true,
1410
- emailVerificationStatus: true
1411
- }
1412
- });
1814
+ let user = await this.config.database.user.findByEmailOrOAuthId(email, oauthId);
1413
1815
  if (user?.oauthProvider && user.oauthProvider !== provider) {
1414
1816
  throw new import_server5.TRPCError({
1415
1817
  code: "BAD_REQUEST",
@@ -1424,19 +1826,17 @@ var OAuthLoginProcedureFactory = class {
1424
1826
  }
1425
1827
  if (!user) {
1426
1828
  const generateUsername = this.config.generateUsername ?? (() => `user_${Date.now()}`);
1427
- user = await this.config.prisma.user.create({
1428
- data: {
1429
- username: generateUsername(),
1430
- email,
1431
- password: null,
1432
- emailVerificationStatus: "VERIFIED",
1433
- oauthProvider: provider,
1434
- oauthId,
1435
- status: "ACTIVE",
1436
- tag: this.config.features.biometric ? "BOT" : "HUMAN",
1437
- twoFaEnabled: false,
1438
- verifiedHumanAt: null
1439
- }
1829
+ user = await this.config.database.user.create({
1830
+ username: generateUsername(),
1831
+ email,
1832
+ password: null,
1833
+ emailVerificationStatus: "VERIFIED",
1834
+ oauthProvider: provider,
1835
+ oauthId,
1836
+ status: "ACTIVE",
1837
+ tag: this.config.features.biometric ? "BOT" : "HUMAN",
1838
+ twoFaEnabled: false,
1839
+ verifiedHumanAt: null
1440
1840
  });
1441
1841
  if (this.config.hooks?.onUserCreated) {
1442
1842
  await this.config.hooks.onUserCreated(user.id, typedInput);
@@ -1452,24 +1852,11 @@ var OAuthLoginProcedureFactory = class {
1452
1852
  throw new import_server5.TRPCError({ code: "FORBIDDEN", message: "Your account has been banned." });
1453
1853
  }
1454
1854
  const extraSessionData = this.config.hooks?.getSessionData ? await this.config.hooks.getSessionData(typedInput) : {};
1455
- const session = await this.config.prisma.session.create({
1456
- data: {
1457
- userId: user.id,
1458
- browserName: detectBrowser(userAgent),
1459
- socketId: null,
1460
- ...extraSessionData
1461
- },
1462
- select: {
1463
- id: true,
1464
- userId: true,
1465
- socketId: true,
1466
- browserName: true,
1467
- issuedAt: true,
1468
- lastUsed: true,
1469
- revokedAt: true,
1470
- deviceId: true,
1471
- twoFaSecret: true
1472
- }
1855
+ const session = await this.config.database.session.create({
1856
+ userId: user.id,
1857
+ browserName: detectBrowser(userAgent),
1858
+ socketId: null,
1859
+ ...extraSessionData
1473
1860
  });
1474
1861
  if (this.config.hooks?.onUserLogin) {
1475
1862
  await this.config.hooks.onUserLogin(user.id, session.id);
@@ -1526,10 +1913,7 @@ var TwoFaProcedureFactory = class {
1526
1913
  return this.authProcedure.mutation(async ({ ctx }) => {
1527
1914
  this.checkConfig();
1528
1915
  const { userId, sessionId } = ctx;
1529
- const user = await this.config.prisma.user.findFirst({
1530
- where: { id: userId },
1531
- select: { twoFaEnabled: true, oauthProvider: true, password: true }
1532
- });
1916
+ const user = await this.config.database.user.findById(userId);
1533
1917
  if (!user) {
1534
1918
  throw new import_server6.TRPCError({ code: "NOT_FOUND", message: "User not found." });
1535
1919
  }
@@ -1543,10 +1927,7 @@ var TwoFaProcedureFactory = class {
1543
1927
  throw new import_server6.TRPCError({ code: "BAD_REQUEST", message: "2FA already enabled." });
1544
1928
  }
1545
1929
  if (this.config.features.twoFaRequiresDevice !== false) {
1546
- const checkSession = await this.config.prisma.session.findFirst({
1547
- where: { userId, id: sessionId },
1548
- select: { deviceId: true }
1549
- });
1930
+ const checkSession = await this.config.database.session.findById(sessionId);
1550
1931
  if (!checkSession?.deviceId) {
1551
1932
  throw new import_server6.TRPCError({
1552
1933
  code: "BAD_REQUEST",
@@ -1554,23 +1935,11 @@ var TwoFaProcedureFactory = class {
1554
1935
  });
1555
1936
  }
1556
1937
  }
1557
- await this.config.prisma.session.updateMany({
1558
- where: { userId, revokedAt: null, NOT: { id: sessionId } },
1559
- data: { revokedAt: /* @__PURE__ */ new Date() }
1560
- });
1561
- await this.config.prisma.session.updateMany({
1562
- where: { userId, NOT: { id: sessionId } },
1563
- data: { twoFaSecret: null }
1564
- });
1938
+ await this.config.database.session.revokeAllByUserId(userId, sessionId);
1939
+ await this.config.database.session.clearTwoFaSecrets(userId, sessionId);
1565
1940
  const secret = generateTotpSecret();
1566
- await this.config.prisma.user.update({
1567
- where: { id: userId },
1568
- data: { twoFaEnabled: true }
1569
- });
1570
- await this.config.prisma.session.update({
1571
- where: { id: sessionId },
1572
- data: { twoFaSecret: secret }
1573
- });
1941
+ await this.config.database.user.update(userId, { twoFaEnabled: true });
1942
+ await this.config.database.session.update(sessionId, { twoFaSecret: secret });
1574
1943
  if (this.config.hooks?.onTwoFaStatusChanged) {
1575
1944
  await this.config.hooks.onTwoFaStatusChanged(userId, true);
1576
1945
  }
@@ -1582,10 +1951,7 @@ var TwoFaProcedureFactory = class {
1582
1951
  this.checkConfig();
1583
1952
  const { userId, sessionId } = ctx;
1584
1953
  const { password } = input;
1585
- const user = await this.config.prisma.user.findFirst({
1586
- where: { id: userId },
1587
- select: { password: true, status: true, oauthProvider: true }
1588
- });
1954
+ const user = await this.config.database.user.findById(userId);
1589
1955
  if (!user) {
1590
1956
  throw new import_server6.TRPCError({ code: "NOT_FOUND", message: "User not found." });
1591
1957
  }
@@ -1608,14 +1974,8 @@ var TwoFaProcedureFactory = class {
1608
1974
  if (!isMatch) {
1609
1975
  throw new import_server6.TRPCError({ code: "FORBIDDEN", message: "Incorrect password." });
1610
1976
  }
1611
- await this.config.prisma.user.update({
1612
- where: { id: userId },
1613
- data: { twoFaEnabled: false }
1614
- });
1615
- await this.config.prisma.session.update({
1616
- where: { id: sessionId },
1617
- data: { twoFaSecret: null }
1618
- });
1977
+ await this.config.database.user.update(userId, { twoFaEnabled: false });
1978
+ await this.config.database.session.update(sessionId, { twoFaSecret: null });
1619
1979
  if (this.config.hooks?.onTwoFaStatusChanged) {
1620
1980
  await this.config.hooks.onTwoFaStatusChanged(userId, false);
1621
1981
  }
@@ -1627,10 +1987,7 @@ var TwoFaProcedureFactory = class {
1627
1987
  this.checkConfig();
1628
1988
  const { userId, sessionId } = ctx;
1629
1989
  const { pushCode } = input;
1630
- const user = await this.config.prisma.user.findFirst({
1631
- where: { id: userId },
1632
- select: { twoFaEnabled: true, oauthProvider: true }
1633
- });
1990
+ const user = await this.config.database.user.findById(userId);
1634
1991
  if (user?.oauthProvider) {
1635
1992
  throw new import_server6.TRPCError({
1636
1993
  code: "FORBIDDEN",
@@ -1640,10 +1997,7 @@ var TwoFaProcedureFactory = class {
1640
1997
  if (!user?.twoFaEnabled) {
1641
1998
  throw new import_server6.TRPCError({ code: "BAD_REQUEST", message: "2FA not enabled." });
1642
1999
  }
1643
- const session = await this.config.prisma.session.findUnique({
1644
- where: { id: sessionId, userId },
1645
- select: { twoFaSecret: true, device: { select: { pushToken: true } } }
1646
- });
2000
+ const session = await this.config.database.session.findByIdWithDevice(sessionId, userId);
1647
2001
  if (!session?.device) {
1648
2002
  throw new import_server6.TRPCError({ code: "BAD_REQUEST", message: "Invalid request" });
1649
2003
  }
@@ -1655,10 +2009,7 @@ var TwoFaProcedureFactory = class {
1655
2009
  return { secret: session.twoFaSecret };
1656
2010
  }
1657
2011
  const secret = generateTotpSecret();
1658
- await this.config.prisma.session.update({
1659
- where: { id: sessionId },
1660
- data: { twoFaSecret: secret }
1661
- });
2012
+ await this.config.database.session.update(sessionId, { twoFaSecret: secret });
1662
2013
  return { secret };
1663
2014
  });
1664
2015
  }
@@ -1666,11 +2017,8 @@ var TwoFaProcedureFactory = class {
1666
2017
  return this.procedure.input(twoFaResetSchema).mutation(async ({ input }) => {
1667
2018
  this.checkConfig();
1668
2019
  const { username, password } = input;
1669
- const user = await this.config.prisma.user.findFirst({
1670
- where: { username: { equals: username, mode: "insensitive" }, twoFaEnabled: true },
1671
- select: { id: true, password: true, email: true }
1672
- });
1673
- if (!user) {
2020
+ const user = await this.config.database.user.findByUsernameInsensitive(username);
2021
+ if (!user || !user.twoFaEnabled) {
1674
2022
  throw new import_server6.TRPCError({ code: "UNAUTHORIZED", message: "Invalid credentials." });
1675
2023
  }
1676
2024
  if (!user.password) {
@@ -1685,9 +2033,7 @@ var TwoFaProcedureFactory = class {
1685
2033
  }
1686
2034
  const otp = generateOtp();
1687
2035
  const expiresAt = new Date(Date.now() + this.config.tokenSettings.otpValidityMs);
1688
- await this.config.prisma.oTP.create({
1689
- data: { userId: user.id, code: otp, expiresAt }
1690
- });
2036
+ await this.config.database.otp.create({ userId: user.id, code: otp, expiresAt });
1691
2037
  if (this.config.emailService) {
1692
2038
  await this.config.emailService.sendOTPEmail(user.email, otp);
1693
2039
  }
@@ -1698,30 +2044,17 @@ var TwoFaProcedureFactory = class {
1698
2044
  return this.procedure.input(twoFaResetVerifySchema).mutation(async ({ input }) => {
1699
2045
  this.checkConfig();
1700
2046
  const { code, username } = input;
1701
- const user = await this.config.prisma.user.findFirst({
1702
- where: { username: { equals: username, mode: "insensitive" } },
1703
- select: { id: true }
1704
- });
2047
+ const user = await this.config.database.user.findByUsernameInsensitive(username);
1705
2048
  if (!user) {
1706
2049
  throw new import_server6.TRPCError({ code: "NOT_FOUND", message: "User not found" });
1707
2050
  }
1708
- const otp = await this.config.prisma.oTP.findFirst({
1709
- where: { userId: user.id, code, expiresAt: { gte: /* @__PURE__ */ new Date() } }
1710
- });
2051
+ const otp = await this.config.database.otp.findValidByUserAndCode(user.id, code);
1711
2052
  if (!otp) {
1712
2053
  throw new import_server6.TRPCError({ code: "FORBIDDEN", message: "Invalid or expired OTP" });
1713
2054
  }
1714
- await this.config.prisma.oTP.delete({
1715
- where: { id: otp.id }
1716
- });
1717
- await this.config.prisma.user.update({
1718
- where: { id: user.id },
1719
- data: { twoFaEnabled: false }
1720
- });
1721
- await this.config.prisma.session.updateMany({
1722
- where: { userId: user.id },
1723
- data: { twoFaSecret: null }
1724
- });
2055
+ await this.config.database.otp.delete(otp.id);
2056
+ await this.config.database.user.update(user.id, { twoFaEnabled: false });
2057
+ await this.config.database.session.clearTwoFaSecrets(user.id);
1725
2058
  return { success: true, message: "2FA has been reset." };
1726
2059
  });
1727
2060
  }
@@ -1730,36 +2063,14 @@ var TwoFaProcedureFactory = class {
1730
2063
  this.checkConfig();
1731
2064
  const { userId, sessionId } = ctx;
1732
2065
  const { pushToken } = input;
1733
- await this.config.prisma.session.updateMany({
1734
- where: {
1735
- userId,
1736
- id: { not: sessionId },
1737
- revokedAt: null,
1738
- device: { pushToken }
1739
- },
1740
- data: { revokedAt: /* @__PURE__ */ new Date() }
1741
- });
1742
- const checkDevice = await this.config.prisma.device.findFirst({
1743
- where: {
1744
- pushToken,
1745
- sessions: { some: { id: sessionId } },
1746
- users: { some: { id: userId } }
1747
- },
1748
- select: { id: true }
1749
- });
2066
+ await this.config.database.session.revokeByDevicePushToken(userId, pushToken, sessionId);
2067
+ const checkDevice = await this.config.database.device.findByTokenSessionAndUser(
2068
+ pushToken,
2069
+ sessionId,
2070
+ userId
2071
+ );
1750
2072
  if (!checkDevice) {
1751
- await this.config.prisma.device.upsert({
1752
- where: { pushToken },
1753
- create: {
1754
- pushToken,
1755
- sessions: { connect: { id: sessionId } },
1756
- users: { connect: { id: userId } }
1757
- },
1758
- update: {
1759
- sessions: { connect: { id: sessionId } },
1760
- users: { connect: { id: userId } }
1761
- }
1762
- });
2073
+ await this.config.database.device.upsertByPushToken(pushToken, sessionId, userId);
1763
2074
  }
1764
2075
  return { registered: true };
1765
2076
  });
@@ -1769,30 +2080,13 @@ var TwoFaProcedureFactory = class {
1769
2080
  this.checkConfig();
1770
2081
  const { userId } = ctx;
1771
2082
  const { pushToken } = input;
1772
- const device = await this.config.prisma.device.findFirst({
1773
- where: {
1774
- users: { some: { id: userId } },
1775
- pushToken
1776
- },
1777
- select: { id: true }
1778
- });
2083
+ const device = await this.config.database.device.findByUserAndToken(userId, pushToken);
1779
2084
  if (device) {
1780
- await this.config.prisma.session.updateMany({
1781
- where: { userId, deviceId: device.id },
1782
- data: { deviceId: null }
1783
- });
1784
- await this.config.prisma.device.update({
1785
- where: { id: device.id },
1786
- data: { users: { disconnect: { id: userId } } }
1787
- });
1788
- const remainingUsers = await this.config.prisma.device.findUnique({
1789
- where: { id: device.id },
1790
- select: { users: { select: { id: true }, take: 1 } }
1791
- });
1792
- if (!remainingUsers?.users.length) {
1793
- await this.config.prisma.device.delete({
1794
- where: { id: device.id }
1795
- });
2085
+ await this.config.database.session.clearDeviceId(userId, device.id);
2086
+ await this.config.database.device.disconnectUser(device.id, userId);
2087
+ const hasUsers = await this.config.database.device.hasRemainingUsers(device.id);
2088
+ if (!hasUsers) {
2089
+ await this.config.database.device.delete(device.id);
1796
2090
  }
1797
2091
  }
1798
2092
  return { deregistered: true };
@@ -1950,8 +2244,10 @@ function createAuthRouter(config) {
1950
2244
  createAuthRouter,
1951
2245
  createAuthToken,
1952
2246
  createConsoleEmailAdapter,
2247
+ createDrizzleAdapter,
1953
2248
  createNoopEmailAdapter,
1954
2249
  createOAuthVerifier,
2250
+ createPrismaAdapter,
1955
2251
  decodeToken,
1956
2252
  defaultAuthConfig,
1957
2253
  defaultCookieSettings,