mailsentry-auth 0.1.1 → 0.1.3
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.d.mts +64 -43
- package/dist/index.d.ts +64 -43
- package/dist/index.js +93 -37
- package/dist/index.mjs +92 -36
- package/dist/middleware.d.mts +7 -12
- package/dist/middleware.mjs +88 -94
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -516,22 +516,22 @@ type AuthEvent = {
|
|
|
516
516
|
sourcePageType?: PageType;
|
|
517
517
|
};
|
|
518
518
|
declare enum PageType {
|
|
519
|
-
LOGIN = "
|
|
520
|
-
DASHBOARD = "
|
|
519
|
+
LOGIN = "login",
|
|
520
|
+
DASHBOARD = "dashboard",
|
|
521
521
|
HOME = "/"
|
|
522
522
|
}
|
|
523
523
|
declare enum NavigationAction {
|
|
524
524
|
NONE = "none",
|
|
525
525
|
REDIRECT = "redirect",
|
|
526
|
-
MODAL = "modal"
|
|
526
|
+
MODAL = "modal",
|
|
527
|
+
CURRENT = "current"
|
|
527
528
|
}
|
|
528
529
|
declare const PageTypePatterns: {
|
|
529
|
-
readonly
|
|
530
|
-
readonly
|
|
531
|
-
readonly "/": PageType.HOME;
|
|
530
|
+
readonly login: PageType.LOGIN;
|
|
531
|
+
readonly dashboard: PageType.DASHBOARD;
|
|
532
532
|
};
|
|
533
533
|
declare const CrossTabBehaviorConfig: {
|
|
534
|
-
readonly
|
|
534
|
+
readonly login: {
|
|
535
535
|
readonly "auth.logged_in": {
|
|
536
536
|
readonly action: NavigationAction.REDIRECT;
|
|
537
537
|
readonly target: PageType.DASHBOARD;
|
|
@@ -546,31 +546,29 @@ declare const CrossTabBehaviorConfig: {
|
|
|
546
546
|
readonly action: NavigationAction.NONE;
|
|
547
547
|
};
|
|
548
548
|
};
|
|
549
|
-
readonly
|
|
549
|
+
readonly dashboard: {
|
|
550
550
|
readonly "auth.logged_in": {
|
|
551
|
-
readonly action: NavigationAction.
|
|
551
|
+
readonly action: NavigationAction.CURRENT;
|
|
552
552
|
};
|
|
553
553
|
readonly "auth.logged_out": {
|
|
554
|
-
readonly action: NavigationAction.
|
|
555
|
-
readonly target: PageType.DASHBOARD;
|
|
554
|
+
readonly action: NavigationAction.CURRENT;
|
|
556
555
|
};
|
|
557
556
|
readonly "auth.email_verified": {
|
|
558
|
-
readonly action: NavigationAction.
|
|
557
|
+
readonly action: NavigationAction.CURRENT;
|
|
559
558
|
};
|
|
560
559
|
readonly "auth.signin_required_modal": {
|
|
561
|
-
readonly action: NavigationAction.
|
|
560
|
+
readonly action: NavigationAction.CURRENT;
|
|
562
561
|
};
|
|
563
562
|
};
|
|
564
563
|
readonly "/": {
|
|
565
564
|
readonly "auth.logged_in": {
|
|
566
|
-
readonly action: NavigationAction.
|
|
565
|
+
readonly action: NavigationAction.NONE;
|
|
567
566
|
};
|
|
568
567
|
readonly "auth.logged_out": {
|
|
569
|
-
readonly action: NavigationAction.
|
|
570
|
-
readonly target: PageType.HOME;
|
|
568
|
+
readonly action: NavigationAction.NONE;
|
|
571
569
|
};
|
|
572
570
|
readonly "auth.email_verified": {
|
|
573
|
-
readonly action: NavigationAction.
|
|
571
|
+
readonly action: NavigationAction.NONE;
|
|
574
572
|
};
|
|
575
573
|
readonly "auth.signin_required_modal": {
|
|
576
574
|
readonly action: NavigationAction.NONE;
|
|
@@ -588,6 +586,7 @@ interface MiddlewareContext {
|
|
|
588
586
|
searchParams: URLSearchParams;
|
|
589
587
|
cookies: NextRequest['cookies'];
|
|
590
588
|
nextUrl: URL;
|
|
589
|
+
hostname: string;
|
|
591
590
|
}
|
|
592
591
|
/**
|
|
593
592
|
* Base interface for middleware handlers
|
|
@@ -629,38 +628,49 @@ declare const getPasswordField: (isLogin: boolean, disabled?: boolean, options?:
|
|
|
629
628
|
declare const getVerificationField: (codeLength?: number, options?: InputProps) => BaseFormField;
|
|
630
629
|
|
|
631
630
|
/**
|
|
632
|
-
* Middleware configuration constants
|
|
631
|
+
* Middleware configuration constants for subdomain-based routing
|
|
633
632
|
*/
|
|
634
633
|
declare class MiddlewareConfig {
|
|
635
|
-
static readonly
|
|
636
|
-
readonly DASHBOARD: "
|
|
634
|
+
static readonly SUBDOMAINS: {
|
|
635
|
+
readonly DASHBOARD: "dashboard";
|
|
637
636
|
};
|
|
638
|
-
static readonly
|
|
637
|
+
static readonly ROUTES: {
|
|
638
|
+
readonly ROOT: "/";
|
|
639
639
|
readonly LOGIN: "/login";
|
|
640
640
|
};
|
|
641
641
|
static readonly ALLOWED_METHODS: readonly ["GET", "HEAD"];
|
|
642
642
|
static readonly QUERY_PARAMS: {
|
|
643
643
|
readonly LOGIN_REQUIRED: "sign_in_required";
|
|
644
644
|
readonly AUTH_CHECKED: "auth_checked";
|
|
645
|
+
readonly REDIRECT_URL: "redirect_url";
|
|
645
646
|
};
|
|
646
647
|
static readonly QUERY_VALUES: {
|
|
647
648
|
readonly LOGIN_REQUIRED: "true";
|
|
648
649
|
readonly AUTH_CHECKED: "1";
|
|
649
650
|
};
|
|
651
|
+
/**
|
|
652
|
+
* Get the base domain from environment or use default
|
|
653
|
+
*/
|
|
654
|
+
static getBaseDomain(): string;
|
|
655
|
+
/**
|
|
656
|
+
* Get the protocol based on environment
|
|
657
|
+
*/
|
|
658
|
+
static getProtocol(): string;
|
|
659
|
+
/**
|
|
660
|
+
* Get the dashboard subdomain URL
|
|
661
|
+
*/
|
|
662
|
+
static getDashboardUrl(path?: string): string;
|
|
650
663
|
}
|
|
651
664
|
/**
|
|
652
|
-
* Middleware matcher patterns
|
|
653
|
-
*
|
|
654
|
-
* - / (home route and all other routes for authentication protection)
|
|
655
|
-
* - /login route (for authenticated user redirection)
|
|
656
|
-
* Excludes: API routes, Next.js internals, static assets, and file extensions
|
|
665
|
+
* Middleware matcher patterns
|
|
666
|
+
* Matches all routes except API routes, Next.js internals, and static assets
|
|
657
667
|
*/
|
|
658
|
-
declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
668
|
+
declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
|
|
659
669
|
/**
|
|
660
|
-
* Middleware configuration
|
|
670
|
+
* Middleware configuration
|
|
661
671
|
*/
|
|
662
672
|
declare const config: {
|
|
663
|
-
matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
673
|
+
matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
|
|
664
674
|
};
|
|
665
675
|
|
|
666
676
|
/**
|
|
@@ -793,11 +803,11 @@ declare class BroadcastChannelEventBus<TEvent> {
|
|
|
793
803
|
/**
|
|
794
804
|
* Cross-Tab Behavior Handler
|
|
795
805
|
* Determines cross-tab behavior based on authentication events and current page context
|
|
796
|
-
* Uses lookup
|
|
806
|
+
* Uses object lookup pattern for page type detection
|
|
797
807
|
*/
|
|
798
808
|
declare class CrossTabBehaviorHandler {
|
|
799
809
|
/**
|
|
800
|
-
* Get current page type
|
|
810
|
+
* Get current page type using object lookup pattern
|
|
801
811
|
*/
|
|
802
812
|
static getCurrentPageType(): PageType;
|
|
803
813
|
/**
|
|
@@ -813,32 +823,43 @@ declare class CrossTabBehaviorHandler {
|
|
|
813
823
|
} | {
|
|
814
824
|
readonly action: NavigationAction.NONE;
|
|
815
825
|
} | {
|
|
816
|
-
readonly action: NavigationAction.
|
|
826
|
+
readonly action: NavigationAction.CURRENT;
|
|
817
827
|
} | {
|
|
818
|
-
readonly action: NavigationAction.
|
|
819
|
-
readonly target: PageType.DASHBOARD;
|
|
828
|
+
readonly action: NavigationAction.CURRENT;
|
|
820
829
|
} | {
|
|
821
|
-
readonly action: NavigationAction.
|
|
830
|
+
readonly action: NavigationAction.CURRENT;
|
|
822
831
|
} | {
|
|
823
|
-
readonly action: NavigationAction.
|
|
832
|
+
readonly action: NavigationAction.CURRENT;
|
|
824
833
|
} | {
|
|
825
|
-
readonly action: NavigationAction.
|
|
834
|
+
readonly action: NavigationAction.NONE;
|
|
826
835
|
} | {
|
|
827
|
-
readonly action: NavigationAction.
|
|
828
|
-
readonly target: PageType.HOME;
|
|
836
|
+
readonly action: NavigationAction.NONE;
|
|
829
837
|
} | {
|
|
830
|
-
readonly action: NavigationAction.
|
|
838
|
+
readonly action: NavigationAction.NONE;
|
|
831
839
|
} | {
|
|
832
840
|
readonly action: NavigationAction.NONE;
|
|
833
841
|
};
|
|
834
842
|
/**
|
|
835
843
|
* Check if current route requires redirect for given event
|
|
844
|
+
* Returns PageType to redirect to, or null if no redirect needed
|
|
836
845
|
*/
|
|
837
846
|
static shouldRedirect(currentPageType: PageType, eventType: AuthEventType): PageType | null;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* URL utility functions
|
|
851
|
+
*/
|
|
852
|
+
declare class UrlUtils {
|
|
853
|
+
/**
|
|
854
|
+
* Extract subdomain from hostname or URL
|
|
855
|
+
* Example: "dashboard.cutly.io" -> "dashboard"
|
|
856
|
+
* Example: "dashboard.localhost" -> "dashboard"
|
|
857
|
+
*/
|
|
858
|
+
static getSubdomain(url: string): string | null;
|
|
838
859
|
/**
|
|
839
|
-
* Check if
|
|
860
|
+
* Check if URL has auth-related query parameters
|
|
840
861
|
*/
|
|
841
|
-
static
|
|
862
|
+
static hasAuthParams(url: string): boolean;
|
|
842
863
|
}
|
|
843
864
|
|
|
844
865
|
/**
|
|
@@ -1489,4 +1510,4 @@ declare const useAuthFlowModal: () => {
|
|
|
1489
1510
|
openModal: () => void;
|
|
1490
1511
|
};
|
|
1491
1512
|
|
|
1492
|
-
export { AUTH_ENDPOINTS, AlertDisplay, type AlertDisplayProps, type AnyStepProps, type ApiErrorResponse, type ApiKeyConfig, type AuthActionCallbacks, type AuthActionOptions, type AuthActionResult, type AuthActionResultFailure, type AuthActionResultSuccess, type AuthActionState, type AuthEvent, AuthEventType, AuthFlowContainer, AuthFlowModal, AuthFlowStep, AuthInitializer, AuthOrchestrator, AuthOrchestratorFactory, AuthResultFactory, AuthService, type AuthState, AuthenticatedState, type AuthenticatedStateProps, AuthenticationStatusContext, type BaseComponentProps, BaseErrorHandler, BaseEventBus, BaseForm, type BaseFormField, type BaseFormProps, type BaseResponse, BaseService, type BaseStepProps, BroadcastChannelEventBus, Channel, CookieUtils, CrossTabBehaviorConfig, CrossTabBehaviorHandler, CrossTabDemo, DevelopmentLogger, EMAIL_SUBMISSION_NAVIGATION, type EmailCheckResult, type EmailExistResponse, EmailStep, type EmailStepProps, EndpointBuilder, type EventBus, ExistingUserLoginStrategy, FormFields, type FormFieldsProps, FormHeader, type FormHeaderProps, GenericErrorHandler, HttpClient, type HttpClientConfig, type HttpError, HttpMethod, type HttpRequestOptions, type HttpResponse, type IAuthOrchestrator, type IAuthService, type IAuthStatusState, type IErrorHandler, type ILogger, type ILoginFlowStrategy, type ITokenManager, LocalStorageUtils, LoggerFactory, type LoginData, LoginFlowStrategyFactory, type LoginRequest, type LoginResponse, MiddlewareConfig, type MiddlewareContext, type MiddlewareHandler, NavigationAction, NetworkErrorHandler, NextAction, PASSWORD_SUBMISSION_NAVIGATION, PageType, PageTypePatterns, PasswordStep, type PasswordStepProps, ProductionLogger, ProfileStateRenderer, ProfileUIState, type PropsFactory, RoleType, SignupFlowStrategy, type Step, type StepComponent, type StepComponentRetriever, type StepConfig, type StepPropsFactoryRegistry, type StepRegistry, type StepRegistryBaseProps, type StepRegistryConfigs, type StepRegistryHandlers, type StepRegistryParams, type StepRegistryState, type StepperActions, type StepperState$1 as StepperState, type Subscription, TokenManager, UnauthenticatedState, type UseAuthActionHandler, type UseAuthEventBusProps, type UseFormSubmissionProps, type UseStepRegistryParams, type UseStepperReturn, type UserProfile, type UserProfileResponse, type UserSession, type UserState, UserStorageManager, type UserStoreState, VERIFICATION_SUBMISSION_NAVIGATION, ValidationErrorHandler, VerificationStep, type VerificationStepProps, type VerifyEmailRequest, type VerifyEmailResponse, config, createAuthSteps, createPropsFactoryRegistry, createStepRegistry, getAuthPageStepMessage, getEmailField, getEmailStepComponent, getPasswordField, getPasswordStepComponent, getStepForEmailSubmission, getStepForPasswordSubmission, getStepForVerificationSubmission, getStepProgressMessage, getVerificationField, getVerificationStepComponent, middlewareMatcher, useAuth, useAuthActionHandler, useAuthEventBus, useAuthFlowModal, useAuthInitializer, useIsAuthenticated, useLogout, useRefreshUser, useSharedEventBus, useSignInRequiredParams, useStepRegistry, useStepRenderer, useStepper, useUser, useUserActions, useUserData, useUserError, useUserLoading, useUserProfile, useUserStore, userSelectors };
|
|
1513
|
+
export { AUTH_ENDPOINTS, AlertDisplay, type AlertDisplayProps, type AnyStepProps, type ApiErrorResponse, type ApiKeyConfig, type AuthActionCallbacks, type AuthActionOptions, type AuthActionResult, type AuthActionResultFailure, type AuthActionResultSuccess, type AuthActionState, type AuthEvent, AuthEventType, AuthFlowContainer, AuthFlowModal, AuthFlowStep, AuthInitializer, AuthOrchestrator, AuthOrchestratorFactory, AuthResultFactory, AuthService, type AuthState, AuthenticatedState, type AuthenticatedStateProps, AuthenticationStatusContext, type BaseComponentProps, BaseErrorHandler, BaseEventBus, BaseForm, type BaseFormField, type BaseFormProps, type BaseResponse, BaseService, type BaseStepProps, BroadcastChannelEventBus, Channel, CookieUtils, CrossTabBehaviorConfig, CrossTabBehaviorHandler, CrossTabDemo, DevelopmentLogger, EMAIL_SUBMISSION_NAVIGATION, type EmailCheckResult, type EmailExistResponse, EmailStep, type EmailStepProps, EndpointBuilder, type EventBus, ExistingUserLoginStrategy, FormFields, type FormFieldsProps, FormHeader, type FormHeaderProps, GenericErrorHandler, HttpClient, type HttpClientConfig, type HttpError, HttpMethod, type HttpRequestOptions, type HttpResponse, type IAuthOrchestrator, type IAuthService, type IAuthStatusState, type IErrorHandler, type ILogger, type ILoginFlowStrategy, type ITokenManager, LocalStorageUtils, LoggerFactory, type LoginData, LoginFlowStrategyFactory, type LoginRequest, type LoginResponse, MiddlewareConfig, type MiddlewareContext, type MiddlewareHandler, NavigationAction, NetworkErrorHandler, NextAction, PASSWORD_SUBMISSION_NAVIGATION, PageType, PageTypePatterns, PasswordStep, type PasswordStepProps, ProductionLogger, ProfileStateRenderer, ProfileUIState, type PropsFactory, RoleType, SignupFlowStrategy, type Step, type StepComponent, type StepComponentRetriever, type StepConfig, type StepPropsFactoryRegistry, type StepRegistry, type StepRegistryBaseProps, type StepRegistryConfigs, type StepRegistryHandlers, type StepRegistryParams, type StepRegistryState, type StepperActions, type StepperState$1 as StepperState, type Subscription, TokenManager, UnauthenticatedState, UrlUtils, type UseAuthActionHandler, type UseAuthEventBusProps, type UseFormSubmissionProps, type UseStepRegistryParams, type UseStepperReturn, type UserProfile, type UserProfileResponse, type UserSession, type UserState, UserStorageManager, type UserStoreState, VERIFICATION_SUBMISSION_NAVIGATION, ValidationErrorHandler, VerificationStep, type VerificationStepProps, type VerifyEmailRequest, type VerifyEmailResponse, config, createAuthSteps, createPropsFactoryRegistry, createStepRegistry, getAuthPageStepMessage, getEmailField, getEmailStepComponent, getPasswordField, getPasswordStepComponent, getStepForEmailSubmission, getStepForPasswordSubmission, getStepForVerificationSubmission, getStepProgressMessage, getVerificationField, getVerificationStepComponent, middlewareMatcher, useAuth, useAuthActionHandler, useAuthEventBus, useAuthFlowModal, useAuthInitializer, useIsAuthenticated, useLogout, useRefreshUser, useSharedEventBus, useSignInRequiredParams, useStepRegistry, useStepRenderer, useStepper, useUser, useUserActions, useUserData, useUserError, useUserLoading, useUserProfile, useUserStore, userSelectors };
|
package/dist/index.d.ts
CHANGED
|
@@ -516,22 +516,22 @@ type AuthEvent = {
|
|
|
516
516
|
sourcePageType?: PageType;
|
|
517
517
|
};
|
|
518
518
|
declare enum PageType {
|
|
519
|
-
LOGIN = "
|
|
520
|
-
DASHBOARD = "
|
|
519
|
+
LOGIN = "login",
|
|
520
|
+
DASHBOARD = "dashboard",
|
|
521
521
|
HOME = "/"
|
|
522
522
|
}
|
|
523
523
|
declare enum NavigationAction {
|
|
524
524
|
NONE = "none",
|
|
525
525
|
REDIRECT = "redirect",
|
|
526
|
-
MODAL = "modal"
|
|
526
|
+
MODAL = "modal",
|
|
527
|
+
CURRENT = "current"
|
|
527
528
|
}
|
|
528
529
|
declare const PageTypePatterns: {
|
|
529
|
-
readonly
|
|
530
|
-
readonly
|
|
531
|
-
readonly "/": PageType.HOME;
|
|
530
|
+
readonly login: PageType.LOGIN;
|
|
531
|
+
readonly dashboard: PageType.DASHBOARD;
|
|
532
532
|
};
|
|
533
533
|
declare const CrossTabBehaviorConfig: {
|
|
534
|
-
readonly
|
|
534
|
+
readonly login: {
|
|
535
535
|
readonly "auth.logged_in": {
|
|
536
536
|
readonly action: NavigationAction.REDIRECT;
|
|
537
537
|
readonly target: PageType.DASHBOARD;
|
|
@@ -546,31 +546,29 @@ declare const CrossTabBehaviorConfig: {
|
|
|
546
546
|
readonly action: NavigationAction.NONE;
|
|
547
547
|
};
|
|
548
548
|
};
|
|
549
|
-
readonly
|
|
549
|
+
readonly dashboard: {
|
|
550
550
|
readonly "auth.logged_in": {
|
|
551
|
-
readonly action: NavigationAction.
|
|
551
|
+
readonly action: NavigationAction.CURRENT;
|
|
552
552
|
};
|
|
553
553
|
readonly "auth.logged_out": {
|
|
554
|
-
readonly action: NavigationAction.
|
|
555
|
-
readonly target: PageType.DASHBOARD;
|
|
554
|
+
readonly action: NavigationAction.CURRENT;
|
|
556
555
|
};
|
|
557
556
|
readonly "auth.email_verified": {
|
|
558
|
-
readonly action: NavigationAction.
|
|
557
|
+
readonly action: NavigationAction.CURRENT;
|
|
559
558
|
};
|
|
560
559
|
readonly "auth.signin_required_modal": {
|
|
561
|
-
readonly action: NavigationAction.
|
|
560
|
+
readonly action: NavigationAction.CURRENT;
|
|
562
561
|
};
|
|
563
562
|
};
|
|
564
563
|
readonly "/": {
|
|
565
564
|
readonly "auth.logged_in": {
|
|
566
|
-
readonly action: NavigationAction.
|
|
565
|
+
readonly action: NavigationAction.NONE;
|
|
567
566
|
};
|
|
568
567
|
readonly "auth.logged_out": {
|
|
569
|
-
readonly action: NavigationAction.
|
|
570
|
-
readonly target: PageType.HOME;
|
|
568
|
+
readonly action: NavigationAction.NONE;
|
|
571
569
|
};
|
|
572
570
|
readonly "auth.email_verified": {
|
|
573
|
-
readonly action: NavigationAction.
|
|
571
|
+
readonly action: NavigationAction.NONE;
|
|
574
572
|
};
|
|
575
573
|
readonly "auth.signin_required_modal": {
|
|
576
574
|
readonly action: NavigationAction.NONE;
|
|
@@ -588,6 +586,7 @@ interface MiddlewareContext {
|
|
|
588
586
|
searchParams: URLSearchParams;
|
|
589
587
|
cookies: NextRequest['cookies'];
|
|
590
588
|
nextUrl: URL;
|
|
589
|
+
hostname: string;
|
|
591
590
|
}
|
|
592
591
|
/**
|
|
593
592
|
* Base interface for middleware handlers
|
|
@@ -629,38 +628,49 @@ declare const getPasswordField: (isLogin: boolean, disabled?: boolean, options?:
|
|
|
629
628
|
declare const getVerificationField: (codeLength?: number, options?: InputProps) => BaseFormField;
|
|
630
629
|
|
|
631
630
|
/**
|
|
632
|
-
* Middleware configuration constants
|
|
631
|
+
* Middleware configuration constants for subdomain-based routing
|
|
633
632
|
*/
|
|
634
633
|
declare class MiddlewareConfig {
|
|
635
|
-
static readonly
|
|
636
|
-
readonly DASHBOARD: "
|
|
634
|
+
static readonly SUBDOMAINS: {
|
|
635
|
+
readonly DASHBOARD: "dashboard";
|
|
637
636
|
};
|
|
638
|
-
static readonly
|
|
637
|
+
static readonly ROUTES: {
|
|
638
|
+
readonly ROOT: "/";
|
|
639
639
|
readonly LOGIN: "/login";
|
|
640
640
|
};
|
|
641
641
|
static readonly ALLOWED_METHODS: readonly ["GET", "HEAD"];
|
|
642
642
|
static readonly QUERY_PARAMS: {
|
|
643
643
|
readonly LOGIN_REQUIRED: "sign_in_required";
|
|
644
644
|
readonly AUTH_CHECKED: "auth_checked";
|
|
645
|
+
readonly REDIRECT_URL: "redirect_url";
|
|
645
646
|
};
|
|
646
647
|
static readonly QUERY_VALUES: {
|
|
647
648
|
readonly LOGIN_REQUIRED: "true";
|
|
648
649
|
readonly AUTH_CHECKED: "1";
|
|
649
650
|
};
|
|
651
|
+
/**
|
|
652
|
+
* Get the base domain from environment or use default
|
|
653
|
+
*/
|
|
654
|
+
static getBaseDomain(): string;
|
|
655
|
+
/**
|
|
656
|
+
* Get the protocol based on environment
|
|
657
|
+
*/
|
|
658
|
+
static getProtocol(): string;
|
|
659
|
+
/**
|
|
660
|
+
* Get the dashboard subdomain URL
|
|
661
|
+
*/
|
|
662
|
+
static getDashboardUrl(path?: string): string;
|
|
650
663
|
}
|
|
651
664
|
/**
|
|
652
|
-
* Middleware matcher patterns
|
|
653
|
-
*
|
|
654
|
-
* - / (home route and all other routes for authentication protection)
|
|
655
|
-
* - /login route (for authenticated user redirection)
|
|
656
|
-
* Excludes: API routes, Next.js internals, static assets, and file extensions
|
|
665
|
+
* Middleware matcher patterns
|
|
666
|
+
* Matches all routes except API routes, Next.js internals, and static assets
|
|
657
667
|
*/
|
|
658
|
-
declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
668
|
+
declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
|
|
659
669
|
/**
|
|
660
|
-
* Middleware configuration
|
|
670
|
+
* Middleware configuration
|
|
661
671
|
*/
|
|
662
672
|
declare const config: {
|
|
663
|
-
matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
673
|
+
matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
|
|
664
674
|
};
|
|
665
675
|
|
|
666
676
|
/**
|
|
@@ -793,11 +803,11 @@ declare class BroadcastChannelEventBus<TEvent> {
|
|
|
793
803
|
/**
|
|
794
804
|
* Cross-Tab Behavior Handler
|
|
795
805
|
* Determines cross-tab behavior based on authentication events and current page context
|
|
796
|
-
* Uses lookup
|
|
806
|
+
* Uses object lookup pattern for page type detection
|
|
797
807
|
*/
|
|
798
808
|
declare class CrossTabBehaviorHandler {
|
|
799
809
|
/**
|
|
800
|
-
* Get current page type
|
|
810
|
+
* Get current page type using object lookup pattern
|
|
801
811
|
*/
|
|
802
812
|
static getCurrentPageType(): PageType;
|
|
803
813
|
/**
|
|
@@ -813,32 +823,43 @@ declare class CrossTabBehaviorHandler {
|
|
|
813
823
|
} | {
|
|
814
824
|
readonly action: NavigationAction.NONE;
|
|
815
825
|
} | {
|
|
816
|
-
readonly action: NavigationAction.
|
|
826
|
+
readonly action: NavigationAction.CURRENT;
|
|
817
827
|
} | {
|
|
818
|
-
readonly action: NavigationAction.
|
|
819
|
-
readonly target: PageType.DASHBOARD;
|
|
828
|
+
readonly action: NavigationAction.CURRENT;
|
|
820
829
|
} | {
|
|
821
|
-
readonly action: NavigationAction.
|
|
830
|
+
readonly action: NavigationAction.CURRENT;
|
|
822
831
|
} | {
|
|
823
|
-
readonly action: NavigationAction.
|
|
832
|
+
readonly action: NavigationAction.CURRENT;
|
|
824
833
|
} | {
|
|
825
|
-
readonly action: NavigationAction.
|
|
834
|
+
readonly action: NavigationAction.NONE;
|
|
826
835
|
} | {
|
|
827
|
-
readonly action: NavigationAction.
|
|
828
|
-
readonly target: PageType.HOME;
|
|
836
|
+
readonly action: NavigationAction.NONE;
|
|
829
837
|
} | {
|
|
830
|
-
readonly action: NavigationAction.
|
|
838
|
+
readonly action: NavigationAction.NONE;
|
|
831
839
|
} | {
|
|
832
840
|
readonly action: NavigationAction.NONE;
|
|
833
841
|
};
|
|
834
842
|
/**
|
|
835
843
|
* Check if current route requires redirect for given event
|
|
844
|
+
* Returns PageType to redirect to, or null if no redirect needed
|
|
836
845
|
*/
|
|
837
846
|
static shouldRedirect(currentPageType: PageType, eventType: AuthEventType): PageType | null;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* URL utility functions
|
|
851
|
+
*/
|
|
852
|
+
declare class UrlUtils {
|
|
853
|
+
/**
|
|
854
|
+
* Extract subdomain from hostname or URL
|
|
855
|
+
* Example: "dashboard.cutly.io" -> "dashboard"
|
|
856
|
+
* Example: "dashboard.localhost" -> "dashboard"
|
|
857
|
+
*/
|
|
858
|
+
static getSubdomain(url: string): string | null;
|
|
838
859
|
/**
|
|
839
|
-
* Check if
|
|
860
|
+
* Check if URL has auth-related query parameters
|
|
840
861
|
*/
|
|
841
|
-
static
|
|
862
|
+
static hasAuthParams(url: string): boolean;
|
|
842
863
|
}
|
|
843
864
|
|
|
844
865
|
/**
|
|
@@ -1489,4 +1510,4 @@ declare const useAuthFlowModal: () => {
|
|
|
1489
1510
|
openModal: () => void;
|
|
1490
1511
|
};
|
|
1491
1512
|
|
|
1492
|
-
export { AUTH_ENDPOINTS, AlertDisplay, type AlertDisplayProps, type AnyStepProps, type ApiErrorResponse, type ApiKeyConfig, type AuthActionCallbacks, type AuthActionOptions, type AuthActionResult, type AuthActionResultFailure, type AuthActionResultSuccess, type AuthActionState, type AuthEvent, AuthEventType, AuthFlowContainer, AuthFlowModal, AuthFlowStep, AuthInitializer, AuthOrchestrator, AuthOrchestratorFactory, AuthResultFactory, AuthService, type AuthState, AuthenticatedState, type AuthenticatedStateProps, AuthenticationStatusContext, type BaseComponentProps, BaseErrorHandler, BaseEventBus, BaseForm, type BaseFormField, type BaseFormProps, type BaseResponse, BaseService, type BaseStepProps, BroadcastChannelEventBus, Channel, CookieUtils, CrossTabBehaviorConfig, CrossTabBehaviorHandler, CrossTabDemo, DevelopmentLogger, EMAIL_SUBMISSION_NAVIGATION, type EmailCheckResult, type EmailExistResponse, EmailStep, type EmailStepProps, EndpointBuilder, type EventBus, ExistingUserLoginStrategy, FormFields, type FormFieldsProps, FormHeader, type FormHeaderProps, GenericErrorHandler, HttpClient, type HttpClientConfig, type HttpError, HttpMethod, type HttpRequestOptions, type HttpResponse, type IAuthOrchestrator, type IAuthService, type IAuthStatusState, type IErrorHandler, type ILogger, type ILoginFlowStrategy, type ITokenManager, LocalStorageUtils, LoggerFactory, type LoginData, LoginFlowStrategyFactory, type LoginRequest, type LoginResponse, MiddlewareConfig, type MiddlewareContext, type MiddlewareHandler, NavigationAction, NetworkErrorHandler, NextAction, PASSWORD_SUBMISSION_NAVIGATION, PageType, PageTypePatterns, PasswordStep, type PasswordStepProps, ProductionLogger, ProfileStateRenderer, ProfileUIState, type PropsFactory, RoleType, SignupFlowStrategy, type Step, type StepComponent, type StepComponentRetriever, type StepConfig, type StepPropsFactoryRegistry, type StepRegistry, type StepRegistryBaseProps, type StepRegistryConfigs, type StepRegistryHandlers, type StepRegistryParams, type StepRegistryState, type StepperActions, type StepperState$1 as StepperState, type Subscription, TokenManager, UnauthenticatedState, type UseAuthActionHandler, type UseAuthEventBusProps, type UseFormSubmissionProps, type UseStepRegistryParams, type UseStepperReturn, type UserProfile, type UserProfileResponse, type UserSession, type UserState, UserStorageManager, type UserStoreState, VERIFICATION_SUBMISSION_NAVIGATION, ValidationErrorHandler, VerificationStep, type VerificationStepProps, type VerifyEmailRequest, type VerifyEmailResponse, config, createAuthSteps, createPropsFactoryRegistry, createStepRegistry, getAuthPageStepMessage, getEmailField, getEmailStepComponent, getPasswordField, getPasswordStepComponent, getStepForEmailSubmission, getStepForPasswordSubmission, getStepForVerificationSubmission, getStepProgressMessage, getVerificationField, getVerificationStepComponent, middlewareMatcher, useAuth, useAuthActionHandler, useAuthEventBus, useAuthFlowModal, useAuthInitializer, useIsAuthenticated, useLogout, useRefreshUser, useSharedEventBus, useSignInRequiredParams, useStepRegistry, useStepRenderer, useStepper, useUser, useUserActions, useUserData, useUserError, useUserLoading, useUserProfile, useUserStore, userSelectors };
|
|
1513
|
+
export { AUTH_ENDPOINTS, AlertDisplay, type AlertDisplayProps, type AnyStepProps, type ApiErrorResponse, type ApiKeyConfig, type AuthActionCallbacks, type AuthActionOptions, type AuthActionResult, type AuthActionResultFailure, type AuthActionResultSuccess, type AuthActionState, type AuthEvent, AuthEventType, AuthFlowContainer, AuthFlowModal, AuthFlowStep, AuthInitializer, AuthOrchestrator, AuthOrchestratorFactory, AuthResultFactory, AuthService, type AuthState, AuthenticatedState, type AuthenticatedStateProps, AuthenticationStatusContext, type BaseComponentProps, BaseErrorHandler, BaseEventBus, BaseForm, type BaseFormField, type BaseFormProps, type BaseResponse, BaseService, type BaseStepProps, BroadcastChannelEventBus, Channel, CookieUtils, CrossTabBehaviorConfig, CrossTabBehaviorHandler, CrossTabDemo, DevelopmentLogger, EMAIL_SUBMISSION_NAVIGATION, type EmailCheckResult, type EmailExistResponse, EmailStep, type EmailStepProps, EndpointBuilder, type EventBus, ExistingUserLoginStrategy, FormFields, type FormFieldsProps, FormHeader, type FormHeaderProps, GenericErrorHandler, HttpClient, type HttpClientConfig, type HttpError, HttpMethod, type HttpRequestOptions, type HttpResponse, type IAuthOrchestrator, type IAuthService, type IAuthStatusState, type IErrorHandler, type ILogger, type ILoginFlowStrategy, type ITokenManager, LocalStorageUtils, LoggerFactory, type LoginData, LoginFlowStrategyFactory, type LoginRequest, type LoginResponse, MiddlewareConfig, type MiddlewareContext, type MiddlewareHandler, NavigationAction, NetworkErrorHandler, NextAction, PASSWORD_SUBMISSION_NAVIGATION, PageType, PageTypePatterns, PasswordStep, type PasswordStepProps, ProductionLogger, ProfileStateRenderer, ProfileUIState, type PropsFactory, RoleType, SignupFlowStrategy, type Step, type StepComponent, type StepComponentRetriever, type StepConfig, type StepPropsFactoryRegistry, type StepRegistry, type StepRegistryBaseProps, type StepRegistryConfigs, type StepRegistryHandlers, type StepRegistryParams, type StepRegistryState, type StepperActions, type StepperState$1 as StepperState, type Subscription, TokenManager, UnauthenticatedState, UrlUtils, type UseAuthActionHandler, type UseAuthEventBusProps, type UseFormSubmissionProps, type UseStepRegistryParams, type UseStepperReturn, type UserProfile, type UserProfileResponse, type UserSession, type UserState, UserStorageManager, type UserStoreState, VERIFICATION_SUBMISSION_NAVIGATION, ValidationErrorHandler, VerificationStep, type VerificationStepProps, type VerifyEmailRequest, type VerifyEmailResponse, config, createAuthSteps, createPropsFactoryRegistry, createStepRegistry, getAuthPageStepMessage, getEmailField, getEmailStepComponent, getPasswordField, getPasswordStepComponent, getStepForEmailSubmission, getStepForPasswordSubmission, getStepForVerificationSubmission, getStepProgressMessage, getVerificationField, getVerificationStepComponent, middlewareMatcher, useAuth, useAuthActionHandler, useAuthEventBus, useAuthFlowModal, useAuthInitializer, useIsAuthenticated, useLogout, useRefreshUser, useSharedEventBus, useSignInRequiredParams, useStepRegistry, useStepRenderer, useStepper, useUser, useUserActions, useUserData, useUserError, useUserLoading, useUserProfile, useUserStore, userSelectors };
|
package/dist/index.js
CHANGED
|
@@ -83,8 +83,8 @@ var AuthEventType = /* @__PURE__ */ ((AuthEventType3) => {
|
|
|
83
83
|
return AuthEventType3;
|
|
84
84
|
})(AuthEventType || {});
|
|
85
85
|
var PageType = /* @__PURE__ */ ((PageType3) => {
|
|
86
|
-
PageType3["LOGIN"] = "
|
|
87
|
-
PageType3["DASHBOARD"] = "
|
|
86
|
+
PageType3["LOGIN"] = "login";
|
|
87
|
+
PageType3["DASHBOARD"] = "dashboard";
|
|
88
88
|
PageType3["HOME"] = "/";
|
|
89
89
|
return PageType3;
|
|
90
90
|
})(PageType || {});
|
|
@@ -92,30 +92,30 @@ var NavigationAction = /* @__PURE__ */ ((NavigationAction2) => {
|
|
|
92
92
|
NavigationAction2["NONE"] = "none";
|
|
93
93
|
NavigationAction2["REDIRECT"] = "redirect";
|
|
94
94
|
NavigationAction2["MODAL"] = "modal";
|
|
95
|
+
NavigationAction2["CURRENT"] = "current";
|
|
95
96
|
return NavigationAction2;
|
|
96
97
|
})(NavigationAction || {});
|
|
97
98
|
var PageTypePatterns = {
|
|
98
|
-
["
|
|
99
|
-
["
|
|
100
|
-
["/" /* HOME */]: "/" /* HOME */
|
|
99
|
+
["login" /* LOGIN */]: "login" /* LOGIN */,
|
|
100
|
+
["dashboard" /* DASHBOARD */]: "dashboard" /* DASHBOARD */
|
|
101
101
|
};
|
|
102
102
|
var CrossTabBehaviorConfig = {
|
|
103
|
-
["
|
|
104
|
-
["auth.logged_in" /* LoggedIn */]: { action: "redirect" /* REDIRECT */, target: "
|
|
103
|
+
["login" /* LOGIN */]: {
|
|
104
|
+
["auth.logged_in" /* LoggedIn */]: { action: "redirect" /* REDIRECT */, target: "dashboard" /* DASHBOARD */ },
|
|
105
105
|
["auth.logged_out" /* LoggedOut */]: { action: "none" /* NONE */ },
|
|
106
106
|
["auth.email_verified" /* EmailVerified */]: { action: "none" /* NONE */ },
|
|
107
107
|
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "none" /* NONE */ }
|
|
108
108
|
},
|
|
109
|
-
["
|
|
110
|
-
["auth.logged_in" /* LoggedIn */]: { action: "
|
|
111
|
-
["auth.logged_out" /* LoggedOut */]: { action: "
|
|
112
|
-
["auth.email_verified" /* EmailVerified */]: { action: "
|
|
113
|
-
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "
|
|
109
|
+
["dashboard" /* DASHBOARD */]: {
|
|
110
|
+
["auth.logged_in" /* LoggedIn */]: { action: "current" /* CURRENT */ },
|
|
111
|
+
["auth.logged_out" /* LoggedOut */]: { action: "current" /* CURRENT */ },
|
|
112
|
+
["auth.email_verified" /* EmailVerified */]: { action: "current" /* CURRENT */ },
|
|
113
|
+
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "current" /* CURRENT */ }
|
|
114
114
|
},
|
|
115
115
|
["/" /* HOME */]: {
|
|
116
|
-
["auth.logged_in" /* LoggedIn */]: { action: "
|
|
117
|
-
["auth.logged_out" /* LoggedOut */]: { action: "
|
|
118
|
-
["auth.email_verified" /* EmailVerified */]: { action: "
|
|
116
|
+
["auth.logged_in" /* LoggedIn */]: { action: "none" /* NONE */ },
|
|
117
|
+
["auth.logged_out" /* LoggedOut */]: { action: "none" /* NONE */ },
|
|
118
|
+
["auth.email_verified" /* EmailVerified */]: { action: "none" /* NONE */ },
|
|
119
119
|
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "none" /* NONE */ }
|
|
120
120
|
}
|
|
121
121
|
};
|
|
@@ -254,13 +254,32 @@ var getVerificationField = (codeLength = 5, options = {}) => ({
|
|
|
254
254
|
|
|
255
255
|
// src/config/middleware.ts
|
|
256
256
|
var MiddlewareConfig = class {
|
|
257
|
+
/**
|
|
258
|
+
* Get the base domain from environment or use default
|
|
259
|
+
*/
|
|
260
|
+
static getBaseDomain() {
|
|
261
|
+
return process.env.NEXT_PUBLIC_BASE_DOMAIN || "cutly.io";
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Get the protocol based on environment
|
|
265
|
+
*/
|
|
266
|
+
static getProtocol() {
|
|
267
|
+
return process.env.NODE_ENV === "production" ? "https" : "http";
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Get the dashboard subdomain URL
|
|
271
|
+
*/
|
|
272
|
+
static getDashboardUrl(path = "") {
|
|
273
|
+
return `${this.getProtocol()}://${this.SUBDOMAINS.DASHBOARD}.${this.getBaseDomain()}${path}`;
|
|
274
|
+
}
|
|
257
275
|
};
|
|
258
|
-
//
|
|
259
|
-
MiddlewareConfig.
|
|
260
|
-
DASHBOARD: "
|
|
276
|
+
// Subdomain configuration
|
|
277
|
+
MiddlewareConfig.SUBDOMAINS = {
|
|
278
|
+
DASHBOARD: "dashboard"
|
|
261
279
|
};
|
|
262
|
-
//
|
|
263
|
-
MiddlewareConfig.
|
|
280
|
+
// Routes
|
|
281
|
+
MiddlewareConfig.ROUTES = {
|
|
282
|
+
ROOT: "/",
|
|
264
283
|
LOGIN: "/login"
|
|
265
284
|
};
|
|
266
285
|
// HTTP methods to process
|
|
@@ -268,7 +287,8 @@ MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
|
|
|
268
287
|
// Query parameters
|
|
269
288
|
MiddlewareConfig.QUERY_PARAMS = {
|
|
270
289
|
LOGIN_REQUIRED: "sign_in_required",
|
|
271
|
-
AUTH_CHECKED: "auth_checked"
|
|
290
|
+
AUTH_CHECKED: "auth_checked",
|
|
291
|
+
REDIRECT_URL: "redirect_url"
|
|
272
292
|
};
|
|
273
293
|
// Query parameter values
|
|
274
294
|
MiddlewareConfig.QUERY_VALUES = {
|
|
@@ -276,8 +296,7 @@ MiddlewareConfig.QUERY_VALUES = {
|
|
|
276
296
|
AUTH_CHECKED: "1"
|
|
277
297
|
};
|
|
278
298
|
var middlewareMatcher = [
|
|
279
|
-
"/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
280
|
-
"/login"
|
|
299
|
+
"/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
281
300
|
];
|
|
282
301
|
var config = {
|
|
283
302
|
matcher: middlewareMatcher
|
|
@@ -744,18 +763,53 @@ var BroadcastChannelEventBus = class _BroadcastChannelEventBus {
|
|
|
744
763
|
}
|
|
745
764
|
};
|
|
746
765
|
|
|
766
|
+
// src/services/utils/url-utils.ts
|
|
767
|
+
var UrlUtils = class {
|
|
768
|
+
/**
|
|
769
|
+
* Extract subdomain from hostname or URL
|
|
770
|
+
* Example: "dashboard.cutly.io" -> "dashboard"
|
|
771
|
+
* Example: "dashboard.localhost" -> "dashboard"
|
|
772
|
+
*/
|
|
773
|
+
static getSubdomain(url) {
|
|
774
|
+
try {
|
|
775
|
+
const domain = new URL(`http://${url}`).hostname;
|
|
776
|
+
const parts = domain.split(".");
|
|
777
|
+
if (parts.length < 2 || domain === "localhost" || /^\d{1,3}(\.\d{1,3}){3}/.test(domain) || domain.startsWith(MiddlewareConfig.getBaseDomain())) {
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
return parts[0] || null;
|
|
781
|
+
} catch (e) {
|
|
782
|
+
return null;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Check if URL has auth-related query parameters
|
|
787
|
+
*/
|
|
788
|
+
static hasAuthParams(url) {
|
|
789
|
+
return url.includes(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED);
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
|
|
747
793
|
// src/services/utils/cross-tab-behavior-handler.ts
|
|
748
794
|
var CrossTabBehaviorHandler = class {
|
|
749
795
|
/**
|
|
750
|
-
* Get current page type
|
|
796
|
+
* Get current page type using object lookup pattern
|
|
751
797
|
*/
|
|
752
798
|
static getCurrentPageType() {
|
|
753
|
-
var _a
|
|
799
|
+
var _a;
|
|
754
800
|
if (typeof window === "undefined") return "/" /* HOME */;
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
801
|
+
try {
|
|
802
|
+
const pathname = window.location.pathname;
|
|
803
|
+
const subdomain = UrlUtils.getSubdomain(window.location.hostname);
|
|
804
|
+
const pageTypeMatchers = {
|
|
805
|
+
["login" /* LOGIN */]: pathname === MiddlewareConfig.ROUTES.LOGIN,
|
|
806
|
+
["dashboard" /* DASHBOARD */]: subdomain === MiddlewareConfig.SUBDOMAINS.DASHBOARD
|
|
807
|
+
};
|
|
808
|
+
const matchedPageType = (_a = Object.entries(pageTypeMatchers).find(([, matches]) => matches)) == null ? void 0 : _a[0];
|
|
809
|
+
return matchedPageType != null ? matchedPageType : "dashboard" /* DASHBOARD */;
|
|
810
|
+
} catch (e) {
|
|
811
|
+
return "dashboard" /* DASHBOARD */;
|
|
812
|
+
}
|
|
759
813
|
}
|
|
760
814
|
/**
|
|
761
815
|
* Get the action configuration for current route and event
|
|
@@ -766,18 +820,12 @@ var CrossTabBehaviorHandler = class {
|
|
|
766
820
|
}
|
|
767
821
|
/**
|
|
768
822
|
* Check if current route requires redirect for given event
|
|
823
|
+
* Returns PageType to redirect to, or null if no redirect needed
|
|
769
824
|
*/
|
|
770
825
|
static shouldRedirect(currentPageType, eventType) {
|
|
771
826
|
const action = this.getAction(currentPageType, eventType);
|
|
772
827
|
return action.action === "redirect" /* REDIRECT */ ? action.target : null;
|
|
773
828
|
}
|
|
774
|
-
/**
|
|
775
|
-
* Check if current route should show modal for given event
|
|
776
|
-
*/
|
|
777
|
-
static shouldShowModal(currentPageType, eventType) {
|
|
778
|
-
const action = this.getAction(currentPageType, eventType);
|
|
779
|
-
return action.action === "modal" /* MODAL */;
|
|
780
|
-
}
|
|
781
829
|
};
|
|
782
830
|
|
|
783
831
|
// src/services/auth/manager/token-manager.ts
|
|
@@ -2315,6 +2363,13 @@ var useAuthEventBus = ({ onLoggedOut, onLoggedIn } = {}) => {
|
|
|
2315
2363
|
window.location.replace(target);
|
|
2316
2364
|
}
|
|
2317
2365
|
},
|
|
2366
|
+
["current" /* CURRENT */]: () => {
|
|
2367
|
+
const isAuthAction = e.type === "auth.logged_in" /* LoggedIn */ || e.type === "auth.logged_out" /* LoggedOut */;
|
|
2368
|
+
const hasParams = UrlUtils.hasAuthParams(window.location.href);
|
|
2369
|
+
if (isAuthAction || !hasParams) {
|
|
2370
|
+
window.location.reload();
|
|
2371
|
+
}
|
|
2372
|
+
},
|
|
2318
2373
|
["modal" /* MODAL */]: () => {
|
|
2319
2374
|
if (e.type === "auth.logged_in" /* LoggedIn */) {
|
|
2320
2375
|
window.location.replace(window.location.href);
|
|
@@ -2988,7 +3043,8 @@ var CrossTabDemo = () => {
|
|
|
2988
3043
|
|
|
2989
3044
|
|
|
2990
3045
|
|
|
2991
|
-
|
|
3046
|
+
|
|
3047
|
+
exports.AUTH_ENDPOINTS = AUTH_ENDPOINTS; exports.AlertDisplay = AlertDisplay; exports.AuthEventType = AuthEventType; exports.AuthFlowContainer = AuthFlowContainer; exports.AuthFlowModal = AuthFlowModal; exports.AuthFlowStep = AuthFlowStep; exports.AuthInitializer = AuthInitializer; exports.AuthOrchestrator = AuthOrchestrator; exports.AuthOrchestratorFactory = AuthOrchestratorFactory; exports.AuthResultFactory = AuthResultFactory; exports.AuthService = AuthService; exports.AuthenticatedState = AuthenticatedState; exports.AuthenticationStatusContext = AuthenticationStatusContext; exports.BaseErrorHandler = BaseErrorHandler; exports.BaseEventBus = BaseEventBus; exports.BaseForm = BaseForm; exports.BaseService = BaseService; exports.BroadcastChannelEventBus = BroadcastChannelEventBus; exports.Channel = Channel; exports.CookieUtils = CookieUtils; exports.CrossTabBehaviorConfig = CrossTabBehaviorConfig; exports.CrossTabBehaviorHandler = CrossTabBehaviorHandler; exports.CrossTabDemo = CrossTabDemo; exports.DevelopmentLogger = DevelopmentLogger; exports.EMAIL_SUBMISSION_NAVIGATION = EMAIL_SUBMISSION_NAVIGATION; exports.EmailStep = EmailStep; exports.EndpointBuilder = EndpointBuilder; exports.ExistingUserLoginStrategy = ExistingUserLoginStrategy; exports.FormFields = FormFields; exports.FormHeader = FormHeader; exports.GenericErrorHandler = GenericErrorHandler; exports.HttpClient = HttpClient; exports.HttpMethod = HttpMethod; exports.LocalStorageUtils = LocalStorageUtils; exports.LoggerFactory = LoggerFactory; exports.LoginFlowStrategyFactory = LoginFlowStrategyFactory; exports.MiddlewareConfig = MiddlewareConfig; exports.NavigationAction = NavigationAction; exports.NetworkErrorHandler = NetworkErrorHandler; exports.NextAction = NextAction; exports.PASSWORD_SUBMISSION_NAVIGATION = PASSWORD_SUBMISSION_NAVIGATION; exports.PageType = PageType; exports.PageTypePatterns = PageTypePatterns; exports.PasswordStep = PasswordStep; exports.ProductionLogger = ProductionLogger; exports.ProfileStateRenderer = ProfileStateRenderer; exports.ProfileUIState = ProfileUIState; exports.RoleType = RoleType; exports.SignupFlowStrategy = SignupFlowStrategy; exports.TokenManager = TokenManager; exports.UnauthenticatedState = UnauthenticatedState; exports.UrlUtils = UrlUtils; exports.UserStorageManager = UserStorageManager; exports.VERIFICATION_SUBMISSION_NAVIGATION = VERIFICATION_SUBMISSION_NAVIGATION; exports.ValidationErrorHandler = ValidationErrorHandler; exports.VerificationStep = VerificationStep; exports.config = config; exports.createAuthSteps = createAuthSteps; exports.createPropsFactoryRegistry = createPropsFactoryRegistry; exports.createStepRegistry = createStepRegistry; exports.getAuthPageStepMessage = getAuthPageStepMessage; exports.getEmailField = getEmailField; exports.getEmailStepComponent = getEmailStepComponent; exports.getPasswordField = getPasswordField; exports.getPasswordStepComponent = getPasswordStepComponent; exports.getStepForEmailSubmission = getStepForEmailSubmission; exports.getStepForPasswordSubmission = getStepForPasswordSubmission; exports.getStepForVerificationSubmission = getStepForVerificationSubmission; exports.getStepProgressMessage = getStepProgressMessage; exports.getVerificationField = getVerificationField; exports.getVerificationStepComponent = getVerificationStepComponent; exports.middlewareMatcher = middlewareMatcher; exports.useAuth = useAuth; exports.useAuthActionHandler = useAuthActionHandler; exports.useAuthEventBus = useAuthEventBus; exports.useAuthFlowModal = useAuthFlowModal; exports.useAuthInitializer = useAuthInitializer; exports.useIsAuthenticated = useIsAuthenticated; exports.useLogout = useLogout; exports.useRefreshUser = useRefreshUser; exports.useSharedEventBus = useSharedEventBus; exports.useSignInRequiredParams = useSignInRequiredParams; exports.useStepRegistry = useStepRegistry; exports.useStepRenderer = useStepRenderer; exports.useStepper = useStepper; exports.useUser = useUser; exports.useUserActions = useUserActions; exports.useUserData = useUserData; exports.useUserError = useUserError; exports.useUserLoading = useUserLoading; exports.useUserProfile = useUserProfile; exports.useUserStore = useUserStore; exports.userSelectors = userSelectors;
|
|
2992
3048
|
/*! Bundled license information:
|
|
2993
3049
|
|
|
2994
3050
|
js-cookie/dist/js.cookie.mjs:
|
package/dist/index.mjs
CHANGED
|
@@ -83,8 +83,8 @@ var AuthEventType = /* @__PURE__ */ ((AuthEventType3) => {
|
|
|
83
83
|
return AuthEventType3;
|
|
84
84
|
})(AuthEventType || {});
|
|
85
85
|
var PageType = /* @__PURE__ */ ((PageType3) => {
|
|
86
|
-
PageType3["LOGIN"] = "
|
|
87
|
-
PageType3["DASHBOARD"] = "
|
|
86
|
+
PageType3["LOGIN"] = "login";
|
|
87
|
+
PageType3["DASHBOARD"] = "dashboard";
|
|
88
88
|
PageType3["HOME"] = "/";
|
|
89
89
|
return PageType3;
|
|
90
90
|
})(PageType || {});
|
|
@@ -92,30 +92,30 @@ var NavigationAction = /* @__PURE__ */ ((NavigationAction2) => {
|
|
|
92
92
|
NavigationAction2["NONE"] = "none";
|
|
93
93
|
NavigationAction2["REDIRECT"] = "redirect";
|
|
94
94
|
NavigationAction2["MODAL"] = "modal";
|
|
95
|
+
NavigationAction2["CURRENT"] = "current";
|
|
95
96
|
return NavigationAction2;
|
|
96
97
|
})(NavigationAction || {});
|
|
97
98
|
var PageTypePatterns = {
|
|
98
|
-
["
|
|
99
|
-
["
|
|
100
|
-
["/" /* HOME */]: "/" /* HOME */
|
|
99
|
+
["login" /* LOGIN */]: "login" /* LOGIN */,
|
|
100
|
+
["dashboard" /* DASHBOARD */]: "dashboard" /* DASHBOARD */
|
|
101
101
|
};
|
|
102
102
|
var CrossTabBehaviorConfig = {
|
|
103
|
-
["
|
|
104
|
-
["auth.logged_in" /* LoggedIn */]: { action: "redirect" /* REDIRECT */, target: "
|
|
103
|
+
["login" /* LOGIN */]: {
|
|
104
|
+
["auth.logged_in" /* LoggedIn */]: { action: "redirect" /* REDIRECT */, target: "dashboard" /* DASHBOARD */ },
|
|
105
105
|
["auth.logged_out" /* LoggedOut */]: { action: "none" /* NONE */ },
|
|
106
106
|
["auth.email_verified" /* EmailVerified */]: { action: "none" /* NONE */ },
|
|
107
107
|
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "none" /* NONE */ }
|
|
108
108
|
},
|
|
109
|
-
["
|
|
110
|
-
["auth.logged_in" /* LoggedIn */]: { action: "
|
|
111
|
-
["auth.logged_out" /* LoggedOut */]: { action: "
|
|
112
|
-
["auth.email_verified" /* EmailVerified */]: { action: "
|
|
113
|
-
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "
|
|
109
|
+
["dashboard" /* DASHBOARD */]: {
|
|
110
|
+
["auth.logged_in" /* LoggedIn */]: { action: "current" /* CURRENT */ },
|
|
111
|
+
["auth.logged_out" /* LoggedOut */]: { action: "current" /* CURRENT */ },
|
|
112
|
+
["auth.email_verified" /* EmailVerified */]: { action: "current" /* CURRENT */ },
|
|
113
|
+
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "current" /* CURRENT */ }
|
|
114
114
|
},
|
|
115
115
|
["/" /* HOME */]: {
|
|
116
|
-
["auth.logged_in" /* LoggedIn */]: { action: "
|
|
117
|
-
["auth.logged_out" /* LoggedOut */]: { action: "
|
|
118
|
-
["auth.email_verified" /* EmailVerified */]: { action: "
|
|
116
|
+
["auth.logged_in" /* LoggedIn */]: { action: "none" /* NONE */ },
|
|
117
|
+
["auth.logged_out" /* LoggedOut */]: { action: "none" /* NONE */ },
|
|
118
|
+
["auth.email_verified" /* EmailVerified */]: { action: "none" /* NONE */ },
|
|
119
119
|
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "none" /* NONE */ }
|
|
120
120
|
}
|
|
121
121
|
};
|
|
@@ -254,13 +254,32 @@ var getVerificationField = (codeLength = 5, options = {}) => ({
|
|
|
254
254
|
|
|
255
255
|
// src/config/middleware.ts
|
|
256
256
|
var MiddlewareConfig = class {
|
|
257
|
+
/**
|
|
258
|
+
* Get the base domain from environment or use default
|
|
259
|
+
*/
|
|
260
|
+
static getBaseDomain() {
|
|
261
|
+
return process.env.NEXT_PUBLIC_BASE_DOMAIN || "cutly.io";
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Get the protocol based on environment
|
|
265
|
+
*/
|
|
266
|
+
static getProtocol() {
|
|
267
|
+
return process.env.NODE_ENV === "production" ? "https" : "http";
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Get the dashboard subdomain URL
|
|
271
|
+
*/
|
|
272
|
+
static getDashboardUrl(path = "") {
|
|
273
|
+
return `${this.getProtocol()}://${this.SUBDOMAINS.DASHBOARD}.${this.getBaseDomain()}${path}`;
|
|
274
|
+
}
|
|
257
275
|
};
|
|
258
|
-
//
|
|
259
|
-
MiddlewareConfig.
|
|
260
|
-
DASHBOARD: "
|
|
276
|
+
// Subdomain configuration
|
|
277
|
+
MiddlewareConfig.SUBDOMAINS = {
|
|
278
|
+
DASHBOARD: "dashboard"
|
|
261
279
|
};
|
|
262
|
-
//
|
|
263
|
-
MiddlewareConfig.
|
|
280
|
+
// Routes
|
|
281
|
+
MiddlewareConfig.ROUTES = {
|
|
282
|
+
ROOT: "/",
|
|
264
283
|
LOGIN: "/login"
|
|
265
284
|
};
|
|
266
285
|
// HTTP methods to process
|
|
@@ -268,7 +287,8 @@ MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
|
|
|
268
287
|
// Query parameters
|
|
269
288
|
MiddlewareConfig.QUERY_PARAMS = {
|
|
270
289
|
LOGIN_REQUIRED: "sign_in_required",
|
|
271
|
-
AUTH_CHECKED: "auth_checked"
|
|
290
|
+
AUTH_CHECKED: "auth_checked",
|
|
291
|
+
REDIRECT_URL: "redirect_url"
|
|
272
292
|
};
|
|
273
293
|
// Query parameter values
|
|
274
294
|
MiddlewareConfig.QUERY_VALUES = {
|
|
@@ -276,8 +296,7 @@ MiddlewareConfig.QUERY_VALUES = {
|
|
|
276
296
|
AUTH_CHECKED: "1"
|
|
277
297
|
};
|
|
278
298
|
var middlewareMatcher = [
|
|
279
|
-
"/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
280
|
-
"/login"
|
|
299
|
+
"/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
281
300
|
];
|
|
282
301
|
var config = {
|
|
283
302
|
matcher: middlewareMatcher
|
|
@@ -744,18 +763,53 @@ var BroadcastChannelEventBus = class _BroadcastChannelEventBus {
|
|
|
744
763
|
}
|
|
745
764
|
};
|
|
746
765
|
|
|
766
|
+
// src/services/utils/url-utils.ts
|
|
767
|
+
var UrlUtils = class {
|
|
768
|
+
/**
|
|
769
|
+
* Extract subdomain from hostname or URL
|
|
770
|
+
* Example: "dashboard.cutly.io" -> "dashboard"
|
|
771
|
+
* Example: "dashboard.localhost" -> "dashboard"
|
|
772
|
+
*/
|
|
773
|
+
static getSubdomain(url) {
|
|
774
|
+
try {
|
|
775
|
+
const domain = new URL(`http://${url}`).hostname;
|
|
776
|
+
const parts = domain.split(".");
|
|
777
|
+
if (parts.length < 2 || domain === "localhost" || /^\d{1,3}(\.\d{1,3}){3}/.test(domain) || domain.startsWith(MiddlewareConfig.getBaseDomain())) {
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
return parts[0] || null;
|
|
781
|
+
} catch (e) {
|
|
782
|
+
return null;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Check if URL has auth-related query parameters
|
|
787
|
+
*/
|
|
788
|
+
static hasAuthParams(url) {
|
|
789
|
+
return url.includes(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED);
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
|
|
747
793
|
// src/services/utils/cross-tab-behavior-handler.ts
|
|
748
794
|
var CrossTabBehaviorHandler = class {
|
|
749
795
|
/**
|
|
750
|
-
* Get current page type
|
|
796
|
+
* Get current page type using object lookup pattern
|
|
751
797
|
*/
|
|
752
798
|
static getCurrentPageType() {
|
|
753
|
-
var _a
|
|
799
|
+
var _a;
|
|
754
800
|
if (typeof window === "undefined") return "/" /* HOME */;
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
801
|
+
try {
|
|
802
|
+
const pathname = window.location.pathname;
|
|
803
|
+
const subdomain = UrlUtils.getSubdomain(window.location.hostname);
|
|
804
|
+
const pageTypeMatchers = {
|
|
805
|
+
["login" /* LOGIN */]: pathname === MiddlewareConfig.ROUTES.LOGIN,
|
|
806
|
+
["dashboard" /* DASHBOARD */]: subdomain === MiddlewareConfig.SUBDOMAINS.DASHBOARD
|
|
807
|
+
};
|
|
808
|
+
const matchedPageType = (_a = Object.entries(pageTypeMatchers).find(([, matches]) => matches)) == null ? void 0 : _a[0];
|
|
809
|
+
return matchedPageType != null ? matchedPageType : "dashboard" /* DASHBOARD */;
|
|
810
|
+
} catch (e) {
|
|
811
|
+
return "dashboard" /* DASHBOARD */;
|
|
812
|
+
}
|
|
759
813
|
}
|
|
760
814
|
/**
|
|
761
815
|
* Get the action configuration for current route and event
|
|
@@ -766,18 +820,12 @@ var CrossTabBehaviorHandler = class {
|
|
|
766
820
|
}
|
|
767
821
|
/**
|
|
768
822
|
* Check if current route requires redirect for given event
|
|
823
|
+
* Returns PageType to redirect to, or null if no redirect needed
|
|
769
824
|
*/
|
|
770
825
|
static shouldRedirect(currentPageType, eventType) {
|
|
771
826
|
const action = this.getAction(currentPageType, eventType);
|
|
772
827
|
return action.action === "redirect" /* REDIRECT */ ? action.target : null;
|
|
773
828
|
}
|
|
774
|
-
/**
|
|
775
|
-
* Check if current route should show modal for given event
|
|
776
|
-
*/
|
|
777
|
-
static shouldShowModal(currentPageType, eventType) {
|
|
778
|
-
const action = this.getAction(currentPageType, eventType);
|
|
779
|
-
return action.action === "modal" /* MODAL */;
|
|
780
|
-
}
|
|
781
829
|
};
|
|
782
830
|
|
|
783
831
|
// src/services/auth/manager/token-manager.ts
|
|
@@ -2315,6 +2363,13 @@ var useAuthEventBus = ({ onLoggedOut, onLoggedIn } = {}) => {
|
|
|
2315
2363
|
window.location.replace(target);
|
|
2316
2364
|
}
|
|
2317
2365
|
},
|
|
2366
|
+
["current" /* CURRENT */]: () => {
|
|
2367
|
+
const isAuthAction = e.type === "auth.logged_in" /* LoggedIn */ || e.type === "auth.logged_out" /* LoggedOut */;
|
|
2368
|
+
const hasParams = UrlUtils.hasAuthParams(window.location.href);
|
|
2369
|
+
if (isAuthAction || !hasParams) {
|
|
2370
|
+
window.location.reload();
|
|
2371
|
+
}
|
|
2372
|
+
},
|
|
2318
2373
|
["modal" /* MODAL */]: () => {
|
|
2319
2374
|
if (e.type === "auth.logged_in" /* LoggedIn */) {
|
|
2320
2375
|
window.location.replace(window.location.href);
|
|
@@ -2947,6 +3002,7 @@ export {
|
|
|
2947
3002
|
SignupFlowStrategy,
|
|
2948
3003
|
TokenManager,
|
|
2949
3004
|
UnauthenticatedState,
|
|
3005
|
+
UrlUtils,
|
|
2950
3006
|
UserStorageManager,
|
|
2951
3007
|
VERIFICATION_SUBMISSION_NAVIGATION,
|
|
2952
3008
|
ValidationErrorHandler,
|
package/dist/middleware.d.mts
CHANGED
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Middleware matcher patterns
|
|
5
|
-
*
|
|
6
|
-
* - / (home route and all other routes for authentication protection)
|
|
7
|
-
* - /login route (for authenticated user redirection)
|
|
8
|
-
* Excludes: API routes, Next.js internals, static assets, and file extensions
|
|
4
|
+
* Middleware matcher patterns
|
|
5
|
+
* Matches all routes except API routes, Next.js internals, and static assets
|
|
9
6
|
*/
|
|
10
|
-
declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
7
|
+
declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
|
|
11
8
|
/**
|
|
12
|
-
* Middleware configuration
|
|
9
|
+
* Middleware configuration
|
|
13
10
|
*/
|
|
14
11
|
declare const config: {
|
|
15
|
-
matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
12
|
+
matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
|
|
16
13
|
};
|
|
17
14
|
|
|
18
15
|
/**
|
|
19
|
-
* Authentication middleware
|
|
16
|
+
* Authentication middleware for subdomain-based routing
|
|
20
17
|
* Chain order:
|
|
21
18
|
* 1. MethodFilterHandler - filters HTTP methods (GET/HEAD only)
|
|
22
|
-
* 2.
|
|
23
|
-
* 3. LoginRedirectHandler - redirects authenticated users away from login
|
|
24
|
-
* 4. AuthenticationHandler - validates JWT and handles query parameter cleanup
|
|
19
|
+
* 2. AuthenticationHandler - validates JWT and adds login params if needed
|
|
25
20
|
*/
|
|
26
21
|
declare function middleware(req: NextRequest): Promise<NextResponse>;
|
|
27
22
|
|
package/dist/middleware.mjs
CHANGED
|
@@ -23,13 +23,32 @@ import { NextResponse } from "next/server";
|
|
|
23
23
|
|
|
24
24
|
// src/config/middleware.ts
|
|
25
25
|
var MiddlewareConfig = class {
|
|
26
|
+
/**
|
|
27
|
+
* Get the base domain from environment or use default
|
|
28
|
+
*/
|
|
29
|
+
static getBaseDomain() {
|
|
30
|
+
return process.env.NEXT_PUBLIC_BASE_DOMAIN || "cutly.io";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the protocol based on environment
|
|
34
|
+
*/
|
|
35
|
+
static getProtocol() {
|
|
36
|
+
return process.env.NODE_ENV === "production" ? "https" : "http";
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get the dashboard subdomain URL
|
|
40
|
+
*/
|
|
41
|
+
static getDashboardUrl(path = "") {
|
|
42
|
+
return `${this.getProtocol()}://${this.SUBDOMAINS.DASHBOARD}.${this.getBaseDomain()}${path}`;
|
|
43
|
+
}
|
|
26
44
|
};
|
|
27
|
-
//
|
|
28
|
-
MiddlewareConfig.
|
|
29
|
-
DASHBOARD: "
|
|
45
|
+
// Subdomain configuration
|
|
46
|
+
MiddlewareConfig.SUBDOMAINS = {
|
|
47
|
+
DASHBOARD: "dashboard"
|
|
30
48
|
};
|
|
31
|
-
//
|
|
32
|
-
MiddlewareConfig.
|
|
49
|
+
// Routes
|
|
50
|
+
MiddlewareConfig.ROUTES = {
|
|
51
|
+
ROOT: "/",
|
|
33
52
|
LOGIN: "/login"
|
|
34
53
|
};
|
|
35
54
|
// HTTP methods to process
|
|
@@ -37,7 +56,8 @@ MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
|
|
|
37
56
|
// Query parameters
|
|
38
57
|
MiddlewareConfig.QUERY_PARAMS = {
|
|
39
58
|
LOGIN_REQUIRED: "sign_in_required",
|
|
40
|
-
AUTH_CHECKED: "auth_checked"
|
|
59
|
+
AUTH_CHECKED: "auth_checked",
|
|
60
|
+
REDIRECT_URL: "redirect_url"
|
|
41
61
|
};
|
|
42
62
|
// Query parameter values
|
|
43
63
|
MiddlewareConfig.QUERY_VALUES = {
|
|
@@ -45,8 +65,7 @@ MiddlewareConfig.QUERY_VALUES = {
|
|
|
45
65
|
AUTH_CHECKED: "1"
|
|
46
66
|
};
|
|
47
67
|
var middlewareMatcher = [
|
|
48
|
-
"/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
49
|
-
"/login"
|
|
68
|
+
"/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
50
69
|
];
|
|
51
70
|
var config = {
|
|
52
71
|
matcher: middlewareMatcher
|
|
@@ -356,6 +375,33 @@ LocalStorageUtils.USER_PROFILE_STORAGE_KEY = "user_profile_data";
|
|
|
356
375
|
LocalStorageUtils.USER_PROFILE_TIMESTAMP_KEY = "user_profile_timestamp";
|
|
357
376
|
LocalStorageUtils.DEFAULT_CACHE_DURATION = 5 * 60 * 1e3;
|
|
358
377
|
|
|
378
|
+
// src/services/utils/url-utils.ts
|
|
379
|
+
var UrlUtils = class {
|
|
380
|
+
/**
|
|
381
|
+
* Extract subdomain from hostname or URL
|
|
382
|
+
* Example: "dashboard.cutly.io" -> "dashboard"
|
|
383
|
+
* Example: "dashboard.localhost" -> "dashboard"
|
|
384
|
+
*/
|
|
385
|
+
static getSubdomain(url) {
|
|
386
|
+
try {
|
|
387
|
+
const domain = new URL(`http://${url}`).hostname;
|
|
388
|
+
const parts = domain.split(".");
|
|
389
|
+
if (parts.length < 2 || domain === "localhost" || /^\d{1,3}(\.\d{1,3}){3}/.test(domain) || domain.startsWith(MiddlewareConfig.getBaseDomain())) {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
return parts[0] || null;
|
|
393
|
+
} catch (e) {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Check if URL has auth-related query parameters
|
|
399
|
+
*/
|
|
400
|
+
static hasAuthParams(url) {
|
|
401
|
+
return url.includes(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED);
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
|
|
359
405
|
// src/services/api/endpoints.ts
|
|
360
406
|
var AUTH_ENDPOINTS = {
|
|
361
407
|
// Email existence check
|
|
@@ -567,6 +613,12 @@ AuthenticationStatusContext.states = /* @__PURE__ */ new Map([
|
|
|
567
613
|
|
|
568
614
|
// src/middlewares/handlers/base-middleware-handler.ts
|
|
569
615
|
var BaseMiddlewareHandler = class {
|
|
616
|
+
/**
|
|
617
|
+
* Check if current request is on dashboard subdomain
|
|
618
|
+
*/
|
|
619
|
+
isDashboardSubdomain(hostname) {
|
|
620
|
+
return UrlUtils.getSubdomain(hostname) === MiddlewareConfig.SUBDOMAINS.DASHBOARD;
|
|
621
|
+
}
|
|
570
622
|
/**
|
|
571
623
|
* Check if user has both access and refresh tokens
|
|
572
624
|
*/
|
|
@@ -575,7 +627,7 @@ var BaseMiddlewareHandler = class {
|
|
|
575
627
|
return cookies.has(accessTokenKey) && cookies.has(refreshTokenKey);
|
|
576
628
|
}
|
|
577
629
|
/**
|
|
578
|
-
* Get authentication cookie keys from environment variables
|
|
630
|
+
* Get authentication cookie keys from environment variables
|
|
579
631
|
*/
|
|
580
632
|
getAuthCookieKeys() {
|
|
581
633
|
return {
|
|
@@ -584,49 +636,18 @@ var BaseMiddlewareHandler = class {
|
|
|
584
636
|
};
|
|
585
637
|
}
|
|
586
638
|
/**
|
|
587
|
-
*
|
|
639
|
+
* Add login modal parameters to current URL
|
|
640
|
+
* Redirects to same page with sign_in_required parameter to trigger modal
|
|
588
641
|
*/
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
return NextResponse.redirect(dashboardUrl);
|
|
592
|
-
}
|
|
593
|
-
/**
|
|
594
|
-
* Create a redirect response to login with authentication parameters
|
|
595
|
-
* Includes loop prevention - won't redirect if already has auth_checked parameter
|
|
596
|
-
*/
|
|
597
|
-
redirectToLoginWithParams(context) {
|
|
598
|
-
const loginUrl = new URL(MiddlewareConfig.AUTH_ROUTES.LOGIN, context.request.url);
|
|
599
|
-
if (context.searchParams.get(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED) === MiddlewareConfig.QUERY_VALUES.AUTH_CHECKED) {
|
|
642
|
+
addLoginModalParams(context) {
|
|
643
|
+
if (this.hasAuthCheckedParam(context.searchParams)) {
|
|
600
644
|
return NextResponse.next();
|
|
601
645
|
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
* Create a redirect response with custom URL and auth parameters
|
|
608
|
-
* Includes loop prevention - won't redirect if target already has auth_checked parameter
|
|
609
|
-
*/
|
|
610
|
-
redirectWithAuthParams(targetUrl) {
|
|
611
|
-
const url = new URL(targetUrl.toString());
|
|
612
|
-
if (url.searchParams.get(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED) === MiddlewareConfig.QUERY_VALUES.AUTH_CHECKED) {
|
|
613
|
-
return NextResponse.next();
|
|
614
|
-
}
|
|
615
|
-
url.searchParams.set(MiddlewareConfig.QUERY_PARAMS.LOGIN_REQUIRED, MiddlewareConfig.QUERY_VALUES.LOGIN_REQUIRED);
|
|
616
|
-
url.searchParams.set(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED, MiddlewareConfig.QUERY_VALUES.AUTH_CHECKED);
|
|
617
|
-
return NextResponse.redirect(url);
|
|
618
|
-
}
|
|
619
|
-
/**
|
|
620
|
-
* Check if the current path is a dashboard route
|
|
621
|
-
*/
|
|
622
|
-
isDashboardRoute(pathname) {
|
|
623
|
-
return pathname.startsWith(MiddlewareConfig.PROTECTED_ROUTES.DASHBOARD);
|
|
624
|
-
}
|
|
625
|
-
/**
|
|
626
|
-
* Check if the current path is the login page
|
|
627
|
-
*/
|
|
628
|
-
isLoginRoute(pathname) {
|
|
629
|
-
return pathname === MiddlewareConfig.AUTH_ROUTES.LOGIN;
|
|
646
|
+
const currentUrl = new URL(context.request.url);
|
|
647
|
+
currentUrl.searchParams.set(MiddlewareConfig.QUERY_PARAMS.LOGIN_REQUIRED, MiddlewareConfig.QUERY_VALUES.LOGIN_REQUIRED);
|
|
648
|
+
currentUrl.searchParams.set(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED, MiddlewareConfig.QUERY_VALUES.AUTH_CHECKED);
|
|
649
|
+
currentUrl.searchParams.set(MiddlewareConfig.QUERY_PARAMS.REDIRECT_URL, context.pathname);
|
|
650
|
+
return NextResponse.redirect(currentUrl);
|
|
630
651
|
}
|
|
631
652
|
/**
|
|
632
653
|
* Check if request method is allowed
|
|
@@ -653,24 +674,25 @@ var BaseMiddlewareHandler = class {
|
|
|
653
674
|
return NextResponse.next();
|
|
654
675
|
}
|
|
655
676
|
/**
|
|
656
|
-
*
|
|
677
|
+
* Remove auth-related query parameters and redirect to clean URL
|
|
657
678
|
*/
|
|
658
|
-
|
|
679
|
+
removeAuthParams(context) {
|
|
659
680
|
const cleanUrl = new URL(context.nextUrl.toString());
|
|
660
681
|
cleanUrl.searchParams.delete(MiddlewareConfig.QUERY_PARAMS.LOGIN_REQUIRED);
|
|
661
682
|
cleanUrl.searchParams.delete(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED);
|
|
683
|
+
cleanUrl.searchParams.delete(MiddlewareConfig.QUERY_PARAMS.REDIRECT_URL);
|
|
662
684
|
return NextResponse.redirect(cleanUrl);
|
|
663
685
|
}
|
|
664
686
|
/**
|
|
665
687
|
* Check if URL has auth-related query parameters that need cleanup
|
|
666
688
|
*/
|
|
667
689
|
hasAuthQueryParams(searchParams) {
|
|
668
|
-
return searchParams.has(MiddlewareConfig.QUERY_PARAMS.LOGIN_REQUIRED) || searchParams.has(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED);
|
|
690
|
+
return searchParams.has(MiddlewareConfig.QUERY_PARAMS.LOGIN_REQUIRED) || searchParams.has(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED) || searchParams.has(MiddlewareConfig.QUERY_PARAMS.REDIRECT_URL);
|
|
669
691
|
}
|
|
670
692
|
/**
|
|
671
|
-
*
|
|
693
|
+
* Validate user authentication by calling getUserProfile API
|
|
672
694
|
*/
|
|
673
|
-
async
|
|
695
|
+
async validateUserAuth(cookies) {
|
|
674
696
|
var _a;
|
|
675
697
|
const { accessTokenKey } = this.getAuthCookieKeys();
|
|
676
698
|
const accessToken = (_a = cookies.get(accessTokenKey)) == null ? void 0 : _a.value;
|
|
@@ -705,60 +727,30 @@ var MethodFilterHandler = class extends BaseMiddlewareHandler {
|
|
|
705
727
|
}
|
|
706
728
|
};
|
|
707
729
|
|
|
708
|
-
// src/middlewares/handlers/route-protection-handler.ts
|
|
709
|
-
var RouteProtectionHandler = class extends BaseMiddlewareHandler {
|
|
710
|
-
handle(context) {
|
|
711
|
-
const { pathname } = context;
|
|
712
|
-
if (!this.isDashboardRoute(pathname)) {
|
|
713
|
-
return this.continue();
|
|
714
|
-
}
|
|
715
|
-
return this.continue();
|
|
716
|
-
}
|
|
717
|
-
};
|
|
718
|
-
|
|
719
730
|
// src/middlewares/handlers/authentication-handler.ts
|
|
720
731
|
var AuthenticationHandler = class extends BaseMiddlewareHandler {
|
|
721
732
|
async handle(context) {
|
|
722
|
-
const { cookies,
|
|
723
|
-
|
|
724
|
-
if (!hasAuthCookies) {
|
|
725
|
-
if (this.isDashboardRoute(pathname)) {
|
|
726
|
-
return this.redirectWithAuthParams(nextUrl);
|
|
727
|
-
}
|
|
733
|
+
const { cookies, hostname } = context;
|
|
734
|
+
if (!this.isDashboardSubdomain(hostname)) {
|
|
728
735
|
return this.continue();
|
|
729
736
|
}
|
|
737
|
+
if (!this.hasAuthenticationCookies(cookies)) {
|
|
738
|
+
return this.addLoginModalParams(context);
|
|
739
|
+
}
|
|
730
740
|
try {
|
|
731
|
-
const response = await this.
|
|
741
|
+
const response = await this.validateUserAuth(cookies);
|
|
732
742
|
if (!response.ok) {
|
|
733
743
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
734
744
|
}
|
|
735
745
|
await response.json();
|
|
736
746
|
if (this.hasAuthQueryParams(context.searchParams)) {
|
|
737
|
-
return this.
|
|
747
|
+
return this.removeAuthParams(context);
|
|
738
748
|
}
|
|
739
749
|
return this.allow();
|
|
740
750
|
} catch (error) {
|
|
741
751
|
console.log("JWT validation failed:", error instanceof Error ? error.message : "Unknown error");
|
|
742
|
-
|
|
743
|
-
return this.redirectWithAuthParams(nextUrl);
|
|
744
|
-
}
|
|
745
|
-
return this.continue();
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
};
|
|
749
|
-
|
|
750
|
-
// src/middlewares/handlers/login-redirect-handler.ts
|
|
751
|
-
var LoginRedirectHandler = class extends BaseMiddlewareHandler {
|
|
752
|
-
handle(context) {
|
|
753
|
-
const { pathname, cookies } = context;
|
|
754
|
-
if (!this.isLoginRoute(pathname)) {
|
|
755
|
-
return this.continue();
|
|
756
|
-
}
|
|
757
|
-
const isAuthenticated = this.hasAuthenticationCookies(cookies);
|
|
758
|
-
if (isAuthenticated) {
|
|
759
|
-
return this.redirectToDashboard(context);
|
|
752
|
+
return this.addLoginModalParams(context);
|
|
760
753
|
}
|
|
761
|
-
return this.continue();
|
|
762
754
|
}
|
|
763
755
|
};
|
|
764
756
|
|
|
@@ -785,15 +777,17 @@ var MiddlewareChain = class {
|
|
|
785
777
|
|
|
786
778
|
// src/middleware.ts
|
|
787
779
|
async function middleware(req) {
|
|
780
|
+
const hostname = req.headers.get("host") || req.nextUrl.hostname;
|
|
788
781
|
const context = {
|
|
789
782
|
request: req,
|
|
790
783
|
method: req.method,
|
|
791
784
|
pathname: req.nextUrl.pathname,
|
|
792
785
|
searchParams: req.nextUrl.searchParams,
|
|
793
786
|
cookies: req.cookies,
|
|
794
|
-
nextUrl: req.nextUrl
|
|
787
|
+
nextUrl: req.nextUrl,
|
|
788
|
+
hostname
|
|
795
789
|
};
|
|
796
|
-
const chain = new MiddlewareChain().addHandler(new MethodFilterHandler()).addHandler(new
|
|
790
|
+
const chain = new MiddlewareChain().addHandler(new MethodFilterHandler()).addHandler(new AuthenticationHandler());
|
|
797
791
|
return await chain.process(context);
|
|
798
792
|
}
|
|
799
793
|
export {
|
package/package.json
CHANGED