@factiii/auth 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,8 +5,10 @@ var signupSchema = z.object({
5
5
  username: z.string().min(1, { message: "Username is required" }).max(30, { message: "Username must be 30 characters or less" }).regex(usernameValidationRegex, {
6
6
  message: "Username can only contain letters, numbers, and underscores"
7
7
  }),
8
- email: z.string().email({ message: "Invalid email address" }),
9
- password: z.string().min(6, { message: "Password must contain at least 6 characters" })
8
+ email: z.string().max(254, { message: "Email must be 254 characters or less" }).email({ message: "Invalid email address" }),
9
+ password: z.string().min(6, { message: "Password must contain at least 6 characters" }).max(72, { message: "Password must be 72 characters or less" }).refine((val) => val.trim().length >= 6, {
10
+ message: "Password cannot be only whitespace"
11
+ })
10
12
  });
11
13
  var loginSchema = z.object({
12
14
  username: z.string().min(1, { message: "Username or email is required" }),
@@ -26,14 +28,14 @@ var requestPasswordResetSchema = z.object({
26
28
  });
27
29
  var resetPasswordSchema = z.object({
28
30
  token: z.string().min(1, { message: "Reset token is required" }),
29
- password: z.string().min(6, { message: "Password must contain at least 6 characters" })
31
+ password: z.string().min(6, { message: "Password must contain at least 6 characters" }).max(72, { message: "Password must be 72 characters or less" })
30
32
  });
31
33
  var checkPasswordResetSchema = z.object({
32
34
  token: z.string().min(1, { message: "Reset token is required" })
33
35
  });
34
36
  var changePasswordSchema = z.object({
35
37
  currentPassword: z.string().min(1, { message: "Current password is required" }),
36
- newPassword: z.string().min(6, { message: "New password must contain at least 6 characters" })
38
+ newPassword: z.string().min(6, { message: "New password must contain at least 6 characters" }).max(72, { message: "Password must be 72 characters or less" })
37
39
  });
38
40
  var twoFaVerifySchema = z.object({
39
41
  code: z.string().min(6, { message: "Verification code is required" }),
@@ -6,7 +6,7 @@ import { z, AnyZodObject } from 'zod';
6
6
  declare const signupSchema: z.ZodObject<{
7
7
  username: z.ZodString;
8
8
  email: z.ZodString;
9
- password: z.ZodString;
9
+ password: z.ZodEffects<z.ZodString, string, string>;
10
10
  }, "strip", z.ZodTypeAny, {
11
11
  email: string;
12
12
  username: string;
@@ -6,7 +6,7 @@ import { z, AnyZodObject } from 'zod';
6
6
  declare const signupSchema: z.ZodObject<{
7
7
  username: z.ZodString;
8
8
  email: z.ZodString;
9
- password: z.ZodString;
9
+ password: z.ZodEffects<z.ZodString, string, string>;
10
10
  }, "strip", z.ZodTypeAny, {
11
11
  email: string;
12
12
  username: string;
package/dist/index.d.mts CHANGED
@@ -6,8 +6,8 @@ import { PrismaClient } from '@prisma/client';
6
6
  import * as _trpc_server from '@trpc/server';
7
7
  import * as zod from 'zod';
8
8
  import { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone';
9
- import { S as SchemaExtensions, A as AuthHooks } from './hooks-CK4f4PHo.mjs';
10
- export { C as ChangePasswordInput, L as LoginInput, a as LogoutInput, O as OAuthLoginInput, R as ResetPasswordInput, b as SignupInput, T as TwoFaVerifyInput, V as VerifyEmailInput, c as biometricVerifySchema, d as changePasswordSchema, e as endAllSessionsSchema, l as loginSchema, f as logoutSchema, o as oAuthLoginSchema, g as otpLoginRequestSchema, h as otpLoginVerifySchema, r as requestPasswordResetSchema, i as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, j as twoFaSetupSchema, k as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-CK4f4PHo.mjs';
9
+ import { S as SchemaExtensions, A as AuthHooks } from './hooks-B41uikq7.mjs';
10
+ export { C as ChangePasswordInput, L as LoginInput, a as LogoutInput, O as OAuthLoginInput, R as ResetPasswordInput, b as SignupInput, T as TwoFaVerifyInput, V as VerifyEmailInput, c as biometricVerifySchema, d as changePasswordSchema, e as endAllSessionsSchema, l as loginSchema, f as logoutSchema, o as oAuthLoginSchema, g as otpLoginRequestSchema, h as otpLoginVerifySchema, r as requestPasswordResetSchema, i as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, j as twoFaSetupSchema, k as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-B41uikq7.mjs';
11
11
  import { SignOptions } from 'jsonwebtoken';
12
12
 
13
13
  //# sourceMappingURL=TRPCError.d.ts.map
@@ -232,6 +232,8 @@ interface TokenSettings {
232
232
  interface AuthFeatures {
233
233
  /** Enable two-factor authentication */
234
234
  twoFa?: boolean;
235
+ /** Require mobile device to enable 2FA (default: true). Set to false for testing. */
236
+ twoFaRequiresDevice?: boolean;
235
237
  /** OAuth providers configuration */
236
238
  oauth?: {
237
239
  google?: boolean;
@@ -657,19 +659,19 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
657
659
  input: inferParser<[TExtensions["signup"]] extends [zod.AnyZodObject] ? zod.ZodObject<{
658
660
  username: zod.ZodString;
659
661
  email: zod.ZodString;
660
- password: zod.ZodString;
662
+ password: zod.ZodEffects<zod.ZodString, string, string>;
661
663
  } & TExtensions["signup"]["shape"], "strip", zod.ZodTypeAny, zod.objectUtil.addQuestionMarks<zod.baseObjectOutputType<{
662
664
  username: zod.ZodString;
663
665
  email: zod.ZodString;
664
- password: zod.ZodString;
666
+ password: zod.ZodEffects<zod.ZodString, string, string>;
665
667
  } & TExtensions["signup"]["shape"]>, any> extends infer T_5 ? { [k_2 in keyof T_5]: T_5[k_2]; } : never, zod.baseObjectInputType<{
666
668
  username: zod.ZodString;
667
669
  email: zod.ZodString;
668
- password: zod.ZodString;
670
+ password: zod.ZodEffects<zod.ZodString, string, string>;
669
671
  } & TExtensions["signup"]["shape"]> extends infer T_6 ? { [k_3 in keyof T_6]: T_6[k_3]; } : never> : zod.ZodObject<{
670
672
  username: zod.ZodString;
671
673
  email: zod.ZodString;
672
- password: zod.ZodString;
674
+ password: zod.ZodEffects<zod.ZodString, string, string>;
673
675
  }, "strip", zod.ZodTypeAny, {
674
676
  email: string;
675
677
  username: string;
@@ -681,19 +683,19 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
681
683
  }>>["in"] extends infer T_7 ? T_7 extends inferParser<[TExtensions["signup"]] extends [zod.AnyZodObject] ? zod.ZodObject<{
682
684
  username: zod.ZodString;
683
685
  email: zod.ZodString;
684
- password: zod.ZodString;
686
+ password: zod.ZodEffects<zod.ZodString, string, string>;
685
687
  } & TExtensions["signup"]["shape"], "strip", zod.ZodTypeAny, zod.objectUtil.addQuestionMarks<zod.baseObjectOutputType<{
686
688
  username: zod.ZodString;
687
689
  email: zod.ZodString;
688
- password: zod.ZodString;
690
+ password: zod.ZodEffects<zod.ZodString, string, string>;
689
691
  } & TExtensions["signup"]["shape"]>, any> extends infer T_8 ? { [k_2 in keyof T_8]: T_8[k_2]; } : never, zod.baseObjectInputType<{
690
692
  username: zod.ZodString;
691
693
  email: zod.ZodString;
692
- password: zod.ZodString;
694
+ password: zod.ZodEffects<zod.ZodString, string, string>;
693
695
  } & TExtensions["signup"]["shape"]> extends infer T_9 ? { [k_3 in keyof T_9]: T_9[k_3]; } : never> : zod.ZodObject<{
694
696
  username: zod.ZodString;
695
697
  email: zod.ZodString;
696
- password: zod.ZodString;
698
+ password: zod.ZodEffects<zod.ZodString, string, string>;
697
699
  }, "strip", zod.ZodTypeAny, {
698
700
  email: string;
699
701
  username: string;
package/dist/index.d.ts CHANGED
@@ -6,8 +6,8 @@ import { PrismaClient } from '@prisma/client';
6
6
  import * as _trpc_server from '@trpc/server';
7
7
  import * as zod from 'zod';
8
8
  import { CreateHTTPContextOptions } from '@trpc/server/adapters/standalone';
9
- import { S as SchemaExtensions, A as AuthHooks } from './hooks-CK4f4PHo.js';
10
- export { C as ChangePasswordInput, L as LoginInput, a as LogoutInput, O as OAuthLoginInput, R as ResetPasswordInput, b as SignupInput, T as TwoFaVerifyInput, V as VerifyEmailInput, c as biometricVerifySchema, d as changePasswordSchema, e as endAllSessionsSchema, l as loginSchema, f as logoutSchema, o as oAuthLoginSchema, g as otpLoginRequestSchema, h as otpLoginVerifySchema, r as requestPasswordResetSchema, i as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, j as twoFaSetupSchema, k as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-CK4f4PHo.js';
9
+ import { S as SchemaExtensions, A as AuthHooks } from './hooks-B41uikq7.js';
10
+ export { C as ChangePasswordInput, L as LoginInput, a as LogoutInput, O as OAuthLoginInput, R as ResetPasswordInput, b as SignupInput, T as TwoFaVerifyInput, V as VerifyEmailInput, c as biometricVerifySchema, d as changePasswordSchema, e as endAllSessionsSchema, l as loginSchema, f as logoutSchema, o as oAuthLoginSchema, g as otpLoginRequestSchema, h as otpLoginVerifySchema, r as requestPasswordResetSchema, i as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, j as twoFaSetupSchema, k as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-B41uikq7.js';
11
11
  import { SignOptions } from 'jsonwebtoken';
12
12
 
13
13
  //# sourceMappingURL=TRPCError.d.ts.map
@@ -232,6 +232,8 @@ interface TokenSettings {
232
232
  interface AuthFeatures {
233
233
  /** Enable two-factor authentication */
234
234
  twoFa?: boolean;
235
+ /** Require mobile device to enable 2FA (default: true). Set to false for testing. */
236
+ twoFaRequiresDevice?: boolean;
235
237
  /** OAuth providers configuration */
236
238
  oauth?: {
237
239
  google?: boolean;
@@ -657,19 +659,19 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
657
659
  input: inferParser<[TExtensions["signup"]] extends [zod.AnyZodObject] ? zod.ZodObject<{
658
660
  username: zod.ZodString;
659
661
  email: zod.ZodString;
660
- password: zod.ZodString;
662
+ password: zod.ZodEffects<zod.ZodString, string, string>;
661
663
  } & TExtensions["signup"]["shape"], "strip", zod.ZodTypeAny, zod.objectUtil.addQuestionMarks<zod.baseObjectOutputType<{
662
664
  username: zod.ZodString;
663
665
  email: zod.ZodString;
664
- password: zod.ZodString;
666
+ password: zod.ZodEffects<zod.ZodString, string, string>;
665
667
  } & TExtensions["signup"]["shape"]>, any> extends infer T_5 ? { [k_2 in keyof T_5]: T_5[k_2]; } : never, zod.baseObjectInputType<{
666
668
  username: zod.ZodString;
667
669
  email: zod.ZodString;
668
- password: zod.ZodString;
670
+ password: zod.ZodEffects<zod.ZodString, string, string>;
669
671
  } & TExtensions["signup"]["shape"]> extends infer T_6 ? { [k_3 in keyof T_6]: T_6[k_3]; } : never> : zod.ZodObject<{
670
672
  username: zod.ZodString;
671
673
  email: zod.ZodString;
672
- password: zod.ZodString;
674
+ password: zod.ZodEffects<zod.ZodString, string, string>;
673
675
  }, "strip", zod.ZodTypeAny, {
674
676
  email: string;
675
677
  username: string;
@@ -681,19 +683,19 @@ declare function createAuthRouter<TExtensions extends SchemaExtensions = {}>(con
681
683
  }>>["in"] extends infer T_7 ? T_7 extends inferParser<[TExtensions["signup"]] extends [zod.AnyZodObject] ? zod.ZodObject<{
682
684
  username: zod.ZodString;
683
685
  email: zod.ZodString;
684
- password: zod.ZodString;
686
+ password: zod.ZodEffects<zod.ZodString, string, string>;
685
687
  } & TExtensions["signup"]["shape"], "strip", zod.ZodTypeAny, zod.objectUtil.addQuestionMarks<zod.baseObjectOutputType<{
686
688
  username: zod.ZodString;
687
689
  email: zod.ZodString;
688
- password: zod.ZodString;
690
+ password: zod.ZodEffects<zod.ZodString, string, string>;
689
691
  } & TExtensions["signup"]["shape"]>, any> extends infer T_8 ? { [k_2 in keyof T_8]: T_8[k_2]; } : never, zod.baseObjectInputType<{
690
692
  username: zod.ZodString;
691
693
  email: zod.ZodString;
692
- password: zod.ZodString;
694
+ password: zod.ZodEffects<zod.ZodString, string, string>;
693
695
  } & TExtensions["signup"]["shape"]> extends infer T_9 ? { [k_3 in keyof T_9]: T_9[k_3]; } : never> : zod.ZodObject<{
694
696
  username: zod.ZodString;
695
697
  email: zod.ZodString;
696
- password: zod.ZodString;
698
+ password: zod.ZodEffects<zod.ZodString, string, string>;
697
699
  }, "strip", zod.ZodTypeAny, {
698
700
  email: string;
699
701
  username: string;
package/dist/index.js CHANGED
@@ -86,22 +86,20 @@ var import_server = require("@trpc/server");
86
86
  function createNoopEmailAdapter() {
87
87
  return {
88
88
  async sendVerificationEmail(email, code) {
89
- console.log(
89
+ console.debug(
90
90
  `[NoopEmailAdapter] Would send verification email to ${email} with code ${code}`
91
91
  );
92
92
  },
93
93
  async sendPasswordResetEmail(email, token) {
94
- console.log(
94
+ console.debug(
95
95
  `[NoopEmailAdapter] Would send password reset email to ${email} with token ${token}`
96
96
  );
97
97
  },
98
98
  async sendOTPEmail(email, otp) {
99
- console.log(
100
- `[NoopEmailAdapter] Would send OTP email to ${email} with code ${otp}`
101
- );
99
+ console.debug(`[NoopEmailAdapter] Would send OTP email to ${email} with code ${otp}`);
102
100
  },
103
101
  async sendLoginNotification(email, browserName, ip) {
104
- console.log(
102
+ console.debug(
105
103
  `[NoopEmailAdapter] Would send login notification to ${email} from ${browserName} (${ip})`
106
104
  );
107
105
  }
@@ -160,6 +158,7 @@ var defaultStorageKeys = {
160
158
  };
161
159
  var defaultFeatures = {
162
160
  twoFa: true,
161
+ twoFaRequiresDevice: true,
163
162
  oauth: { google: true, apple: true },
164
163
  biometric: false,
165
164
  emailVerification: true,
@@ -307,9 +306,7 @@ function decodeToken(token) {
307
306
  }
308
307
  }
309
308
  function isJwtError(error) {
310
- return error instanceof Error && ["TokenExpiredError", "JsonWebTokenError", "NotBeforeError"].includes(
311
- error.name
312
- );
309
+ return error instanceof Error && ["TokenExpiredError", "JsonWebTokenError", "NotBeforeError"].includes(error.name);
313
310
  }
314
311
  function isTokenExpiredError(error) {
315
312
  return isJwtError(error) && error.name === "TokenExpiredError";
@@ -363,11 +360,7 @@ ${errorStack}` : null,
363
360
  select: { id: true, userId: true, socketId: true }
364
361
  });
365
362
  if (session) {
366
- await config.hooks.onSessionRevoked(
367
- session.userId,
368
- session.socketId,
369
- description
370
- );
363
+ await config.hooks.onSessionRevoked(session.userId, session.socketId, description);
371
364
  }
372
365
  }
373
366
  } catch {
@@ -436,13 +429,7 @@ ${errorStack}` : null,
436
429
  });
437
430
  }
438
431
  if (session.user.status === "BANNED") {
439
- await revokeSession(
440
- ctx,
441
- session.id,
442
- "Session revoked: User banned",
443
- void 0,
444
- path
445
- );
432
+ await revokeSession(ctx, session.id, "Session revoked: User banned", void 0, path);
446
433
  throw new import_server.TRPCError({
447
434
  message: "Unauthorized",
448
435
  code: "UNAUTHORIZED"
@@ -450,9 +437,7 @@ ${errorStack}` : null,
450
437
  }
451
438
  if (config.features?.biometric && config.hooks?.getBiometricTimeout) {
452
439
  const timeoutMs = await config.hooks.getBiometricTimeout();
453
- if (timeoutMs !== null && !["auth.refresh", "auth.verifyBiometric", "auth.logout"].includes(
454
- path
455
- )) {
440
+ if (timeoutMs !== null && !["auth.refresh", "auth.verifyBiometric", "auth.logout"].includes(path)) {
456
441
  if (!session.user.verifiedHumanAt) {
457
442
  throw new import_server.TRPCError({
458
443
  message: "Biometric verification not completed. Please verify again.",
@@ -460,9 +445,7 @@ ${errorStack}` : null,
460
445
  });
461
446
  }
462
447
  const now = /* @__PURE__ */ new Date();
463
- const verificationExpiry = new Date(
464
- session.user.verifiedHumanAt.getTime() + timeoutMs
465
- );
448
+ const verificationExpiry = new Date(session.user.verifiedHumanAt.getTime() + timeoutMs);
466
449
  if (now > verificationExpiry) {
467
450
  throw new import_server.TRPCError({
468
451
  message: "Biometric verification expired. Please verify again.",
@@ -534,13 +517,7 @@ ${errorStack}` : null,
534
517
  });
535
518
  }
536
519
  if (err instanceof import_server.TRPCError && err.code === "UNAUTHORIZED") {
537
- await revokeSession(
538
- ctx,
539
- null,
540
- "Session revoked: Unauthorized",
541
- errorStack,
542
- path
543
- );
520
+ await revokeSession(ctx, null, "Session revoked: Unauthorized", errorStack, path);
544
521
  throw new import_server.TRPCError({
545
522
  message: "Unauthorized",
546
523
  code: "UNAUTHORIZED"
@@ -552,13 +529,7 @@ ${errorStack}` : null,
552
529
  if (!meta?.authRequired) {
553
530
  return next({ ctx: { ...ctx, userId: 0 } });
554
531
  }
555
- await revokeSession(
556
- ctx,
557
- null,
558
- "Session revoked: No token sent",
559
- void 0,
560
- path
561
- );
532
+ await revokeSession(ctx, null, "Session revoked: No token sent", void 0, path);
562
533
  throw new import_server.TRPCError({ message: "Unauthorized", code: "UNAUTHORIZED" });
563
534
  }
564
535
  });
@@ -579,25 +550,19 @@ function detectBrowser(userAgent) {
579
550
  return "iOS Browser (Chrome)";
580
551
  if (/iphone|ipad|ipod/i.test(userAgent) && /fxios/i.test(userAgent))
581
552
  return "iOS Browser (Firefox)";
582
- if (/iphone|ipad|ipod/i.test(userAgent) && /edg\//i.test(userAgent))
583
- return "iOS Browser (Edge)";
553
+ if (/iphone|ipad|ipod/i.test(userAgent) && /edg\//i.test(userAgent)) return "iOS Browser (Edge)";
584
554
  if (/android/i.test(userAgent) && !/chrome|firefox|samsungbrowser|opr\/|edg\//i.test(userAgent)) {
585
555
  return "Android App";
586
556
  }
587
- if (/android/i.test(userAgent) && /chrome/i.test(userAgent))
588
- return "Android Browser (Chrome)";
589
- if (/android/i.test(userAgent) && /firefox/i.test(userAgent))
590
- return "Android Browser (Firefox)";
557
+ if (/android/i.test(userAgent) && /chrome/i.test(userAgent)) return "Android Browser (Chrome)";
558
+ if (/android/i.test(userAgent) && /firefox/i.test(userAgent)) return "Android Browser (Firefox)";
591
559
  if (/android/i.test(userAgent) && /samsungbrowser/i.test(userAgent))
592
560
  return "Android Browser (Samsung)";
593
- if (/android/i.test(userAgent) && /opr\//i.test(userAgent))
594
- return "Android Browser (Opera)";
595
- if (/android/i.test(userAgent) && /edg\//i.test(userAgent))
596
- return "Android Browser (Edge)";
561
+ if (/android/i.test(userAgent) && /opr\//i.test(userAgent)) return "Android Browser (Opera)";
562
+ if (/android/i.test(userAgent) && /edg\//i.test(userAgent)) return "Android Browser (Edge)";
597
563
  if (/chrome|chromium/i.test(userAgent)) return "Chrome";
598
564
  if (/firefox/i.test(userAgent)) return "Firefox";
599
- if (/safari/i.test(userAgent) && !/chrome|chromium|crios/i.test(userAgent))
600
- return "Safari";
565
+ if (/safari/i.test(userAgent) && !/chrome|chromium|crios/i.test(userAgent)) return "Safari";
601
566
  if (/opr\//i.test(userAgent)) return "Opera";
602
567
  if (/edg\//i.test(userAgent)) return "Edge";
603
568
  return "Unknown";
@@ -631,16 +596,10 @@ function createOAuthVerifier(keys) {
631
596
  return async function verifyOAuthToken(provider, token, extra) {
632
597
  if (provider === "GOOGLE") {
633
598
  if (!keys.google?.clientId) {
634
- throw new OAuthVerificationError(
635
- "Google OAuth configuration missing",
636
- 500
637
- );
599
+ throw new OAuthVerificationError("Google OAuth configuration missing", 500);
638
600
  }
639
601
  if (!googleClient) {
640
- throw new OAuthVerificationError(
641
- "Google OAuth client not initialized",
642
- 500
643
- );
602
+ throw new OAuthVerificationError("Google OAuth client not initialized", 500);
644
603
  }
645
604
  const audience = [keys.google.clientId];
646
605
  if (keys.google.iosClientId) {
@@ -661,10 +620,7 @@ function createOAuthVerifier(keys) {
661
620
  }
662
621
  if (provider === "APPLE") {
663
622
  if (!keys.apple?.clientId) {
664
- throw new OAuthVerificationError(
665
- "Apple OAuth configuration missing",
666
- 500
667
- );
623
+ throw new OAuthVerificationError("Apple OAuth configuration missing", 500);
668
624
  }
669
625
  const audience = [keys.apple.clientId];
670
626
  if (keys.apple.iosClientId) {
@@ -744,8 +700,10 @@ var signupSchema = import_zod.z.object({
744
700
  username: import_zod.z.string().min(1, { message: "Username is required" }).max(30, { message: "Username must be 30 characters or less" }).regex(usernameValidationRegex, {
745
701
  message: "Username can only contain letters, numbers, and underscores"
746
702
  }),
747
- email: import_zod.z.string().email({ message: "Invalid email address" }),
748
- password: import_zod.z.string().min(6, { message: "Password must contain at least 6 characters" })
703
+ email: import_zod.z.string().max(254, { message: "Email must be 254 characters or less" }).email({ message: "Invalid email address" }),
704
+ password: import_zod.z.string().min(6, { message: "Password must contain at least 6 characters" }).max(72, { message: "Password must be 72 characters or less" }).refine((val) => val.trim().length >= 6, {
705
+ message: "Password cannot be only whitespace"
706
+ })
749
707
  });
750
708
  var loginSchema = import_zod.z.object({
751
709
  username: import_zod.z.string().min(1, { message: "Username or email is required" }),
@@ -765,14 +723,14 @@ var requestPasswordResetSchema = import_zod.z.object({
765
723
  });
766
724
  var resetPasswordSchema = import_zod.z.object({
767
725
  token: import_zod.z.string().min(1, { message: "Reset token is required" }),
768
- password: import_zod.z.string().min(6, { message: "Password must contain at least 6 characters" })
726
+ password: import_zod.z.string().min(6, { message: "Password must contain at least 6 characters" }).max(72, { message: "Password must be 72 characters or less" })
769
727
  });
770
728
  var checkPasswordResetSchema = import_zod.z.object({
771
729
  token: import_zod.z.string().min(1, { message: "Reset token is required" })
772
730
  });
773
731
  var changePasswordSchema = import_zod.z.object({
774
732
  currentPassword: import_zod.z.string().min(1, { message: "Current password is required" }),
775
- newPassword: import_zod.z.string().min(6, { message: "New password must contain at least 6 characters" })
733
+ newPassword: import_zod.z.string().min(6, { message: "New password must contain at least 6 characters" }).max(72, { message: "Password must be 72 characters or less" })
776
734
  });
777
735
  var twoFaVerifySchema = import_zod.z.object({
778
736
  code: import_zod.z.string().min(6, { message: "Verification code is required" }),
@@ -1162,7 +1120,11 @@ var BaseProcedureFactory = class {
1162
1120
  });
1163
1121
  for (const session of sessionsToRevoke) {
1164
1122
  if (this.config.hooks?.onSessionRevoked) {
1165
- await this.config.hooks.onSessionRevoked(session.id, session.socketId, "End all sessions");
1123
+ await this.config.hooks.onSessionRevoked(
1124
+ session.id,
1125
+ session.socketId,
1126
+ "End all sessions"
1127
+ );
1166
1128
  }
1167
1129
  }
1168
1130
  if (!skipCurrentSession) {
@@ -1491,14 +1453,14 @@ var OAuthLoginProcedureFactory = class {
1491
1453
  }
1492
1454
  const { email, oauthId } = await this.verifyOAuthToken(provider, idToken, appleUser);
1493
1455
  if (!email) {
1494
- throw new import_server5.TRPCError({ code: "BAD_REQUEST", message: "Email not provided by OAuth provider" });
1456
+ throw new import_server5.TRPCError({
1457
+ code: "BAD_REQUEST",
1458
+ message: "Email not provided by OAuth provider"
1459
+ });
1495
1460
  }
1496
1461
  let user = await this.config.prisma.user.findFirst({
1497
1462
  where: {
1498
- OR: [
1499
- { email: { equals: email, mode: "insensitive" } },
1500
- { oauthId: { equals: oauthId } }
1501
- ]
1463
+ OR: [{ email: { equals: email, mode: "insensitive" } }, { oauthId: { equals: oauthId } }]
1502
1464
  },
1503
1465
  select: {
1504
1466
  id: true,
@@ -1648,15 +1610,17 @@ var TwoFaProcedureFactory = class {
1648
1610
  if (user.twoFaEnabled) {
1649
1611
  throw new import_server6.TRPCError({ code: "BAD_REQUEST", message: "2FA already enabled." });
1650
1612
  }
1651
- const checkSession = await this.config.prisma.session.findFirst({
1652
- where: { userId, id: sessionId },
1653
- select: { deviceId: true }
1654
- });
1655
- if (!checkSession?.deviceId) {
1656
- throw new import_server6.TRPCError({
1657
- code: "BAD_REQUEST",
1658
- message: "You must be logged in on mobile to enable 2FA."
1613
+ if (this.config.features.twoFaRequiresDevice !== false) {
1614
+ const checkSession = await this.config.prisma.session.findFirst({
1615
+ where: { userId, id: sessionId },
1616
+ select: { deviceId: true }
1659
1617
  });
1618
+ if (!checkSession?.deviceId) {
1619
+ throw new import_server6.TRPCError({
1620
+ code: "BAD_REQUEST",
1621
+ message: "You must be logged in on mobile to enable 2FA."
1622
+ });
1623
+ }
1660
1624
  }
1661
1625
  await this.config.prisma.session.updateMany({
1662
1626
  where: { userId, revokedAt: null, NOT: { id: sessionId } },
@@ -1975,10 +1939,7 @@ function getClientIp(req) {
1975
1939
  }
1976
1940
 
1977
1941
  // src/router.ts
1978
- var createContext = ({
1979
- req,
1980
- res
1981
- }) => ({
1942
+ var createContext = ({ req, res }) => ({
1982
1943
  headers: req.headers,
1983
1944
  userId: null,
1984
1945
  sessionId: null,
@@ -1991,9 +1952,7 @@ var AuthRouterFactory = class {
1991
1952
  constructor(userConfig) {
1992
1953
  this.userConfig = userConfig;
1993
1954
  this.config = createAuthConfig(this.userConfig);
1994
- this.schemas = createSchemas(
1995
- this.config.schemaExtensions
1996
- );
1955
+ this.schemas = createSchemas(this.config.schemaExtensions);
1997
1956
  this.t = createTrpcBuilder(this.config);
1998
1957
  this.authGuard = createAuthGuard(this.config, this.t);
1999
1958
  this.procedure = createBaseProcedure(this.t, this.authGuard);
@@ -2005,10 +1964,7 @@ var AuthRouterFactory = class {
2005
1964
  this.procedure,
2006
1965
  this.authProcedure
2007
1966
  );
2008
- const biometricRoutes = new BiometricProcedureFactory(
2009
- this.config,
2010
- this.authProcedure
2011
- );
1967
+ const biometricRoutes = new BiometricProcedureFactory(this.config, this.authProcedure);
2012
1968
  const emailVerificationRoutes = new EmailVerificationProcedureFactory(
2013
1969
  this.config,
2014
1970
  this.authProcedure
@@ -2017,11 +1973,7 @@ var AuthRouterFactory = class {
2017
1973
  this.config,
2018
1974
  this.procedure
2019
1975
  );
2020
- const twoFaRoutes = new TwoFaProcedureFactory(
2021
- this.config,
2022
- this.procedure,
2023
- this.authProcedure
2024
- );
1976
+ const twoFaRoutes = new TwoFaProcedureFactory(this.config, this.procedure, this.authProcedure);
2025
1977
  return this.t.router({
2026
1978
  ...baseRoutes.createBaseProcedures(this.schemas),
2027
1979
  ...oAuthLoginRoutes.createOAuthLoginProcedures(this.schemas),
package/dist/index.mjs CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  twoFaSetupSchema,
22
22
  twoFaVerifySchema,
23
23
  verifyEmailSchema
24
- } from "./chunk-2DOUP275.mjs";
24
+ } from "./chunk-PYVDWODF.mjs";
25
25
 
26
26
  // src/middleware/authGuard.ts
27
27
  import { TRPCError } from "@trpc/server";
@@ -30,22 +30,20 @@ import { TRPCError } from "@trpc/server";
30
30
  function createNoopEmailAdapter() {
31
31
  return {
32
32
  async sendVerificationEmail(email, code) {
33
- console.log(
33
+ console.debug(
34
34
  `[NoopEmailAdapter] Would send verification email to ${email} with code ${code}`
35
35
  );
36
36
  },
37
37
  async sendPasswordResetEmail(email, token) {
38
- console.log(
38
+ console.debug(
39
39
  `[NoopEmailAdapter] Would send password reset email to ${email} with token ${token}`
40
40
  );
41
41
  },
42
42
  async sendOTPEmail(email, otp) {
43
- console.log(
44
- `[NoopEmailAdapter] Would send OTP email to ${email} with code ${otp}`
45
- );
43
+ console.debug(`[NoopEmailAdapter] Would send OTP email to ${email} with code ${otp}`);
46
44
  },
47
45
  async sendLoginNotification(email, browserName, ip) {
48
- console.log(
46
+ console.debug(
49
47
  `[NoopEmailAdapter] Would send login notification to ${email} from ${browserName} (${ip})`
50
48
  );
51
49
  }
@@ -104,6 +102,7 @@ var defaultStorageKeys = {
104
102
  };
105
103
  var defaultFeatures = {
106
104
  twoFa: true,
105
+ twoFaRequiresDevice: true,
107
106
  oauth: { google: true, apple: true },
108
107
  biometric: false,
109
108
  emailVerification: true,
@@ -251,9 +250,7 @@ function decodeToken(token) {
251
250
  }
252
251
  }
253
252
  function isJwtError(error) {
254
- return error instanceof Error && ["TokenExpiredError", "JsonWebTokenError", "NotBeforeError"].includes(
255
- error.name
256
- );
253
+ return error instanceof Error && ["TokenExpiredError", "JsonWebTokenError", "NotBeforeError"].includes(error.name);
257
254
  }
258
255
  function isTokenExpiredError(error) {
259
256
  return isJwtError(error) && error.name === "TokenExpiredError";
@@ -307,11 +304,7 @@ ${errorStack}` : null,
307
304
  select: { id: true, userId: true, socketId: true }
308
305
  });
309
306
  if (session) {
310
- await config.hooks.onSessionRevoked(
311
- session.userId,
312
- session.socketId,
313
- description
314
- );
307
+ await config.hooks.onSessionRevoked(session.userId, session.socketId, description);
315
308
  }
316
309
  }
317
310
  } catch {
@@ -380,13 +373,7 @@ ${errorStack}` : null,
380
373
  });
381
374
  }
382
375
  if (session.user.status === "BANNED") {
383
- await revokeSession(
384
- ctx,
385
- session.id,
386
- "Session revoked: User banned",
387
- void 0,
388
- path
389
- );
376
+ await revokeSession(ctx, session.id, "Session revoked: User banned", void 0, path);
390
377
  throw new TRPCError({
391
378
  message: "Unauthorized",
392
379
  code: "UNAUTHORIZED"
@@ -394,9 +381,7 @@ ${errorStack}` : null,
394
381
  }
395
382
  if (config.features?.biometric && config.hooks?.getBiometricTimeout) {
396
383
  const timeoutMs = await config.hooks.getBiometricTimeout();
397
- if (timeoutMs !== null && !["auth.refresh", "auth.verifyBiometric", "auth.logout"].includes(
398
- path
399
- )) {
384
+ if (timeoutMs !== null && !["auth.refresh", "auth.verifyBiometric", "auth.logout"].includes(path)) {
400
385
  if (!session.user.verifiedHumanAt) {
401
386
  throw new TRPCError({
402
387
  message: "Biometric verification not completed. Please verify again.",
@@ -404,9 +389,7 @@ ${errorStack}` : null,
404
389
  });
405
390
  }
406
391
  const now = /* @__PURE__ */ new Date();
407
- const verificationExpiry = new Date(
408
- session.user.verifiedHumanAt.getTime() + timeoutMs
409
- );
392
+ const verificationExpiry = new Date(session.user.verifiedHumanAt.getTime() + timeoutMs);
410
393
  if (now > verificationExpiry) {
411
394
  throw new TRPCError({
412
395
  message: "Biometric verification expired. Please verify again.",
@@ -478,13 +461,7 @@ ${errorStack}` : null,
478
461
  });
479
462
  }
480
463
  if (err instanceof TRPCError && err.code === "UNAUTHORIZED") {
481
- await revokeSession(
482
- ctx,
483
- null,
484
- "Session revoked: Unauthorized",
485
- errorStack,
486
- path
487
- );
464
+ await revokeSession(ctx, null, "Session revoked: Unauthorized", errorStack, path);
488
465
  throw new TRPCError({
489
466
  message: "Unauthorized",
490
467
  code: "UNAUTHORIZED"
@@ -496,13 +473,7 @@ ${errorStack}` : null,
496
473
  if (!meta?.authRequired) {
497
474
  return next({ ctx: { ...ctx, userId: 0 } });
498
475
  }
499
- await revokeSession(
500
- ctx,
501
- null,
502
- "Session revoked: No token sent",
503
- void 0,
504
- path
505
- );
476
+ await revokeSession(ctx, null, "Session revoked: No token sent", void 0, path);
506
477
  throw new TRPCError({ message: "Unauthorized", code: "UNAUTHORIZED" });
507
478
  }
508
479
  });
@@ -523,25 +494,19 @@ function detectBrowser(userAgent) {
523
494
  return "iOS Browser (Chrome)";
524
495
  if (/iphone|ipad|ipod/i.test(userAgent) && /fxios/i.test(userAgent))
525
496
  return "iOS Browser (Firefox)";
526
- if (/iphone|ipad|ipod/i.test(userAgent) && /edg\//i.test(userAgent))
527
- return "iOS Browser (Edge)";
497
+ if (/iphone|ipad|ipod/i.test(userAgent) && /edg\//i.test(userAgent)) return "iOS Browser (Edge)";
528
498
  if (/android/i.test(userAgent) && !/chrome|firefox|samsungbrowser|opr\/|edg\//i.test(userAgent)) {
529
499
  return "Android App";
530
500
  }
531
- if (/android/i.test(userAgent) && /chrome/i.test(userAgent))
532
- return "Android Browser (Chrome)";
533
- if (/android/i.test(userAgent) && /firefox/i.test(userAgent))
534
- return "Android Browser (Firefox)";
501
+ if (/android/i.test(userAgent) && /chrome/i.test(userAgent)) return "Android Browser (Chrome)";
502
+ if (/android/i.test(userAgent) && /firefox/i.test(userAgent)) return "Android Browser (Firefox)";
535
503
  if (/android/i.test(userAgent) && /samsungbrowser/i.test(userAgent))
536
504
  return "Android Browser (Samsung)";
537
- if (/android/i.test(userAgent) && /opr\//i.test(userAgent))
538
- return "Android Browser (Opera)";
539
- if (/android/i.test(userAgent) && /edg\//i.test(userAgent))
540
- return "Android Browser (Edge)";
505
+ if (/android/i.test(userAgent) && /opr\//i.test(userAgent)) return "Android Browser (Opera)";
506
+ if (/android/i.test(userAgent) && /edg\//i.test(userAgent)) return "Android Browser (Edge)";
541
507
  if (/chrome|chromium/i.test(userAgent)) return "Chrome";
542
508
  if (/firefox/i.test(userAgent)) return "Firefox";
543
- if (/safari/i.test(userAgent) && !/chrome|chromium|crios/i.test(userAgent))
544
- return "Safari";
509
+ if (/safari/i.test(userAgent) && !/chrome|chromium|crios/i.test(userAgent)) return "Safari";
545
510
  if (/opr\//i.test(userAgent)) return "Opera";
546
511
  if (/edg\//i.test(userAgent)) return "Edge";
547
512
  return "Unknown";
@@ -575,16 +540,10 @@ function createOAuthVerifier(keys) {
575
540
  return async function verifyOAuthToken(provider, token, extra) {
576
541
  if (provider === "GOOGLE") {
577
542
  if (!keys.google?.clientId) {
578
- throw new OAuthVerificationError(
579
- "Google OAuth configuration missing",
580
- 500
581
- );
543
+ throw new OAuthVerificationError("Google OAuth configuration missing", 500);
582
544
  }
583
545
  if (!googleClient) {
584
- throw new OAuthVerificationError(
585
- "Google OAuth client not initialized",
586
- 500
587
- );
546
+ throw new OAuthVerificationError("Google OAuth client not initialized", 500);
588
547
  }
589
548
  const audience = [keys.google.clientId];
590
549
  if (keys.google.iosClientId) {
@@ -605,10 +564,7 @@ function createOAuthVerifier(keys) {
605
564
  }
606
565
  if (provider === "APPLE") {
607
566
  if (!keys.apple?.clientId) {
608
- throw new OAuthVerificationError(
609
- "Apple OAuth configuration missing",
610
- 500
611
- );
567
+ throw new OAuthVerificationError("Apple OAuth configuration missing", 500);
612
568
  }
613
569
  const audience = [keys.apple.clientId];
614
570
  if (keys.apple.iosClientId) {
@@ -1014,7 +970,11 @@ var BaseProcedureFactory = class {
1014
970
  });
1015
971
  for (const session of sessionsToRevoke) {
1016
972
  if (this.config.hooks?.onSessionRevoked) {
1017
- await this.config.hooks.onSessionRevoked(session.id, session.socketId, "End all sessions");
973
+ await this.config.hooks.onSessionRevoked(
974
+ session.id,
975
+ session.socketId,
976
+ "End all sessions"
977
+ );
1018
978
  }
1019
979
  }
1020
980
  if (!skipCurrentSession) {
@@ -1343,14 +1303,14 @@ var OAuthLoginProcedureFactory = class {
1343
1303
  }
1344
1304
  const { email, oauthId } = await this.verifyOAuthToken(provider, idToken, appleUser);
1345
1305
  if (!email) {
1346
- throw new TRPCError5({ code: "BAD_REQUEST", message: "Email not provided by OAuth provider" });
1306
+ throw new TRPCError5({
1307
+ code: "BAD_REQUEST",
1308
+ message: "Email not provided by OAuth provider"
1309
+ });
1347
1310
  }
1348
1311
  let user = await this.config.prisma.user.findFirst({
1349
1312
  where: {
1350
- OR: [
1351
- { email: { equals: email, mode: "insensitive" } },
1352
- { oauthId: { equals: oauthId } }
1353
- ]
1313
+ OR: [{ email: { equals: email, mode: "insensitive" } }, { oauthId: { equals: oauthId } }]
1354
1314
  },
1355
1315
  select: {
1356
1316
  id: true,
@@ -1500,15 +1460,17 @@ var TwoFaProcedureFactory = class {
1500
1460
  if (user.twoFaEnabled) {
1501
1461
  throw new TRPCError6({ code: "BAD_REQUEST", message: "2FA already enabled." });
1502
1462
  }
1503
- const checkSession = await this.config.prisma.session.findFirst({
1504
- where: { userId, id: sessionId },
1505
- select: { deviceId: true }
1506
- });
1507
- if (!checkSession?.deviceId) {
1508
- throw new TRPCError6({
1509
- code: "BAD_REQUEST",
1510
- message: "You must be logged in on mobile to enable 2FA."
1463
+ if (this.config.features.twoFaRequiresDevice !== false) {
1464
+ const checkSession = await this.config.prisma.session.findFirst({
1465
+ where: { userId, id: sessionId },
1466
+ select: { deviceId: true }
1511
1467
  });
1468
+ if (!checkSession?.deviceId) {
1469
+ throw new TRPCError6({
1470
+ code: "BAD_REQUEST",
1471
+ message: "You must be logged in on mobile to enable 2FA."
1472
+ });
1473
+ }
1512
1474
  }
1513
1475
  await this.config.prisma.session.updateMany({
1514
1476
  where: { userId, revokedAt: null, NOT: { id: sessionId } },
@@ -1827,10 +1789,7 @@ function getClientIp(req) {
1827
1789
  }
1828
1790
 
1829
1791
  // src/router.ts
1830
- var createContext = ({
1831
- req,
1832
- res
1833
- }) => ({
1792
+ var createContext = ({ req, res }) => ({
1834
1793
  headers: req.headers,
1835
1794
  userId: null,
1836
1795
  sessionId: null,
@@ -1843,9 +1802,7 @@ var AuthRouterFactory = class {
1843
1802
  constructor(userConfig) {
1844
1803
  this.userConfig = userConfig;
1845
1804
  this.config = createAuthConfig(this.userConfig);
1846
- this.schemas = createSchemas(
1847
- this.config.schemaExtensions
1848
- );
1805
+ this.schemas = createSchemas(this.config.schemaExtensions);
1849
1806
  this.t = createTrpcBuilder(this.config);
1850
1807
  this.authGuard = createAuthGuard(this.config, this.t);
1851
1808
  this.procedure = createBaseProcedure(this.t, this.authGuard);
@@ -1857,10 +1814,7 @@ var AuthRouterFactory = class {
1857
1814
  this.procedure,
1858
1815
  this.authProcedure
1859
1816
  );
1860
- const biometricRoutes = new BiometricProcedureFactory(
1861
- this.config,
1862
- this.authProcedure
1863
- );
1817
+ const biometricRoutes = new BiometricProcedureFactory(this.config, this.authProcedure);
1864
1818
  const emailVerificationRoutes = new EmailVerificationProcedureFactory(
1865
1819
  this.config,
1866
1820
  this.authProcedure
@@ -1869,11 +1823,7 @@ var AuthRouterFactory = class {
1869
1823
  this.config,
1870
1824
  this.procedure
1871
1825
  );
1872
- const twoFaRoutes = new TwoFaProcedureFactory(
1873
- this.config,
1874
- this.procedure,
1875
- this.authProcedure
1876
- );
1826
+ const twoFaRoutes = new TwoFaProcedureFactory(this.config, this.procedure, this.authProcedure);
1877
1827
  return this.t.router({
1878
1828
  ...baseRoutes.createBaseProcedures(this.schemas),
1879
1829
  ...oAuthLoginRoutes.createOAuthLoginProcedures(this.schemas),
@@ -1,2 +1,2 @@
1
1
  import 'zod';
2
- export { m as AuthSchemas, C as ChangePasswordInput, n as CreatedSchemas, L as LoginInput, p as LoginSchemaInput, a as LogoutInput, O as OAuthLoginInput, q as OAuthSchemaInput, R as ResetPasswordInput, b as SignupInput, u as SignupSchemaInput, T as TwoFaVerifyInput, V as VerifyEmailInput, c as biometricVerifySchema, d as changePasswordSchema, w as checkPasswordResetSchema, x as createSchemas, y as deregisterPushTokenSchema, z as disableTwofaSchema, e as endAllSessionsSchema, B as getTwofaSecretSchema, l as loginSchema, f as logoutSchema, o as oAuthLoginSchema, g as otpLoginRequestSchema, h as otpLoginVerifySchema, D as registerPushTokenSchema, r as requestPasswordResetSchema, E as resendVerificationSchema, i as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, F as twoFaResetVerifySchema, j as twoFaSetupSchema, k as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-CK4f4PHo.mjs';
2
+ export { m as AuthSchemas, C as ChangePasswordInput, n as CreatedSchemas, L as LoginInput, p as LoginSchemaInput, a as LogoutInput, O as OAuthLoginInput, q as OAuthSchemaInput, R as ResetPasswordInput, b as SignupInput, u as SignupSchemaInput, T as TwoFaVerifyInput, V as VerifyEmailInput, c as biometricVerifySchema, d as changePasswordSchema, w as checkPasswordResetSchema, x as createSchemas, y as deregisterPushTokenSchema, z as disableTwofaSchema, e as endAllSessionsSchema, B as getTwofaSecretSchema, l as loginSchema, f as logoutSchema, o as oAuthLoginSchema, g as otpLoginRequestSchema, h as otpLoginVerifySchema, D as registerPushTokenSchema, r as requestPasswordResetSchema, E as resendVerificationSchema, i as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, F as twoFaResetVerifySchema, j as twoFaSetupSchema, k as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-B41uikq7.mjs';
@@ -1,2 +1,2 @@
1
1
  import 'zod';
2
- export { m as AuthSchemas, C as ChangePasswordInput, n as CreatedSchemas, L as LoginInput, p as LoginSchemaInput, a as LogoutInput, O as OAuthLoginInput, q as OAuthSchemaInput, R as ResetPasswordInput, b as SignupInput, u as SignupSchemaInput, T as TwoFaVerifyInput, V as VerifyEmailInput, c as biometricVerifySchema, d as changePasswordSchema, w as checkPasswordResetSchema, x as createSchemas, y as deregisterPushTokenSchema, z as disableTwofaSchema, e as endAllSessionsSchema, B as getTwofaSecretSchema, l as loginSchema, f as logoutSchema, o as oAuthLoginSchema, g as otpLoginRequestSchema, h as otpLoginVerifySchema, D as registerPushTokenSchema, r as requestPasswordResetSchema, E as resendVerificationSchema, i as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, F as twoFaResetVerifySchema, j as twoFaSetupSchema, k as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-CK4f4PHo.js';
2
+ export { m as AuthSchemas, C as ChangePasswordInput, n as CreatedSchemas, L as LoginInput, p as LoginSchemaInput, a as LogoutInput, O as OAuthLoginInput, q as OAuthSchemaInput, R as ResetPasswordInput, b as SignupInput, u as SignupSchemaInput, T as TwoFaVerifyInput, V as VerifyEmailInput, c as biometricVerifySchema, d as changePasswordSchema, w as checkPasswordResetSchema, x as createSchemas, y as deregisterPushTokenSchema, z as disableTwofaSchema, e as endAllSessionsSchema, B as getTwofaSecretSchema, l as loginSchema, f as logoutSchema, o as oAuthLoginSchema, g as otpLoginRequestSchema, h as otpLoginVerifySchema, D as registerPushTokenSchema, r as requestPasswordResetSchema, E as resendVerificationSchema, i as resetPasswordSchema, s as signupSchema, t as twoFaResetSchema, F as twoFaResetVerifySchema, j as twoFaSetupSchema, k as twoFaVerifySchema, v as verifyEmailSchema } from './hooks-B41uikq7.js';
@@ -51,8 +51,10 @@ var signupSchema = import_zod.z.object({
51
51
  username: import_zod.z.string().min(1, { message: "Username is required" }).max(30, { message: "Username must be 30 characters or less" }).regex(usernameValidationRegex, {
52
52
  message: "Username can only contain letters, numbers, and underscores"
53
53
  }),
54
- email: import_zod.z.string().email({ message: "Invalid email address" }),
55
- password: import_zod.z.string().min(6, { message: "Password must contain at least 6 characters" })
54
+ email: import_zod.z.string().max(254, { message: "Email must be 254 characters or less" }).email({ message: "Invalid email address" }),
55
+ password: import_zod.z.string().min(6, { message: "Password must contain at least 6 characters" }).max(72, { message: "Password must be 72 characters or less" }).refine((val) => val.trim().length >= 6, {
56
+ message: "Password cannot be only whitespace"
57
+ })
56
58
  });
57
59
  var loginSchema = import_zod.z.object({
58
60
  username: import_zod.z.string().min(1, { message: "Username or email is required" }),
@@ -72,14 +74,14 @@ var requestPasswordResetSchema = import_zod.z.object({
72
74
  });
73
75
  var resetPasswordSchema = import_zod.z.object({
74
76
  token: import_zod.z.string().min(1, { message: "Reset token is required" }),
75
- password: import_zod.z.string().min(6, { message: "Password must contain at least 6 characters" })
77
+ password: import_zod.z.string().min(6, { message: "Password must contain at least 6 characters" }).max(72, { message: "Password must be 72 characters or less" })
76
78
  });
77
79
  var checkPasswordResetSchema = import_zod.z.object({
78
80
  token: import_zod.z.string().min(1, { message: "Reset token is required" })
79
81
  });
80
82
  var changePasswordSchema = import_zod.z.object({
81
83
  currentPassword: import_zod.z.string().min(1, { message: "Current password is required" }),
82
- newPassword: import_zod.z.string().min(6, { message: "New password must contain at least 6 characters" })
84
+ newPassword: import_zod.z.string().min(6, { message: "New password must contain at least 6 characters" }).max(72, { message: "Password must be 72 characters or less" })
83
85
  });
84
86
  var twoFaVerifySchema = import_zod.z.object({
85
87
  code: import_zod.z.string().min(6, { message: "Verification code is required" }),
@@ -22,7 +22,7 @@ import {
22
22
  twoFaSetupSchema,
23
23
  twoFaVerifySchema,
24
24
  verifyEmailSchema
25
- } from "./chunk-2DOUP275.mjs";
25
+ } from "./chunk-PYVDWODF.mjs";
26
26
  export {
27
27
  biometricVerifySchema,
28
28
  changePasswordSchema,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@factiii/auth",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -53,10 +53,16 @@
53
53
  "build": "tsup",
54
54
  "dev": "tsup --watch",
55
55
  "check-types": "tsc --noEmit",
56
- "lint": "eslint src --ext .ts,.tsx",
57
- "lint:fix": "eslint src --ext .ts,.tsx --fix",
56
+ "lint": "eslint src",
57
+ "lint:fix": "eslint src --fix",
58
+ "format": "prettier --check src",
59
+ "format:fix": "prettier --write src",
58
60
  "clean": "rm -rf dist node_modules/.cache .turbo",
59
- "prepublishOnly": "npm run build"
61
+ "prepublishOnly": "npm run build",
62
+ "e2e": "pnpm e2e:db:up && playwright test --reporter=list; pnpm e2e:db:down",
63
+ "e2e:ui": "pnpm e2e:db:up && playwright test --ui",
64
+ "e2e:db:up": "docker compose -f e2e/docker-compose.yml up -d --wait && prisma generate --schema=e2e/server/schema.prisma --config=e2e/server/prisma.config.ts && prisma migrate reset --schema=e2e/server/schema.prisma --config=e2e/server/prisma.config.ts --force",
65
+ "e2e:db:down": "docker compose -f e2e/docker-compose.yml down"
60
66
  },
61
67
  "dependencies": {
62
68
  "@trpc/server": "11.8.0",
@@ -83,22 +89,39 @@
83
89
  }
84
90
  },
85
91
  "devDependencies": {
92
+ "@playwright/test": "^1.58.1",
93
+ "@prisma/adapter-better-sqlite3": "^7.3.0",
94
+ "@prisma/adapter-pg": "^7.3.0",
86
95
  "@prisma/client": "^7.1.0",
96
+ "@trpc/client": "^11.8.0",
87
97
  "@trpc/server": "11.8.0",
88
98
  "@types/bcryptjs": "^2.4.6",
99
+ "@types/better-sqlite3": "^7.6.13",
89
100
  "@types/jsonwebtoken": "^9.0.9",
90
101
  "@types/node": "^20.19.0",
102
+ "@types/pg": "^8.16.0",
103
+ "@types/react": "^19.2.11",
104
+ "@types/react-dom": "^19.2.3",
91
105
  "@typescript-eslint/eslint-plugin": "^7.18.0",
92
106
  "@typescript-eslint/parser": "^7.18.0",
107
+ "@vitejs/plugin-react": "^5.1.3",
108
+ "better-sqlite3": "^12.6.2",
93
109
  "eslint": "^8.57.0",
110
+ "pg": "^8.18.0",
111
+ "prettier": "^3.8.1",
94
112
  "prisma": "^7.1.0",
113
+ "react": "^19.2.4",
114
+ "react-dom": "^19.2.4",
115
+ "react-router-dom": "^7.2.0",
95
116
  "superjson": "^1.13.3",
96
117
  "tsup": "^8.3.5",
118
+ "tsx": "^4.21.0",
97
119
  "typescript": "5.9.3",
120
+ "vite": "^7.3.1",
98
121
  "zod": "3.24.2"
99
122
  },
100
123
  "engines": {
101
124
  "node": ">=18.0.0"
102
125
  },
103
- "packageManager": "pnpm@10.26.0+sha512.3b3f6c725ebe712506c0ab1ad4133cf86b1f4b687effce62a9b38b4d72e3954242e643190fc51fa1642949c735f403debd44f5cb0edd657abe63a8b6a7e1e402"
126
+ "packageManager": "pnpm@10.26.0"
104
127
  }