@fastshot/auth 1.0.1 → 1.0.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.
Files changed (47) hide show
  1. package/package.json +3 -4
  2. package/src/auth.ts +216 -0
  3. package/src/constants.ts +56 -0
  4. package/{dist/hooks/index.d.ts → src/hooks/index.ts} +2 -1
  5. package/src/hooks/useAppleSignIn.ts +92 -0
  6. package/src/hooks/useAuthCallback.ts +135 -0
  7. package/src/hooks/useGoogleSignIn.ts +95 -0
  8. package/{dist/index.js → src/index.ts} +42 -3
  9. package/src/types.ts +109 -0
  10. package/src/utils/deepLink.ts +100 -0
  11. package/src/utils/index.ts +14 -0
  12. package/src/utils/session.ts +45 -0
  13. package/src/utils/ticketExchange.ts +84 -0
  14. package/dist/auth.d.ts +0 -82
  15. package/dist/auth.d.ts.map +0 -1
  16. package/dist/auth.js +0 -149
  17. package/dist/constants.d.ts +0 -38
  18. package/dist/constants.d.ts.map +0 -1
  19. package/dist/constants.js +0 -48
  20. package/dist/hooks/index.d.ts.map +0 -1
  21. package/dist/hooks/index.js +0 -3
  22. package/dist/hooks/useAppleSignIn.d.ts +0 -47
  23. package/dist/hooks/useAppleSignIn.d.ts.map +0 -1
  24. package/dist/hooks/useAppleSignIn.js +0 -60
  25. package/dist/hooks/useAuthCallback.d.ts +0 -56
  26. package/dist/hooks/useAuthCallback.d.ts.map +0 -1
  27. package/dist/hooks/useAuthCallback.js +0 -97
  28. package/dist/hooks/useGoogleSignIn.d.ts +0 -49
  29. package/dist/hooks/useGoogleSignIn.d.ts.map +0 -1
  30. package/dist/hooks/useGoogleSignIn.js +0 -61
  31. package/dist/index.d.ts +0 -61
  32. package/dist/index.d.ts.map +0 -1
  33. package/dist/types.d.ts +0 -95
  34. package/dist/types.d.ts.map +0 -1
  35. package/dist/types.js +0 -1
  36. package/dist/utils/deepLink.d.ts +0 -26
  37. package/dist/utils/deepLink.d.ts.map +0 -1
  38. package/dist/utils/deepLink.js +0 -55
  39. package/dist/utils/index.d.ts +0 -4
  40. package/dist/utils/index.d.ts.map +0 -1
  41. package/dist/utils/index.js +0 -3
  42. package/dist/utils/session.d.ts +0 -7
  43. package/dist/utils/session.d.ts.map +0 -1
  44. package/dist/utils/session.js +0 -25
  45. package/dist/utils/ticketExchange.d.ts +0 -14
  46. package/dist/utils/ticketExchange.d.ts.map +0 -1
  47. package/dist/utils/ticketExchange.js +0 -54
package/package.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "@fastshot/auth",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "OAuth authentication SDK for Expo React Native applications with Supabase",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
5
+ "main": "src/index.ts",
7
6
  "repository": {
8
7
  "type": "git",
9
8
  "directory": "packages/fastshot-auth"
@@ -34,6 +33,6 @@
34
33
  "typescript": "~5.9.2"
35
34
  },
36
35
  "files": [
37
- "dist"
36
+ "src"
38
37
  ]
39
38
  }
package/src/auth.ts ADDED
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Core authentication functions for OAuth with auth-broker
3
+ */
4
+
5
+ import * as WebBrowser from 'expo-web-browser';
6
+ import type { SupabaseClient, Session } from '@supabase/supabase-js';
7
+ import { AUTH_CONFIG } from './constants';
8
+ import type {
9
+ OAuthProvider,
10
+ AuthMode,
11
+ AuthCallbackResult,
12
+ AuthError,
13
+ } from './types';
14
+ import {
15
+ getDefaultCallbackUrl,
16
+ parseCallbackUrl,
17
+ isAuthCallbackUrl,
18
+ buildOAuthStartUrl,
19
+ exchangeTicket,
20
+ restoreSession,
21
+ createAuthError,
22
+ } from './utils';
23
+
24
+ /**
25
+ * Get the project ID from environment variables
26
+ */
27
+ function getProjectId(): string {
28
+ const projectId = AUTH_CONFIG.PROJECT_ID;
29
+
30
+ if (!projectId) {
31
+ throw createAuthError(
32
+ 'UNKNOWN_ERROR',
33
+ 'Project ID not found. Ensure EXPO_PUBLIC_PROJECT_ID is set in your .env file.'
34
+ );
35
+ }
36
+
37
+ return projectId;
38
+ }
39
+
40
+ /**
41
+ * Configuration for sign-in function
42
+ */
43
+ export interface SignInOptions {
44
+ /** Supabase client for session restoration */
45
+ supabaseClient: SupabaseClient;
46
+ /** Custom return URL (defaults to fastshot://auth/callback) */
47
+ returnTo?: string;
48
+ /** Auth mode: 'browser' (default) or 'webview' */
49
+ mode?: AuthMode;
50
+ /** Email hint for Google sign-in */
51
+ loginHint?: string;
52
+ }
53
+
54
+ /**
55
+ * Sign in with Google OAuth
56
+ *
57
+ * Opens the system browser to initiate Google OAuth flow via auth-broker.
58
+ * After successful authentication, the browser redirects back to the app.
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * import { signInWithGoogle } from '@fastshot/auth';
63
+ * import { supabase } from './lib/supabase';
64
+ *
65
+ * await signInWithGoogle({ supabaseClient: supabase });
66
+ * ```
67
+ */
68
+ export async function signInWithGoogle(options: SignInOptions): Promise<void> {
69
+ return signInWithProvider('google', options);
70
+ }
71
+
72
+ /**
73
+ * Sign in with Apple OAuth
74
+ *
75
+ * Opens the system browser to initiate Apple OAuth flow via auth-broker.
76
+ * After successful authentication, the browser redirects back to the app.
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * import { signInWithApple } from '@fastshot/auth';
81
+ * import { supabase } from './lib/supabase';
82
+ *
83
+ * await signInWithApple({ supabaseClient: supabase });
84
+ * ```
85
+ */
86
+ export async function signInWithApple(options: SignInOptions): Promise<void> {
87
+ return signInWithProvider('apple', options);
88
+ }
89
+
90
+ /**
91
+ * Generic sign-in with OAuth provider
92
+ */
93
+ async function signInWithProvider(
94
+ provider: OAuthProvider,
95
+ options: SignInOptions
96
+ ): Promise<void> {
97
+ const {
98
+ supabaseClient,
99
+ returnTo = getDefaultCallbackUrl(),
100
+ mode = 'browser',
101
+ loginHint,
102
+ } = options;
103
+
104
+ const projectId = getProjectId();
105
+
106
+ const authUrl = buildOAuthStartUrl(provider, {
107
+ tenant: projectId,
108
+ returnTo,
109
+ mode,
110
+ loginHint,
111
+ });
112
+
113
+ // Open browser for OAuth flow
114
+ const result = await WebBrowser.openAuthSessionAsync(authUrl, returnTo);
115
+
116
+ if (result.type === 'cancel' || result.type === 'dismiss') {
117
+ throw createAuthError('BROWSER_DISMISSED', 'Authentication was cancelled');
118
+ }
119
+
120
+ // Handle successful auth callback and restore session
121
+ if (result.type === 'success' && result.url) {
122
+ const callbackResult = await handleAuthCallback(result.url, supabaseClient);
123
+ if (!callbackResult.success) {
124
+ throw createAuthError('UNKNOWN_ERROR', callbackResult.error || 'Failed to complete authentication');
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Handle OAuth callback URL and restore session
131
+ *
132
+ * Call this when your app receives a deep link callback from OAuth.
133
+ * This function exchanges the ticket for tokens and restores the Supabase session.
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * import { handleAuthCallback } from '@fastshot/auth';
138
+ * import { supabase } from './lib/supabase';
139
+ * import * as Linking from 'expo-linking';
140
+ *
141
+ * Linking.addEventListener('url', async ({ url }) => {
142
+ * const result = await handleAuthCallback(url, supabase);
143
+ * if (result.success) {
144
+ * console.log('Logged in as:', result.user?.email);
145
+ * }
146
+ * });
147
+ * ```
148
+ */
149
+ export async function handleAuthCallback(
150
+ url: string,
151
+ supabaseClient: SupabaseClient
152
+ ): Promise<AuthCallbackResult> {
153
+ // Check if this is an auth callback URL
154
+ if (!isAuthCallbackUrl(url)) {
155
+ return {
156
+ success: false,
157
+ error: 'Not an auth callback URL',
158
+ };
159
+ }
160
+
161
+ const { ticket, error, errorDescription } = parseCallbackUrl(url);
162
+
163
+ // Handle OAuth error from auth-broker
164
+ if (error) {
165
+ return {
166
+ success: false,
167
+ error: errorDescription || error,
168
+ };
169
+ }
170
+
171
+ // No ticket means something went wrong
172
+ if (!ticket) {
173
+ return {
174
+ success: false,
175
+ error: 'No ticket in callback URL',
176
+ };
177
+ }
178
+
179
+ try {
180
+ // Exchange ticket for session tokens
181
+ const exchangeResponse = await exchangeTicket(ticket);
182
+
183
+ // Restore session to Supabase client
184
+ const session = await restoreSession(supabaseClient, exchangeResponse);
185
+
186
+ return {
187
+ success: true,
188
+ session,
189
+ user: session.user,
190
+ };
191
+ } catch (err) {
192
+ const authError = err as AuthError;
193
+ return {
194
+ success: false,
195
+ error: authError.message || 'Failed to complete authentication',
196
+ };
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Sign out from Supabase
202
+ *
203
+ * @example
204
+ * ```typescript
205
+ * import { signOut } from '@fastshot/auth';
206
+ * import { supabase } from './lib/supabase';
207
+ *
208
+ * await signOut(supabase);
209
+ * ```
210
+ */
211
+ export async function signOut(supabaseClient: SupabaseClient): Promise<void> {
212
+ const { error } = await supabaseClient.auth.signOut();
213
+ if (error) {
214
+ throw createAuthError('UNKNOWN_ERROR', `Sign out failed: ${error.message}`, error);
215
+ }
216
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Get environment variable with fallback
3
+ * Works in both React Native (process.env.EXPO_PUBLIC_*) and Node.js environments
4
+ */
5
+ function getEnvVar(key: string, fallback: string): string {
6
+ // React Native / Expo environment
7
+ if (typeof process !== 'undefined' && process.env) {
8
+ return process.env[key] || fallback;
9
+ }
10
+ return fallback;
11
+ }
12
+
13
+ /**
14
+ * Auth Broker configuration
15
+ * URLs are read from environment variables at runtime
16
+ *
17
+ * Required env vars:
18
+ * - EXPO_PUBLIC_AUTH_BROKER_URL: Auth broker service URL
19
+ * - EXPO_PUBLIC_PROJECT_ID: Fastshot project ID
20
+ */
21
+ export const AUTH_CONFIG = {
22
+ /** Auth broker URL - must be set via EXPO_PUBLIC_AUTH_BROKER_URL */
23
+ get AUTH_BROKER_URL(): string {
24
+ return getEnvVar('EXPO_PUBLIC_AUTH_BROKER_URL', '');
25
+ },
26
+ /** Project ID for authentication */
27
+ get PROJECT_ID(): string | undefined {
28
+ return getEnvVar('EXPO_PUBLIC_PROJECT_ID', '');
29
+ },
30
+ /** Deep link scheme for OAuth callback */
31
+ DEEP_LINK_SCHEME: 'fastshot',
32
+ /** Callback path for OAuth */
33
+ CALLBACK_PATH: 'auth/callback',
34
+ } as const;
35
+
36
+ /**
37
+ * OAuth endpoints on the auth broker
38
+ */
39
+ export const AUTH_ENDPOINTS = {
40
+ GOOGLE_START: '/v1/auth/google/start',
41
+ APPLE_START: '/v1/auth/apple/start',
42
+ EXCHANGE_TICKET: '/v1/auth/exchange',
43
+ } as const;
44
+
45
+ /**
46
+ * Supported OAuth providers
47
+ */
48
+ export type OAuthProvider = 'google' | 'apple';
49
+
50
+ /**
51
+ * Default configuration values
52
+ */
53
+ export const DEFAULT_AUTH_CONFIG = {
54
+ TIMEOUT: 30000, // 30 seconds
55
+ MODE: 'browser' as const,
56
+ } as const;
@@ -1,7 +1,8 @@
1
1
  export { useGoogleSignIn } from './useGoogleSignIn';
2
2
  export type { UseGoogleSignInConfig, UseGoogleSignInResult } from './useGoogleSignIn';
3
+
3
4
  export { useAppleSignIn } from './useAppleSignIn';
4
5
  export type { UseAppleSignInConfig, UseAppleSignInResult } from './useAppleSignIn';
6
+
5
7
  export { useAuthCallback } from './useAuthCallback';
6
8
  export type { UseAuthCallbackConfig, UseAuthCallbackResult } from './useAuthCallback';
7
- //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,92 @@
1
+ import { useState, useCallback } from 'react';
2
+ import type { SupabaseClient } from '@supabase/supabase-js';
3
+ import { signInWithApple } from '../auth';
4
+ import type { AuthError, AuthMode } from '../types';
5
+ import { isAuthError, createAuthError } from '../utils';
6
+
7
+ export interface UseAppleSignInConfig {
8
+ /** Supabase client instance */
9
+ supabaseClient: SupabaseClient;
10
+ /** Custom return URL */
11
+ returnTo?: string;
12
+ /** Auth mode */
13
+ mode?: AuthMode;
14
+ /** Callback on error */
15
+ onError?: (error: AuthError) => void;
16
+ }
17
+
18
+ export interface UseAppleSignInResult {
19
+ /** Trigger Apple sign-in */
20
+ signIn: () => Promise<void>;
21
+ /** Whether sign-in is in progress */
22
+ isLoading: boolean;
23
+ /** Error from last sign-in attempt */
24
+ error: AuthError | null;
25
+ /** Reset error state */
26
+ reset: () => void;
27
+ }
28
+
29
+ /**
30
+ * React hook for Apple sign-in with auth-broker
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * import { useAppleSignIn } from '@fastshot/auth';
35
+ * import { supabase } from '../lib/supabase';
36
+ *
37
+ * function LoginScreen() {
38
+ * const { signIn, isLoading, error } = useAppleSignIn({
39
+ * supabaseClient: supabase,
40
+ * });
41
+ *
42
+ * return (
43
+ * <Button
44
+ * title={isLoading ? 'Signing in...' : 'Sign in with Apple'}
45
+ * onPress={signIn}
46
+ * disabled={isLoading}
47
+ * />
48
+ * );
49
+ * }
50
+ * ```
51
+ */
52
+ export function useAppleSignIn(config: UseAppleSignInConfig): UseAppleSignInResult {
53
+ const [isLoading, setIsLoading] = useState(false);
54
+ const [error, setError] = useState<AuthError | null>(null);
55
+
56
+ const signIn = useCallback(async () => {
57
+ setIsLoading(true);
58
+ setError(null);
59
+
60
+ try {
61
+ await signInWithApple({
62
+ supabaseClient: config.supabaseClient,
63
+ returnTo: config.returnTo,
64
+ mode: config.mode,
65
+ });
66
+ } catch (err) {
67
+ const authError = isAuthError(err)
68
+ ? err
69
+ : createAuthError(
70
+ 'UNKNOWN_ERROR',
71
+ err instanceof Error ? err.message : 'Unknown error',
72
+ err
73
+ );
74
+
75
+ setError(authError);
76
+ config.onError?.(authError);
77
+ } finally {
78
+ setIsLoading(false);
79
+ }
80
+ }, [config]);
81
+
82
+ const reset = useCallback(() => {
83
+ setError(null);
84
+ }, []);
85
+
86
+ return {
87
+ signIn,
88
+ isLoading,
89
+ error,
90
+ reset,
91
+ };
92
+ }
@@ -0,0 +1,135 @@
1
+ import { useState, useEffect, useCallback } from 'react';
2
+ import * as Linking from 'expo-linking';
3
+ import type { SupabaseClient, Session, User } from '@supabase/supabase-js';
4
+ import { handleAuthCallback } from '../auth';
5
+ import { isAuthCallbackUrl } from '../utils';
6
+ import type { AuthError, AuthCallbackResult } from '../types';
7
+ import { createAuthError } from '../utils';
8
+
9
+ export interface UseAuthCallbackConfig {
10
+ /** Supabase client instance */
11
+ supabaseClient: SupabaseClient;
12
+ /** Callback when authentication succeeds */
13
+ onSuccess?: (result: { session: Session; user: User }) => void;
14
+ /** Callback when authentication fails */
15
+ onError?: (error: AuthError) => void;
16
+ /** Whether to automatically listen for deep links (default: true) */
17
+ autoListen?: boolean;
18
+ }
19
+
20
+ export interface UseAuthCallbackResult {
21
+ /** Whether callback is being processed */
22
+ isProcessing: boolean;
23
+ /** Error if callback processing failed */
24
+ error: AuthError | null;
25
+ /** Manually handle a callback URL */
26
+ handleUrl: (url: string) => Promise<AuthCallbackResult>;
27
+ }
28
+
29
+ /**
30
+ * React hook to handle OAuth callback deep links
31
+ *
32
+ * This hook automatically listens for deep link callbacks and restores
33
+ * the Supabase session when authentication completes.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * import { useAuthCallback } from '@fastshot/auth';
38
+ * import { supabase } from '../lib/supabase';
39
+ *
40
+ * function App() {
41
+ * const { isProcessing, error } = useAuthCallback({
42
+ * supabaseClient: supabase,
43
+ * onSuccess: ({ user }) => {
44
+ * console.log('Logged in:', user.email);
45
+ * navigation.navigate('Home');
46
+ * },
47
+ * onError: (error) => {
48
+ * Alert.alert('Login Failed', error.message);
49
+ * },
50
+ * });
51
+ *
52
+ * if (isProcessing) {
53
+ * return <LoadingScreen message="Completing sign-in..." />;
54
+ * }
55
+ *
56
+ * return <MainApp />;
57
+ * }
58
+ * ```
59
+ */
60
+ export function useAuthCallback(config: UseAuthCallbackConfig): UseAuthCallbackResult {
61
+ const { supabaseClient, onSuccess, onError, autoListen = true } = config;
62
+ const [isProcessing, setIsProcessing] = useState(false);
63
+ const [error, setError] = useState<AuthError | null>(null);
64
+
65
+ const handleUrl = useCallback(
66
+ async (url: string): Promise<AuthCallbackResult> => {
67
+ // Skip if not an auth callback URL
68
+ if (!isAuthCallbackUrl(url)) {
69
+ return { success: false, error: 'Not an auth callback URL' };
70
+ }
71
+
72
+ setIsProcessing(true);
73
+ setError(null);
74
+
75
+ try {
76
+ const result = await handleAuthCallback(url, supabaseClient);
77
+
78
+ if (result.success && result.session && result.user) {
79
+ onSuccess?.({ session: result.session, user: result.user });
80
+ } else if (!result.success && result.error) {
81
+ const authError = createAuthError('CALLBACK_ERROR', result.error);
82
+ setError(authError);
83
+ onError?.(authError);
84
+ }
85
+
86
+ return result;
87
+ } catch (err) {
88
+ const authError = createAuthError(
89
+ 'CALLBACK_ERROR',
90
+ err instanceof Error ? err.message : 'Failed to process callback',
91
+ err
92
+ );
93
+ setError(authError);
94
+ onError?.(authError);
95
+
96
+ return { success: false, error: authError.message };
97
+ } finally {
98
+ setIsProcessing(false);
99
+ }
100
+ },
101
+ [supabaseClient, onSuccess, onError]
102
+ );
103
+
104
+ // Auto-listen for deep links
105
+ useEffect(() => {
106
+ if (!autoListen) return;
107
+
108
+ // Handle URL that opened the app
109
+ const checkInitialUrl = async () => {
110
+ const initialUrl = await Linking.getInitialURL();
111
+ if (initialUrl && isAuthCallbackUrl(initialUrl)) {
112
+ handleUrl(initialUrl);
113
+ }
114
+ };
115
+
116
+ checkInitialUrl();
117
+
118
+ // Listen for incoming URLs while app is running
119
+ const subscription = Linking.addEventListener('url', ({ url }) => {
120
+ if (isAuthCallbackUrl(url)) {
121
+ handleUrl(url);
122
+ }
123
+ });
124
+
125
+ return () => {
126
+ subscription.remove();
127
+ };
128
+ }, [autoListen, handleUrl]);
129
+
130
+ return {
131
+ isProcessing,
132
+ error,
133
+ handleUrl,
134
+ };
135
+ }
@@ -0,0 +1,95 @@
1
+ import { useState, useCallback } from 'react';
2
+ import type { SupabaseClient } from '@supabase/supabase-js';
3
+ import { signInWithGoogle } from '../auth';
4
+ import type { AuthError, AuthMode } from '../types';
5
+ import { isAuthError, createAuthError } from '../utils';
6
+
7
+ export interface UseGoogleSignInConfig {
8
+ /** Supabase client instance */
9
+ supabaseClient: SupabaseClient;
10
+ /** Custom return URL */
11
+ returnTo?: string;
12
+ /** Auth mode */
13
+ mode?: AuthMode;
14
+ /** Email hint */
15
+ loginHint?: string;
16
+ /** Callback on error */
17
+ onError?: (error: AuthError) => void;
18
+ }
19
+
20
+ export interface UseGoogleSignInResult {
21
+ /** Trigger Google sign-in */
22
+ signIn: () => Promise<void>;
23
+ /** Whether sign-in is in progress */
24
+ isLoading: boolean;
25
+ /** Error from last sign-in attempt */
26
+ error: AuthError | null;
27
+ /** Reset error state */
28
+ reset: () => void;
29
+ }
30
+
31
+ /**
32
+ * React hook for Google sign-in with auth-broker
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * import { useGoogleSignIn } from '@fastshot/auth';
37
+ * import { supabase } from '../lib/supabase';
38
+ *
39
+ * function LoginScreen() {
40
+ * const { signIn, isLoading, error } = useGoogleSignIn({
41
+ * supabaseClient: supabase,
42
+ * });
43
+ *
44
+ * return (
45
+ * <Button
46
+ * title={isLoading ? 'Signing in...' : 'Sign in with Google'}
47
+ * onPress={signIn}
48
+ * disabled={isLoading}
49
+ * />
50
+ * );
51
+ * }
52
+ * ```
53
+ */
54
+ export function useGoogleSignIn(config: UseGoogleSignInConfig): UseGoogleSignInResult {
55
+ const [isLoading, setIsLoading] = useState(false);
56
+ const [error, setError] = useState<AuthError | null>(null);
57
+
58
+ const signIn = useCallback(async () => {
59
+ setIsLoading(true);
60
+ setError(null);
61
+
62
+ try {
63
+ await signInWithGoogle({
64
+ supabaseClient: config.supabaseClient,
65
+ returnTo: config.returnTo,
66
+ mode: config.mode,
67
+ loginHint: config.loginHint,
68
+ });
69
+ } catch (err) {
70
+ const authError = isAuthError(err)
71
+ ? err
72
+ : createAuthError(
73
+ 'UNKNOWN_ERROR',
74
+ err instanceof Error ? err.message : 'Unknown error',
75
+ err
76
+ );
77
+
78
+ setError(authError);
79
+ config.onError?.(authError);
80
+ } finally {
81
+ setIsLoading(false);
82
+ }
83
+ }, [config]);
84
+
85
+ const reset = useCallback(() => {
86
+ setError(null);
87
+ }, []);
88
+
89
+ return {
90
+ signIn,
91
+ isLoading,
92
+ error,
93
+ reset,
94
+ };
95
+ }
@@ -51,11 +51,50 @@
51
51
  * const result = await handleAuthCallback(url, supabase);
52
52
  * ```
53
53
  */
54
+
54
55
  // Core auth functions
55
- export { signInWithGoogle, signInWithApple, handleAuthCallback, signOut, } from './auth';
56
+ export {
57
+ signInWithGoogle,
58
+ signInWithApple,
59
+ handleAuthCallback,
60
+ signOut,
61
+ } from './auth';
62
+ export type { SignInOptions } from './auth';
63
+
56
64
  // React hooks
57
- export { useGoogleSignIn, useAppleSignIn, useAuthCallback, } from './hooks';
65
+ export {
66
+ useGoogleSignIn,
67
+ useAppleSignIn,
68
+ useAuthCallback,
69
+ } from './hooks';
70
+ export type {
71
+ UseGoogleSignInConfig,
72
+ UseGoogleSignInResult,
73
+ UseAppleSignInConfig,
74
+ UseAppleSignInResult,
75
+ UseAuthCallbackConfig,
76
+ UseAuthCallbackResult,
77
+ } from './hooks';
78
+
58
79
  // Utilities (for advanced usage)
59
- export { exchangeTicket, isAuthCallbackUrl, parseCallbackUrl, getDefaultCallbackUrl, createAuthError, isAuthError, } from './utils';
80
+ export {
81
+ exchangeTicket,
82
+ isAuthCallbackUrl,
83
+ parseCallbackUrl,
84
+ getDefaultCallbackUrl,
85
+ createAuthError,
86
+ isAuthError,
87
+ } from './utils';
88
+
89
+ // Types
90
+ export type {
91
+ OAuthProvider,
92
+ AuthMode,
93
+ AuthError,
94
+ AuthErrorType,
95
+ AuthCallbackResult,
96
+ ExchangeTicketResponse,
97
+ } from './types';
98
+
60
99
  // Constants (for debugging/customization)
61
100
  export { AUTH_CONFIG, AUTH_ENDPOINTS } from './constants';