@cranberry-money/shared-services 1.0.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 (50) hide show
  1. package/README.md +288 -0
  2. package/dist/adapters/MobileApiClient.d.ts +68 -0
  3. package/dist/adapters/MobileApiClient.d.ts.map +1 -0
  4. package/dist/adapters/MobileApiClient.js +240 -0
  5. package/dist/adapters/MobileTokenStorage.d.ts +43 -0
  6. package/dist/adapters/MobileTokenStorage.d.ts.map +1 -0
  7. package/dist/adapters/MobileTokenStorage.js +128 -0
  8. package/dist/adapters/WebApiClient.d.ts +28 -0
  9. package/dist/adapters/WebApiClient.d.ts.map +1 -0
  10. package/dist/adapters/WebApiClient.js +119 -0
  11. package/dist/adapters/WebTokenStorage.d.ts +38 -0
  12. package/dist/adapters/WebTokenStorage.d.ts.map +1 -0
  13. package/dist/adapters/WebTokenStorage.js +86 -0
  14. package/dist/auth/AuthManager.d.ts +81 -0
  15. package/dist/auth/AuthManager.d.ts.map +1 -0
  16. package/dist/auth/AuthManager.js +223 -0
  17. package/dist/auth/createAuthManager.d.ts +63 -0
  18. package/dist/auth/createAuthManager.d.ts.map +1 -0
  19. package/dist/auth/createAuthManager.js +103 -0
  20. package/dist/auth/useAuthManager.d.ts +66 -0
  21. package/dist/auth/useAuthManager.d.ts.map +1 -0
  22. package/dist/auth/useAuthManager.js +133 -0
  23. package/dist/core/BaseApiClient.d.ts +82 -0
  24. package/dist/core/BaseApiClient.d.ts.map +1 -0
  25. package/dist/core/BaseApiClient.js +89 -0
  26. package/dist/core/TokenStorage.d.ts +45 -0
  27. package/dist/core/TokenStorage.d.ts.map +1 -0
  28. package/dist/core/TokenStorage.js +23 -0
  29. package/dist/index.d.ts +19 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +23 -0
  32. package/dist/query/QueryClient.d.ts +82 -0
  33. package/dist/query/QueryClient.d.ts.map +1 -0
  34. package/dist/query/QueryClient.js +136 -0
  35. package/dist/query/useAuth.d.ts +64 -0
  36. package/dist/query/useAuth.d.ts.map +1 -0
  37. package/dist/query/useAuth.js +144 -0
  38. package/dist/query/usePortfolios.d.ts +79 -0
  39. package/dist/query/usePortfolios.d.ts.map +1 -0
  40. package/dist/query/usePortfolios.js +172 -0
  41. package/dist/services/AuthService.d.ts +75 -0
  42. package/dist/services/AuthService.d.ts.map +1 -0
  43. package/dist/services/AuthService.js +83 -0
  44. package/dist/services/BaseService.d.ts +48 -0
  45. package/dist/services/BaseService.d.ts.map +1 -0
  46. package/dist/services/BaseService.js +51 -0
  47. package/dist/services/PortfolioService.d.ts +100 -0
  48. package/dist/services/PortfolioService.d.ts.map +1 -0
  49. package/dist/services/PortfolioService.js +68 -0
  50. package/package.json +56 -0
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Cross-platform Authentication Manager
3
+ *
4
+ * Centralizes authentication logic and state management across web and mobile platforms.
5
+ * Handles token storage, automatic refresh, and authentication state persistence.
6
+ */
7
+ import { AuthService } from '../services/AuthService';
8
+ export class AuthManager {
9
+ constructor(config) {
10
+ this.currentState = {
11
+ isAuthenticated: false,
12
+ isLoading: false,
13
+ user: null,
14
+ error: null,
15
+ };
16
+ this.apiClient = config.apiClient;
17
+ this.tokenStorage = config.tokenStorage;
18
+ this.authService = new AuthService(config.apiClient);
19
+ this.onAuthStateChange = config.onAuthStateChange;
20
+ this.autoRefreshEnabled = config.autoRefreshEnabled ?? true;
21
+ // Set token storage on API client
22
+ this.apiClient.setTokenStorage(this.tokenStorage);
23
+ }
24
+ /**
25
+ * Get current authentication state
26
+ */
27
+ getState() {
28
+ return { ...this.currentState };
29
+ }
30
+ /**
31
+ * Initialize authentication manager
32
+ * Checks for existing tokens and validates authentication state
33
+ */
34
+ async initialize() {
35
+ this.updateState({ isLoading: true, error: null });
36
+ try {
37
+ const hasTokens = await this.tokenStorage.hasTokens();
38
+ if (!hasTokens) {
39
+ this.updateState({
40
+ isAuthenticated: false,
41
+ isLoading: false,
42
+ user: null
43
+ });
44
+ return this.currentState;
45
+ }
46
+ // Validate tokens by fetching user profile
47
+ const user = await this.authService.getProfile();
48
+ this.updateState({
49
+ isAuthenticated: true,
50
+ isLoading: false,
51
+ user,
52
+ error: null,
53
+ });
54
+ // Start auto-refresh if enabled
55
+ if (this.autoRefreshEnabled) {
56
+ this.startAutoRefresh();
57
+ }
58
+ }
59
+ catch (error) {
60
+ // Tokens are invalid, clear them
61
+ await this.tokenStorage.clearTokens();
62
+ this.updateState({
63
+ isAuthenticated: false,
64
+ isLoading: false,
65
+ user: null,
66
+ error: error instanceof Error ? error.message : 'Authentication failed',
67
+ });
68
+ }
69
+ return this.currentState;
70
+ }
71
+ /**
72
+ * Sign in user with credentials
73
+ */
74
+ async signin(credentials) {
75
+ this.updateState({ isLoading: true, error: null });
76
+ try {
77
+ const response = await this.authService.signin(credentials);
78
+ // Store tokens if provided in response (mobile)
79
+ if (response && typeof response === 'object' && 'access' in response && 'refresh' in response) {
80
+ await this.tokenStorage.storeTokens(response);
81
+ }
82
+ // Fetch user profile
83
+ const user = await this.authService.getProfile();
84
+ this.updateState({
85
+ isAuthenticated: true,
86
+ isLoading: false,
87
+ user,
88
+ error: null,
89
+ });
90
+ // Start auto-refresh if enabled
91
+ if (this.autoRefreshEnabled) {
92
+ this.startAutoRefresh();
93
+ }
94
+ }
95
+ catch (error) {
96
+ this.updateState({
97
+ isAuthenticated: false,
98
+ isLoading: false,
99
+ user: null,
100
+ error: error instanceof Error ? error.message : 'Sign in failed',
101
+ });
102
+ }
103
+ return this.currentState;
104
+ }
105
+ /**
106
+ * Sign out user
107
+ */
108
+ async signout() {
109
+ this.updateState({ isLoading: true, error: null });
110
+ try {
111
+ // Call sign out endpoint
112
+ await this.authService.signout();
113
+ }
114
+ catch (error) {
115
+ // Log error but continue with local cleanup
116
+ console.warn('Sign out API call failed:', error);
117
+ }
118
+ // Always clear local state regardless of API call result
119
+ await this.tokenStorage.clearTokens();
120
+ this.stopAutoRefresh();
121
+ this.updateState({
122
+ isAuthenticated: false,
123
+ isLoading: false,
124
+ user: null,
125
+ error: null,
126
+ });
127
+ return this.currentState;
128
+ }
129
+ /**
130
+ * Sign up new user
131
+ */
132
+ async signup(userData) {
133
+ this.updateState({ isLoading: true, error: null });
134
+ try {
135
+ await this.authService.signup(userData);
136
+ this.updateState({ isLoading: false, error: null });
137
+ return { success: true };
138
+ }
139
+ catch (error) {
140
+ this.updateState({
141
+ isLoading: false,
142
+ error: error instanceof Error ? error.message : 'Sign up failed',
143
+ });
144
+ return {
145
+ success: false,
146
+ error: error instanceof Error ? error.message : 'Sign up failed'
147
+ };
148
+ }
149
+ }
150
+ /**
151
+ * Refresh authentication tokens
152
+ */
153
+ async refreshTokens() {
154
+ try {
155
+ const tokens = await this.tokenStorage.retrieveTokens();
156
+ if (!tokens?.refresh) {
157
+ return false;
158
+ }
159
+ const newTokens = await this.authService.refreshToken({ refresh: tokens.refresh });
160
+ await this.tokenStorage.storeTokens(newTokens);
161
+ return true;
162
+ }
163
+ catch (error) {
164
+ console.error('Token refresh failed:', error);
165
+ // Clear invalid tokens
166
+ await this.tokenStorage.clearTokens();
167
+ this.updateState({
168
+ isAuthenticated: false,
169
+ user: null,
170
+ error: 'Session expired',
171
+ });
172
+ return false;
173
+ }
174
+ }
175
+ /**
176
+ * Update user profile in state
177
+ */
178
+ async refreshProfile() {
179
+ if (!this.currentState.isAuthenticated)
180
+ return;
181
+ try {
182
+ const user = await this.authService.getProfile();
183
+ this.updateState({ user });
184
+ }
185
+ catch (error) {
186
+ console.error('Profile refresh failed:', error);
187
+ }
188
+ }
189
+ /**
190
+ * Start automatic token refresh
191
+ */
192
+ startAutoRefresh() {
193
+ this.stopAutoRefresh();
194
+ // Check every 5 minutes
195
+ this.refreshTimer = setInterval(async () => {
196
+ if (this.currentState.isAuthenticated) {
197
+ await this.refreshTokens();
198
+ }
199
+ }, 5 * 60 * 1000);
200
+ }
201
+ /**
202
+ * Stop automatic token refresh
203
+ */
204
+ stopAutoRefresh() {
205
+ if (this.refreshTimer) {
206
+ clearInterval(this.refreshTimer);
207
+ this.refreshTimer = undefined;
208
+ }
209
+ }
210
+ /**
211
+ * Update authentication state and notify listeners
212
+ */
213
+ updateState(updates) {
214
+ this.currentState = { ...this.currentState, ...updates };
215
+ this.onAuthStateChange?.(this.currentState);
216
+ }
217
+ /**
218
+ * Clean up resources
219
+ */
220
+ dispose() {
221
+ this.stopAutoRefresh();
222
+ }
223
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Factory functions to create platform-specific AuthManager instances
3
+ *
4
+ * Provides convenient setup for web and mobile authentication with
5
+ * appropriate API clients and token storage implementations.
6
+ */
7
+ import { AuthManager, type AuthManagerConfig } from './AuthManager';
8
+ import { type SecureStoreInterface } from '../adapters/MobileTokenStorage';
9
+ export interface WebAuthManagerConfig {
10
+ apiBaseUrl: string;
11
+ onAuthStateChange?: AuthManagerConfig['onAuthStateChange'];
12
+ autoRefreshEnabled?: boolean;
13
+ apiTimeout?: number;
14
+ }
15
+ export interface MobileAuthManagerConfig {
16
+ apiBaseUrl: string;
17
+ secureStore: SecureStoreInterface;
18
+ onAuthStateChange?: AuthManagerConfig['onAuthStateChange'];
19
+ autoRefreshEnabled?: boolean;
20
+ retryAttempts?: number;
21
+ offlineQueueEnabled?: boolean;
22
+ apiTimeout?: number;
23
+ }
24
+ /**
25
+ * Create AuthManager for web applications
26
+ * Uses cookie-based authentication with fetch API
27
+ */
28
+ export declare function createWebAuthManager(config: WebAuthManagerConfig): AuthManager;
29
+ /**
30
+ * Create AuthManager for mobile applications
31
+ * Uses secure storage with token-based authentication
32
+ */
33
+ export declare function createMobileAuthManager(config: MobileAuthManagerConfig): AuthManager;
34
+ /**
35
+ * Create Expo-specific AuthManager
36
+ * Convenience function for Expo applications using SecureStore
37
+ */
38
+ export declare function createExpoAuthManager(config: Omit<MobileAuthManagerConfig, 'secureStore'> & {
39
+ expoSecureStore: SecureStoreInterface;
40
+ }): AuthManager;
41
+ /**
42
+ * AuthManager factory for different platforms
43
+ */
44
+ export declare const authManagerFactory: {
45
+ readonly web: typeof createWebAuthManager;
46
+ readonly mobile: typeof createMobileAuthManager;
47
+ readonly expo: typeof createExpoAuthManager;
48
+ };
49
+ /**
50
+ * Platform detection utility
51
+ */
52
+ export declare function detectPlatform(): 'web' | 'mobile';
53
+ /**
54
+ * Auto-create AuthManager based on platform
55
+ */
56
+ export declare function createAuthManagerForPlatform(config: {
57
+ apiBaseUrl: string;
58
+ onAuthStateChange?: AuthManagerConfig['onAuthStateChange'];
59
+ secureStore?: SecureStoreInterface;
60
+ retryAttempts?: number;
61
+ offlineQueueEnabled?: boolean;
62
+ }): AuthManager;
63
+ //# sourceMappingURL=createAuthManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAuthManager.d.ts","sourceRoot":"","sources":["../../src/auth/createAuthManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAIpE,OAAO,EAAsB,KAAK,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAE/F,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IAC3D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,oBAAoB,CAAC;IAClC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IAC3D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,WAAW,CAe9E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,uBAAuB,GAAG,WAAW,CAgBpF;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,IAAI,CAAC,uBAAuB,EAAE,aAAa,CAAC,GAAG;IACrD,eAAe,EAAE,oBAAoB,CAAC;CACvC,GACA,WAAW,CAKb;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;;CAIrB,CAAC;AAEX;;GAEG;AACH,wBAAgB,cAAc,IAAI,KAAK,GAAG,QAAQ,CAajD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,mBAAmB,CAAC,CAAC;IAE3D,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,GAAG,WAAW,CAqBd"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Factory functions to create platform-specific AuthManager instances
3
+ *
4
+ * Provides convenient setup for web and mobile authentication with
5
+ * appropriate API clients and token storage implementations.
6
+ */
7
+ import { AuthManager } from './AuthManager';
8
+ import { WebApiClient } from '../adapters/WebApiClient';
9
+ import { WebTokenStorage } from '../adapters/WebTokenStorage';
10
+ import { MobileApiClient } from '../adapters/MobileApiClient';
11
+ import { MobileTokenStorage } from '../adapters/MobileTokenStorage';
12
+ /**
13
+ * Create AuthManager for web applications
14
+ * Uses cookie-based authentication with fetch API
15
+ */
16
+ export function createWebAuthManager(config) {
17
+ const apiClient = new WebApiClient({
18
+ baseURL: config.apiBaseUrl,
19
+ withCredentials: true, // Enable cookies
20
+ timeout: config.apiTimeout || 30000,
21
+ });
22
+ const tokenStorage = new WebTokenStorage();
23
+ return new AuthManager({
24
+ apiClient,
25
+ tokenStorage,
26
+ onAuthStateChange: config.onAuthStateChange,
27
+ autoRefreshEnabled: config.autoRefreshEnabled ?? true,
28
+ });
29
+ }
30
+ /**
31
+ * Create AuthManager for mobile applications
32
+ * Uses secure storage with token-based authentication
33
+ */
34
+ export function createMobileAuthManager(config) {
35
+ const apiClient = new MobileApiClient({
36
+ baseURL: config.apiBaseUrl,
37
+ timeout: config.apiTimeout || 30000,
38
+ retryAttempts: config.retryAttempts || 3,
39
+ offlineQueueEnabled: config.offlineQueueEnabled ?? true,
40
+ });
41
+ const tokenStorage = new MobileTokenStorage(config.secureStore);
42
+ return new AuthManager({
43
+ apiClient,
44
+ tokenStorage,
45
+ onAuthStateChange: config.onAuthStateChange,
46
+ autoRefreshEnabled: config.autoRefreshEnabled ?? true,
47
+ });
48
+ }
49
+ /**
50
+ * Create Expo-specific AuthManager
51
+ * Convenience function for Expo applications using SecureStore
52
+ */
53
+ export function createExpoAuthManager(config) {
54
+ return createMobileAuthManager({
55
+ ...config,
56
+ secureStore: config.expoSecureStore,
57
+ });
58
+ }
59
+ /**
60
+ * AuthManager factory for different platforms
61
+ */
62
+ export const authManagerFactory = {
63
+ web: createWebAuthManager,
64
+ mobile: createMobileAuthManager,
65
+ expo: createExpoAuthManager,
66
+ };
67
+ /**
68
+ * Platform detection utility
69
+ */
70
+ export function detectPlatform() {
71
+ // Simple platform detection
72
+ if (typeof window !== 'undefined' && window.document) {
73
+ return 'web';
74
+ }
75
+ // Check for React Native environment
76
+ if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
77
+ return 'mobile';
78
+ }
79
+ // Default to web for SSR environments
80
+ return 'web';
81
+ }
82
+ /**
83
+ * Auto-create AuthManager based on platform
84
+ */
85
+ export function createAuthManagerForPlatform(config) {
86
+ const platform = detectPlatform();
87
+ if (platform === 'mobile') {
88
+ if (!config.secureStore) {
89
+ throw new Error('SecureStore is required for mobile platform');
90
+ }
91
+ return createMobileAuthManager({
92
+ apiBaseUrl: config.apiBaseUrl,
93
+ secureStore: config.secureStore,
94
+ onAuthStateChange: config.onAuthStateChange,
95
+ retryAttempts: config.retryAttempts,
96
+ offlineQueueEnabled: config.offlineQueueEnabled,
97
+ });
98
+ }
99
+ return createWebAuthManager({
100
+ apiBaseUrl: config.apiBaseUrl,
101
+ onAuthStateChange: config.onAuthStateChange,
102
+ });
103
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * React hook for AuthManager integration
3
+ *
4
+ * Provides a React-friendly interface to the AuthManager with
5
+ * automatic state synchronization and React Query integration.
6
+ */
7
+ import React from 'react';
8
+ import type { AuthManager, AuthState } from './AuthManager';
9
+ import type { SigninPayload, SignupPayload } from '../services/AuthService';
10
+ export interface UseAuthManagerOptions {
11
+ authManager: AuthManager;
12
+ enableQueryInvalidation?: boolean;
13
+ }
14
+ export declare function useAuthManager({ authManager, enableQueryInvalidation }: UseAuthManagerOptions): {
15
+ getState: () => AuthState;
16
+ clearError: () => void;
17
+ signin: (credentials: SigninPayload) => Promise<AuthState>;
18
+ signout: () => Promise<AuthState>;
19
+ signup: (userData: SignupPayload) => Promise<{
20
+ success: boolean;
21
+ error?: string;
22
+ }>;
23
+ refreshTokens: () => Promise<boolean>;
24
+ refreshProfile: () => Promise<void>;
25
+ isSignedIn: boolean;
26
+ isSignedOut: boolean;
27
+ hasUser: boolean;
28
+ hasError: boolean;
29
+ isAuthenticated: boolean;
30
+ isLoading: boolean;
31
+ user: import("..").UserProfile | null;
32
+ error: string | null;
33
+ };
34
+ /**
35
+ * Higher-order component for AuthManager integration
36
+ */
37
+ export declare function withAuthManager<P extends object>(Component: React.ComponentType<P & {
38
+ authManager: ReturnType<typeof useAuthManager>;
39
+ }>, authManager: AuthManager): (props: P) => import("react/jsx-runtime").JSX.Element;
40
+ export declare function AuthManagerProvider({ children, authManager }: {
41
+ children: React.ReactNode;
42
+ authManager: AuthManager;
43
+ }): import("react/jsx-runtime").JSX.Element;
44
+ export declare function useAuthManagerContext(options?: {
45
+ enableQueryInvalidation?: boolean;
46
+ }): {
47
+ getState: () => AuthState;
48
+ clearError: () => void;
49
+ signin: (credentials: SigninPayload) => Promise<AuthState>;
50
+ signout: () => Promise<AuthState>;
51
+ signup: (userData: SignupPayload) => Promise<{
52
+ success: boolean;
53
+ error?: string;
54
+ }>;
55
+ refreshTokens: () => Promise<boolean>;
56
+ refreshProfile: () => Promise<void>;
57
+ isSignedIn: boolean;
58
+ isSignedOut: boolean;
59
+ hasUser: boolean;
60
+ hasError: boolean;
61
+ isAuthenticated: boolean;
62
+ isLoading: boolean;
63
+ user: import("..").UserProfile | null;
64
+ error: string | null;
65
+ };
66
+ //# sourceMappingURL=useAuthManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuthManager.d.ts","sourceRoot":"","sources":["../../src/auth/useAuthManager.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAA+E,MAAM,OAAO,CAAC;AAEpG,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAG5E,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,WAAW,CAAC;IACzB,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,wBAAgB,cAAc,CAAC,EAAE,WAAW,EAAE,uBAA8B,EAAE,EAAE,qBAAqB;;;0BA4DrE,aAAa;;uBAYhB,aAAa;;;;;;;;;;;;;;EAsCzC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAC9C,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,GAAG;IAAE,WAAW,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAA;CAAE,CAAC,EACtF,WAAW,EAAE,WAAW,IAEW,OAAO,CAAC,6CAK5C;AAOD,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,WAAW,EACZ,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,WAAW,EAAE,WAAW,CAAC;CAC1B,2CAMA;AAED,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE;IAAE,uBAAuB,CAAC,EAAE,OAAO,CAAA;CAAE;;;0BArFrD,aAAa;;uBAYhB,aAAa;;;;;;;;;;;;;;EAoFzC"}
@@ -0,0 +1,133 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * React hook for AuthManager integration
4
+ *
5
+ * Provides a React-friendly interface to the AuthManager with
6
+ * automatic state synchronization and React Query integration.
7
+ */
8
+ import { useEffect, useState, useCallback, useMemo, createContext, useContext } from 'react';
9
+ import { useQueryClient } from '@tanstack/react-query';
10
+ import { queryKeys } from '../query/QueryClient';
11
+ export function useAuthManager({ authManager, enableQueryInvalidation = true }) {
12
+ const queryClient = useQueryClient();
13
+ const [authState, setAuthState] = useState(() => authManager.getState());
14
+ // Initialize auth manager on mount
15
+ useEffect(() => {
16
+ let mounted = true;
17
+ const initialize = async () => {
18
+ try {
19
+ await authManager.initialize();
20
+ if (mounted) {
21
+ setAuthState(authManager.getState());
22
+ }
23
+ }
24
+ catch (error) {
25
+ console.error('AuthManager initialization failed:', error);
26
+ }
27
+ };
28
+ initialize();
29
+ return () => {
30
+ mounted = false;
31
+ };
32
+ }, [authManager]);
33
+ // Subscribe to auth state changes
34
+ useEffect(() => {
35
+ const unsubscribe = (newState) => {
36
+ setAuthState(newState);
37
+ // Invalidate auth-related queries when authentication state changes
38
+ if (enableQueryInvalidation) {
39
+ if (newState.isAuthenticated && !authState.isAuthenticated) {
40
+ // User signed in - invalidate all queries to refresh data
41
+ queryClient.invalidateQueries();
42
+ }
43
+ else if (!newState.isAuthenticated && authState.isAuthenticated) {
44
+ // User signed out - clear all queries
45
+ queryClient.clear();
46
+ }
47
+ else if (newState.user && newState.user !== authState.user) {
48
+ // User profile changed - invalidate auth queries
49
+ queryClient.invalidateQueries({ queryKey: queryKeys.auth.profile() });
50
+ }
51
+ }
52
+ };
53
+ // Set up state change listener
54
+ const originalOnChange = authManager['onAuthStateChange'];
55
+ authManager['onAuthStateChange'] = (state) => {
56
+ unsubscribe(state);
57
+ originalOnChange?.(state);
58
+ };
59
+ return () => {
60
+ authManager['onAuthStateChange'] = originalOnChange;
61
+ };
62
+ }, [authManager, authState, queryClient, enableQueryInvalidation]);
63
+ // Memoized action functions
64
+ const actions = useMemo(() => ({
65
+ signin: async (credentials) => {
66
+ const result = await authManager.signin(credentials);
67
+ setAuthState(result);
68
+ return result;
69
+ },
70
+ signout: async () => {
71
+ const result = await authManager.signout();
72
+ setAuthState(result);
73
+ return result;
74
+ },
75
+ signup: async (userData) => {
76
+ return authManager.signup(userData);
77
+ },
78
+ refreshTokens: async () => {
79
+ return authManager.refreshTokens();
80
+ },
81
+ refreshProfile: async () => {
82
+ await authManager.refreshProfile();
83
+ setAuthState(authManager.getState());
84
+ },
85
+ }), [authManager]);
86
+ // Convenience getters
87
+ const derived = useMemo(() => ({
88
+ isSignedIn: authState.isAuthenticated,
89
+ isSignedOut: !authState.isAuthenticated && !authState.isLoading,
90
+ hasUser: !!authState.user,
91
+ hasError: !!authState.error,
92
+ }), [authState]);
93
+ return {
94
+ // State
95
+ ...authState,
96
+ ...derived,
97
+ // Actions
98
+ ...actions,
99
+ // Utilities
100
+ getState: useCallback(() => authManager.getState(), [authManager]),
101
+ clearError: useCallback(() => {
102
+ if (authState.error) {
103
+ setAuthState((prev) => ({ ...prev, error: null }));
104
+ }
105
+ }, [authState.error]),
106
+ };
107
+ }
108
+ /**
109
+ * Higher-order component for AuthManager integration
110
+ */
111
+ export function withAuthManager(Component, authManager) {
112
+ return function AuthManagerWrapper(props) {
113
+ const authManagerHook = useAuthManager({ authManager });
114
+ return _jsx(Component, { ...props, authManager: authManagerHook });
115
+ };
116
+ }
117
+ /**
118
+ * Context provider for AuthManager (optional pattern)
119
+ */
120
+ const AuthManagerContext = createContext(null);
121
+ export function AuthManagerProvider({ children, authManager }) {
122
+ return (_jsx(AuthManagerContext.Provider, { value: authManager, children: children }));
123
+ }
124
+ export function useAuthManagerContext(options) {
125
+ const authManager = useContext(AuthManagerContext);
126
+ if (!authManager) {
127
+ throw new Error('useAuthManagerContext must be used within an AuthManagerProvider');
128
+ }
129
+ return useAuthManager({
130
+ authManager,
131
+ enableQueryInvalidation: options?.enableQueryInvalidation
132
+ });
133
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Base API Client abstraction for cross-platform HTTP requests
3
+ *
4
+ * This provides a platform-agnostic interface for making HTTP requests
5
+ * with consistent error handling, authentication, and response processing.
6
+ */
7
+ import type { TokenStorage } from './TokenStorage';
8
+ export interface RequestConfig {
9
+ url: string;
10
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
11
+ data?: unknown;
12
+ params?: Record<string, unknown>;
13
+ headers?: Record<string, string>;
14
+ timeout?: number;
15
+ }
16
+ export interface ApiResponse<T = unknown> {
17
+ data: T;
18
+ status: number;
19
+ statusText: string;
20
+ headers: Record<string, string>;
21
+ }
22
+ export interface ApiError {
23
+ message: string;
24
+ status?: number;
25
+ code?: string;
26
+ data?: unknown;
27
+ }
28
+ export interface ApiClientConfig {
29
+ baseURL: string;
30
+ timeout?: number;
31
+ defaultHeaders?: Record<string, string>;
32
+ withCredentials?: boolean;
33
+ }
34
+ /**
35
+ * Abstract base class for API clients
36
+ * Platform-specific implementations should extend this class
37
+ */
38
+ export declare abstract class BaseApiClient {
39
+ protected baseURL: string;
40
+ protected timeout: number;
41
+ protected defaultHeaders: Record<string, string>;
42
+ protected tokenStorage?: TokenStorage;
43
+ protected withCredentials: boolean;
44
+ constructor(config: ApiClientConfig);
45
+ /**
46
+ * Set token storage implementation
47
+ */
48
+ setTokenStorage(storage: TokenStorage): void;
49
+ /**
50
+ * Make HTTP request - must be implemented by platform-specific clients
51
+ */
52
+ abstract request<T = unknown>(config: RequestConfig): Promise<ApiResponse<T>>;
53
+ /**
54
+ * Convenience methods for common HTTP operations
55
+ */
56
+ get<T = unknown>(url: string, params?: Record<string, unknown>): Promise<ApiResponse<T>>;
57
+ post<T = unknown>(url: string, data?: unknown): Promise<ApiResponse<T>>;
58
+ put<T = unknown>(url: string, data?: unknown): Promise<ApiResponse<T>>;
59
+ patch<T = unknown>(url: string, data?: unknown): Promise<ApiResponse<T>>;
60
+ delete<T = unknown>(url: string): Promise<ApiResponse<T>>;
61
+ /**
62
+ * Build full URL from relative path
63
+ */
64
+ protected buildUrl(url: string): string;
65
+ /**
66
+ * Merge headers with defaults and authentication
67
+ */
68
+ protected buildHeaders(headers?: Record<string, string>): Promise<Record<string, string>>;
69
+ /**
70
+ * Handle API errors consistently
71
+ */
72
+ protected createError(message: string, status?: number, code?: string, data?: unknown): ApiError;
73
+ /**
74
+ * Check if error is authentication related
75
+ */
76
+ protected isAuthError(error: ApiError): boolean;
77
+ /**
78
+ * Handle token refresh logic (to be implemented by platform adapters)
79
+ */
80
+ protected handleTokenRefresh(): Promise<boolean>;
81
+ }
82
+ //# sourceMappingURL=BaseApiClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseApiClient.d.ts","sourceRoot":"","sources":["../../src/core/BaseApiClient.ts"],"names":[],"mappings":"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"}