@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,89 @@
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
+ /**
8
+ * Abstract base class for API clients
9
+ * Platform-specific implementations should extend this class
10
+ */
11
+ export class BaseApiClient {
12
+ constructor(config) {
13
+ this.baseURL = config.baseURL;
14
+ this.timeout = config.timeout || 30000;
15
+ this.defaultHeaders = config.defaultHeaders || {};
16
+ this.withCredentials = config.withCredentials || false;
17
+ }
18
+ /**
19
+ * Set token storage implementation
20
+ */
21
+ setTokenStorage(storage) {
22
+ this.tokenStorage = storage;
23
+ }
24
+ /**
25
+ * Convenience methods for common HTTP operations
26
+ */
27
+ async get(url, params) {
28
+ return this.request({ url, method: 'GET', params });
29
+ }
30
+ async post(url, data) {
31
+ return this.request({ url, method: 'POST', data });
32
+ }
33
+ async put(url, data) {
34
+ return this.request({ url, method: 'PUT', data });
35
+ }
36
+ async patch(url, data) {
37
+ return this.request({ url, method: 'PATCH', data });
38
+ }
39
+ async delete(url) {
40
+ return this.request({ url, method: 'DELETE' });
41
+ }
42
+ /**
43
+ * Build full URL from relative path
44
+ */
45
+ buildUrl(url) {
46
+ if (url.startsWith('http')) {
47
+ return url;
48
+ }
49
+ return `${this.baseURL.replace(/\/$/, '')}/${url.replace(/^\//, '')}`;
50
+ }
51
+ /**
52
+ * Merge headers with defaults and authentication
53
+ */
54
+ async buildHeaders(headers = {}) {
55
+ const mergedHeaders = { ...this.defaultHeaders, ...headers };
56
+ // Add authentication header if token storage is available and tokens exist
57
+ if (this.tokenStorage) {
58
+ const tokens = await this.tokenStorage.retrieveTokens();
59
+ if (tokens?.access) {
60
+ mergedHeaders['Authorization'] = `Bearer ${tokens.access}`;
61
+ }
62
+ }
63
+ return mergedHeaders;
64
+ }
65
+ /**
66
+ * Handle API errors consistently
67
+ */
68
+ createError(message, status, code, data) {
69
+ return {
70
+ message,
71
+ status,
72
+ code,
73
+ data,
74
+ };
75
+ }
76
+ /**
77
+ * Check if error is authentication related
78
+ */
79
+ isAuthError(error) {
80
+ return error.status === 401 || error.code === 'UNAUTHORIZED';
81
+ }
82
+ /**
83
+ * Handle token refresh logic (to be implemented by platform adapters)
84
+ */
85
+ async handleTokenRefresh() {
86
+ // Default implementation - override in platform-specific clients
87
+ return false;
88
+ }
89
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Token storage abstraction for cross-platform authentication
3
+ *
4
+ * This interface provides a consistent API for storing authentication tokens
5
+ * across different platforms (web cookies, mobile secure storage, etc.)
6
+ */
7
+ export interface TokenPair {
8
+ access: string;
9
+ refresh: string;
10
+ }
11
+ export interface TokenStorage {
12
+ /**
13
+ * Store authentication tokens securely
14
+ * @param tokens - The access and refresh tokens to store
15
+ */
16
+ storeTokens(tokens: TokenPair): Promise<void>;
17
+ /**
18
+ * Retrieve stored authentication tokens
19
+ * @returns The stored tokens or null if none exist
20
+ */
21
+ retrieveTokens(): Promise<TokenPair | null>;
22
+ /**
23
+ * Clear all stored authentication tokens
24
+ */
25
+ clearTokens(): Promise<void>;
26
+ /**
27
+ * Check if tokens are currently stored
28
+ * @returns True if tokens exist, false otherwise
29
+ */
30
+ hasTokens(): Promise<boolean>;
31
+ }
32
+ /**
33
+ * Base implementation with common utilities
34
+ */
35
+ export declare abstract class BaseTokenStorage implements TokenStorage {
36
+ abstract storeTokens(tokens: TokenPair): Promise<void>;
37
+ abstract retrieveTokens(): Promise<TokenPair | null>;
38
+ abstract clearTokens(): Promise<void>;
39
+ hasTokens(): Promise<boolean>;
40
+ /**
41
+ * Validate token format (basic validation)
42
+ */
43
+ protected validateTokens(tokens: TokenPair): boolean;
44
+ }
45
+ //# sourceMappingURL=TokenStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenStorage.d.ts","sourceRoot":"","sources":["../../src/core/TokenStorage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9C;;;OAGG;IACH,cAAc,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAE5C;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7B;;;OAGG;IACH,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,8BAAsB,gBAAiB,YAAW,YAAY;IAC5D,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IACtD,QAAQ,CAAC,cAAc,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IACpD,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAE/B,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAKnC;;OAEG;IACH,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO;CAKrD"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Token storage abstraction for cross-platform authentication
3
+ *
4
+ * This interface provides a consistent API for storing authentication tokens
5
+ * across different platforms (web cookies, mobile secure storage, etc.)
6
+ */
7
+ /**
8
+ * Base implementation with common utilities
9
+ */
10
+ export class BaseTokenStorage {
11
+ async hasTokens() {
12
+ const tokens = await this.retrieveTokens();
13
+ return tokens !== null && tokens.access !== '' && tokens.refresh !== '';
14
+ }
15
+ /**
16
+ * Validate token format (basic validation)
17
+ */
18
+ validateTokens(tokens) {
19
+ return !!(tokens.access && tokens.refresh &&
20
+ typeof tokens.access === 'string' &&
21
+ typeof tokens.refresh === 'string');
22
+ }
23
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Centralized export of all shared services
3
+ */
4
+ export * from './core/TokenStorage';
5
+ export * from './core/BaseApiClient';
6
+ export * from './adapters/WebTokenStorage';
7
+ export * from './adapters/WebApiClient';
8
+ export * from './adapters/MobileTokenStorage';
9
+ export * from './adapters/MobileApiClient';
10
+ export * from './services/BaseService';
11
+ export * from './services/AuthService';
12
+ export * from './services/PortfolioService';
13
+ export * from './query/QueryClient';
14
+ export * from './query/useAuth';
15
+ export * from './query/usePortfolios';
16
+ export * from './auth/AuthManager';
17
+ export * from './auth/createAuthManager';
18
+ export * from './auth/useAuthManager';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAG3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAG5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Centralized export of all shared services
3
+ */
4
+ // Core abstractions
5
+ export * from './core/TokenStorage';
6
+ export * from './core/BaseApiClient';
7
+ // Platform adapters
8
+ export * from './adapters/WebTokenStorage';
9
+ export * from './adapters/WebApiClient';
10
+ export * from './adapters/MobileTokenStorage';
11
+ export * from './adapters/MobileApiClient';
12
+ // Services
13
+ export * from './services/BaseService';
14
+ export * from './services/AuthService';
15
+ export * from './services/PortfolioService';
16
+ // React Query integration
17
+ export * from './query/QueryClient';
18
+ export * from './query/useAuth';
19
+ export * from './query/usePortfolios';
20
+ // Authentication Manager
21
+ export * from './auth/AuthManager';
22
+ export * from './auth/createAuthManager';
23
+ export * from './auth/useAuthManager';
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Shared React Query client configuration
3
+ *
4
+ * Provides platform-optimized React Query configurations for web and mobile
5
+ * with appropriate caching, retry, and offline behavior settings.
6
+ */
7
+ import { QueryClient } from '@tanstack/react-query';
8
+ export type Platform = 'web' | 'mobile';
9
+ export interface CreateQueryClientOptions {
10
+ platform: Platform;
11
+ defaultStaleTime?: number;
12
+ defaultRetryCount?: number;
13
+ enableOfflineSupport?: boolean;
14
+ }
15
+ /**
16
+ * Create a QueryClient with platform-optimized defaults
17
+ */
18
+ export declare const createQueryClient: (options: CreateQueryClientOptions) => QueryClient;
19
+ /**
20
+ * Default query keys factory
21
+ * Provides consistent query key structure across the application
22
+ */
23
+ export declare const queryKeys: {
24
+ readonly auth: {
25
+ readonly profile: () => readonly ["auth", "profile"];
26
+ readonly status: () => readonly ["auth", "status"];
27
+ };
28
+ readonly portfolios: {
29
+ readonly all: () => readonly ["portfolios"];
30
+ readonly detail: (id: string) => readonly ["portfolios", string];
31
+ readonly holdings: (id: string) => readonly ["portfolios", string, "holdings"];
32
+ readonly allocations: (id: string) => readonly ["portfolios", string, "allocations"];
33
+ };
34
+ readonly instruments: {
35
+ readonly all: (filters?: Record<string, unknown>) => readonly ["instruments", Record<string, unknown> | undefined];
36
+ readonly detail: (id: string) => readonly ["instruments", string];
37
+ readonly search: (query: string) => readonly ["instruments", "search", string];
38
+ };
39
+ readonly trades: {
40
+ readonly all: (filters?: Record<string, unknown>) => readonly ["trades", Record<string, unknown> | undefined];
41
+ readonly target: (filters?: Record<string, unknown>) => readonly ["trades", "target", Record<string, unknown> | undefined];
42
+ readonly detail: (id: string) => readonly ["trades", string];
43
+ };
44
+ readonly reference: {
45
+ readonly countries: () => readonly ["reference", "countries"];
46
+ readonly sectors: () => readonly ["reference", "sectors"];
47
+ readonly industries: () => readonly ["reference", "industries"];
48
+ readonly exchanges: () => readonly ["reference", "exchanges"];
49
+ };
50
+ readonly users: {
51
+ readonly profile: () => readonly ["users", "profile"];
52
+ readonly preferences: () => readonly ["users", "preferences"];
53
+ };
54
+ };
55
+ /**
56
+ * Common query options factory
57
+ */
58
+ export declare const createQueryOptions: {
59
+ /**
60
+ * Create options for frequently updated data
61
+ */
62
+ realtime: (platform: Platform) => {
63
+ staleTime: number;
64
+ refetchInterval: number;
65
+ };
66
+ /**
67
+ * Create options for static reference data
68
+ */
69
+ reference: () => {
70
+ staleTime: number;
71
+ gcTime: number;
72
+ refetchOnWindowFocus: boolean;
73
+ refetchOnReconnect: boolean;
74
+ };
75
+ /**
76
+ * Create options for user-specific data
77
+ */
78
+ user: (platform: Platform) => {
79
+ staleTime: number;
80
+ };
81
+ };
82
+ //# sourceMappingURL=QueryClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryClient.d.ts","sourceRoot":"","sources":["../../src/query/QueryClient.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAA0B,MAAM,uBAAuB,CAAC;AAE5E,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,QAAQ,CAAC;AAExC,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,QAAQ,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,wBAAwB,KAAG,WA4CrE,CAAC;AA2BF;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;;8BAUL,MAAM;gCACJ,MAAM;mCACH,MAAM;;;iCAKR,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;8BAC1B,MAAM;iCACH,MAAM;;;iCAKN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oCACpB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;8BAC7B,MAAM;;;;;;;;;;;;CAgBb,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,kBAAkB;IAC7B;;OAEG;yBACkB,QAAQ;;;;IAK7B;;OAEG;;;;;;;IAQH;;OAEG;qBACc,QAAQ;;;CAG1B,CAAC"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Shared React Query client configuration
3
+ *
4
+ * Provides platform-optimized React Query configurations for web and mobile
5
+ * with appropriate caching, retry, and offline behavior settings.
6
+ */
7
+ import { QueryClient } from '@tanstack/react-query';
8
+ /**
9
+ * Create a QueryClient with platform-optimized defaults
10
+ */
11
+ export const createQueryClient = (options) => {
12
+ const { platform, defaultStaleTime, defaultRetryCount, enableOfflineSupport = platform === 'mobile', } = options;
13
+ // Platform-specific defaults
14
+ const platformDefaults = getPlatformDefaults(platform);
15
+ const config = {
16
+ defaultOptions: {
17
+ queries: {
18
+ // Stale time - how long data stays fresh
19
+ staleTime: defaultStaleTime ?? platformDefaults.staleTime,
20
+ // Cache time - how long data stays in cache after becoming stale
21
+ gcTime: platformDefaults.gcTime,
22
+ // Retry configuration
23
+ retry: defaultRetryCount ?? platformDefaults.retry,
24
+ retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
25
+ // Refetch behavior
26
+ refetchOnWindowFocus: platformDefaults.refetchOnWindowFocus,
27
+ refetchOnReconnect: platformDefaults.refetchOnReconnect,
28
+ refetchOnMount: true,
29
+ // Network mode for offline support
30
+ networkMode: enableOfflineSupport ? 'offlineFirst' : 'online',
31
+ },
32
+ mutations: {
33
+ // Retry mutations on network errors
34
+ retry: platform === 'mobile' ? 2 : 1,
35
+ retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 10000),
36
+ // Network mode for offline support
37
+ networkMode: enableOfflineSupport ? 'offlineFirst' : 'online',
38
+ },
39
+ },
40
+ };
41
+ return new QueryClient(config);
42
+ };
43
+ /**
44
+ * Get platform-specific default configurations
45
+ */
46
+ function getPlatformDefaults(platform) {
47
+ if (platform === 'mobile') {
48
+ return {
49
+ // Mobile: Longer stale times for better offline experience
50
+ staleTime: 5 * 60 * 1000, // 5 minutes
51
+ gcTime: 10 * 60 * 1000, // 10 minutes
52
+ retry: 3, // More retries for unstable connections
53
+ refetchOnWindowFocus: false, // No window focus on mobile
54
+ refetchOnReconnect: true, // Refetch when network reconnects
55
+ };
56
+ }
57
+ else {
58
+ return {
59
+ // Web: Shorter stale times for more responsive experience
60
+ staleTime: 30 * 1000, // 30 seconds
61
+ gcTime: 5 * 60 * 1000, // 5 minutes
62
+ retry: 1, // Single retry for stable connections
63
+ refetchOnWindowFocus: true, // Refetch when user returns to tab
64
+ refetchOnReconnect: true, // Refetch when network reconnects
65
+ };
66
+ }
67
+ }
68
+ /**
69
+ * Default query keys factory
70
+ * Provides consistent query key structure across the application
71
+ */
72
+ export const queryKeys = {
73
+ // Authentication
74
+ auth: {
75
+ profile: () => ['auth', 'profile'],
76
+ status: () => ['auth', 'status'],
77
+ },
78
+ // Portfolios
79
+ portfolios: {
80
+ all: () => ['portfolios'],
81
+ detail: (id) => ['portfolios', id],
82
+ holdings: (id) => ['portfolios', id, 'holdings'],
83
+ allocations: (id) => ['portfolios', id, 'allocations'],
84
+ },
85
+ // Instruments
86
+ instruments: {
87
+ all: (filters) => ['instruments', filters],
88
+ detail: (id) => ['instruments', id],
89
+ search: (query) => ['instruments', 'search', query],
90
+ },
91
+ // Trades
92
+ trades: {
93
+ all: (filters) => ['trades', filters],
94
+ target: (filters) => ['trades', 'target', filters],
95
+ detail: (id) => ['trades', id],
96
+ },
97
+ // Reference data
98
+ reference: {
99
+ countries: () => ['reference', 'countries'],
100
+ sectors: () => ['reference', 'sectors'],
101
+ industries: () => ['reference', 'industries'],
102
+ exchanges: () => ['reference', 'exchanges'],
103
+ },
104
+ // Users
105
+ users: {
106
+ profile: () => ['users', 'profile'],
107
+ preferences: () => ['users', 'preferences'],
108
+ },
109
+ };
110
+ /**
111
+ * Common query options factory
112
+ */
113
+ export const createQueryOptions = {
114
+ /**
115
+ * Create options for frequently updated data
116
+ */
117
+ realtime: (platform) => ({
118
+ staleTime: platform === 'mobile' ? 1 * 60 * 1000 : 10 * 1000, // 1min mobile, 10s web
119
+ refetchInterval: platform === 'mobile' ? 2 * 60 * 1000 : 30 * 1000, // 2min mobile, 30s web
120
+ }),
121
+ /**
122
+ * Create options for static reference data
123
+ */
124
+ reference: () => ({
125
+ staleTime: 24 * 60 * 60 * 1000, // 24 hours
126
+ gcTime: 48 * 60 * 60 * 1000, // 48 hours
127
+ refetchOnWindowFocus: false,
128
+ refetchOnReconnect: false,
129
+ }),
130
+ /**
131
+ * Create options for user-specific data
132
+ */
133
+ user: (platform) => ({
134
+ staleTime: platform === 'mobile' ? 10 * 60 * 1000 : 2 * 60 * 1000, // 10min mobile, 2min web
135
+ }),
136
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Shared authentication React Query hooks
3
+ *
4
+ * Provides consistent authentication state management and operations
5
+ * across web and mobile platforms with proper query invalidation.
6
+ */
7
+ import { type UseMutationOptions } from '@tanstack/react-query';
8
+ import type { AuthService, SigninPayload, SignupPayload, EmailVerificationPayload } from '../services/AuthService';
9
+ export interface UseAuthOptions {
10
+ authService: AuthService;
11
+ enabled?: boolean;
12
+ }
13
+ export interface AuthMutationOptions<TData, TVariables> extends Omit<UseMutationOptions<TData, Error, TVariables>, 'mutationFn'> {
14
+ authService: AuthService;
15
+ }
16
+ /**
17
+ * Get current user profile with authentication status
18
+ */
19
+ export declare function useProfile({ authService, enabled }: UseAuthOptions): import("@tanstack/react-query").UseQueryResult<import("..").UserProfile, Error>;
20
+ /**
21
+ * Check authentication status
22
+ */
23
+ export declare function useAuthStatus({ authService, enabled }: UseAuthOptions): import("@tanstack/react-query").UseQueryResult<{
24
+ authenticated: boolean;
25
+ }, Error>;
26
+ /**
27
+ * Sign in mutation
28
+ */
29
+ export declare function useSignin(options: AuthMutationOptions<unknown, SigninPayload>): import("@tanstack/react-query").UseMutationResult<unknown, Error, SigninPayload, unknown>;
30
+ /**
31
+ * Sign out mutation
32
+ */
33
+ export declare function useSignout(options: AuthMutationOptions<unknown, void>): import("@tanstack/react-query").UseMutationResult<unknown, Error, void, unknown>;
34
+ /**
35
+ * Sign up mutation
36
+ */
37
+ export declare function useSignup(options: AuthMutationOptions<unknown, SignupPayload>): import("@tanstack/react-query").UseMutationResult<unknown, Error, SignupPayload, unknown>;
38
+ /**
39
+ * Email verification mutation
40
+ */
41
+ export declare function useVerifyEmail(options: AuthMutationOptions<unknown, EmailVerificationPayload>): import("@tanstack/react-query").UseMutationResult<unknown, Error, EmailVerificationPayload, unknown>;
42
+ /**
43
+ * Resend verification code mutation
44
+ */
45
+ export declare function useResendVerification(options: AuthMutationOptions<unknown, void>): import("@tanstack/react-query").UseMutationResult<unknown, Error, void, unknown>;
46
+ /**
47
+ * Composite auth hook that provides complete authentication state
48
+ */
49
+ export declare function useAuth(options: UseAuthOptions): {
50
+ user: import("..").UserProfile | undefined;
51
+ isAuthenticated: boolean;
52
+ isLoading: boolean;
53
+ isLoadingProfile: boolean;
54
+ isLoadingStatus: boolean;
55
+ error: Error | null;
56
+ profileError: Error | null;
57
+ statusError: Error | null;
58
+ refetchProfile: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("..").UserProfile, Error>>;
59
+ refetchStatus: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<{
60
+ authenticated: boolean;
61
+ }, Error>>;
62
+ refetch: () => void;
63
+ };
64
+ //# sourceMappingURL=useAuth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAuth.d.ts","sourceRoot":"","sources":["../../src/query/useAuth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAyC,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACvG,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAGnH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB,CAAC,KAAK,EAAE,UAAU,CAAE,SACtD,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC;IAChE,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,EAAE,WAAW,EAAE,OAAc,EAAE,EAAE,cAAc,mFAczE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,WAAW,EAAE,OAAc,EAAE,EAAE,cAAc;;UAQ5E;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,6FAgB7E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,oFAerE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,mBAAmB,CAAC,OAAO,EAAE,aAAa,CAAC,6FAe7E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,mBAAmB,CAAC,OAAO,EAAE,wBAAwB,CAAC,wGAe7F;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,oFAOhF;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc;;;;;;;;;;;;;;EA2B9C"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Shared authentication React Query hooks
3
+ *
4
+ * Provides consistent authentication state management and operations
5
+ * across web and mobile platforms with proper query invalidation.
6
+ */
7
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
8
+ import { queryKeys } from './QueryClient';
9
+ /**
10
+ * Get current user profile with authentication status
11
+ */
12
+ export function useProfile({ authService, enabled = true }) {
13
+ return useQuery({
14
+ queryKey: queryKeys.auth.profile(),
15
+ queryFn: () => authService.getProfile(),
16
+ enabled,
17
+ retry: (failureCount, error) => {
18
+ // Don't retry on authentication errors
19
+ if (error && 'status' in error && error.status === 401) {
20
+ return false;
21
+ }
22
+ return failureCount < 3;
23
+ },
24
+ staleTime: 2 * 60 * 1000, // 2 minutes
25
+ });
26
+ }
27
+ /**
28
+ * Check authentication status
29
+ */
30
+ export function useAuthStatus({ authService, enabled = true }) {
31
+ return useQuery({
32
+ queryKey: queryKeys.auth.status(),
33
+ queryFn: () => authService.checkStatus(),
34
+ enabled,
35
+ retry: false, // Don't retry auth status checks
36
+ staleTime: 1 * 60 * 1000, // 1 minute
37
+ });
38
+ }
39
+ /**
40
+ * Sign in mutation
41
+ */
42
+ export function useSignin(options) {
43
+ const queryClient = useQueryClient();
44
+ const { authService, ...mutationOptions } = options;
45
+ return useMutation({
46
+ mutationFn: (data) => authService.signin(data),
47
+ onSuccess: (...args) => {
48
+ // Invalidate auth-related queries
49
+ queryClient.invalidateQueries({ queryKey: queryKeys.auth.profile() });
50
+ queryClient.invalidateQueries({ queryKey: queryKeys.auth.status() });
51
+ // Call user's onSuccess if provided
52
+ mutationOptions.onSuccess?.(...args);
53
+ },
54
+ ...mutationOptions,
55
+ });
56
+ }
57
+ /**
58
+ * Sign out mutation
59
+ */
60
+ export function useSignout(options) {
61
+ const queryClient = useQueryClient();
62
+ const { authService, ...mutationOptions } = options;
63
+ return useMutation({
64
+ mutationFn: () => authService.signout(),
65
+ onSuccess: (...args) => {
66
+ // Clear all cached data on signout
67
+ queryClient.clear();
68
+ // Call user's onSuccess if provided
69
+ mutationOptions.onSuccess?.(...args);
70
+ },
71
+ ...mutationOptions,
72
+ });
73
+ }
74
+ /**
75
+ * Sign up mutation
76
+ */
77
+ export function useSignup(options) {
78
+ const { authService, ...mutationOptions } = options;
79
+ return useMutation({
80
+ mutationFn: (data) => authService.signup(data),
81
+ onSuccess: (...args) => {
82
+ // Optionally invalidate auth queries if signup auto-signs in
83
+ // const queryClient = useQueryClient();
84
+ // queryClient.invalidateQueries({ queryKey: queryKeys.auth.profile() });
85
+ // Call user's onSuccess if provided
86
+ mutationOptions.onSuccess?.(...args);
87
+ },
88
+ ...mutationOptions,
89
+ });
90
+ }
91
+ /**
92
+ * Email verification mutation
93
+ */
94
+ export function useVerifyEmail(options) {
95
+ const queryClient = useQueryClient();
96
+ const { authService, ...mutationOptions } = options;
97
+ return useMutation({
98
+ mutationFn: (data) => authService.verifyEmail(data),
99
+ onSuccess: (...args) => {
100
+ // Invalidate profile to get updated verification status
101
+ queryClient.invalidateQueries({ queryKey: queryKeys.auth.profile() });
102
+ // Call user's onSuccess if provided
103
+ mutationOptions.onSuccess?.(...args);
104
+ },
105
+ ...mutationOptions,
106
+ });
107
+ }
108
+ /**
109
+ * Resend verification code mutation
110
+ */
111
+ export function useResendVerification(options) {
112
+ const { authService, ...mutationOptions } = options;
113
+ return useMutation({
114
+ mutationFn: () => authService.resendVerificationCode(),
115
+ ...mutationOptions,
116
+ });
117
+ }
118
+ /**
119
+ * Composite auth hook that provides complete authentication state
120
+ */
121
+ export function useAuth(options) {
122
+ const profileQuery = useProfile(options);
123
+ const statusQuery = useAuthStatus(options);
124
+ return {
125
+ // Data
126
+ user: profileQuery.data,
127
+ isAuthenticated: !!(statusQuery.data && profileQuery.data),
128
+ // Loading states
129
+ isLoading: profileQuery.isLoading || statusQuery.isLoading,
130
+ isLoadingProfile: profileQuery.isLoading,
131
+ isLoadingStatus: statusQuery.isLoading,
132
+ // Error states
133
+ error: profileQuery.error || statusQuery.error,
134
+ profileError: profileQuery.error,
135
+ statusError: statusQuery.error,
136
+ // Refetch functions
137
+ refetchProfile: profileQuery.refetch,
138
+ refetchStatus: statusQuery.refetch,
139
+ refetch: () => {
140
+ profileQuery.refetch();
141
+ statusQuery.refetch();
142
+ },
143
+ };
144
+ }