@authon/react-native 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +39 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +39 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/index.d.cts +0 -297
- package/dist/index.d.ts +0 -297
package/dist/index.cjs
CHANGED
|
@@ -49,10 +49,13 @@ var import_react = require("react");
|
|
|
49
49
|
|
|
50
50
|
// src/client.ts
|
|
51
51
|
var DEFAULT_API_URL = "https://api.authon.dev";
|
|
52
|
-
|
|
52
|
+
function getStorageKey(publishableKey) {
|
|
53
|
+
return `authon_session_${publishableKey.slice(0, 16)}`;
|
|
54
|
+
}
|
|
53
55
|
var AuthonMobileClient = class {
|
|
54
56
|
apiUrl;
|
|
55
57
|
publishableKey;
|
|
58
|
+
storageKey;
|
|
56
59
|
tokens = null;
|
|
57
60
|
user = null;
|
|
58
61
|
storage = null;
|
|
@@ -65,6 +68,7 @@ var AuthonMobileClient = class {
|
|
|
65
68
|
constructor(config) {
|
|
66
69
|
this.publishableKey = config.publishableKey;
|
|
67
70
|
this.apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\/$/, "");
|
|
71
|
+
this.storageKey = getStorageKey(config.publishableKey);
|
|
68
72
|
}
|
|
69
73
|
setStorage(storage) {
|
|
70
74
|
this.storage = storage;
|
|
@@ -72,7 +76,7 @@ var AuthonMobileClient = class {
|
|
|
72
76
|
// ── Initialization ──
|
|
73
77
|
async initialize() {
|
|
74
78
|
if (!this.storage) return null;
|
|
75
|
-
const stored = await this.storage.getItem(
|
|
79
|
+
const stored = await this.storage.getItem(this.storageKey);
|
|
76
80
|
if (!stored) return null;
|
|
77
81
|
try {
|
|
78
82
|
const tokens = JSON.parse(stored);
|
|
@@ -83,7 +87,7 @@ var AuthonMobileClient = class {
|
|
|
83
87
|
}
|
|
84
88
|
return await this.refreshToken(tokens.refreshToken);
|
|
85
89
|
} catch {
|
|
86
|
-
await this.storage.removeItem(
|
|
90
|
+
await this.storage.removeItem(this.storageKey);
|
|
87
91
|
return null;
|
|
88
92
|
}
|
|
89
93
|
}
|
|
@@ -105,15 +109,38 @@ var AuthonMobileClient = class {
|
|
|
105
109
|
// ── Auth ──
|
|
106
110
|
async signIn(params) {
|
|
107
111
|
const res = await this.request("POST", "/v1/auth/signin", params);
|
|
108
|
-
|
|
109
|
-
|
|
112
|
+
if (res.needsVerification) {
|
|
113
|
+
this.emit("verificationRequired", res.email);
|
|
114
|
+
return { needsVerification: true, email: res.email };
|
|
115
|
+
}
|
|
116
|
+
if (res.mfaRequired) {
|
|
117
|
+
this.emit("mfaRequired", res.mfaToken);
|
|
118
|
+
return { mfaRequired: true, mfaToken: res.mfaToken };
|
|
119
|
+
}
|
|
120
|
+
const authRes = res;
|
|
121
|
+
this.tokens = this.toTokenPair(authRes);
|
|
122
|
+
this.user = authRes.user;
|
|
110
123
|
await this.persistTokens();
|
|
111
124
|
this.scheduleRefresh(this.tokens.expiresAt);
|
|
112
|
-
this.emit("signedIn",
|
|
113
|
-
return { tokens: this.tokens, user:
|
|
125
|
+
this.emit("signedIn", authRes.user);
|
|
126
|
+
return { tokens: this.tokens, user: authRes.user };
|
|
114
127
|
}
|
|
115
128
|
async signUp(params) {
|
|
116
129
|
const res = await this.request("POST", "/v1/auth/signup", params);
|
|
130
|
+
if (res.needsVerification) {
|
|
131
|
+
this.emit("verificationRequired", res.email);
|
|
132
|
+
return { needsVerification: true, email: res.email };
|
|
133
|
+
}
|
|
134
|
+
const authRes = res;
|
|
135
|
+
this.tokens = this.toTokenPair(authRes);
|
|
136
|
+
this.user = authRes.user;
|
|
137
|
+
await this.persistTokens();
|
|
138
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
139
|
+
this.emit("signedIn", authRes.user);
|
|
140
|
+
return { tokens: this.tokens, user: authRes.user };
|
|
141
|
+
}
|
|
142
|
+
async verifyEmail(email, code) {
|
|
143
|
+
const res = await this.request("POST", "/v1/auth/verify-email", { email, code });
|
|
117
144
|
this.tokens = this.toTokenPair(res);
|
|
118
145
|
this.user = res.user;
|
|
119
146
|
await this.persistTokens();
|
|
@@ -121,6 +148,9 @@ var AuthonMobileClient = class {
|
|
|
121
148
|
this.emit("signedIn", res.user);
|
|
122
149
|
return { tokens: this.tokens, user: res.user };
|
|
123
150
|
}
|
|
151
|
+
async resendVerificationCode(email) {
|
|
152
|
+
await this.request("POST", "/v1/auth/resend-code", { email });
|
|
153
|
+
}
|
|
124
154
|
async signOut() {
|
|
125
155
|
if (this.tokens) {
|
|
126
156
|
try {
|
|
@@ -360,7 +390,7 @@ var AuthonMobileClient = class {
|
|
|
360
390
|
this.user = null;
|
|
361
391
|
this.clearRefreshTimer();
|
|
362
392
|
if (this.storage) {
|
|
363
|
-
this.storage.removeItem(
|
|
393
|
+
this.storage.removeItem(this.storageKey).catch(() => {
|
|
364
394
|
});
|
|
365
395
|
}
|
|
366
396
|
}
|
|
@@ -381,7 +411,7 @@ var AuthonMobileClient = class {
|
|
|
381
411
|
}
|
|
382
412
|
async persistTokens() {
|
|
383
413
|
if (this.storage && this.tokens) {
|
|
384
|
-
await this.storage.setItem(
|
|
414
|
+
await this.storage.setItem(this.storageKey, JSON.stringify(this.tokens));
|
|
385
415
|
}
|
|
386
416
|
}
|
|
387
417
|
toTokenPair(res) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/AuthonProvider.tsx","../src/client.ts","../src/useAuthon.ts","../src/useUser.ts","../src/useAuthonWeb3.ts","../src/useAuthonPasswordless.ts","../src/useAuthonPasskeys.ts","../src/icons.tsx","../src/SocialButton.tsx","../src/SocialButtons.tsx"],"sourcesContent":["export { AuthonProvider, AuthonContext } from './AuthonProvider';\nexport type { AuthonContextValue } from './AuthonProvider';\nexport { useAuthon } from './useAuthon';\nexport { useUser } from './useUser';\nexport { useAuthonWeb3 } from './useAuthonWeb3';\nexport type { UseAuthonWeb3Return, Web3LinkWalletParams } from './useAuthonWeb3';\nexport { useAuthonPasswordless } from './useAuthonPasswordless';\nexport type { UseAuthonPasswordlessReturn } from './useAuthonPasswordless';\nexport { useAuthonPasskeys } from './useAuthonPasskeys';\nexport type { UseAuthonPasskeysReturn } from './useAuthonPasskeys';\nexport { AuthonMobileClient } from './client';\nexport { ProviderIcon } from './icons';\nexport { SocialButton } from './SocialButton';\nexport type { SocialButtonProps } from './SocialButton';\nexport { SocialButtons } from './SocialButtons';\nexport type { SocialButtonsProps } from './SocialButtons';\nexport type {\n AuthonReactNativeConfig,\n AuthState,\n AuthonUser,\n SignInParams,\n SignUpParams,\n StartOAuthOptions,\n OAuthFlowMode,\n AuthonEventType,\n AuthonEvents,\n BrandingConfig,\n OAuthProviderType,\n TokenPair,\n OAuthCompletedResponse,\n OAuthErrorResponse,\n} from './types';\n","import React, { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { BrandingConfig, OAuthProviderType } from '@authon/shared';\nimport { AuthonMobileClient } from './client';\nimport type {\n AuthState,\n AuthonReactNativeConfig,\n AuthonUser,\n SignInParams,\n SignUpParams,\n StartOAuthOptions,\n AuthonEventType,\n AuthonEvents,\n} from './types';\n\nexport interface AuthonContextValue extends AuthState {\n user: AuthonUser | null;\n signIn: (params: SignInParams) => Promise<void>;\n signUp: (params: SignUpParams) => Promise<void>;\n signOut: () => Promise<void>;\n getToken: () => string | null;\n /** Available OAuth providers (fetched from API) */\n providers: OAuthProviderType[];\n /** Branding config (fetched from API) */\n branding: BrandingConfig | null;\n /** Start OAuth flow — returns { url, state }. Open url in browser, then call completeOAuth(state) */\n startOAuth: (\n provider: OAuthProviderType,\n options?: string | StartOAuthOptions,\n ) => Promise<{ url: string; state: string }>;\n /** Poll for OAuth result after user completes browser flow */\n completeOAuth: (state: string) => Promise<void>;\n /** Subscribe to auth events */\n on: <K extends AuthonEventType>(event: K, listener: AuthonEvents[K]) => () => void;\n /** Get the underlying client instance */\n client: AuthonMobileClient;\n}\n\nexport const AuthonContext = createContext<AuthonContextValue | null>(null);\n\ninterface AuthonProviderProps extends AuthonReactNativeConfig {\n children: React.ReactNode;\n storage?: {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n };\n}\n\nexport function AuthonProvider({ children, storage, ...config }: AuthonProviderProps) {\n const clientRef = useRef<AuthonMobileClient | null>(null);\n const [authState, setAuthState] = useState<AuthState>({\n isLoaded: false,\n isSignedIn: false,\n userId: null,\n sessionId: null,\n accessToken: null,\n });\n const [user, setUser] = useState<AuthonUser | null>(null);\n const [providers, setProviders] = useState<OAuthProviderType[]>([]);\n const [branding, setBranding] = useState<BrandingConfig | null>(null);\n\n if (!clientRef.current) {\n clientRef.current = new AuthonMobileClient(config);\n }\n\n const client = clientRef.current;\n\n useEffect(() => {\n if (storage) {\n client.setStorage(storage);\n }\n\n const init = async () => {\n // Initialize tokens from storage\n const tokens = await client.initialize();\n\n // Fetch providers + branding in parallel\n await client.ensureInitialized();\n const p = await client.getProviders();\n const b = await client.getBranding();\n setProviders(p);\n setBranding(b);\n\n if (tokens) {\n const u = await client.getUser();\n setUser(u);\n setAuthState({\n isLoaded: true,\n isSignedIn: true,\n userId: u?.id || null,\n sessionId: null,\n accessToken: tokens.accessToken,\n });\n } else {\n setAuthState((prev) => ({ ...prev, isLoaded: true }));\n }\n };\n\n init();\n\n // Listen for auth events to keep state in sync\n const unsubs = [\n client.on('signedOut', () => {\n setUser(null);\n setAuthState({\n isLoaded: true,\n isSignedIn: false,\n userId: null,\n sessionId: null,\n accessToken: null,\n });\n }),\n client.on('tokenRefreshed', () => {\n const token = client.getAccessToken();\n if (token) {\n setAuthState((prev) => ({ ...prev, accessToken: token }));\n }\n }),\n ];\n\n return () => {\n unsubs.forEach((fn) => fn());\n client.destroy();\n };\n }, []);\n\n const signIn = useCallback(async (params: SignInParams) => {\n const { tokens, user: u } = await client.signIn(params);\n setUser(u);\n setAuthState({\n isLoaded: true,\n isSignedIn: true,\n userId: u?.id || null,\n sessionId: null,\n accessToken: tokens.accessToken,\n });\n }, [client]);\n\n const signUp = useCallback(async (params: SignUpParams) => {\n const { tokens, user: u } = await client.signUp(params);\n setUser(u);\n setAuthState({\n isLoaded: true,\n isSignedIn: true,\n userId: u?.id || null,\n sessionId: null,\n accessToken: tokens.accessToken,\n });\n }, [client]);\n\n const signOut = useCallback(async () => {\n await client.signOut();\n // State is updated via the 'signedOut' event listener\n }, [client]);\n\n const getToken = useCallback(() => {\n return client.getAccessToken();\n }, [client]);\n\n const startOAuth = useCallback(\n async (provider: OAuthProviderType, options?: string | StartOAuthOptions) => {\n return client.getOAuthUrl(provider, options);\n },\n [client],\n );\n\n const completeOAuthCb = useCallback(\n async (state: string) => {\n const { tokens, user: u } = await client.completeOAuth(state);\n setUser(u);\n setAuthState({\n isLoaded: true,\n isSignedIn: true,\n userId: u?.id || null,\n sessionId: null,\n accessToken: tokens.accessToken,\n });\n },\n [client],\n );\n\n const on = useCallback(\n <K extends AuthonEventType>(event: K, listener: AuthonEvents[K]) => {\n return client.on(event, listener);\n },\n [client],\n );\n\n const value = useMemo<AuthonContextValue>(\n () => ({\n ...authState,\n user,\n signIn,\n signUp,\n signOut,\n getToken,\n providers,\n branding,\n startOAuth,\n completeOAuth: completeOAuthCb,\n on,\n client,\n }),\n [authState, user, signIn, signUp, signOut, getToken, providers, branding, startOAuth, completeOAuthCb, on, client],\n );\n\n return <AuthonContext.Provider value={value}>{children}</AuthonContext.Provider>;\n}\n","import type {\n BrandingConfig,\n OAuthProviderType,\n PasskeyCredential,\n Web3Chain,\n Web3NonceResponse,\n Web3Wallet,\n Web3WalletType,\n} from '@authon/shared';\nimport type {\n AuthonReactNativeConfig,\n AuthonUser,\n SignInParams,\n SignUpParams,\n StartOAuthOptions,\n TokenPair,\n ApiAuthResponse,\n OAuthCompletedResponse,\n OAuthErrorResponse,\n AuthonEventType,\n AuthonEvents,\n} from './types';\n\nconst DEFAULT_API_URL = 'https://api.authon.dev';\n\ntype TokenStorage = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n};\n\ninterface ProvidersResponse {\n providers: OAuthProviderType[];\n providerConfigs?: Partial<Record<OAuthProviderType, { oauthFlow?: StartOAuthOptions['flow'] }>>;\n}\n\ntype OAuthPollResponse = OAuthCompletedResponse | OAuthErrorResponse;\n\nconst STORAGE_KEY = 'authon-tokens';\n\nexport class AuthonMobileClient {\n private apiUrl: string;\n private publishableKey: string;\n private tokens: TokenPair | null = null;\n private user: AuthonUser | null = null;\n private storage: TokenStorage | null = null;\n private refreshTimer: ReturnType<typeof setTimeout> | null = null;\n private listeners: Map<string, Set<(...args: unknown[]) => void>> = new Map();\n\n // Cached provider/branding data\n private _providers: OAuthProviderType[] = [];\n private _branding: BrandingConfig | null = null;\n private _initialized = false;\n\n constructor(config: AuthonReactNativeConfig) {\n this.publishableKey = config.publishableKey;\n this.apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\\/$/, '');\n }\n\n setStorage(storage: TokenStorage) {\n this.storage = storage;\n }\n\n // ── Initialization ──\n\n async initialize(): Promise<TokenPair | null> {\n if (!this.storage) return null;\n\n const stored = await this.storage.getItem(STORAGE_KEY);\n if (!stored) return null;\n\n try {\n const tokens: TokenPair = JSON.parse(stored);\n if (tokens.expiresAt > Date.now()) {\n this.tokens = tokens;\n this.scheduleRefresh(tokens.expiresAt);\n return tokens;\n }\n // Try refreshing\n return await this.refreshToken(tokens.refreshToken);\n } catch {\n await this.storage.removeItem(STORAGE_KEY);\n return null;\n }\n }\n\n /** Fetch providers + branding from API (lazy, cached) */\n async ensureInitialized(): Promise<void> {\n if (this._initialized) return;\n try {\n const [branding, providersRes] = await Promise.all([\n this.request('GET', '/v1/auth/branding') as Promise<BrandingConfig>,\n this.request('GET', '/v1/auth/providers') as Promise<ProvidersResponse>,\n ]);\n this._branding = branding;\n this._providers = providersRes.providers;\n this._initialized = true;\n } catch (err) {\n this.emit('error', err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n // ── Auth ──\n\n async signIn(params: SignInParams): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const res = (await this.request('POST', '/v1/auth/signin', params)) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n this.user = res.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', res.user);\n return { tokens: this.tokens, user: res.user };\n }\n\n async signUp(params: SignUpParams): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const res = (await this.request('POST', '/v1/auth/signup', params)) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n this.user = res.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', res.user);\n return { tokens: this.tokens, user: res.user };\n }\n\n async signOut(): Promise<void> {\n if (this.tokens) {\n try {\n await this.request('POST', '/v1/auth/signout', undefined);\n } catch {\n // Ignore sign-out errors\n }\n }\n this.clearSession();\n this.emit('signedOut');\n }\n\n async getUser(): Promise<AuthonUser | null> {\n if (!this.tokens) return null;\n try {\n const user = (await this.request('GET', '/v1/auth/me')) as AuthonUser;\n this.user = user;\n return user;\n } catch {\n return null;\n }\n }\n\n getCachedUser(): AuthonUser | null {\n return this.user;\n }\n\n // ── Token management ──\n\n async refreshToken(refreshToken?: string): Promise<TokenPair | null> {\n const token = refreshToken || this.tokens?.refreshToken;\n if (!token) return null;\n\n try {\n const res = await fetch(`${this.apiUrl}/v1/auth/token/refresh`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.publishableKey,\n },\n body: JSON.stringify({ refreshToken: token }),\n });\n\n if (!res.ok) {\n this.clearSession();\n return null;\n }\n\n const data = (await res.json()) as ApiAuthResponse;\n this.tokens = this.toTokenPair(data);\n this.user = data.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('tokenRefreshed');\n return this.tokens;\n } catch {\n return null;\n }\n }\n\n getAccessToken(): string | null {\n return this.tokens?.accessToken || null;\n }\n\n isAuthenticated(): boolean {\n return this.tokens !== null && this.tokens.expiresAt > Date.now();\n }\n\n // ── OAuth ──\n\n async getProviders(): Promise<OAuthProviderType[]> {\n await this.ensureInitialized();\n return this._providers;\n }\n\n async getBranding(): Promise<BrandingConfig | null> {\n await this.ensureInitialized();\n return this._branding;\n }\n\n async getOAuthUrl(\n provider: string,\n options?: string | StartOAuthOptions,\n ): Promise<{ url: string; state: string }> {\n const normalized =\n typeof options === 'string'\n ? { redirectUri: options }\n : (options ?? {});\n const redirectUri = normalized.redirectUri || `${this.apiUrl}/v1/auth/oauth/redirect`;\n const flow = normalized.flow || 'redirect';\n const params = new URLSearchParams({ redirectUri, flow });\n if (normalized.returnTo) {\n params.set('returnTo', normalized.returnTo);\n }\n return (await this.request(\n 'GET',\n `/v1/auth/oauth/${provider}/url?${params.toString()}`,\n )) as { url: string; state: string };\n }\n\n async pollOAuth(state: string): Promise<OAuthPollResponse | null> {\n try {\n const res = await fetch(\n `${this.apiUrl}/v1/auth/oauth/poll?state=${encodeURIComponent(state)}`,\n { headers: { 'x-api-key': this.publishableKey } },\n );\n if (!res.ok) return null;\n const data = (await res.json()) as Record<string, unknown>;\n if (data.status === 'completed' && data.accessToken) {\n return data as unknown as OAuthCompletedResponse;\n }\n if (data.status === 'error') {\n return {\n status: 'error',\n message: typeof data.message === 'string' ? data.message : 'OAuth failed',\n };\n }\n return null;\n } catch {\n return null;\n }\n }\n\n /** Poll for OAuth completion (3 minute timeout, matching JS SDK) */\n async completeOAuth(state: string): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const maxAttempts = 360; // 3 minutes at 500ms intervals\n for (let i = 0; i < maxAttempts; i++) {\n const result = await this.pollOAuth(state);\n if (result) {\n if (result.status === 'error') {\n throw new Error(result.message || 'OAuth failed');\n }\n this.tokens = this.toTokenPair(result);\n this.user = result.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', result.user);\n return { tokens: this.tokens, user: result.user };\n }\n await new Promise((r) => setTimeout(r, 500));\n }\n throw new Error('OAuth timeout');\n }\n\n getApiUrl(): string {\n return this.apiUrl;\n }\n\n // ── Web3 ──\n\n async web3GetNonce(\n address: string,\n chain: Web3Chain,\n walletType: Web3WalletType,\n chainId?: number,\n ): Promise<Web3NonceResponse> {\n return this.request('POST', '/v1/auth/web3/nonce', {\n address,\n chain,\n walletType,\n ...(chainId != null ? { chainId } : {}),\n }) as Promise<Web3NonceResponse>;\n }\n\n async web3Verify(\n message: string,\n signature: string,\n address: string,\n chain: Web3Chain,\n walletType: Web3WalletType,\n ): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const res = (await this.request('POST', '/v1/auth/web3/verify', {\n message,\n signature,\n address,\n chain,\n walletType,\n })) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n this.user = res.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', res.user);\n return { tokens: this.tokens, user: res.user };\n }\n\n async web3GetWallets(): Promise<Web3Wallet[]> {\n return this.request('GET', '/v1/auth/web3/wallets') as Promise<Web3Wallet[]>;\n }\n\n async web3LinkWallet(params: {\n address: string;\n chain: Web3Chain;\n walletType: Web3WalletType;\n chainId?: number;\n message: string;\n signature: string;\n }): Promise<Web3Wallet> {\n return this.request('POST', '/v1/auth/web3/wallets/link', params) as Promise<Web3Wallet>;\n }\n\n async web3UnlinkWallet(walletId: string): Promise<void> {\n await this.requestAuth('DELETE', `/v1/auth/web3/wallets/${walletId}`);\n }\n\n // ── Passwordless ──\n\n async passwordlessSendCode(identifier: string, type: 'email' | 'sms' = 'email'): Promise<void> {\n if (type === 'sms') {\n await this.request('POST', '/v1/auth/passwordless/sms-otp', { phone: identifier });\n } else {\n await this.request('POST', '/v1/auth/passwordless/email-otp', { email: identifier });\n }\n }\n\n async passwordlessVerifyCode(\n identifier: string,\n code: string,\n ): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const res = (await this.request('POST', '/v1/auth/passwordless/verify', {\n email: identifier,\n code,\n })) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n this.user = res.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', res.user);\n return { tokens: this.tokens, user: res.user };\n }\n\n // ── Passkeys ──\n\n async passkeyStartRegister(name?: string): Promise<{ options: Record<string, unknown> }> {\n return this.requestAuth(\n 'POST',\n '/v1/auth/passkeys/register/options',\n name ? { name } : undefined,\n ) as Promise<{ options: Record<string, unknown> }>;\n }\n\n async passkeyCompleteRegister(credential: Record<string, unknown>): Promise<PasskeyCredential> {\n return this.requestAuth(\n 'POST',\n '/v1/auth/passkeys/register/verify',\n credential,\n ) as Promise<PasskeyCredential>;\n }\n\n async passkeyStartAuth(email?: string): Promise<{ options: Record<string, unknown> }> {\n return this.request(\n 'POST',\n '/v1/auth/passkeys/authenticate/options',\n email ? { email } : undefined,\n ) as Promise<{ options: Record<string, unknown> }>;\n }\n\n async passkeyCompleteAuth(\n credential: Record<string, unknown>,\n ): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const res = (await this.request(\n 'POST',\n '/v1/auth/passkeys/authenticate/verify',\n credential,\n )) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n this.user = res.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', res.user);\n return { tokens: this.tokens, user: res.user };\n }\n\n async passkeyList(): Promise<PasskeyCredential[]> {\n return this.requestAuth('GET', '/v1/auth/passkeys') as Promise<PasskeyCredential[]>;\n }\n\n async passkeyDelete(credentialId: string): Promise<void> {\n await this.requestAuth('DELETE', `/v1/auth/passkeys/${credentialId}`);\n }\n\n // ── Event system ──\n\n on<K extends AuthonEventType>(event: K, listener: AuthonEvents[K]): () => void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set());\n const set = this.listeners.get(event)!;\n set.add(listener as (...args: unknown[]) => void);\n return () => set.delete(listener as (...args: unknown[]) => void);\n }\n\n private emit(event: string, ...args: unknown[]): void {\n this.listeners.get(event)?.forEach((fn) => fn(...args));\n }\n\n // ── Cleanup ──\n\n destroy(): void {\n this.clearRefreshTimer();\n this.listeners.clear();\n }\n\n // ── Private ──\n\n private clearSession(): void {\n this.tokens = null;\n this.user = null;\n this.clearRefreshTimer();\n if (this.storage) {\n this.storage.removeItem(STORAGE_KEY).catch(() => {});\n }\n }\n\n private clearRefreshTimer(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n /** Schedule auto-refresh 60 seconds before token expiry (like JS SDK) */\n private scheduleRefresh(expiresAt: number): void {\n this.clearRefreshTimer();\n const refreshIn = Math.max(expiresAt - Date.now() - 60_000, 30_000);\n this.refreshTimer = setTimeout(() => {\n this.refreshToken().catch(() => {});\n }, refreshIn);\n }\n\n private async persistTokens(): Promise<void> {\n if (this.storage && this.tokens) {\n await this.storage.setItem(STORAGE_KEY, JSON.stringify(this.tokens));\n }\n }\n\n private toTokenPair(res: ApiAuthResponse): TokenPair {\n return {\n accessToken: res.accessToken,\n refreshToken: res.refreshToken,\n expiresAt: Date.now() + res.expiresIn * 1000,\n };\n }\n\n private async requestAuth(method: string, path: string, body?: unknown): Promise<unknown> {\n if (!this.tokens?.accessToken) throw new Error('Must be signed in');\n return this.request(method, path, body);\n }\n\n private async request(method: string, path: string, body?: unknown): Promise<unknown> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': this.publishableKey,\n };\n\n if (this.tokens?.accessToken) {\n headers['Authorization'] = `Bearer ${this.tokens.accessToken}`;\n }\n\n const res = await fetch(`${this.apiUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n const error = await res.json().catch(() => ({ message: res.statusText }));\n const msg = Array.isArray(error.message)\n ? error.message[0]\n : error.message || `Request failed with status ${res.status}`;\n throw new Error(msg);\n }\n\n const text = await res.text();\n return text ? JSON.parse(text) : undefined;\n }\n}\n","import { useContext } from 'react';\nimport { AuthonContext, type AuthonContextValue } from './AuthonProvider';\n\nexport function useAuthon(): AuthonContextValue {\n const context = useContext(AuthonContext);\n if (!context) {\n throw new Error('useAuthon must be used within an <AuthonProvider>');\n }\n return context;\n}\n","import { useAuthon } from './useAuthon';\nimport type { AuthonUser } from './types';\n\nexport function useUser(): {\n isLoaded: boolean;\n isSignedIn: boolean;\n user: AuthonUser | null;\n} {\n const { isLoaded, isSignedIn, user } = useAuthon();\n return { isLoaded, isSignedIn, user };\n}\n","import { useCallback, useContext, useState } from 'react';\nimport type { Web3Chain, Web3NonceResponse, Web3Wallet, Web3WalletType } from '@authon/shared';\nimport { AuthonContext } from './AuthonProvider';\n\nexport interface Web3LinkWalletParams {\n address: string;\n chain: Web3Chain;\n walletType: Web3WalletType;\n chainId?: number;\n message: string;\n signature: string;\n}\n\nexport interface UseAuthonWeb3Return {\n getNonce: (\n address: string,\n chain: Web3Chain,\n walletType: Web3WalletType,\n chainId?: number,\n ) => Promise<Web3NonceResponse | null>;\n verify: (\n message: string,\n signature: string,\n address: string,\n chain: Web3Chain,\n walletType: Web3WalletType,\n ) => Promise<boolean>;\n getWallets: () => Promise<Web3Wallet[] | null>;\n linkWallet: (params: Web3LinkWalletParams) => Promise<Web3Wallet | null>;\n unlinkWallet: (walletId: string) => Promise<boolean>;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport function useAuthonWeb3(): UseAuthonWeb3Return {\n const ctx = useContext(AuthonContext);\n if (!ctx) throw new Error('useAuthonWeb3 must be used within <AuthonProvider>');\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const wrap = useCallback(async <T>(fn: () => Promise<T>): Promise<T | null> => {\n setIsLoading(true);\n setError(null);\n try {\n return await fn();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const getNonce = useCallback(\n (address: string, chain: Web3Chain, walletType: Web3WalletType, chainId?: number) =>\n wrap(() => ctx.client.web3GetNonce(address, chain, walletType, chainId)),\n [ctx.client, wrap],\n );\n\n const verify = useCallback(\n async (\n message: string,\n signature: string,\n address: string,\n chain: Web3Chain,\n walletType: Web3WalletType,\n ) => {\n const result = await wrap(() =>\n ctx.client.web3Verify(message, signature, address, chain, walletType),\n );\n return result !== null;\n },\n [ctx.client, wrap],\n );\n\n const getWallets = useCallback(\n () => wrap(() => ctx.client.web3GetWallets()),\n [ctx.client, wrap],\n );\n\n const linkWallet = useCallback(\n (params: Web3LinkWalletParams) => wrap(() => ctx.client.web3LinkWallet(params)),\n [ctx.client, wrap],\n );\n\n const unlinkWallet = useCallback(\n async (walletId: string) => {\n const result = await wrap(() => ctx.client.web3UnlinkWallet(walletId));\n return result !== null;\n },\n [ctx.client, wrap],\n );\n\n return {\n getNonce,\n verify,\n getWallets,\n linkWallet,\n unlinkWallet,\n isLoading,\n error,\n };\n}\n","import { useCallback, useContext, useState } from 'react';\nimport { AuthonContext } from './AuthonProvider';\nimport type { AuthonUser, TokenPair } from './types';\n\nexport interface UseAuthonPasswordlessReturn {\n sendCode: (identifier: string, type?: 'email' | 'sms') => Promise<boolean>;\n verifyCode: (\n identifier: string,\n code: string,\n ) => Promise<{ tokens: TokenPair; user: AuthonUser } | null>;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport function useAuthonPasswordless(): UseAuthonPasswordlessReturn {\n const ctx = useContext(AuthonContext);\n if (!ctx) throw new Error('useAuthonPasswordless must be used within <AuthonProvider>');\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const wrap = useCallback(async <T>(fn: () => Promise<T>): Promise<T | null> => {\n setIsLoading(true);\n setError(null);\n try {\n return await fn();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const sendCode = useCallback(\n async (identifier: string, type: 'email' | 'sms' = 'email') => {\n const result = await wrap(() => ctx.client.passwordlessSendCode(identifier, type));\n return result !== null;\n },\n [ctx.client, wrap],\n );\n\n const verifyCode = useCallback(\n (identifier: string, code: string) =>\n wrap(() => ctx.client.passwordlessVerifyCode(identifier, code)),\n [ctx.client, wrap],\n );\n\n return {\n sendCode,\n verifyCode,\n isLoading,\n error,\n };\n}\n","import { useCallback, useContext, useState } from 'react';\nimport type { PasskeyCredential } from '@authon/shared';\nimport { AuthonContext } from './AuthonProvider';\nimport type { AuthonUser, TokenPair } from './types';\n\nexport interface UseAuthonPasskeysReturn {\n startRegister: (name?: string) => Promise<{ options: Record<string, unknown> } | null>;\n completeRegister: (credential: Record<string, unknown>) => Promise<PasskeyCredential | null>;\n startAuth: (email?: string) => Promise<{ options: Record<string, unknown> } | null>;\n completeAuth: (\n credential: Record<string, unknown>,\n ) => Promise<{ tokens: TokenPair; user: AuthonUser } | null>;\n listPasskeys: () => Promise<PasskeyCredential[] | null>;\n deletePasskey: (credentialId: string) => Promise<boolean>;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport function useAuthonPasskeys(): UseAuthonPasskeysReturn {\n const ctx = useContext(AuthonContext);\n if (!ctx) throw new Error('useAuthonPasskeys must be used within <AuthonProvider>');\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const wrap = useCallback(async <T>(fn: () => Promise<T>): Promise<T | null> => {\n setIsLoading(true);\n setError(null);\n try {\n return await fn();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const startRegister = useCallback(\n (name?: string) => wrap(() => ctx.client.passkeyStartRegister(name)),\n [ctx.client, wrap],\n );\n\n const completeRegister = useCallback(\n (credential: Record<string, unknown>) =>\n wrap(() => ctx.client.passkeyCompleteRegister(credential)),\n [ctx.client, wrap],\n );\n\n const startAuth = useCallback(\n (email?: string) => wrap(() => ctx.client.passkeyStartAuth(email)),\n [ctx.client, wrap],\n );\n\n const completeAuth = useCallback(\n (credential: Record<string, unknown>) =>\n wrap(() => ctx.client.passkeyCompleteAuth(credential)),\n [ctx.client, wrap],\n );\n\n const listPasskeys = useCallback(\n () => wrap(() => ctx.client.passkeyList()),\n [ctx.client, wrap],\n );\n\n const deletePasskey = useCallback(\n async (credentialId: string) => {\n const result = await wrap(() => ctx.client.passkeyDelete(credentialId));\n return result !== null;\n },\n [ctx.client, wrap],\n );\n\n return {\n startRegister,\n completeRegister,\n startAuth,\n completeAuth,\n listPasskeys,\n deletePasskey,\n isLoading,\n error,\n };\n}\n","import React from 'react';\nimport Svg, { Path, Rect } from 'react-native-svg';\nimport type { OAuthProviderType } from '@authon/shared';\n\ninterface IconProps {\n size?: number;\n color?: string;\n}\n\nfunction GoogleIcon({ size = 20 }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size}>\n <Path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\" />\n <Path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" />\n <Path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <Path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </Svg>\n );\n}\n\nfunction AppleIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size} fill={color}>\n <Path d=\"M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.48-3.24 0-1.44.62-2.2.44-3.06-.4C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z\" />\n </Svg>\n );\n}\n\nfunction KakaoIcon({ size = 20 }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size}>\n <Path fill=\"#191919\" d=\"M12 3C6.48 3 2 6.36 2 10.43c0 2.62 1.75 4.93 4.37 6.23l-1.12 4.14c-.1.36.31.65.62.44l4.93-3.26c.39.04.79.06 1.2.06 5.52 0 10-3.36 10-7.61C22 6.36 17.52 3 12 3z\" />\n </Svg>\n );\n}\n\nfunction NaverIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size}>\n <Path fill={color} d=\"M16.273 12.845 7.376 0H0v24h7.726V11.156L16.624 24H24V0h-7.727v12.845Z\" />\n </Svg>\n );\n}\n\nfunction FacebookIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size}>\n <Path fill={color} d=\"M24 12.07C24 5.41 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.04V9.41c0-3.02 1.8-4.7 4.54-4.7 1.31 0 2.68.24 2.68.24v2.97h-1.5c-1.5 0-1.96.93-1.96 1.89v2.26h3.33l-.53 3.49h-2.8V24C19.62 23.1 24 18.1 24 12.07z\" />\n </Svg>\n );\n}\n\nfunction GithubIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size} fill={color}>\n <Path d=\"M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z\" />\n </Svg>\n );\n}\n\nfunction DiscordIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size} fill={color}>\n <Path d=\"M20.32 4.37a19.8 19.8 0 00-4.89-1.52.07.07 0 00-.08.04c-.21.38-.44.87-.61 1.26a18.27 18.27 0 00-5.49 0 12.64 12.64 0 00-.62-1.26.07.07 0 00-.08-.04 19.74 19.74 0 00-4.89 1.52.07.07 0 00-.03.03C1.11 8.39.34 12.28.73 16.12a.08.08 0 00.03.06 19.9 19.9 0 005.99 3.03.08.08 0 00.08-.03c.46-.63.87-1.3 1.22-2a.08.08 0 00-.04-.11 13.1 13.1 0 01-1.87-.9.08.08 0 01-.01-.13c.13-.09.25-.19.37-.29a.07.07 0 01.08-.01c3.93 1.8 8.18 1.8 12.07 0a.07.07 0 01.08 0c.12.1.25.2.37.3a.08.08 0 01-.01.12c-.6.35-1.22.65-1.87.9a.08.08 0 00-.04.1c.36.7.77 1.37 1.22 2a.08.08 0 00.08.03 19.83 19.83 0 006-3.03.08.08 0 00.03-.05c.47-4.87-.78-9.09-3.3-12.84a.06.06 0 00-.03-.03zM8.02 13.62c-1.11 0-2.03-1.02-2.03-2.28 0-1.26.9-2.28 2.03-2.28 1.14 0 2.04 1.03 2.03 2.28 0 1.26-.9 2.28-2.03 2.28zm7.5 0c-1.11 0-2.03-1.02-2.03-2.28 0-1.26.9-2.28 2.03-2.28 1.14 0 2.04 1.03 2.03 2.28 0 1.26-.89 2.28-2.03 2.28z\" />\n </Svg>\n );\n}\n\nfunction XIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size} fill={color}>\n <Path d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\" />\n </Svg>\n );\n}\n\nfunction LineIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size} fill={color}>\n <Path d=\"M19.365 9.863c.349 0 .63.285.63.631 0 .345-.281.63-.63.63H17.61v1.125h1.755c.349 0 .63.283.63.63 0 .344-.281.629-.63.629h-2.386c-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63h2.386c.346 0 .627.285.627.63 0 .349-.281.63-.63.63H17.61v1.125h1.755zm-3.855 3.016c0 .27-.174.51-.432.596-.064.021-.133.031-.199.031-.211 0-.391-.09-.51-.25l-2.443-3.317v2.94c0 .344-.279.629-.631.629-.346 0-.626-.285-.626-.629V8.108c0-.27.173-.51.43-.595.06-.023.136-.033.194-.033.195 0 .375.104.495.254l2.462 3.33V8.108c0-.345.282-.63.63-.63.345 0 .63.285.63.63v4.771zm-5.741 0c0 .344-.282.629-.631.629-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63.346 0 .628.285.628.63v4.771zm-2.466.629H4.917c-.345 0-.63-.285-.63-.629V8.108c0-.345.285-.63.63-.63.348 0 .63.285.63.63v4.141h1.756c.348 0 .629.283.629.63 0 .344-.282.629-.629.629M24 10.314C24 4.943 18.615.572 12 .572S0 4.943 0 10.314c0 4.811 4.27 8.842 10.035 9.608.391.082.923.258 1.058.59.12.301.079.766.038 1.08l-.164 1.02c-.045.301-.24 1.186 1.049.645 1.291-.539 6.916-4.078 9.436-6.975C23.176 14.393 24 12.458 24 10.314\" />\n </Svg>\n );\n}\n\nfunction MicrosoftIcon({ size = 20 }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size}>\n <Rect fill=\"#F25022\" x={1} y={1} width={10} height={10} />\n <Rect fill=\"#7FBA00\" x={13} y={1} width={10} height={10} />\n <Rect fill=\"#00A4EF\" x={1} y={13} width={10} height={10} />\n <Rect fill=\"#FFB900\" x={13} y={13} width={10} height={10} />\n </Svg>\n );\n}\n\nconst ICON_MAP: Record<OAuthProviderType, React.FC<IconProps>> = {\n google: GoogleIcon,\n apple: AppleIcon,\n kakao: KakaoIcon,\n naver: NaverIcon,\n facebook: FacebookIcon,\n github: GithubIcon,\n discord: DiscordIcon,\n x: XIcon,\n line: LineIcon,\n microsoft: MicrosoftIcon,\n};\n\nexport function ProviderIcon({ provider, size = 20, color }: IconProps & { provider: OAuthProviderType }) {\n const Icon = ICON_MAP[provider];\n if (!Icon) return null;\n return <Icon size={size} color={color} />;\n}\n","import React from 'react';\nimport {\n TouchableOpacity,\n Text,\n ActivityIndicator,\n StyleSheet,\n type ViewStyle,\n type TextStyle,\n} from 'react-native';\nimport { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES, type OAuthProviderType } from '@authon/shared';\nimport { ProviderIcon } from './icons';\n\nexport interface SocialButtonProps {\n provider: OAuthProviderType;\n onPress: (provider: OAuthProviderType) => void;\n loading?: boolean;\n disabled?: boolean;\n /** Override button label. Default: \"Continue with {Provider}\" */\n label?: string;\n /** Compact mode — icon-only square button (default: false) */\n compact?: boolean;\n /** Override button style */\n style?: ViewStyle;\n /** Override label text style */\n labelStyle?: TextStyle;\n /** Icon size (default: 20, compact default: 24) */\n iconSize?: number;\n /** Border radius (default: 10) */\n borderRadius?: number;\n /** Button height (default: 48) */\n height?: number;\n /** Button size for compact mode (default: 48) */\n size?: number;\n}\n\nexport function SocialButton({\n provider,\n onPress,\n loading = false,\n disabled = false,\n label,\n compact = false,\n style,\n labelStyle,\n iconSize,\n borderRadius = 10,\n height = 48,\n size = 48,\n}: SocialButtonProps) {\n const colors = PROVIDER_COLORS[provider] || { bg: '#333', text: '#fff' };\n const displayName = PROVIDER_DISPLAY_NAMES[provider] || provider;\n const buttonLabel = label ?? `Continue with ${displayName}`;\n const needsBorder = colors.bg.toLowerCase() === '#ffffff';\n const resolvedIconSize = iconSize ?? (compact ? 24 : 20);\n\n if (compact) {\n return (\n <TouchableOpacity\n style={[\n styles.compactButton,\n {\n backgroundColor: colors.bg,\n borderRadius,\n width: size,\n height: size,\n },\n needsBorder && styles.bordered,\n style,\n ]}\n onPress={() => onPress(provider)}\n disabled={disabled || loading}\n activeOpacity={0.8}\n >\n {loading ? (\n <ActivityIndicator color={colors.text} size=\"small\" />\n ) : (\n <ProviderIcon provider={provider} size={resolvedIconSize} color={colors.text} />\n )}\n </TouchableOpacity>\n );\n }\n\n return (\n <TouchableOpacity\n style={[\n styles.button,\n {\n backgroundColor: colors.bg,\n borderRadius,\n height,\n },\n needsBorder && styles.bordered,\n style,\n ]}\n onPress={() => onPress(provider)}\n disabled={disabled || loading}\n activeOpacity={0.8}\n >\n {loading ? (\n <ActivityIndicator color={colors.text} size=\"small\" />\n ) : (\n <>\n <ProviderIcon provider={provider} size={resolvedIconSize} color={colors.text} />\n <Text\n style={[\n styles.label,\n { color: colors.text },\n labelStyle,\n ]}\n numberOfLines={1}\n >\n {buttonLabel}\n </Text>\n </>\n )}\n </TouchableOpacity>\n );\n}\n\nconst styles = StyleSheet.create({\n button: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 10,\n paddingHorizontal: 16,\n },\n compactButton: {\n alignItems: 'center',\n justifyContent: 'center',\n },\n bordered: {\n borderWidth: 1,\n borderColor: '#dadce0',\n },\n label: {\n fontSize: 15,\n fontWeight: '600',\n },\n});\n","import React, { useState } from 'react';\nimport { View, StyleSheet, Linking, type ViewStyle } from 'react-native';\nimport type { OAuthProviderType } from '@authon/shared';\nimport { useAuthon } from './useAuthon';\nimport { SocialButton, type SocialButtonProps } from './SocialButton';\n\nexport interface SocialButtonsProps {\n /** Called after successful OAuth sign-in */\n onSuccess?: () => void;\n /** Called on OAuth error */\n onError?: (error: Error) => void;\n /** Container style */\n style?: ViewStyle;\n /** Gap between buttons (default: 10, compact default: 12) */\n gap?: number;\n /** Compact mode — icon-only square buttons in a row (default: false) */\n compact?: boolean;\n /** Custom labels per provider. e.g. { google: 'Google로 로그인' } */\n labels?: Partial<Record<OAuthProviderType, string>>;\n /** Props to pass through to each SocialButton */\n buttonProps?: Partial<Omit<SocialButtonProps, 'provider' | 'onPress' | 'loading' | 'disabled' | 'compact' | 'label'>>;\n}\n\nexport function SocialButtons({\n onSuccess,\n onError,\n style,\n gap,\n compact = false,\n labels,\n buttonProps,\n}: SocialButtonsProps) {\n const { providers, startOAuth, completeOAuth } = useAuthon();\n const [loadingProvider, setLoadingProvider] = useState<string | null>(null);\n\n if (providers.length === 0) return null;\n\n const resolvedGap = gap ?? (compact ? 12 : 10);\n\n const handlePress = async (provider: OAuthProviderType) => {\n setLoadingProvider(provider);\n try {\n const { url, state } = await startOAuth(provider);\n await Linking.openURL(url);\n await completeOAuth(state);\n onSuccess?.();\n } catch (e: any) {\n const error = e instanceof Error ? e : new Error(String(e));\n onError?.(error);\n } finally {\n setLoadingProvider(null);\n }\n };\n\n return (\n <View\n style={[\n compact ? styles.compactContainer : styles.container,\n { gap: resolvedGap },\n style,\n ]}\n >\n {providers.map((provider) => (\n <SocialButton\n key={provider}\n provider={provider}\n onPress={handlePress}\n loading={loadingProvider === provider}\n disabled={!!loadingProvider}\n compact={compact}\n label={labels?.[provider]}\n {...buttonProps}\n />\n ))}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n container: {},\n compactContainer: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n justifyContent: 'center',\n },\n});\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_react","import_jsx_runtime","Svg","import_react","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","styles"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/AuthonProvider.tsx","../src/client.ts","../src/useAuthon.ts","../src/useUser.ts","../src/useAuthonWeb3.ts","../src/useAuthonPasswordless.ts","../src/useAuthonPasskeys.ts","../src/icons.tsx","../src/SocialButton.tsx","../src/SocialButtons.tsx"],"sourcesContent":["export { AuthonProvider, AuthonContext } from './AuthonProvider';\nexport type { AuthonContextValue } from './AuthonProvider';\nexport { useAuthon } from './useAuthon';\nexport { useUser } from './useUser';\nexport { useAuthonWeb3 } from './useAuthonWeb3';\nexport type { UseAuthonWeb3Return, Web3LinkWalletParams } from './useAuthonWeb3';\nexport { useAuthonPasswordless } from './useAuthonPasswordless';\nexport type { UseAuthonPasswordlessReturn } from './useAuthonPasswordless';\nexport { useAuthonPasskeys } from './useAuthonPasskeys';\nexport type { UseAuthonPasskeysReturn } from './useAuthonPasskeys';\nexport { AuthonMobileClient } from './client';\nexport { ProviderIcon } from './icons';\nexport { SocialButton } from './SocialButton';\nexport type { SocialButtonProps } from './SocialButton';\nexport { SocialButtons } from './SocialButtons';\nexport type { SocialButtonsProps } from './SocialButtons';\nexport type {\n AuthonReactNativeConfig,\n AuthState,\n AuthonUser,\n SignInParams,\n SignUpParams,\n StartOAuthOptions,\n OAuthFlowMode,\n AuthonEventType,\n AuthonEvents,\n BrandingConfig,\n OAuthProviderType,\n TokenPair,\n OAuthCompletedResponse,\n OAuthErrorResponse,\n} from './types';\n","import React, { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { BrandingConfig, OAuthProviderType } from '@authon/shared';\nimport { AuthonMobileClient } from './client';\nimport type {\n AuthState,\n AuthonReactNativeConfig,\n AuthonUser,\n SignInParams,\n SignUpParams,\n StartOAuthOptions,\n AuthonEventType,\n AuthonEvents,\n} from './types';\n\nexport interface AuthonContextValue extends AuthState {\n user: AuthonUser | null;\n signIn: (params: SignInParams) => Promise<void>;\n signUp: (params: SignUpParams) => Promise<void>;\n signOut: () => Promise<void>;\n getToken: () => string | null;\n /** Available OAuth providers (fetched from API) */\n providers: OAuthProviderType[];\n /** Branding config (fetched from API) */\n branding: BrandingConfig | null;\n /** Start OAuth flow — returns { url, state }. Open url in browser, then call completeOAuth(state) */\n startOAuth: (\n provider: OAuthProviderType,\n options?: string | StartOAuthOptions,\n ) => Promise<{ url: string; state: string }>;\n /** Poll for OAuth result after user completes browser flow */\n completeOAuth: (state: string) => Promise<void>;\n /** Subscribe to auth events */\n on: <K extends AuthonEventType>(event: K, listener: AuthonEvents[K]) => () => void;\n /** Get the underlying client instance */\n client: AuthonMobileClient;\n}\n\nexport const AuthonContext = createContext<AuthonContextValue | null>(null);\n\ninterface AuthonProviderProps extends AuthonReactNativeConfig {\n children: React.ReactNode;\n storage?: {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n };\n}\n\nexport function AuthonProvider({ children, storage, ...config }: AuthonProviderProps) {\n const clientRef = useRef<AuthonMobileClient | null>(null);\n const [authState, setAuthState] = useState<AuthState>({\n isLoaded: false,\n isSignedIn: false,\n userId: null,\n sessionId: null,\n accessToken: null,\n });\n const [user, setUser] = useState<AuthonUser | null>(null);\n const [providers, setProviders] = useState<OAuthProviderType[]>([]);\n const [branding, setBranding] = useState<BrandingConfig | null>(null);\n\n if (!clientRef.current) {\n clientRef.current = new AuthonMobileClient(config);\n }\n\n const client = clientRef.current;\n\n useEffect(() => {\n if (storage) {\n client.setStorage(storage);\n }\n\n const init = async () => {\n // Initialize tokens from storage\n const tokens = await client.initialize();\n\n // Fetch providers + branding in parallel\n await client.ensureInitialized();\n const p = await client.getProviders();\n const b = await client.getBranding();\n setProviders(p);\n setBranding(b);\n\n if (tokens) {\n const u = await client.getUser();\n setUser(u);\n setAuthState({\n isLoaded: true,\n isSignedIn: true,\n userId: u?.id || null,\n sessionId: null,\n accessToken: tokens.accessToken,\n });\n } else {\n setAuthState((prev) => ({ ...prev, isLoaded: true }));\n }\n };\n\n init();\n\n // Listen for auth events to keep state in sync\n const unsubs = [\n client.on('signedOut', () => {\n setUser(null);\n setAuthState({\n isLoaded: true,\n isSignedIn: false,\n userId: null,\n sessionId: null,\n accessToken: null,\n });\n }),\n client.on('tokenRefreshed', () => {\n const token = client.getAccessToken();\n if (token) {\n setAuthState((prev) => ({ ...prev, accessToken: token }));\n }\n }),\n ];\n\n return () => {\n unsubs.forEach((fn) => fn());\n client.destroy();\n };\n }, []);\n\n const signIn = useCallback(async (params: SignInParams) => {\n const { tokens, user: u } = await client.signIn(params);\n setUser(u);\n setAuthState({\n isLoaded: true,\n isSignedIn: true,\n userId: u?.id || null,\n sessionId: null,\n accessToken: tokens.accessToken,\n });\n }, [client]);\n\n const signUp = useCallback(async (params: SignUpParams) => {\n const { tokens, user: u } = await client.signUp(params);\n setUser(u);\n setAuthState({\n isLoaded: true,\n isSignedIn: true,\n userId: u?.id || null,\n sessionId: null,\n accessToken: tokens.accessToken,\n });\n }, [client]);\n\n const signOut = useCallback(async () => {\n await client.signOut();\n // State is updated via the 'signedOut' event listener\n }, [client]);\n\n const getToken = useCallback(() => {\n return client.getAccessToken();\n }, [client]);\n\n const startOAuth = useCallback(\n async (provider: OAuthProviderType, options?: string | StartOAuthOptions) => {\n return client.getOAuthUrl(provider, options);\n },\n [client],\n );\n\n const completeOAuthCb = useCallback(\n async (state: string) => {\n const { tokens, user: u } = await client.completeOAuth(state);\n setUser(u);\n setAuthState({\n isLoaded: true,\n isSignedIn: true,\n userId: u?.id || null,\n sessionId: null,\n accessToken: tokens.accessToken,\n });\n },\n [client],\n );\n\n const on = useCallback(\n <K extends AuthonEventType>(event: K, listener: AuthonEvents[K]) => {\n return client.on(event, listener);\n },\n [client],\n );\n\n const value = useMemo<AuthonContextValue>(\n () => ({\n ...authState,\n user,\n signIn,\n signUp,\n signOut,\n getToken,\n providers,\n branding,\n startOAuth,\n completeOAuth: completeOAuthCb,\n on,\n client,\n }),\n [authState, user, signIn, signUp, signOut, getToken, providers, branding, startOAuth, completeOAuthCb, on, client],\n );\n\n return <AuthonContext.Provider value={value}>{children}</AuthonContext.Provider>;\n}\n","import type {\n BrandingConfig,\n OAuthProviderType,\n PasskeyCredential,\n Web3Chain,\n Web3NonceResponse,\n Web3Wallet,\n Web3WalletType,\n} from '@authon/shared';\nimport type {\n AuthonReactNativeConfig,\n AuthonUser,\n SignInParams,\n SignUpParams,\n StartOAuthOptions,\n TokenPair,\n ApiAuthResponse,\n OAuthCompletedResponse,\n OAuthErrorResponse,\n AuthonEventType,\n AuthonEvents,\n} from './types';\n\nconst DEFAULT_API_URL = 'https://api.authon.dev';\n\ntype TokenStorage = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n removeItem(key: string): Promise<void>;\n};\n\ninterface ProvidersResponse {\n providers: OAuthProviderType[];\n providerConfigs?: Partial<Record<OAuthProviderType, { oauthFlow?: StartOAuthOptions['flow'] }>>;\n}\n\ntype OAuthPollResponse = OAuthCompletedResponse | OAuthErrorResponse;\n\nfunction getStorageKey(publishableKey: string): string {\n return `authon_session_${publishableKey.slice(0, 16)}`;\n}\n\nexport class AuthonMobileClient {\n private apiUrl: string;\n private publishableKey: string;\n private storageKey: string;\n private tokens: TokenPair | null = null;\n private user: AuthonUser | null = null;\n private storage: TokenStorage | null = null;\n private refreshTimer: ReturnType<typeof setTimeout> | null = null;\n private listeners: Map<string, Set<(...args: unknown[]) => void>> = new Map();\n\n // Cached provider/branding data\n private _providers: OAuthProviderType[] = [];\n private _branding: BrandingConfig | null = null;\n private _initialized = false;\n\n constructor(config: AuthonReactNativeConfig) {\n this.publishableKey = config.publishableKey;\n this.apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\\/$/, '');\n this.storageKey = getStorageKey(config.publishableKey);\n }\n\n setStorage(storage: TokenStorage) {\n this.storage = storage;\n }\n\n // ── Initialization ──\n\n async initialize(): Promise<TokenPair | null> {\n if (!this.storage) return null;\n\n const stored = await this.storage.getItem(this.storageKey);\n if (!stored) return null;\n\n try {\n const tokens: TokenPair = JSON.parse(stored);\n if (tokens.expiresAt > Date.now()) {\n this.tokens = tokens;\n this.scheduleRefresh(tokens.expiresAt);\n return tokens;\n }\n // Try refreshing\n return await this.refreshToken(tokens.refreshToken);\n } catch {\n await this.storage.removeItem(this.storageKey);\n return null;\n }\n }\n\n /** Fetch providers + branding from API (lazy, cached) */\n async ensureInitialized(): Promise<void> {\n if (this._initialized) return;\n try {\n const [branding, providersRes] = await Promise.all([\n this.request('GET', '/v1/auth/branding') as Promise<BrandingConfig>,\n this.request('GET', '/v1/auth/providers') as Promise<ProvidersResponse>,\n ]);\n this._branding = branding;\n this._providers = providersRes.providers;\n this._initialized = true;\n } catch (err) {\n this.emit('error', err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n // ── Auth ──\n\n async signIn(\n params: SignInParams,\n ): Promise<\n | { tokens: TokenPair; user: AuthonUser }\n | { needsVerification: true; email: string }\n | { mfaRequired: true; mfaToken: string }\n > {\n const res = (await this.request('POST', '/v1/auth/signin', params)) as any;\n if (res.needsVerification) {\n this.emit('verificationRequired', res.email);\n return { needsVerification: true as const, email: res.email };\n }\n if (res.mfaRequired) {\n this.emit('mfaRequired', res.mfaToken);\n return { mfaRequired: true as const, mfaToken: res.mfaToken };\n }\n const authRes = res as ApiAuthResponse;\n this.tokens = this.toTokenPair(authRes);\n this.user = authRes.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', authRes.user);\n return { tokens: this.tokens, user: authRes.user };\n }\n\n async signUp(\n params: SignUpParams,\n ): Promise<{ tokens: TokenPair; user: AuthonUser } | { needsVerification: true; email: string }> {\n const res = (await this.request('POST', '/v1/auth/signup', params)) as any;\n if (res.needsVerification) {\n this.emit('verificationRequired', res.email);\n return { needsVerification: true as const, email: res.email };\n }\n const authRes = res as ApiAuthResponse;\n this.tokens = this.toTokenPair(authRes);\n this.user = authRes.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', authRes.user);\n return { tokens: this.tokens, user: authRes.user };\n }\n\n async verifyEmail(email: string, code: string): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const res = (await this.request('POST', '/v1/auth/verify-email', { email, code })) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n this.user = res.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', res.user);\n return { tokens: this.tokens, user: res.user };\n }\n\n async resendVerificationCode(email: string): Promise<void> {\n await this.request('POST', '/v1/auth/resend-code', { email });\n }\n\n async signOut(): Promise<void> {\n if (this.tokens) {\n try {\n await this.request('POST', '/v1/auth/signout', undefined);\n } catch {\n // Ignore sign-out errors\n }\n }\n this.clearSession();\n this.emit('signedOut');\n }\n\n async getUser(): Promise<AuthonUser | null> {\n if (!this.tokens) return null;\n try {\n const user = (await this.request('GET', '/v1/auth/me')) as AuthonUser;\n this.user = user;\n return user;\n } catch {\n return null;\n }\n }\n\n getCachedUser(): AuthonUser | null {\n return this.user;\n }\n\n // ── Token management ──\n\n async refreshToken(refreshToken?: string): Promise<TokenPair | null> {\n const token = refreshToken || this.tokens?.refreshToken;\n if (!token) return null;\n\n try {\n const res = await fetch(`${this.apiUrl}/v1/auth/token/refresh`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.publishableKey,\n },\n body: JSON.stringify({ refreshToken: token }),\n });\n\n if (!res.ok) {\n this.clearSession();\n return null;\n }\n\n const data = (await res.json()) as ApiAuthResponse;\n this.tokens = this.toTokenPair(data);\n this.user = data.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('tokenRefreshed');\n return this.tokens;\n } catch {\n return null;\n }\n }\n\n getAccessToken(): string | null {\n return this.tokens?.accessToken || null;\n }\n\n isAuthenticated(): boolean {\n return this.tokens !== null && this.tokens.expiresAt > Date.now();\n }\n\n // ── OAuth ──\n\n async getProviders(): Promise<OAuthProviderType[]> {\n await this.ensureInitialized();\n return this._providers;\n }\n\n async getBranding(): Promise<BrandingConfig | null> {\n await this.ensureInitialized();\n return this._branding;\n }\n\n async getOAuthUrl(\n provider: string,\n options?: string | StartOAuthOptions,\n ): Promise<{ url: string; state: string }> {\n const normalized =\n typeof options === 'string'\n ? { redirectUri: options }\n : (options ?? {});\n const redirectUri = normalized.redirectUri || `${this.apiUrl}/v1/auth/oauth/redirect`;\n const flow = normalized.flow || 'redirect';\n const params = new URLSearchParams({ redirectUri, flow });\n if (normalized.returnTo) {\n params.set('returnTo', normalized.returnTo);\n }\n return (await this.request(\n 'GET',\n `/v1/auth/oauth/${provider}/url?${params.toString()}`,\n )) as { url: string; state: string };\n }\n\n async pollOAuth(state: string): Promise<OAuthPollResponse | null> {\n try {\n const res = await fetch(\n `${this.apiUrl}/v1/auth/oauth/poll?state=${encodeURIComponent(state)}`,\n { headers: { 'x-api-key': this.publishableKey } },\n );\n if (!res.ok) return null;\n const data = (await res.json()) as Record<string, unknown>;\n if (data.status === 'completed' && data.accessToken) {\n return data as unknown as OAuthCompletedResponse;\n }\n if (data.status === 'error') {\n return {\n status: 'error',\n message: typeof data.message === 'string' ? data.message : 'OAuth failed',\n };\n }\n return null;\n } catch {\n return null;\n }\n }\n\n /** Poll for OAuth completion (3 minute timeout, matching JS SDK) */\n async completeOAuth(state: string): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const maxAttempts = 360; // 3 minutes at 500ms intervals\n for (let i = 0; i < maxAttempts; i++) {\n const result = await this.pollOAuth(state);\n if (result) {\n if (result.status === 'error') {\n throw new Error(result.message || 'OAuth failed');\n }\n this.tokens = this.toTokenPair(result);\n this.user = result.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', result.user);\n return { tokens: this.tokens, user: result.user };\n }\n await new Promise((r) => setTimeout(r, 500));\n }\n throw new Error('OAuth timeout');\n }\n\n getApiUrl(): string {\n return this.apiUrl;\n }\n\n // ── Web3 ──\n\n async web3GetNonce(\n address: string,\n chain: Web3Chain,\n walletType: Web3WalletType,\n chainId?: number,\n ): Promise<Web3NonceResponse> {\n return this.request('POST', '/v1/auth/web3/nonce', {\n address,\n chain,\n walletType,\n ...(chainId != null ? { chainId } : {}),\n }) as Promise<Web3NonceResponse>;\n }\n\n async web3Verify(\n message: string,\n signature: string,\n address: string,\n chain: Web3Chain,\n walletType: Web3WalletType,\n ): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const res = (await this.request('POST', '/v1/auth/web3/verify', {\n message,\n signature,\n address,\n chain,\n walletType,\n })) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n this.user = res.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', res.user);\n return { tokens: this.tokens, user: res.user };\n }\n\n async web3GetWallets(): Promise<Web3Wallet[]> {\n return this.request('GET', '/v1/auth/web3/wallets') as Promise<Web3Wallet[]>;\n }\n\n async web3LinkWallet(params: {\n address: string;\n chain: Web3Chain;\n walletType: Web3WalletType;\n chainId?: number;\n message: string;\n signature: string;\n }): Promise<Web3Wallet> {\n return this.request('POST', '/v1/auth/web3/wallets/link', params) as Promise<Web3Wallet>;\n }\n\n async web3UnlinkWallet(walletId: string): Promise<void> {\n await this.requestAuth('DELETE', `/v1/auth/web3/wallets/${walletId}`);\n }\n\n // ── Passwordless ──\n\n async passwordlessSendCode(identifier: string, type: 'email' | 'sms' = 'email'): Promise<void> {\n if (type === 'sms') {\n await this.request('POST', '/v1/auth/passwordless/sms-otp', { phone: identifier });\n } else {\n await this.request('POST', '/v1/auth/passwordless/email-otp', { email: identifier });\n }\n }\n\n async passwordlessVerifyCode(\n identifier: string,\n code: string,\n ): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const res = (await this.request('POST', '/v1/auth/passwordless/verify', {\n email: identifier,\n code,\n })) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n this.user = res.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', res.user);\n return { tokens: this.tokens, user: res.user };\n }\n\n // ── Passkeys ──\n\n async passkeyStartRegister(name?: string): Promise<{ options: Record<string, unknown> }> {\n return this.requestAuth(\n 'POST',\n '/v1/auth/passkeys/register/options',\n name ? { name } : undefined,\n ) as Promise<{ options: Record<string, unknown> }>;\n }\n\n async passkeyCompleteRegister(credential: Record<string, unknown>): Promise<PasskeyCredential> {\n return this.requestAuth(\n 'POST',\n '/v1/auth/passkeys/register/verify',\n credential,\n ) as Promise<PasskeyCredential>;\n }\n\n async passkeyStartAuth(email?: string): Promise<{ options: Record<string, unknown> }> {\n return this.request(\n 'POST',\n '/v1/auth/passkeys/authenticate/options',\n email ? { email } : undefined,\n ) as Promise<{ options: Record<string, unknown> }>;\n }\n\n async passkeyCompleteAuth(\n credential: Record<string, unknown>,\n ): Promise<{ tokens: TokenPair; user: AuthonUser }> {\n const res = (await this.request(\n 'POST',\n '/v1/auth/passkeys/authenticate/verify',\n credential,\n )) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n this.user = res.user;\n await this.persistTokens();\n this.scheduleRefresh(this.tokens.expiresAt);\n this.emit('signedIn', res.user);\n return { tokens: this.tokens, user: res.user };\n }\n\n async passkeyList(): Promise<PasskeyCredential[]> {\n return this.requestAuth('GET', '/v1/auth/passkeys') as Promise<PasskeyCredential[]>;\n }\n\n async passkeyDelete(credentialId: string): Promise<void> {\n await this.requestAuth('DELETE', `/v1/auth/passkeys/${credentialId}`);\n }\n\n // ── Event system ──\n\n on<K extends AuthonEventType>(event: K, listener: AuthonEvents[K]): () => void {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set());\n const set = this.listeners.get(event)!;\n set.add(listener as (...args: unknown[]) => void);\n return () => set.delete(listener as (...args: unknown[]) => void);\n }\n\n private emit(event: string, ...args: unknown[]): void {\n this.listeners.get(event)?.forEach((fn) => fn(...args));\n }\n\n // ── Cleanup ──\n\n destroy(): void {\n this.clearRefreshTimer();\n this.listeners.clear();\n }\n\n // ── Private ──\n\n private clearSession(): void {\n this.tokens = null;\n this.user = null;\n this.clearRefreshTimer();\n if (this.storage) {\n this.storage.removeItem(this.storageKey).catch(() => {});\n }\n }\n\n private clearRefreshTimer(): void {\n if (this.refreshTimer) {\n clearTimeout(this.refreshTimer);\n this.refreshTimer = null;\n }\n }\n\n /** Schedule auto-refresh 60 seconds before token expiry (like JS SDK) */\n private scheduleRefresh(expiresAt: number): void {\n this.clearRefreshTimer();\n const refreshIn = Math.max(expiresAt - Date.now() - 60_000, 30_000);\n this.refreshTimer = setTimeout(() => {\n this.refreshToken().catch(() => {});\n }, refreshIn);\n }\n\n private async persistTokens(): Promise<void> {\n if (this.storage && this.tokens) {\n await this.storage.setItem(this.storageKey, JSON.stringify(this.tokens));\n }\n }\n\n private toTokenPair(res: ApiAuthResponse): TokenPair {\n return {\n accessToken: res.accessToken,\n refreshToken: res.refreshToken,\n expiresAt: Date.now() + res.expiresIn * 1000,\n };\n }\n\n private async requestAuth(method: string, path: string, body?: unknown): Promise<unknown> {\n if (!this.tokens?.accessToken) throw new Error('Must be signed in');\n return this.request(method, path, body);\n }\n\n private async request(method: string, path: string, body?: unknown): Promise<unknown> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': this.publishableKey,\n };\n\n if (this.tokens?.accessToken) {\n headers['Authorization'] = `Bearer ${this.tokens.accessToken}`;\n }\n\n const res = await fetch(`${this.apiUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n const error = await res.json().catch(() => ({ message: res.statusText }));\n const msg = Array.isArray(error.message)\n ? error.message[0]\n : error.message || `Request failed with status ${res.status}`;\n throw new Error(msg);\n }\n\n const text = await res.text();\n return text ? JSON.parse(text) : undefined;\n }\n}\n","import { useContext } from 'react';\nimport { AuthonContext, type AuthonContextValue } from './AuthonProvider';\n\nexport function useAuthon(): AuthonContextValue {\n const context = useContext(AuthonContext);\n if (!context) {\n throw new Error('useAuthon must be used within an <AuthonProvider>');\n }\n return context;\n}\n","import { useAuthon } from './useAuthon';\nimport type { AuthonUser } from './types';\n\nexport function useUser(): {\n isLoaded: boolean;\n isSignedIn: boolean;\n user: AuthonUser | null;\n} {\n const { isLoaded, isSignedIn, user } = useAuthon();\n return { isLoaded, isSignedIn, user };\n}\n","import { useCallback, useContext, useState } from 'react';\nimport type { Web3Chain, Web3NonceResponse, Web3Wallet, Web3WalletType } from '@authon/shared';\nimport { AuthonContext } from './AuthonProvider';\n\nexport interface Web3LinkWalletParams {\n address: string;\n chain: Web3Chain;\n walletType: Web3WalletType;\n chainId?: number;\n message: string;\n signature: string;\n}\n\nexport interface UseAuthonWeb3Return {\n getNonce: (\n address: string,\n chain: Web3Chain,\n walletType: Web3WalletType,\n chainId?: number,\n ) => Promise<Web3NonceResponse | null>;\n verify: (\n message: string,\n signature: string,\n address: string,\n chain: Web3Chain,\n walletType: Web3WalletType,\n ) => Promise<boolean>;\n getWallets: () => Promise<Web3Wallet[] | null>;\n linkWallet: (params: Web3LinkWalletParams) => Promise<Web3Wallet | null>;\n unlinkWallet: (walletId: string) => Promise<boolean>;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport function useAuthonWeb3(): UseAuthonWeb3Return {\n const ctx = useContext(AuthonContext);\n if (!ctx) throw new Error('useAuthonWeb3 must be used within <AuthonProvider>');\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const wrap = useCallback(async <T>(fn: () => Promise<T>): Promise<T | null> => {\n setIsLoading(true);\n setError(null);\n try {\n return await fn();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const getNonce = useCallback(\n (address: string, chain: Web3Chain, walletType: Web3WalletType, chainId?: number) =>\n wrap(() => ctx.client.web3GetNonce(address, chain, walletType, chainId)),\n [ctx.client, wrap],\n );\n\n const verify = useCallback(\n async (\n message: string,\n signature: string,\n address: string,\n chain: Web3Chain,\n walletType: Web3WalletType,\n ) => {\n const result = await wrap(() =>\n ctx.client.web3Verify(message, signature, address, chain, walletType),\n );\n return result !== null;\n },\n [ctx.client, wrap],\n );\n\n const getWallets = useCallback(\n () => wrap(() => ctx.client.web3GetWallets()),\n [ctx.client, wrap],\n );\n\n const linkWallet = useCallback(\n (params: Web3LinkWalletParams) => wrap(() => ctx.client.web3LinkWallet(params)),\n [ctx.client, wrap],\n );\n\n const unlinkWallet = useCallback(\n async (walletId: string) => {\n const result = await wrap(() => ctx.client.web3UnlinkWallet(walletId));\n return result !== null;\n },\n [ctx.client, wrap],\n );\n\n return {\n getNonce,\n verify,\n getWallets,\n linkWallet,\n unlinkWallet,\n isLoading,\n error,\n };\n}\n","import { useCallback, useContext, useState } from 'react';\nimport { AuthonContext } from './AuthonProvider';\nimport type { AuthonUser, TokenPair } from './types';\n\nexport interface UseAuthonPasswordlessReturn {\n sendCode: (identifier: string, type?: 'email' | 'sms') => Promise<boolean>;\n verifyCode: (\n identifier: string,\n code: string,\n ) => Promise<{ tokens: TokenPair; user: AuthonUser } | null>;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport function useAuthonPasswordless(): UseAuthonPasswordlessReturn {\n const ctx = useContext(AuthonContext);\n if (!ctx) throw new Error('useAuthonPasswordless must be used within <AuthonProvider>');\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const wrap = useCallback(async <T>(fn: () => Promise<T>): Promise<T | null> => {\n setIsLoading(true);\n setError(null);\n try {\n return await fn();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const sendCode = useCallback(\n async (identifier: string, type: 'email' | 'sms' = 'email') => {\n const result = await wrap(() => ctx.client.passwordlessSendCode(identifier, type));\n return result !== null;\n },\n [ctx.client, wrap],\n );\n\n const verifyCode = useCallback(\n (identifier: string, code: string) =>\n wrap(() => ctx.client.passwordlessVerifyCode(identifier, code)),\n [ctx.client, wrap],\n );\n\n return {\n sendCode,\n verifyCode,\n isLoading,\n error,\n };\n}\n","import { useCallback, useContext, useState } from 'react';\nimport type { PasskeyCredential } from '@authon/shared';\nimport { AuthonContext } from './AuthonProvider';\nimport type { AuthonUser, TokenPair } from './types';\n\nexport interface UseAuthonPasskeysReturn {\n startRegister: (name?: string) => Promise<{ options: Record<string, unknown> } | null>;\n completeRegister: (credential: Record<string, unknown>) => Promise<PasskeyCredential | null>;\n startAuth: (email?: string) => Promise<{ options: Record<string, unknown> } | null>;\n completeAuth: (\n credential: Record<string, unknown>,\n ) => Promise<{ tokens: TokenPair; user: AuthonUser } | null>;\n listPasskeys: () => Promise<PasskeyCredential[] | null>;\n deletePasskey: (credentialId: string) => Promise<boolean>;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport function useAuthonPasskeys(): UseAuthonPasskeysReturn {\n const ctx = useContext(AuthonContext);\n if (!ctx) throw new Error('useAuthonPasskeys must be used within <AuthonProvider>');\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const wrap = useCallback(async <T>(fn: () => Promise<T>): Promise<T | null> => {\n setIsLoading(true);\n setError(null);\n try {\n return await fn();\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)));\n return null;\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n const startRegister = useCallback(\n (name?: string) => wrap(() => ctx.client.passkeyStartRegister(name)),\n [ctx.client, wrap],\n );\n\n const completeRegister = useCallback(\n (credential: Record<string, unknown>) =>\n wrap(() => ctx.client.passkeyCompleteRegister(credential)),\n [ctx.client, wrap],\n );\n\n const startAuth = useCallback(\n (email?: string) => wrap(() => ctx.client.passkeyStartAuth(email)),\n [ctx.client, wrap],\n );\n\n const completeAuth = useCallback(\n (credential: Record<string, unknown>) =>\n wrap(() => ctx.client.passkeyCompleteAuth(credential)),\n [ctx.client, wrap],\n );\n\n const listPasskeys = useCallback(\n () => wrap(() => ctx.client.passkeyList()),\n [ctx.client, wrap],\n );\n\n const deletePasskey = useCallback(\n async (credentialId: string) => {\n const result = await wrap(() => ctx.client.passkeyDelete(credentialId));\n return result !== null;\n },\n [ctx.client, wrap],\n );\n\n return {\n startRegister,\n completeRegister,\n startAuth,\n completeAuth,\n listPasskeys,\n deletePasskey,\n isLoading,\n error,\n };\n}\n","import React from 'react';\nimport Svg, { Path, Rect } from 'react-native-svg';\nimport type { OAuthProviderType } from '@authon/shared';\n\ninterface IconProps {\n size?: number;\n color?: string;\n}\n\nfunction GoogleIcon({ size = 20 }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size}>\n <Path fill=\"#4285F4\" d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z\" />\n <Path fill=\"#34A853\" d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" />\n <Path fill=\"#FBBC05\" d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" />\n <Path fill=\"#EA4335\" d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" />\n </Svg>\n );\n}\n\nfunction AppleIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size} fill={color}>\n <Path d=\"M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.48-3.24 0-1.44.62-2.2.44-3.06-.4C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z\" />\n </Svg>\n );\n}\n\nfunction KakaoIcon({ size = 20 }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size}>\n <Path fill=\"#191919\" d=\"M12 3C6.48 3 2 6.36 2 10.43c0 2.62 1.75 4.93 4.37 6.23l-1.12 4.14c-.1.36.31.65.62.44l4.93-3.26c.39.04.79.06 1.2.06 5.52 0 10-3.36 10-7.61C22 6.36 17.52 3 12 3z\" />\n </Svg>\n );\n}\n\nfunction NaverIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size}>\n <Path fill={color} d=\"M16.273 12.845 7.376 0H0v24h7.726V11.156L16.624 24H24V0h-7.727v12.845Z\" />\n </Svg>\n );\n}\n\nfunction FacebookIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size}>\n <Path fill={color} d=\"M24 12.07C24 5.41 18.63 0 12 0S0 5.4 0 12.07C0 18.1 4.39 23.1 10.13 24v-8.44H7.08v-3.49h3.04V9.41c0-3.02 1.8-4.7 4.54-4.7 1.31 0 2.68.24 2.68.24v2.97h-1.5c-1.5 0-1.96.93-1.96 1.89v2.26h3.33l-.53 3.49h-2.8V24C19.62 23.1 24 18.1 24 12.07z\" />\n </Svg>\n );\n}\n\nfunction GithubIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size} fill={color}>\n <Path d=\"M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z\" />\n </Svg>\n );\n}\n\nfunction DiscordIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size} fill={color}>\n <Path d=\"M20.32 4.37a19.8 19.8 0 00-4.89-1.52.07.07 0 00-.08.04c-.21.38-.44.87-.61 1.26a18.27 18.27 0 00-5.49 0 12.64 12.64 0 00-.62-1.26.07.07 0 00-.08-.04 19.74 19.74 0 00-4.89 1.52.07.07 0 00-.03.03C1.11 8.39.34 12.28.73 16.12a.08.08 0 00.03.06 19.9 19.9 0 005.99 3.03.08.08 0 00.08-.03c.46-.63.87-1.3 1.22-2a.08.08 0 00-.04-.11 13.1 13.1 0 01-1.87-.9.08.08 0 01-.01-.13c.13-.09.25-.19.37-.29a.07.07 0 01.08-.01c3.93 1.8 8.18 1.8 12.07 0a.07.07 0 01.08 0c.12.1.25.2.37.3a.08.08 0 01-.01.12c-.6.35-1.22.65-1.87.9a.08.08 0 00-.04.1c.36.7.77 1.37 1.22 2a.08.08 0 00.08.03 19.83 19.83 0 006-3.03.08.08 0 00.03-.05c.47-4.87-.78-9.09-3.3-12.84a.06.06 0 00-.03-.03zM8.02 13.62c-1.11 0-2.03-1.02-2.03-2.28 0-1.26.9-2.28 2.03-2.28 1.14 0 2.04 1.03 2.03 2.28 0 1.26-.9 2.28-2.03 2.28zm7.5 0c-1.11 0-2.03-1.02-2.03-2.28 0-1.26.9-2.28 2.03-2.28 1.14 0 2.04 1.03 2.03 2.28 0 1.26-.89 2.28-2.03 2.28z\" />\n </Svg>\n );\n}\n\nfunction XIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size} fill={color}>\n <Path d=\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\" />\n </Svg>\n );\n}\n\nfunction LineIcon({ size = 20, color = '#fff' }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size} fill={color}>\n <Path d=\"M19.365 9.863c.349 0 .63.285.63.631 0 .345-.281.63-.63.63H17.61v1.125h1.755c.349 0 .63.283.63.63 0 .344-.281.629-.63.629h-2.386c-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63h2.386c.346 0 .627.285.627.63 0 .349-.281.63-.63.63H17.61v1.125h1.755zm-3.855 3.016c0 .27-.174.51-.432.596-.064.021-.133.031-.199.031-.211 0-.391-.09-.51-.25l-2.443-3.317v2.94c0 .344-.279.629-.631.629-.346 0-.626-.285-.626-.629V8.108c0-.27.173-.51.43-.595.06-.023.136-.033.194-.033.195 0 .375.104.495.254l2.462 3.33V8.108c0-.345.282-.63.63-.63.345 0 .63.285.63.63v4.771zm-5.741 0c0 .344-.282.629-.631.629-.345 0-.627-.285-.627-.629V8.108c0-.345.282-.63.63-.63.346 0 .628.285.628.63v4.771zm-2.466.629H4.917c-.345 0-.63-.285-.63-.629V8.108c0-.345.285-.63.63-.63.348 0 .63.285.63.63v4.141h1.756c.348 0 .629.283.629.63 0 .344-.282.629-.629.629M24 10.314C24 4.943 18.615.572 12 .572S0 4.943 0 10.314c0 4.811 4.27 8.842 10.035 9.608.391.082.923.258 1.058.59.12.301.079.766.038 1.08l-.164 1.02c-.045.301-.24 1.186 1.049.645 1.291-.539 6.916-4.078 9.436-6.975C23.176 14.393 24 12.458 24 10.314\" />\n </Svg>\n );\n}\n\nfunction MicrosoftIcon({ size = 20 }: IconProps) {\n return (\n <Svg viewBox=\"0 0 24 24\" width={size} height={size}>\n <Rect fill=\"#F25022\" x={1} y={1} width={10} height={10} />\n <Rect fill=\"#7FBA00\" x={13} y={1} width={10} height={10} />\n <Rect fill=\"#00A4EF\" x={1} y={13} width={10} height={10} />\n <Rect fill=\"#FFB900\" x={13} y={13} width={10} height={10} />\n </Svg>\n );\n}\n\nconst ICON_MAP: Record<OAuthProviderType, React.FC<IconProps>> = {\n google: GoogleIcon,\n apple: AppleIcon,\n kakao: KakaoIcon,\n naver: NaverIcon,\n facebook: FacebookIcon,\n github: GithubIcon,\n discord: DiscordIcon,\n x: XIcon,\n line: LineIcon,\n microsoft: MicrosoftIcon,\n};\n\nexport function ProviderIcon({ provider, size = 20, color }: IconProps & { provider: OAuthProviderType }) {\n const Icon = ICON_MAP[provider];\n if (!Icon) return null;\n return <Icon size={size} color={color} />;\n}\n","import React from 'react';\nimport {\n TouchableOpacity,\n Text,\n ActivityIndicator,\n StyleSheet,\n type ViewStyle,\n type TextStyle,\n} from 'react-native';\nimport { PROVIDER_COLORS, PROVIDER_DISPLAY_NAMES, type OAuthProviderType } from '@authon/shared';\nimport { ProviderIcon } from './icons';\n\nexport interface SocialButtonProps {\n provider: OAuthProviderType;\n onPress: (provider: OAuthProviderType) => void;\n loading?: boolean;\n disabled?: boolean;\n /** Override button label. Default: \"Continue with {Provider}\" */\n label?: string;\n /** Compact mode — icon-only square button (default: false) */\n compact?: boolean;\n /** Override button style */\n style?: ViewStyle;\n /** Override label text style */\n labelStyle?: TextStyle;\n /** Icon size (default: 20, compact default: 24) */\n iconSize?: number;\n /** Border radius (default: 10) */\n borderRadius?: number;\n /** Button height (default: 48) */\n height?: number;\n /** Button size for compact mode (default: 48) */\n size?: number;\n}\n\nexport function SocialButton({\n provider,\n onPress,\n loading = false,\n disabled = false,\n label,\n compact = false,\n style,\n labelStyle,\n iconSize,\n borderRadius = 10,\n height = 48,\n size = 48,\n}: SocialButtonProps) {\n const colors = PROVIDER_COLORS[provider] || { bg: '#333', text: '#fff' };\n const displayName = PROVIDER_DISPLAY_NAMES[provider] || provider;\n const buttonLabel = label ?? `Continue with ${displayName}`;\n const needsBorder = colors.bg.toLowerCase() === '#ffffff';\n const resolvedIconSize = iconSize ?? (compact ? 24 : 20);\n\n if (compact) {\n return (\n <TouchableOpacity\n style={[\n styles.compactButton,\n {\n backgroundColor: colors.bg,\n borderRadius,\n width: size,\n height: size,\n },\n needsBorder && styles.bordered,\n style,\n ]}\n onPress={() => onPress(provider)}\n disabled={disabled || loading}\n activeOpacity={0.8}\n >\n {loading ? (\n <ActivityIndicator color={colors.text} size=\"small\" />\n ) : (\n <ProviderIcon provider={provider} size={resolvedIconSize} color={colors.text} />\n )}\n </TouchableOpacity>\n );\n }\n\n return (\n <TouchableOpacity\n style={[\n styles.button,\n {\n backgroundColor: colors.bg,\n borderRadius,\n height,\n },\n needsBorder && styles.bordered,\n style,\n ]}\n onPress={() => onPress(provider)}\n disabled={disabled || loading}\n activeOpacity={0.8}\n >\n {loading ? (\n <ActivityIndicator color={colors.text} size=\"small\" />\n ) : (\n <>\n <ProviderIcon provider={provider} size={resolvedIconSize} color={colors.text} />\n <Text\n style={[\n styles.label,\n { color: colors.text },\n labelStyle,\n ]}\n numberOfLines={1}\n >\n {buttonLabel}\n </Text>\n </>\n )}\n </TouchableOpacity>\n );\n}\n\nconst styles = StyleSheet.create({\n button: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 10,\n paddingHorizontal: 16,\n },\n compactButton: {\n alignItems: 'center',\n justifyContent: 'center',\n },\n bordered: {\n borderWidth: 1,\n borderColor: '#dadce0',\n },\n label: {\n fontSize: 15,\n fontWeight: '600',\n },\n});\n","import React, { useState } from 'react';\nimport { View, StyleSheet, Linking, type ViewStyle } from 'react-native';\nimport type { OAuthProviderType } from '@authon/shared';\nimport { useAuthon } from './useAuthon';\nimport { SocialButton, type SocialButtonProps } from './SocialButton';\n\nexport interface SocialButtonsProps {\n /** Called after successful OAuth sign-in */\n onSuccess?: () => void;\n /** Called on OAuth error */\n onError?: (error: Error) => void;\n /** Container style */\n style?: ViewStyle;\n /** Gap between buttons (default: 10, compact default: 12) */\n gap?: number;\n /** Compact mode — icon-only square buttons in a row (default: false) */\n compact?: boolean;\n /** Custom labels per provider. e.g. { google: 'Google로 로그인' } */\n labels?: Partial<Record<OAuthProviderType, string>>;\n /** Props to pass through to each SocialButton */\n buttonProps?: Partial<Omit<SocialButtonProps, 'provider' | 'onPress' | 'loading' | 'disabled' | 'compact' | 'label'>>;\n}\n\nexport function SocialButtons({\n onSuccess,\n onError,\n style,\n gap,\n compact = false,\n labels,\n buttonProps,\n}: SocialButtonsProps) {\n const { providers, startOAuth, completeOAuth } = useAuthon();\n const [loadingProvider, setLoadingProvider] = useState<string | null>(null);\n\n if (providers.length === 0) return null;\n\n const resolvedGap = gap ?? (compact ? 12 : 10);\n\n const handlePress = async (provider: OAuthProviderType) => {\n setLoadingProvider(provider);\n try {\n const { url, state } = await startOAuth(provider);\n await Linking.openURL(url);\n await completeOAuth(state);\n onSuccess?.();\n } catch (e: any) {\n const error = e instanceof Error ? e : new Error(String(e));\n onError?.(error);\n } finally {\n setLoadingProvider(null);\n }\n };\n\n return (\n <View\n style={[\n compact ? styles.compactContainer : styles.container,\n { gap: resolvedGap },\n style,\n ]}\n >\n {providers.map((provider) => (\n <SocialButton\n key={provider}\n provider={provider}\n onPress={handlePress}\n loading={loadingProvider === provider}\n disabled={!!loadingProvider}\n compact={compact}\n label={labels?.[provider]}\n {...buttonProps}\n />\n ))}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n container: {},\n compactContainer: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n justifyContent: 'center',\n },\n});\n"],"mappings":"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","names":["import_react","import_react","import_react","import_react","import_react","import_jsx_runtime","Svg","import_react","import_jsx_runtime","import_react","import_react_native","import_jsx_runtime","styles"]}
|
package/dist/index.js
CHANGED
|
@@ -3,10 +3,13 @@ import { createContext, useCallback, useEffect, useMemo, useRef, useState } from
|
|
|
3
3
|
|
|
4
4
|
// src/client.ts
|
|
5
5
|
var DEFAULT_API_URL = "https://api.authon.dev";
|
|
6
|
-
|
|
6
|
+
function getStorageKey(publishableKey) {
|
|
7
|
+
return `authon_session_${publishableKey.slice(0, 16)}`;
|
|
8
|
+
}
|
|
7
9
|
var AuthonMobileClient = class {
|
|
8
10
|
apiUrl;
|
|
9
11
|
publishableKey;
|
|
12
|
+
storageKey;
|
|
10
13
|
tokens = null;
|
|
11
14
|
user = null;
|
|
12
15
|
storage = null;
|
|
@@ -19,6 +22,7 @@ var AuthonMobileClient = class {
|
|
|
19
22
|
constructor(config) {
|
|
20
23
|
this.publishableKey = config.publishableKey;
|
|
21
24
|
this.apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\/$/, "");
|
|
25
|
+
this.storageKey = getStorageKey(config.publishableKey);
|
|
22
26
|
}
|
|
23
27
|
setStorage(storage) {
|
|
24
28
|
this.storage = storage;
|
|
@@ -26,7 +30,7 @@ var AuthonMobileClient = class {
|
|
|
26
30
|
// ── Initialization ──
|
|
27
31
|
async initialize() {
|
|
28
32
|
if (!this.storage) return null;
|
|
29
|
-
const stored = await this.storage.getItem(
|
|
33
|
+
const stored = await this.storage.getItem(this.storageKey);
|
|
30
34
|
if (!stored) return null;
|
|
31
35
|
try {
|
|
32
36
|
const tokens = JSON.parse(stored);
|
|
@@ -37,7 +41,7 @@ var AuthonMobileClient = class {
|
|
|
37
41
|
}
|
|
38
42
|
return await this.refreshToken(tokens.refreshToken);
|
|
39
43
|
} catch {
|
|
40
|
-
await this.storage.removeItem(
|
|
44
|
+
await this.storage.removeItem(this.storageKey);
|
|
41
45
|
return null;
|
|
42
46
|
}
|
|
43
47
|
}
|
|
@@ -59,15 +63,38 @@ var AuthonMobileClient = class {
|
|
|
59
63
|
// ── Auth ──
|
|
60
64
|
async signIn(params) {
|
|
61
65
|
const res = await this.request("POST", "/v1/auth/signin", params);
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
if (res.needsVerification) {
|
|
67
|
+
this.emit("verificationRequired", res.email);
|
|
68
|
+
return { needsVerification: true, email: res.email };
|
|
69
|
+
}
|
|
70
|
+
if (res.mfaRequired) {
|
|
71
|
+
this.emit("mfaRequired", res.mfaToken);
|
|
72
|
+
return { mfaRequired: true, mfaToken: res.mfaToken };
|
|
73
|
+
}
|
|
74
|
+
const authRes = res;
|
|
75
|
+
this.tokens = this.toTokenPair(authRes);
|
|
76
|
+
this.user = authRes.user;
|
|
64
77
|
await this.persistTokens();
|
|
65
78
|
this.scheduleRefresh(this.tokens.expiresAt);
|
|
66
|
-
this.emit("signedIn",
|
|
67
|
-
return { tokens: this.tokens, user:
|
|
79
|
+
this.emit("signedIn", authRes.user);
|
|
80
|
+
return { tokens: this.tokens, user: authRes.user };
|
|
68
81
|
}
|
|
69
82
|
async signUp(params) {
|
|
70
83
|
const res = await this.request("POST", "/v1/auth/signup", params);
|
|
84
|
+
if (res.needsVerification) {
|
|
85
|
+
this.emit("verificationRequired", res.email);
|
|
86
|
+
return { needsVerification: true, email: res.email };
|
|
87
|
+
}
|
|
88
|
+
const authRes = res;
|
|
89
|
+
this.tokens = this.toTokenPair(authRes);
|
|
90
|
+
this.user = authRes.user;
|
|
91
|
+
await this.persistTokens();
|
|
92
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
93
|
+
this.emit("signedIn", authRes.user);
|
|
94
|
+
return { tokens: this.tokens, user: authRes.user };
|
|
95
|
+
}
|
|
96
|
+
async verifyEmail(email, code) {
|
|
97
|
+
const res = await this.request("POST", "/v1/auth/verify-email", { email, code });
|
|
71
98
|
this.tokens = this.toTokenPair(res);
|
|
72
99
|
this.user = res.user;
|
|
73
100
|
await this.persistTokens();
|
|
@@ -75,6 +102,9 @@ var AuthonMobileClient = class {
|
|
|
75
102
|
this.emit("signedIn", res.user);
|
|
76
103
|
return { tokens: this.tokens, user: res.user };
|
|
77
104
|
}
|
|
105
|
+
async resendVerificationCode(email) {
|
|
106
|
+
await this.request("POST", "/v1/auth/resend-code", { email });
|
|
107
|
+
}
|
|
78
108
|
async signOut() {
|
|
79
109
|
if (this.tokens) {
|
|
80
110
|
try {
|
|
@@ -314,7 +344,7 @@ var AuthonMobileClient = class {
|
|
|
314
344
|
this.user = null;
|
|
315
345
|
this.clearRefreshTimer();
|
|
316
346
|
if (this.storage) {
|
|
317
|
-
this.storage.removeItem(
|
|
347
|
+
this.storage.removeItem(this.storageKey).catch(() => {
|
|
318
348
|
});
|
|
319
349
|
}
|
|
320
350
|
}
|
|
@@ -335,7 +365,7 @@ var AuthonMobileClient = class {
|
|
|
335
365
|
}
|
|
336
366
|
async persistTokens() {
|
|
337
367
|
if (this.storage && this.tokens) {
|
|
338
|
-
await this.storage.setItem(
|
|
368
|
+
await this.storage.setItem(this.storageKey, JSON.stringify(this.tokens));
|
|
339
369
|
}
|
|
340
370
|
}
|
|
341
371
|
toTokenPair(res) {
|