rystem.authentication.social.client 0.5.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.
Files changed (141) hide show
  1. package/README.md +1903 -0
  2. package/lib/buttons/CreateSocialButton.d.ts +15 -0
  3. package/lib/buttons/CreateSocialButton.js +158 -0
  4. package/lib/buttons/SocialLoginButtons.d.ts +2 -0
  5. package/lib/buttons/SocialLoginButtons.js +22 -0
  6. package/lib/buttons/SocialLogoutButton.d.ts +3 -0
  7. package/lib/buttons/SocialLogoutButton.js +11 -0
  8. package/lib/buttons/graphics/AmazonLoginButton.d.ts +1 -0
  9. package/lib/buttons/graphics/AmazonLoginButton.js +10 -0
  10. package/lib/buttons/graphics/AppleLoginButton.d.ts +1 -0
  11. package/lib/buttons/graphics/AppleLoginButton.js +17 -0
  12. package/lib/buttons/graphics/BufferLoginButton.d.ts +1 -0
  13. package/lib/buttons/graphics/BufferLoginButton.js +17 -0
  14. package/lib/buttons/graphics/DiscordLoginButton.d.ts +1 -0
  15. package/lib/buttons/graphics/DiscordLoginButton.js +17 -0
  16. package/lib/buttons/graphics/FacebookLoginButton.d.ts +1 -0
  17. package/lib/buttons/graphics/FacebookLoginButton.js +10 -0
  18. package/lib/buttons/graphics/GithubLoginButton.d.ts +1 -0
  19. package/lib/buttons/graphics/GithubLoginButton.js +10 -0
  20. package/lib/buttons/graphics/GoogleLoginButton.d.ts +1 -0
  21. package/lib/buttons/graphics/GoogleLoginButton.js +10 -0
  22. package/lib/buttons/graphics/InstagramLoginButton.d.ts +1 -0
  23. package/lib/buttons/graphics/InstagramLoginButton.js +10 -0
  24. package/lib/buttons/graphics/LinkedInLoginButton.d.ts +1 -0
  25. package/lib/buttons/graphics/LinkedInLoginButton.js +10 -0
  26. package/lib/buttons/graphics/MetamaskLoginButton.d.ts +1 -0
  27. package/lib/buttons/graphics/MetamaskLoginButton.js +25 -0
  28. package/lib/buttons/graphics/MicrosoftLoginButton.d.ts +1 -0
  29. package/lib/buttons/graphics/MicrosoftLoginButton.js +10 -0
  30. package/lib/buttons/graphics/OktaLoginButton.d.ts +1 -0
  31. package/lib/buttons/graphics/OktaLoginButton.js +17 -0
  32. package/lib/buttons/graphics/PinterestLoginButton.d.ts +1 -0
  33. package/lib/buttons/graphics/PinterestLoginButton.js +10 -0
  34. package/lib/buttons/graphics/SlackLoginButton.d.ts +1 -0
  35. package/lib/buttons/graphics/SlackLoginButton.js +17 -0
  36. package/lib/buttons/graphics/SocialButtonStyle.d.ts +8 -0
  37. package/lib/buttons/graphics/SocialButtonStyle.js +2 -0
  38. package/lib/buttons/graphics/SocialLoginButton.d.ts +2 -0
  39. package/lib/buttons/graphics/SocialLoginButton.js +46 -0
  40. package/lib/buttons/graphics/TelegramLoginButton.d.ts +1 -0
  41. package/lib/buttons/graphics/TelegramLoginButton.js +17 -0
  42. package/lib/buttons/graphics/TikTokLoginButton.d.ts +1 -0
  43. package/lib/buttons/graphics/TikTokLoginButton.js +10 -0
  44. package/lib/buttons/graphics/XLoginButton.d.ts +1 -0
  45. package/lib/buttons/graphics/XLoginButton.js +10 -0
  46. package/lib/buttons/graphics/YahooLoginButton.d.ts +1 -0
  47. package/lib/buttons/graphics/YahooLoginButton.js +17 -0
  48. package/lib/buttons/graphics/ZaloLoginButton.d.ts +1 -0
  49. package/lib/buttons/graphics/ZaloLoginButton.js +17 -0
  50. package/lib/buttons/singles/AmazonButton.d.ts +2 -0
  51. package/lib/buttons/singles/AmazonButton.js +33 -0
  52. package/lib/buttons/singles/FacebookButton.d.ts +2 -0
  53. package/lib/buttons/singles/FacebookButton.js +55 -0
  54. package/lib/buttons/singles/GitHubButton.d.ts +2 -0
  55. package/lib/buttons/singles/GitHubButton.js +19 -0
  56. package/lib/buttons/singles/GoogleButton.d.ts +2 -0
  57. package/lib/buttons/singles/GoogleButton.js +44 -0
  58. package/lib/buttons/singles/InstagramButton.d.ts +2 -0
  59. package/lib/buttons/singles/InstagramButton.js +21 -0
  60. package/lib/buttons/singles/LinkedinButton.d.ts +2 -0
  61. package/lib/buttons/singles/LinkedinButton.js +23 -0
  62. package/lib/buttons/singles/MicrosoftButton.d.ts +2 -0
  63. package/lib/buttons/singles/MicrosoftButton.js +68 -0
  64. package/lib/buttons/singles/PinterestButton.d.ts +2 -0
  65. package/lib/buttons/singles/PinterestButton.js +22 -0
  66. package/lib/buttons/singles/TikTokButton.d.ts +2 -0
  67. package/lib/buttons/singles/TikTokButton.js +18 -0
  68. package/lib/buttons/singles/XButton.d.ts +2 -0
  69. package/lib/buttons/singles/XButton.js +24 -0
  70. package/lib/components/BrandIcons.d.ts +64 -0
  71. package/lib/components/BrandIcons.js +76 -0
  72. package/lib/components/ModernSocialButton.d.ts +21 -0
  73. package/lib/components/ModernSocialButton.js +23 -0
  74. package/lib/context/SocialLoginContext.d.ts +4 -0
  75. package/lib/context/SocialLoginContext.js +10 -0
  76. package/lib/context/SocialLoginWrapper.d.ts +3 -0
  77. package/lib/context/SocialLoginWrapper.js +137 -0
  78. package/lib/hooks/removeSocialLogin.d.ts +1 -0
  79. package/lib/hooks/removeSocialLogin.js +14 -0
  80. package/lib/hooks/useSocialToken.d.ts +2 -0
  81. package/lib/hooks/useSocialToken.js +21 -0
  82. package/lib/hooks/useSocialUser.d.ts +2 -0
  83. package/lib/hooks/useSocialUser.js +30 -0
  84. package/lib/index.d.ts +47 -0
  85. package/lib/index.js +90 -0
  86. package/lib/models/SocialButtonProps.d.ts +3 -0
  87. package/lib/models/SocialButtonProps.js +2 -0
  88. package/lib/models/SocialButtonsProps.d.ts +4 -0
  89. package/lib/models/SocialButtonsProps.js +2 -0
  90. package/lib/models/SocialToken.d.ts +6 -0
  91. package/lib/models/SocialToken.js +2 -0
  92. package/lib/models/SocialUser.d.ts +5 -0
  93. package/lib/models/SocialUser.js +2 -0
  94. package/lib/models/Token.d.ts +6 -0
  95. package/lib/models/Token.js +2 -0
  96. package/lib/models/setup/LoginMode.d.ts +13 -0
  97. package/lib/models/setup/LoginMode.js +17 -0
  98. package/lib/models/setup/PlatformConfig.d.ts +45 -0
  99. package/lib/models/setup/PlatformConfig.js +19 -0
  100. package/lib/models/setup/PlatformType.d.ts +21 -0
  101. package/lib/models/setup/PlatformType.js +25 -0
  102. package/lib/models/setup/ProviderType.d.ts +13 -0
  103. package/lib/models/setup/ProviderType.js +17 -0
  104. package/lib/models/setup/SocialLoginErrorResponse.d.ts +6 -0
  105. package/lib/models/setup/SocialLoginErrorResponse.js +2 -0
  106. package/lib/models/setup/SocialLoginSettings.d.ts +66 -0
  107. package/lib/models/setup/SocialLoginSettings.js +2 -0
  108. package/lib/models/setup/SocialParameter.d.ts +3 -0
  109. package/lib/models/setup/SocialParameter.js +2 -0
  110. package/lib/services/IRoutingService.d.ts +123 -0
  111. package/lib/services/IRoutingService.js +2 -0
  112. package/lib/services/IStorageService.d.ts +33 -0
  113. package/lib/services/IStorageService.js +2 -0
  114. package/lib/services/LocalStorageService.d.ts +32 -0
  115. package/lib/services/LocalStorageService.js +93 -0
  116. package/lib/services/MockRoutingService.example.d.ts +96 -0
  117. package/lib/services/MockRoutingService.example.js +153 -0
  118. package/lib/services/NextAppRouterRoutingService.example.d.ts +75 -0
  119. package/lib/services/NextAppRouterRoutingService.example.js +128 -0
  120. package/lib/services/PkceStorageService.d.ts +55 -0
  121. package/lib/services/PkceStorageService.js +103 -0
  122. package/lib/services/ReactRouterRoutingService.example.d.ts +69 -0
  123. package/lib/services/ReactRouterRoutingService.example.js +121 -0
  124. package/lib/services/TokenStorageService.d.ts +34 -0
  125. package/lib/services/TokenStorageService.js +90 -0
  126. package/lib/services/UserStorageService.d.ts +29 -0
  127. package/lib/services/UserStorageService.js +56 -0
  128. package/lib/services/WindowRoutingService.d.ts +74 -0
  129. package/lib/services/WindowRoutingService.js +118 -0
  130. package/lib/setup/SocialLoginManager.d.ts +12 -0
  131. package/lib/setup/SocialLoginManager.js +106 -0
  132. package/lib/setup/getSocialLoginSettings.d.ts +2 -0
  133. package/lib/setup/getSocialLoginSettings.js +8 -0
  134. package/lib/setup/setupSocialLogin.d.ts +2 -0
  135. package/lib/setup/setupSocialLogin.js +62 -0
  136. package/lib/styles/SocialButton.css +365 -0
  137. package/lib/utils/pkce.d.ts +18 -0
  138. package/lib/utils/pkce.js +44 -0
  139. package/lib/utils/platform.d.ts +30 -0
  140. package/lib/utils/platform.js +103 -0
  141. package/package.json +45 -0
@@ -0,0 +1,66 @@
1
+ import { SocialLoginErrorResponse, SocialParameter } from "../..";
2
+ import { PlatformConfig } from "./PlatformConfig";
3
+ import { IStorageService } from "../../services/IStorageService";
4
+ import { IRoutingService } from "../../services/IRoutingService";
5
+ export interface SocialLoginSettings {
6
+ apiUri: string;
7
+ automaticRefresh: boolean;
8
+ identityTransformer?: IIdentityTransformer<any>;
9
+ onLoginFailure: (data: SocialLoginErrorResponse) => void;
10
+ title: string | null;
11
+ /**
12
+ * Storage service for persisting tokens, PKCE verifiers, etc.
13
+ * Default: LocalStorageService (browser localStorage)
14
+ *
15
+ * @example Custom secure storage for mobile
16
+ * storageService: new SecureStorageService()
17
+ */
18
+ storageService: IStorageService;
19
+ /**
20
+ * Routing service for URL parameter reading and navigation
21
+ * Default: WindowRoutingService (uses window.location and window.history)
22
+ *
23
+ * IMPORTANT: Required for React Router, Next.js App Router, and other client-side routing frameworks
24
+ * to properly handle OAuth callbacks, redirects, and return URLs.
25
+ *
26
+ * @example React Router with useSearchParams, useNavigate, and useLocation hooks
27
+ * routingService: new ReactRouterRoutingService()
28
+ *
29
+ * @example Next.js App Router with useRouter, usePathname, and useSearchParams
30
+ * routingService: new NextAppRouterRoutingService()
31
+ */
32
+ routingService: IRoutingService;
33
+ /**
34
+ * Platform configuration (Web, iOS, Android)
35
+ *
36
+ * @example Web configuration (auto-detect domain)
37
+ * platform: {
38
+ * type: PlatformType.Web,
39
+ * redirectPath: "/account/login"
40
+ * }
41
+ *
42
+ * @example React Native iOS configuration
43
+ * platform: {
44
+ * type: PlatformType.iOS,
45
+ * redirectPath: "myapp://oauth/callback" // Complete deep link
46
+ * }
47
+ *
48
+ * @default { type: 'auto', redirectPath: '/account/login', loginMode: 'popup' }
49
+ */
50
+ platform?: PlatformConfig;
51
+ google: SocialParameter;
52
+ microsoft: SocialParameter;
53
+ facebook: SocialParameter;
54
+ github: SocialParameter;
55
+ amazon: SocialParameter;
56
+ linkedin: SocialParameter;
57
+ x: SocialParameter;
58
+ instagram: SocialParameter;
59
+ pinterest: SocialParameter;
60
+ tiktok: SocialParameter;
61
+ }
62
+ export interface IIdentityTransformer<TIdentity> {
63
+ toPlain: (input: TIdentity | any) => any;
64
+ fromPlain: (input: any) => TIdentity;
65
+ retrieveUsername: (input: TIdentity) => string;
66
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export interface SocialParameter {
2
+ clientId: string | null;
3
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Unified routing service for URL parameter reading and navigation
3
+ * Handles both OAuth callback detection and client-side routing operations
4
+ *
5
+ * This service solves compatibility issues with client-side routing frameworks
6
+ * (React Router, Next.js, Remix) where native browser APIs bypass the router.
7
+ *
8
+ * @example Default (Vanilla React, no routing library)
9
+ * ```typescript
10
+ * const routingService = new WindowRoutingService();
11
+ * setupSocialLogin(x => {
12
+ * x.routingService = routingService; // Uses window.location and window.history
13
+ * });
14
+ * ```
15
+ *
16
+ * @example React Router
17
+ * ```typescript
18
+ * const routingService = new ReactRouterRoutingService();
19
+ * setupSocialLogin(x => {
20
+ * x.routingService = routingService;
21
+ * });
22
+ *
23
+ * // In component:
24
+ * const [searchParams] = useSearchParams();
25
+ * const navigate = useNavigate();
26
+ * const location = useLocation();
27
+ * routingService.initialize(() => searchParams, navigate, location);
28
+ * ```
29
+ */
30
+ export interface IRoutingService {
31
+ /**
32
+ * Get a single URL parameter value
33
+ * Used for reading OAuth callback parameters (code, state)
34
+ *
35
+ * @param key - Parameter name (e.g., 'code', 'state')
36
+ * @returns Parameter value or null if not found
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const code = routingService.getSearchParam('code');
41
+ * const state = routingService.getSearchParam('state');
42
+ * ```
43
+ */
44
+ getSearchParam(key: string): string | null;
45
+ /**
46
+ * Get all URL parameters
47
+ * Used for debugging or advanced OAuth scenarios
48
+ *
49
+ * @returns URLSearchParams object with all query parameters
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const allParams = routingService.getAllSearchParams();
54
+ * console.log('OAuth callback params:', allParams.toString());
55
+ * ```
56
+ */
57
+ getAllSearchParams(): URLSearchParams;
58
+ /**
59
+ * Get current path including search parameters
60
+ * Used for saving return URL before OAuth redirect
61
+ *
62
+ * @returns Current route path with query string (e.g., "/dashboard?tab=settings")
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * // Save current location before OAuth
67
+ * const returnUrl = routingService.getCurrentPath();
68
+ * storageService.set('return_url', returnUrl);
69
+ * ```
70
+ */
71
+ getCurrentPath(): string;
72
+ /**
73
+ * Navigate to a URL (for OAuth redirects and internal navigation)
74
+ *
75
+ * @param url - Full URL (https://...) for external OAuth, or path (/login) for internal
76
+ *
77
+ * @example OAuth redirect
78
+ * ```typescript
79
+ * routingService.navigateTo('https://login.microsoftonline.com/oauth2/authorize?...');
80
+ * ```
81
+ *
82
+ * @example Internal navigation (React Router)
83
+ * ```typescript
84
+ * routingService.navigateTo('/dashboard'); // Calls navigate() internally
85
+ * ```
86
+ */
87
+ navigateTo(url: string): void;
88
+ /**
89
+ * Replace current URL without full navigation (cleanup after OAuth callback)
90
+ * Updates URL bar without triggering page reload or adding to browser history
91
+ *
92
+ * @param path - Path to replace current URL with
93
+ *
94
+ * @example Clean URL after OAuth
95
+ * ```typescript
96
+ * // Before: /account/login?code=ABC123&state=microsoft
97
+ * routingService.navigateReplace('/account/login');
98
+ * // After: /account/login (query params removed)
99
+ * ```
100
+ */
101
+ navigateReplace(path: string): void;
102
+ /**
103
+ * Open URL in popup window (for popup mode OAuth)
104
+ *
105
+ * @param url - URL to open in popup
106
+ * @param name - Window name/target
107
+ * @param features - Window features (size, position, menubar, etc.)
108
+ * @returns Window reference or null if blocked by popup blocker
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * const popup = routingService.openPopup(
113
+ * 'https://oauth.provider.com/authorize',
114
+ * 'oauth_popup',
115
+ * 'width=450,height=730,top=100,left=100'
116
+ * );
117
+ * if (!popup) {
118
+ * alert('Popup blocked! Please allow popups for this site.');
119
+ * }
120
+ * ```
121
+ */
122
+ openPopup(url: string, name: string, features: string): Window | null;
123
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Generic storage service interface (key-value storage)
3
+ * Allows different infrastructure implementations (localStorage, secure storage, Redis, etc.)
4
+ */
5
+ export interface IStorageService {
6
+ /**
7
+ * Get value by key
8
+ * @param key Storage key
9
+ * @returns Value or null if not found
10
+ */
11
+ get(key: string): string | null;
12
+ /**
13
+ * Set value for key
14
+ * @param key Storage key
15
+ * @param value Value to store
16
+ */
17
+ set(key: string, value: string): void;
18
+ /**
19
+ * Remove value by key
20
+ * @param key Storage key
21
+ */
22
+ remove(key: string): void;
23
+ /**
24
+ * Check if key exists
25
+ * @param key Storage key
26
+ * @returns True if key exists
27
+ */
28
+ has(key: string): boolean;
29
+ /**
30
+ * Clear all stored values (optional)
31
+ */
32
+ clear?(): void;
33
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,32 @@
1
+ import { IStorageService } from "./IStorageService";
2
+ /**
3
+ * Default storage implementation using browser localStorage
4
+ * Works for web applications (browser environment)
5
+ * For React Native, provide a custom IStorageService implementation
6
+ */
7
+ export declare class LocalStorageService implements IStorageService {
8
+ /**
9
+ * Check if localStorage is available (browser environment)
10
+ */
11
+ private isAvailable;
12
+ /**
13
+ * Get value from localStorage
14
+ */
15
+ get(key: string): string | null;
16
+ /**
17
+ * Set value in localStorage
18
+ */
19
+ set(key: string, value: string): void;
20
+ /**
21
+ * Remove value from localStorage
22
+ */
23
+ remove(key: string): void;
24
+ /**
25
+ * Check if key exists in localStorage
26
+ */
27
+ has(key: string): boolean;
28
+ /**
29
+ * Clear all localStorage
30
+ */
31
+ clear(): void;
32
+ }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LocalStorageService = void 0;
4
+ /**
5
+ * Default storage implementation using browser localStorage
6
+ * Works for web applications (browser environment)
7
+ * For React Native, provide a custom IStorageService implementation
8
+ */
9
+ class LocalStorageService {
10
+ /**
11
+ * Check if localStorage is available (browser environment)
12
+ */
13
+ isAvailable() {
14
+ return typeof window !== 'undefined' && typeof localStorage !== 'undefined';
15
+ }
16
+ /**
17
+ * Get value from localStorage
18
+ */
19
+ get(key) {
20
+ if (!this.isAvailable()) {
21
+ console.warn('LocalStorageService: localStorage not available (React Native or SSR?)');
22
+ return null;
23
+ }
24
+ try {
25
+ return localStorage.getItem(key);
26
+ }
27
+ catch (error) {
28
+ console.error(`LocalStorageService: Error getting key "${key}"`, error);
29
+ return null;
30
+ }
31
+ }
32
+ /**
33
+ * Set value in localStorage
34
+ */
35
+ set(key, value) {
36
+ if (!this.isAvailable()) {
37
+ console.warn('LocalStorageService: localStorage not available (React Native or SSR?)');
38
+ return;
39
+ }
40
+ try {
41
+ localStorage.setItem(key, value);
42
+ }
43
+ catch (error) {
44
+ console.error(`LocalStorageService: Error setting key "${key}"`, error);
45
+ }
46
+ }
47
+ /**
48
+ * Remove value from localStorage
49
+ */
50
+ remove(key) {
51
+ if (!this.isAvailable()) {
52
+ console.warn('LocalStorageService: localStorage not available (React Native or SSR?)');
53
+ return;
54
+ }
55
+ try {
56
+ localStorage.removeItem(key);
57
+ }
58
+ catch (error) {
59
+ console.error(`LocalStorageService: Error removing key "${key}"`, error);
60
+ }
61
+ }
62
+ /**
63
+ * Check if key exists in localStorage
64
+ */
65
+ has(key) {
66
+ if (!this.isAvailable()) {
67
+ return false;
68
+ }
69
+ try {
70
+ return localStorage.getItem(key) !== null;
71
+ }
72
+ catch (error) {
73
+ console.error(`LocalStorageService: Error checking key "${key}"`, error);
74
+ return false;
75
+ }
76
+ }
77
+ /**
78
+ * Clear all localStorage
79
+ */
80
+ clear() {
81
+ if (!this.isAvailable()) {
82
+ console.warn('LocalStorageService: localStorage not available (React Native or SSR?)');
83
+ return;
84
+ }
85
+ try {
86
+ localStorage.clear();
87
+ }
88
+ catch (error) {
89
+ console.error('LocalStorageService: Error clearing storage', error);
90
+ }
91
+ }
92
+ }
93
+ exports.LocalStorageService = LocalStorageService;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Mock Routing Service for unit testing
3
+ *
4
+ * This is a simple in-memory implementation for testing purposes.
5
+ * Allows setting URL parameters and controlling navigation programmatically.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { MockRoutingService } from './MockRoutingService';
10
+ *
11
+ * const mockRouting = new MockRoutingService();
12
+ *
13
+ * // Setup test data
14
+ * mockRouting.setSearchParam('code', 'test-auth-code-12345');
15
+ * mockRouting.setSearchParam('state', 'microsoft');
16
+ * mockRouting.setCurrentPath('/account/login?tab=oauth');
17
+ *
18
+ * setupSocialLogin(x => {
19
+ * x.routingService = mockRouting;
20
+ * // ... rest of test config
21
+ * });
22
+ *
23
+ * // In your test
24
+ * expect(mockRouting.getSearchParam('code')).toBe('test-auth-code-12345');
25
+ * expect(mockRouting.wasNavigateToCalledWith('https://oauth.provider.com')).toBe(true);
26
+ * ```
27
+ */
28
+ import type { IRoutingService } from './IRoutingService';
29
+ /**
30
+ * Mock Routing Service for testing
31
+ * Stores state in-memory and tracks navigation calls
32
+ */
33
+ export declare class MockRoutingService implements IRoutingService {
34
+ private params;
35
+ private currentPath;
36
+ private navigationHistory;
37
+ private replaceHistory;
38
+ private popupCalls;
39
+ /**
40
+ * Set a URL parameter (for testing OAuth callbacks)
41
+ * @param key - Parameter name
42
+ * @param value - Parameter value
43
+ */
44
+ setSearchParam(key: string, value: string): void;
45
+ /**
46
+ * Set multiple parameters at once
47
+ * @param params - Object with key-value pairs
48
+ */
49
+ setSearchParams(params: Record<string, string>): void;
50
+ /**
51
+ * Set the current path
52
+ * @param path - Path with query string (e.g., "/dashboard?tab=settings")
53
+ */
54
+ setCurrentPath(path: string): void;
55
+ /**
56
+ * Clear all state (for test cleanup)
57
+ */
58
+ reset(): void;
59
+ /**
60
+ * Check if navigateTo was called with specific URL
61
+ * @param url - URL to check
62
+ * @returns True if navigateTo was called with this URL
63
+ */
64
+ wasNavigateToCalledWith(url: string): boolean;
65
+ /**
66
+ * Get all navigateTo calls
67
+ * @returns Array of URLs passed to navigateTo
68
+ */
69
+ getNavigationHistory(): string[];
70
+ /**
71
+ * Check if navigateReplace was called with specific path
72
+ * @param path - Path to check
73
+ * @returns True if navigateReplace was called with this path
74
+ */
75
+ wasReplaceCalledWith(path: string): boolean;
76
+ /**
77
+ * Get all navigateReplace calls
78
+ * @returns Array of paths passed to navigateReplace
79
+ */
80
+ getReplaceHistory(): string[];
81
+ /**
82
+ * Get all openPopup calls
83
+ * @returns Array of popup call parameters
84
+ */
85
+ getPopupCalls(): Array<{
86
+ url: string;
87
+ name: string;
88
+ features: string;
89
+ }>;
90
+ getSearchParam(key: string): string | null;
91
+ getAllSearchParams(): URLSearchParams;
92
+ getCurrentPath(): string;
93
+ navigateTo(url: string): void;
94
+ navigateReplace(path: string): void;
95
+ openPopup(url: string, name: string, features: string): Window | null;
96
+ }
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ /**
3
+ * Mock Routing Service for unit testing
4
+ *
5
+ * This is a simple in-memory implementation for testing purposes.
6
+ * Allows setting URL parameters and controlling navigation programmatically.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { MockRoutingService } from './MockRoutingService';
11
+ *
12
+ * const mockRouting = new MockRoutingService();
13
+ *
14
+ * // Setup test data
15
+ * mockRouting.setSearchParam('code', 'test-auth-code-12345');
16
+ * mockRouting.setSearchParam('state', 'microsoft');
17
+ * mockRouting.setCurrentPath('/account/login?tab=oauth');
18
+ *
19
+ * setupSocialLogin(x => {
20
+ * x.routingService = mockRouting;
21
+ * // ... rest of test config
22
+ * });
23
+ *
24
+ * // In your test
25
+ * expect(mockRouting.getSearchParam('code')).toBe('test-auth-code-12345');
26
+ * expect(mockRouting.wasNavigateToCalledWith('https://oauth.provider.com')).toBe(true);
27
+ * ```
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.MockRoutingService = void 0;
31
+ /**
32
+ * Mock Routing Service for testing
33
+ * Stores state in-memory and tracks navigation calls
34
+ */
35
+ class MockRoutingService {
36
+ params = new Map();
37
+ currentPath = '/';
38
+ navigationHistory = [];
39
+ replaceHistory = [];
40
+ popupCalls = [];
41
+ // ===== Setup Methods (for tests) =====
42
+ /**
43
+ * Set a URL parameter (for testing OAuth callbacks)
44
+ * @param key - Parameter name
45
+ * @param value - Parameter value
46
+ */
47
+ setSearchParam(key, value) {
48
+ this.params.set(key, value);
49
+ }
50
+ /**
51
+ * Set multiple parameters at once
52
+ * @param params - Object with key-value pairs
53
+ */
54
+ setSearchParams(params) {
55
+ Object.entries(params).forEach(([key, value]) => {
56
+ this.params.set(key, value);
57
+ });
58
+ }
59
+ /**
60
+ * Set the current path
61
+ * @param path - Path with query string (e.g., "/dashboard?tab=settings")
62
+ */
63
+ setCurrentPath(path) {
64
+ this.currentPath = path;
65
+ }
66
+ /**
67
+ * Clear all state (for test cleanup)
68
+ */
69
+ reset() {
70
+ this.params.clear();
71
+ this.currentPath = '/';
72
+ this.navigationHistory = [];
73
+ this.replaceHistory = [];
74
+ this.popupCalls = [];
75
+ }
76
+ // ===== Verification Methods (for test assertions) =====
77
+ /**
78
+ * Check if navigateTo was called with specific URL
79
+ * @param url - URL to check
80
+ * @returns True if navigateTo was called with this URL
81
+ */
82
+ wasNavigateToCalledWith(url) {
83
+ return this.navigationHistory.includes(url);
84
+ }
85
+ /**
86
+ * Get all navigateTo calls
87
+ * @returns Array of URLs passed to navigateTo
88
+ */
89
+ getNavigationHistory() {
90
+ return [...this.navigationHistory];
91
+ }
92
+ /**
93
+ * Check if navigateReplace was called with specific path
94
+ * @param path - Path to check
95
+ * @returns True if navigateReplace was called with this path
96
+ */
97
+ wasReplaceCalledWith(path) {
98
+ return this.replaceHistory.includes(path);
99
+ }
100
+ /**
101
+ * Get all navigateReplace calls
102
+ * @returns Array of paths passed to navigateReplace
103
+ */
104
+ getReplaceHistory() {
105
+ return [...this.replaceHistory];
106
+ }
107
+ /**
108
+ * Get all openPopup calls
109
+ * @returns Array of popup call parameters
110
+ */
111
+ getPopupCalls() {
112
+ return [...this.popupCalls];
113
+ }
114
+ // ===== IRoutingService Implementation =====
115
+ getSearchParam(key) {
116
+ return this.params.get(key) || null;
117
+ }
118
+ getAllSearchParams() {
119
+ const urlParams = new URLSearchParams();
120
+ this.params.forEach((value, key) => {
121
+ urlParams.set(key, value);
122
+ });
123
+ return urlParams;
124
+ }
125
+ getCurrentPath() {
126
+ return this.currentPath;
127
+ }
128
+ navigateTo(url) {
129
+ this.navigationHistory.push(url);
130
+ // In real scenario, external URLs would do full page navigation
131
+ // In tests, we just track the call
132
+ if (url.startsWith('http://') || url.startsWith('https://')) {
133
+ console.log('[MockRouting] External navigation (tracked):', url);
134
+ }
135
+ else {
136
+ console.log('[MockRouting] Internal navigation (tracked):', url);
137
+ this.currentPath = url;
138
+ }
139
+ }
140
+ navigateReplace(path) {
141
+ this.replaceHistory.push(path);
142
+ this.currentPath = path;
143
+ console.log('[MockRouting] Replace URL (tracked):', path);
144
+ }
145
+ openPopup(url, name, features) {
146
+ this.popupCalls.push({ url, name, features });
147
+ console.log('[MockRouting] Popup open (tracked):', { url, name });
148
+ // In tests, we don't actually open popups
149
+ // Return a mock Window object if needed for testing
150
+ return null;
151
+ }
152
+ }
153
+ exports.MockRoutingService = MockRoutingService;
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Unified Routing Service for Next.js App Router (v13+)
3
+ *
4
+ * This service handles both URL parameter reading and navigation for Next.js with App Router.
5
+ * Copy this file to your project and remove the `.example` extension.
6
+ *
7
+ * IMPORTANT: This must be used in Client Components ('use client')
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * 'use client';
12
+ *
13
+ * import { NextAppRouterRoutingService } from './NextAppRouterRoutingService';
14
+ * import { useRouter, usePathname, useSearchParams } from 'next/navigation';
15
+ *
16
+ * const routingService = new NextAppRouterRoutingService();
17
+ *
18
+ * setupSocialLogin(x => {
19
+ * x.routingService = routingService;
20
+ * });
21
+ *
22
+ * export default function LoginPage() {
23
+ * const router = useRouter();
24
+ * const pathname = usePathname();
25
+ * const searchParams = useSearchParams();
26
+ *
27
+ * useEffect(() => {
28
+ * // Single initialization with all hooks
29
+ * routingService.initialize(router, pathname, searchParams);
30
+ * }, [router, pathname, searchParams]);
31
+ *
32
+ * return <div>Your login page</div>;
33
+ * }
34
+ * ```
35
+ */
36
+ import type { IRoutingService } from './IRoutingService';
37
+ /**
38
+ * Routing Service for Next.js App Router (v13+)
39
+ * Uses useRouter, usePathname, and useSearchParams from next/navigation
40
+ *
41
+ * NOTE: Only works in Client Components ('use client' directive required)
42
+ */
43
+ export declare class NextAppRouterRoutingService implements IRoutingService {
44
+ private router;
45
+ private pathname;
46
+ private searchParams;
47
+ /**
48
+ * Initialize with Next.js navigation hooks
49
+ * MUST be called inside a Client Component ('use client')
50
+ *
51
+ * @param router - The router from useRouter() hook
52
+ * @param pathname - The pathname from usePathname() hook
53
+ * @param searchParams - The searchParams from useSearchParams() hook
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * 'use client';
58
+ *
59
+ * const router = useRouter();
60
+ * const pathname = usePathname();
61
+ * const searchParams = useSearchParams();
62
+ *
63
+ * useEffect(() => {
64
+ * routingService.initialize(router, pathname, searchParams);
65
+ * }, [router, pathname, searchParams]);
66
+ * ```
67
+ */
68
+ initialize(router: any, pathname: string, searchParams: URLSearchParams | null): void;
69
+ getSearchParam(key: string): string | null;
70
+ getAllSearchParams(): URLSearchParams;
71
+ getCurrentPath(): string;
72
+ navigateTo(url: string): void;
73
+ navigateReplace(path: string): void;
74
+ openPopup(url: string, name: string, features: string): Window | null;
75
+ }