mailsentry-auth 0.2.3 → 0.2.5

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
@@ -91,11 +91,11 @@ var AuthEventType = /* @__PURE__ */ ((AuthEventType3) => {
91
91
  AuthEventType3["SignInRequiredModal"] = "auth.signin_required_modal";
92
92
  return AuthEventType3;
93
93
  })(AuthEventType || {});
94
- var PageType = /* @__PURE__ */ ((PageType2) => {
95
- PageType2["LOGIN"] = "/login";
96
- PageType2["DASHBOARD"] = "dashboard";
97
- PageType2["HOME"] = "/";
98
- return PageType2;
94
+ var PageType = /* @__PURE__ */ ((PageType4) => {
95
+ PageType4["LOGIN"] = "/login";
96
+ PageType4["DASHBOARD"] = "dashboard";
97
+ PageType4["HOME"] = "/";
98
+ return PageType4;
99
99
  })(PageType || {});
100
100
  var NavigationAction = /* @__PURE__ */ ((NavigationAction2) => {
101
101
  NavigationAction2["NONE"] = "none";
@@ -109,7 +109,7 @@ var PageTypePatterns = {
109
109
  };
110
110
  var CrossTabBehaviorConfig = {
111
111
  ["/login" /* LOGIN */]: {
112
- ["auth.logged_in" /* LoggedIn */]: { action: "none" /* NONE */ },
112
+ ["auth.logged_in" /* LoggedIn */]: { action: "reload" /* RELOAD */ },
113
113
  ["auth.logged_out" /* LoggedOut */]: { action: "none" /* NONE */ },
114
114
  ["auth.email_verified" /* EmailVerified */]: { action: "none" /* NONE */ },
115
115
  ["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "none" /* NONE */ }
@@ -117,7 +117,7 @@ var CrossTabBehaviorConfig = {
117
117
  ["dashboard" /* DASHBOARD */]: {
118
118
  ["auth.logged_in" /* LoggedIn */]: { action: "reload" /* RELOAD */ },
119
119
  ["auth.logged_out" /* LoggedOut */]: { action: "reload" /* RELOAD */ },
120
- ["auth.email_verified" /* EmailVerified */]: { action: "reload" /* RELOAD */ },
120
+ ["auth.email_verified" /* EmailVerified */]: { action: "none" /* NONE */ },
121
121
  ["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "none" /* NONE */ }
122
122
  },
123
123
  ["/" /* HOME */]: {
@@ -566,6 +566,9 @@ var PasswordStep = ({
566
566
  // src/components/auth/verification-step.tsx
567
567
 
568
568
 
569
+
570
+ var RESEND_COUNTDOWN_SECONDS = 60;
571
+ var COUNTDOWN_INTERVAL_MS = 1e3;
569
572
  var VerificationStep = ({
570
573
  title,
571
574
  description,
@@ -574,27 +577,48 @@ var VerificationStep = ({
574
577
  submitButtonText,
575
578
  isLoading = false,
576
579
  codeLength = 5,
577
- showResendButton = true,
578
580
  initialValues,
579
581
  email
580
582
  }) => {
581
- const handleSubmit = async (values) => {
582
- await onSubmit(values.verificationCode);
583
- };
584
- const fields = [
585
- getVerificationField(codeLength, { disabled: isLoading }, email)
586
- ];
587
- const additionalActions = /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: showResendButton && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
583
+ const [countdown, setCountdown] = _react.useState.call(void 0, RESEND_COUNTDOWN_SECONDS);
584
+ const canResend = _react.useMemo.call(void 0, () => countdown === 0, [countdown]);
585
+ _react.useEffect.call(void 0, () => {
586
+ if (countdown === 0) return;
587
+ const timer = setTimeout(() => {
588
+ setCountdown((prev) => prev - 1);
589
+ }, COUNTDOWN_INTERVAL_MS);
590
+ return () => clearTimeout(timer);
591
+ }, [countdown]);
592
+ const handleSubmit = _react.useCallback.call(void 0,
593
+ async (values) => {
594
+ await onSubmit(values.verificationCode);
595
+ },
596
+ [onSubmit]
597
+ );
598
+ const handleResendClick = _react.useCallback.call(void 0, async () => {
599
+ if (!canResend || !onResendCode) return;
600
+ setCountdown(RESEND_COUNTDOWN_SECONDS);
601
+ await onResendCode();
602
+ }, [canResend, onResendCode]);
603
+ const fields = _react.useMemo.call(void 0,
604
+ () => [getVerificationField(codeLength, { disabled: isLoading }, email)],
605
+ [codeLength, isLoading, email]
606
+ );
607
+ const resendButtonText = _react.useMemo.call(void 0,
608
+ () => canResend ? "Resend verification code" : `Resend verification code (${countdown}s)`,
609
+ [canResend, countdown]
610
+ );
611
+ const additionalActions = /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
588
612
  _antd.Button,
589
613
  {
590
614
  type: "link",
591
- onClick: onResendCode,
592
- disabled: isLoading,
615
+ onClick: handleResendClick,
616
+ disabled: isLoading || !canResend,
593
617
  block: true,
594
618
  className: "mb-2",
595
- children: "Resend verification code"
619
+ children: resendButtonText
596
620
  }
597
- ) });
621
+ );
598
622
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
599
623
  BaseForm,
600
624
  {
@@ -631,6 +655,9 @@ var FinishStep = () => {
631
655
 
632
656
  // src/components/auth/forgot-password-step.tsx
633
657
 
658
+
659
+
660
+ var { Title: Title2 } = _antd.Typography;
634
661
  var ForgotPasswordStep = ({
635
662
  title,
636
663
  description,
@@ -640,13 +667,23 @@ var ForgotPasswordStep = ({
640
667
  submitButtonText,
641
668
  initialValues
642
669
  }) => {
670
+ const [showSuccess, setShowSuccess] = _react.useState.call(void 0, false);
671
+ _react.useEffect.call(void 0, () => {
672
+ if (showSuccess) {
673
+ const timer = setTimeout(() => {
674
+ setShowSuccess(false);
675
+ }, 5e3);
676
+ return () => clearTimeout(timer);
677
+ }
678
+ }, [showSuccess]);
643
679
  const handleSubmit = async (values) => {
644
680
  await onSubmit(values.email);
681
+ setShowSuccess(true);
645
682
  };
646
683
  const fields = [
647
684
  getEmailField({ disabled: isLoading, value: email })
648
685
  ];
649
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
686
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: showSuccess ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Title2, { level: 3, className: "block mb-6", children: "We've sent an email with instructions to reset your password. Please check your inbox." }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
650
687
  BaseForm,
651
688
  {
652
689
  title,
@@ -657,7 +694,7 @@ var ForgotPasswordStep = ({
657
694
  isLoading,
658
695
  initialValues: initialValues || { email }
659
696
  }
660
- );
697
+ ) });
661
698
  };
662
699
 
663
700
  // src/components/auth/step-renderer.tsx
@@ -702,10 +739,10 @@ var createPropsFactoryRegistry = ({
702
739
  description: `Please enter the verification code sent to ${state.email}`,
703
740
  submitButtonText: "Verify Email",
704
741
  email: state.email,
705
- onSubmit: handlers.handleVerificationSubmit,
742
+ onSubmit: handlers.handleVerificationSubmit || (async () => {
743
+ }),
706
744
  onResendCode: handlers.handleResendCode,
707
- codeLength: configs.verificationStepConfig.codeLength,
708
- showResendButton: configs.verificationStepConfig.showResendButton
745
+ codeLength: configs.verificationStepConfig.codeLength
709
746
  }),
710
747
  ["finish" /* FINISH */]: () => __spreadProps(__spreadValues({}, baseProps), {
711
748
  title: "Success",
@@ -1969,7 +2006,11 @@ var AUTH_ENDPOINTS = {
1969
2006
  GET_USER_PROFILE: "/auth/user/profile",
1970
2007
  GET_ME: "/auth/user/me",
1971
2008
  // User logout
1972
- LOGOUT: "/auth/logout"
2009
+ LOGOUT: "/auth/logout",
2010
+ // Password reset
2011
+ FORGOT_PASSWORD: "/auth/user/forget-password",
2012
+ // Verification
2013
+ RESEND_VERIFICATION: "/auth/user/generate-verification"
1973
2014
  };
1974
2015
  var EndpointBuilder = class {
1975
2016
  };
@@ -2028,6 +2069,20 @@ var AuthService = class extends BaseService {
2028
2069
  const endpoint = AUTH_ENDPOINTS.LOGOUT;
2029
2070
  return this.post(endpoint);
2030
2071
  }
2072
+ /**
2073
+ * Send forgot password email
2074
+ */
2075
+ async forgotPassword(email) {
2076
+ const endpoint = AUTH_ENDPOINTS.FORGOT_PASSWORD;
2077
+ return this.post(endpoint, { email });
2078
+ }
2079
+ /**
2080
+ * Resend verification code
2081
+ */
2082
+ async resendVerification(email) {
2083
+ const endpoint = AUTH_ENDPOINTS.RESEND_VERIFICATION;
2084
+ return this.post(endpoint, { email });
2085
+ }
2031
2086
  };
2032
2087
 
2033
2088
  // src/services/auth/manager/user-storage-manager.ts
@@ -2373,9 +2428,8 @@ var GenericErrorHandler = class extends BaseErrorHandler {
2373
2428
 
2374
2429
  // src/services/auth/auth-orchestrator.ts
2375
2430
  var AuthOrchestrator = class {
2376
- constructor(authService, eventBus, tokenManager) {
2431
+ constructor(authService, tokenManager) {
2377
2432
  this.authService = authService;
2378
- this.eventBus = eventBus;
2379
2433
  this.tokenManager = tokenManager || new TokenManager(CookieUtils);
2380
2434
  this.userStorageManager = new UserStorageManager(LocalStorageUtils);
2381
2435
  this.logger = LoggerFactory.create();
@@ -2461,14 +2515,6 @@ var AuthOrchestrator = class {
2461
2515
  this.tokenManager
2462
2516
  );
2463
2517
  const result = await strategy.execute(credentials);
2464
- if (result.success && result.data.isVerifiedEmail) {
2465
- const currentPageType = CrossTabBehaviorHandler.getCurrentPageType();
2466
- this.eventBus.publish({
2467
- type: "auth.logged_in" /* LoggedIn */,
2468
- userId: String(result.data.profile.user._id),
2469
- sourcePageType: currentPageType
2470
- });
2471
- }
2472
2518
  return result;
2473
2519
  } catch (error) {
2474
2520
  return this.errorHandler.handle(error, "Login flow");
@@ -2490,12 +2536,6 @@ var AuthOrchestrator = class {
2490
2536
  domain: this.tokenManager.getDomainInfo().domain
2491
2537
  }
2492
2538
  });
2493
- const currentPageType = CrossTabBehaviorHandler.getCurrentPageType();
2494
- this.eventBus.publish({
2495
- type: "auth.logged_in" /* LoggedIn */,
2496
- userId: String(completeLoginData.profile.user._id),
2497
- sourcePageType: currentPageType
2498
- });
2499
2539
  return AuthResultFactory.createSuccess(completeLoginData);
2500
2540
  } catch (error) {
2501
2541
  return this.errorHandler.handle(error, "Google Login");
@@ -2511,7 +2551,6 @@ var AuthOrchestrator = class {
2511
2551
  const verificationResult = await this.authService.verifyEmail(verificationRequest);
2512
2552
  const isVerified = verificationResult === true || ((_a = verificationResult == null ? void 0 : verificationResult.data) == null ? void 0 : _a.isVerified);
2513
2553
  if (isVerified) {
2514
- this.eventBus.publish({ type: "auth.email_verified" /* EmailVerified */, email });
2515
2554
  return AuthResultFactory.createSuccess({ isVerified: true });
2516
2555
  }
2517
2556
  return AuthResultFactory.createFailure("Email verification failed");
@@ -2535,11 +2574,6 @@ var AuthOrchestrator = class {
2535
2574
  } finally {
2536
2575
  this.tokenManager.clearTokens();
2537
2576
  this.userStorageManager.clearUserProfile();
2538
- const currentPageType = CrossTabBehaviorHandler.getCurrentPageType();
2539
- this.eventBus.publish({
2540
- type: "auth.logged_out" /* LoggedOut */,
2541
- sourcePageType: currentPageType
2542
- });
2543
2577
  this.logger.log("Logout cleanup completed:", {
2544
2578
  clearedTokens: Object.keys(tokenInfo).filter((key) => tokenInfo[key]),
2545
2579
  domainInfo: this.tokenManager.getDomainInfo()
@@ -2613,6 +2647,32 @@ var AuthOrchestrator = class {
2613
2647
  return this.errorHandler.handle(error, "Get token info");
2614
2648
  }
2615
2649
  }
2650
+ /**
2651
+ * Handle forgot password flow
2652
+ */
2653
+ async handleForgotPassword(email) {
2654
+ try {
2655
+ await this.authService.forgotPassword(email);
2656
+ return AuthResultFactory.createSuccess({
2657
+ message: "We've sent an email with instructions to reset your password. Please check your inbox."
2658
+ });
2659
+ } catch (error) {
2660
+ return this.errorHandler.handle(error, "Forgot password");
2661
+ }
2662
+ }
2663
+ /**
2664
+ * Handle resend verification code
2665
+ */
2666
+ async handleResendVerification(email) {
2667
+ try {
2668
+ await this.authService.resendVerification(email);
2669
+ return AuthResultFactory.createSuccess({
2670
+ message: "Verification code sent successfully."
2671
+ });
2672
+ } catch (error) {
2673
+ return this.errorHandler.handle(error, "Resend verification");
2674
+ }
2675
+ }
2616
2676
  };
2617
2677
  var AuthOrchestratorFactory = class {
2618
2678
  /**
@@ -2620,14 +2680,13 @@ var AuthOrchestratorFactory = class {
2620
2680
  */
2621
2681
  static create() {
2622
2682
  const authService = new AuthService();
2623
- const eventBus = BroadcastChannelEventBus.getInstance("auth-event-channel" /* AUTH */);
2624
- return new AuthOrchestrator(authService, eventBus);
2683
+ return new AuthOrchestrator(authService);
2625
2684
  }
2626
2685
  /**
2627
2686
  * Create AuthOrchestrator with custom dependencies
2628
2687
  */
2629
- static createWithDependencies(authService, eventBus, tokenManager) {
2630
- return new AuthOrchestrator(authService, eventBus, tokenManager);
2688
+ static createWithDependencies(authService, tokenManager) {
2689
+ return new AuthOrchestrator(authService, tokenManager);
2631
2690
  }
2632
2691
  };
2633
2692
 
@@ -2706,6 +2765,12 @@ var useUserStore = _zustand.create.call(void 0, )(
2706
2765
  });
2707
2766
  try {
2708
2767
  await _authOrchestrator.handleLogout();
2768
+ const eventBus = BroadcastChannelEventBus.getInstance("auth-event-channel" /* AUTH */);
2769
+ const currentPageType = CrossTabBehaviorHandler.getCurrentPageType();
2770
+ eventBus.publish({
2771
+ type: "auth.logged_out" /* LoggedOut */,
2772
+ sourcePageType: currentPageType
2773
+ });
2709
2774
  } catch (error) {
2710
2775
  console.error("Error during logout cleanup:", error);
2711
2776
  } finally {
@@ -3070,6 +3135,7 @@ function AuthFlowContainer({
3070
3135
  }) {
3071
3136
  const showRightSideImage = variant === "with_image" /* WITH_IMAGE */ && !!backgroundImage;
3072
3137
  const authOrchestrator = AuthOrchestratorFactory.create();
3138
+ const eventBus = useSharedEventBus();
3073
3139
  const { state: actionState, executeAction, clearAll } = useAuthActionHandler();
3074
3140
  const { getStepComponent } = useStepRenderer();
3075
3141
  const [email, setEmail] = _react.useState.call(void 0, "");
@@ -3085,8 +3151,7 @@ function AuthFlowContainer({
3085
3151
  showEmailField: true
3086
3152
  },
3087
3153
  verificationStepConfig: {
3088
- codeLength: 5,
3089
- showResendButton: false
3154
+ codeLength: 5
3090
3155
  }
3091
3156
  };
3092
3157
  const stepperConfig = {
@@ -3137,7 +3202,10 @@ function AuthFlowContainer({
3137
3202
  },
3138
3203
  {
3139
3204
  condition: () => true,
3140
- execute: () => handleSuccess()
3205
+ execute: () => {
3206
+ publishLoggedInEvent(String(data.profile.user._id));
3207
+ handleSuccess();
3208
+ }
3141
3209
  }
3142
3210
  ];
3143
3211
  (_a = actionPipeline.find((action) => action.condition())) == null ? void 0 : _a.execute();
@@ -3154,9 +3222,9 @@ function AuthFlowContainer({
3154
3222
  return await authOrchestrator.handleEmailVerification(email, code);
3155
3223
  },
3156
3224
  {
3157
- onSuccess: (data) => {
3225
+ onSuccess: async (data) => {
3158
3226
  setAuthData(data);
3159
- handlePasswordSubmitAfterVerification(password);
3227
+ await handlePasswordSubmitAfterVerification(password);
3160
3228
  setPassword("");
3161
3229
  },
3162
3230
  onError: (error) => {
@@ -3174,6 +3242,7 @@ function AuthFlowContainer({
3174
3242
  {
3175
3243
  onSuccess: (data) => {
3176
3244
  setAuthData(data);
3245
+ publishLoggedInEvent(String(data.profile.user._id));
3177
3246
  handleSuccess();
3178
3247
  },
3179
3248
  onError: (error) => {
@@ -3190,6 +3259,7 @@ function AuthFlowContainer({
3190
3259
  {
3191
3260
  onSuccess: (data) => {
3192
3261
  setAuthData(data);
3262
+ publishLoggedInEvent(String(data.profile.user._id));
3193
3263
  handleSuccess();
3194
3264
  },
3195
3265
  onError: (error) => {
@@ -3198,11 +3268,30 @@ function AuthFlowContainer({
3198
3268
  }
3199
3269
  );
3200
3270
  };
3271
+ const handleResendCode = async () => {
3272
+ await executeAction(
3273
+ async () => {
3274
+ return await authOrchestrator.handleResendVerification(email);
3275
+ },
3276
+ {
3277
+ onSuccess: () => {
3278
+ },
3279
+ onError: (error) => {
3280
+ console.error(error);
3281
+ }
3282
+ }
3283
+ );
3284
+ };
3285
+ const publishLoggedInEvent = (userId) => {
3286
+ const currentPageType = CrossTabBehaviorHandler.getCurrentPageType();
3287
+ eventBus.publish({
3288
+ type: "auth.logged_in" /* LoggedIn */,
3289
+ userId,
3290
+ sourcePageType: currentPageType
3291
+ });
3292
+ };
3201
3293
  const handleSuccess = () => {
3202
3294
  stepperActions.goToStep("finish" /* FINISH */);
3203
- setTimeout(() => {
3204
- window.location.href = UrlUtils.getDashboardUrl(window.location);
3205
- }, 1e3);
3206
3295
  };
3207
3296
  const goBackToEmail = () => {
3208
3297
  stepperActions.goToStep("email" /* EMAIL */);
@@ -3217,7 +3306,18 @@ function AuthFlowContainer({
3217
3306
  clearAll();
3218
3307
  };
3219
3308
  const handleForgotPassword = async (emailValue) => {
3220
- console.log("Sending forgot password link to:", emailValue);
3309
+ await executeAction(
3310
+ async () => {
3311
+ return await authOrchestrator.handleForgotPassword(emailValue);
3312
+ },
3313
+ {
3314
+ onSuccess: () => {
3315
+ },
3316
+ onError: (error) => {
3317
+ console.error(error);
3318
+ }
3319
+ }
3320
+ );
3221
3321
  };
3222
3322
  const onForgotPasswordClick = () => {
3223
3323
  stepperActions.goToStep("forgot-password" /* FORGOT_PASSWORD */);
@@ -3228,8 +3328,7 @@ function AuthFlowContainer({
3228
3328
  handleEmailSubmit,
3229
3329
  handlePasswordSubmit,
3230
3330
  handleVerificationSubmit,
3231
- handleResendCode: () => {
3232
- },
3331
+ handleResendCode,
3233
3332
  goBackToEmail,
3234
3333
  goBackToPassword,
3235
3334
  onGoogleSignIn: handleGoogleSignIn,
@@ -3477,7 +3576,7 @@ var ProfileStateRenderer = () => {
3477
3576
  // src/components/demo/cross-tab-demo.tsx
3478
3577
 
3479
3578
 
3480
- var { Title: Title2, Text: Text2, Paragraph: Paragraph2 } = _antd.Typography;
3579
+ var { Title: Title3, Text: Text2, Paragraph: Paragraph2 } = _antd.Typography;
3481
3580
  var CrossTabDemo = () => {
3482
3581
  var _a;
3483
3582
  const { isAuthenticated, user } = useAuth();
@@ -3490,7 +3589,7 @@ var CrossTabDemo = () => {
3490
3589
  style: { marginTop: "2rem" },
3491
3590
  children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _antd.Space, { direction: "vertical", size: "middle", className: "w-full", children: [
3492
3591
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
3493
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Title2, { level: 4, children: "Current Status" }),
3592
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Title3, { level: 4, children: "Current Status" }),
3494
3593
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _antd.Space, { children: [
3495
3594
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Text2, { strong: true, children: "Authentication:" }),
3496
3595
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _antd.Tag, { color: isAuthenticated ? "green" : "red", children: isAuthenticated ? "Authenticated" : "Not Authenticated" })
@@ -3509,7 +3608,7 @@ var CrossTabDemo = () => {
3509
3608
  ] })
3510
3609
  ] }),
3511
3610
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
3512
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Title2, { level: 4, children: "How It Works" }),
3611
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Title3, { level: 4, children: "How It Works" }),
3513
3612
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Paragraph2, { children: "This application now supports enhanced cross-tab authentication handling:" }),
3514
3613
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { marginLeft: "1rem" }, children: [
3515
3614
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Paragraph2, { children: [
@@ -3531,7 +3630,7 @@ var CrossTabDemo = () => {
3531
3630
  ] })
3532
3631
  ] }),
3533
3632
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
3534
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Title2, { level: 4, children: "Test Instructions" }),
3633
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Title3, { level: 4, children: "Test Instructions" }),
3535
3634
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Paragraph2, { children: [
3536
3635
  "1. Open this page in multiple browser tabs",
3537
3636
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),