@authon/react-native 0.1.21 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +211 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +95 -45
- package/dist/index.d.ts +95 -45
- package/dist/index.js +211 -27
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -33,12 +33,19 @@ var import_react = require("react");
|
|
|
33
33
|
|
|
34
34
|
// src/client.ts
|
|
35
35
|
var DEFAULT_API_URL = "https://api.authon.dev";
|
|
36
|
-
var STORAGE_KEY = "
|
|
36
|
+
var STORAGE_KEY = "authon-tokens";
|
|
37
37
|
var AuthonMobileClient = class {
|
|
38
38
|
apiUrl;
|
|
39
39
|
publishableKey;
|
|
40
40
|
tokens = null;
|
|
41
|
+
user = null;
|
|
41
42
|
storage = null;
|
|
43
|
+
refreshTimer = null;
|
|
44
|
+
listeners = /* @__PURE__ */ new Map();
|
|
45
|
+
// Cached provider/branding data
|
|
46
|
+
_providers = [];
|
|
47
|
+
_branding = null;
|
|
48
|
+
_initialized = false;
|
|
42
49
|
constructor(config) {
|
|
43
50
|
this.publishableKey = config.publishableKey;
|
|
44
51
|
this.apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\/$/, "");
|
|
@@ -46,6 +53,7 @@ var AuthonMobileClient = class {
|
|
|
46
53
|
setStorage(storage) {
|
|
47
54
|
this.storage = storage;
|
|
48
55
|
}
|
|
56
|
+
// ── Initialization ──
|
|
49
57
|
async initialize() {
|
|
50
58
|
if (!this.storage) return null;
|
|
51
59
|
const stored = await this.storage.getItem(STORAGE_KEY);
|
|
@@ -54,6 +62,7 @@ var AuthonMobileClient = class {
|
|
|
54
62
|
const tokens = JSON.parse(stored);
|
|
55
63
|
if (tokens.expiresAt > Date.now()) {
|
|
56
64
|
this.tokens = tokens;
|
|
65
|
+
this.scheduleRefresh(tokens.expiresAt);
|
|
57
66
|
return tokens;
|
|
58
67
|
}
|
|
59
68
|
return await this.refreshToken(tokens.refreshToken);
|
|
@@ -62,17 +71,39 @@ var AuthonMobileClient = class {
|
|
|
62
71
|
return null;
|
|
63
72
|
}
|
|
64
73
|
}
|
|
74
|
+
/** Fetch providers + branding from API (lazy, cached) */
|
|
75
|
+
async ensureInitialized() {
|
|
76
|
+
if (this._initialized) return;
|
|
77
|
+
try {
|
|
78
|
+
const [branding, providersRes] = await Promise.all([
|
|
79
|
+
this.request("GET", "/v1/auth/branding"),
|
|
80
|
+
this.request("GET", "/v1/auth/providers")
|
|
81
|
+
]);
|
|
82
|
+
this._branding = branding;
|
|
83
|
+
this._providers = providersRes.providers;
|
|
84
|
+
this._initialized = true;
|
|
85
|
+
} catch (err) {
|
|
86
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// ── Auth ──
|
|
65
90
|
async signIn(params) {
|
|
66
91
|
const res = await this.request("POST", "/v1/auth/signin", params);
|
|
67
92
|
this.tokens = this.toTokenPair(res);
|
|
93
|
+
this.user = res.user;
|
|
68
94
|
await this.persistTokens();
|
|
69
|
-
|
|
95
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
96
|
+
this.emit("signedIn", res.user);
|
|
97
|
+
return { tokens: this.tokens, user: res.user };
|
|
70
98
|
}
|
|
71
99
|
async signUp(params) {
|
|
72
100
|
const res = await this.request("POST", "/v1/auth/signup", params);
|
|
73
101
|
this.tokens = this.toTokenPair(res);
|
|
102
|
+
this.user = res.user;
|
|
74
103
|
await this.persistTokens();
|
|
75
|
-
|
|
104
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
105
|
+
this.emit("signedIn", res.user);
|
|
106
|
+
return { tokens: this.tokens, user: res.user };
|
|
76
107
|
}
|
|
77
108
|
async signOut() {
|
|
78
109
|
if (this.tokens) {
|
|
@@ -81,19 +112,23 @@ var AuthonMobileClient = class {
|
|
|
81
112
|
} catch {
|
|
82
113
|
}
|
|
83
114
|
}
|
|
84
|
-
this.
|
|
85
|
-
|
|
86
|
-
await this.storage.removeItem(STORAGE_KEY);
|
|
87
|
-
}
|
|
115
|
+
this.clearSession();
|
|
116
|
+
this.emit("signedOut");
|
|
88
117
|
}
|
|
89
118
|
async getUser() {
|
|
90
119
|
if (!this.tokens) return null;
|
|
91
120
|
try {
|
|
92
|
-
|
|
121
|
+
const user = await this.request("GET", "/v1/auth/me");
|
|
122
|
+
this.user = user;
|
|
123
|
+
return user;
|
|
93
124
|
} catch {
|
|
94
125
|
return null;
|
|
95
126
|
}
|
|
96
127
|
}
|
|
128
|
+
getCachedUser() {
|
|
129
|
+
return this.user;
|
|
130
|
+
}
|
|
131
|
+
// ── Token management ──
|
|
97
132
|
async refreshToken(refreshToken) {
|
|
98
133
|
const token = refreshToken || this.tokens?.refreshToken;
|
|
99
134
|
if (!token) return null;
|
|
@@ -107,13 +142,15 @@ var AuthonMobileClient = class {
|
|
|
107
142
|
body: JSON.stringify({ refreshToken: token })
|
|
108
143
|
});
|
|
109
144
|
if (!res.ok) {
|
|
110
|
-
this.
|
|
111
|
-
if (this.storage) await this.storage.removeItem(STORAGE_KEY);
|
|
145
|
+
this.clearSession();
|
|
112
146
|
return null;
|
|
113
147
|
}
|
|
114
148
|
const data = await res.json();
|
|
115
149
|
this.tokens = this.toTokenPair(data);
|
|
150
|
+
this.user = data.user;
|
|
116
151
|
await this.persistTokens();
|
|
152
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
153
|
+
this.emit("tokenRefreshed");
|
|
117
154
|
return this.tokens;
|
|
118
155
|
} catch {
|
|
119
156
|
return null;
|
|
@@ -125,6 +162,98 @@ var AuthonMobileClient = class {
|
|
|
125
162
|
isAuthenticated() {
|
|
126
163
|
return this.tokens !== null && this.tokens.expiresAt > Date.now();
|
|
127
164
|
}
|
|
165
|
+
// ── OAuth ──
|
|
166
|
+
async getProviders() {
|
|
167
|
+
await this.ensureInitialized();
|
|
168
|
+
return this._providers;
|
|
169
|
+
}
|
|
170
|
+
async getBranding() {
|
|
171
|
+
await this.ensureInitialized();
|
|
172
|
+
return this._branding;
|
|
173
|
+
}
|
|
174
|
+
async getOAuthUrl(provider, redirectUri) {
|
|
175
|
+
const params = new URLSearchParams({ redirectUri, flow: "redirect" });
|
|
176
|
+
return await this.request(
|
|
177
|
+
"GET",
|
|
178
|
+
`/v1/auth/oauth/${provider}/url?${params.toString()}`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
async pollOAuth(state) {
|
|
182
|
+
try {
|
|
183
|
+
const res = await fetch(
|
|
184
|
+
`${this.apiUrl}/v1/auth/oauth/poll?state=${encodeURIComponent(state)}`,
|
|
185
|
+
{ headers: { "x-api-key": this.publishableKey } }
|
|
186
|
+
);
|
|
187
|
+
if (!res.ok) return null;
|
|
188
|
+
const data = await res.json();
|
|
189
|
+
if (data.status === "completed" && data.accessToken) {
|
|
190
|
+
return data;
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
} catch {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** Poll for OAuth completion (3 minute timeout, matching JS SDK) */
|
|
198
|
+
async completeOAuth(state) {
|
|
199
|
+
const maxAttempts = 360;
|
|
200
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
201
|
+
const result = await this.pollOAuth(state);
|
|
202
|
+
if (result) {
|
|
203
|
+
this.tokens = this.toTokenPair(result);
|
|
204
|
+
this.user = result.user;
|
|
205
|
+
await this.persistTokens();
|
|
206
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
207
|
+
this.emit("signedIn", result.user);
|
|
208
|
+
return { tokens: this.tokens, user: result.user };
|
|
209
|
+
}
|
|
210
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
211
|
+
}
|
|
212
|
+
throw new Error("OAuth timeout");
|
|
213
|
+
}
|
|
214
|
+
getApiUrl() {
|
|
215
|
+
return this.apiUrl;
|
|
216
|
+
}
|
|
217
|
+
// ── Event system ──
|
|
218
|
+
on(event, listener) {
|
|
219
|
+
if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
220
|
+
const set = this.listeners.get(event);
|
|
221
|
+
set.add(listener);
|
|
222
|
+
return () => set.delete(listener);
|
|
223
|
+
}
|
|
224
|
+
emit(event, ...args) {
|
|
225
|
+
this.listeners.get(event)?.forEach((fn) => fn(...args));
|
|
226
|
+
}
|
|
227
|
+
// ── Cleanup ──
|
|
228
|
+
destroy() {
|
|
229
|
+
this.clearRefreshTimer();
|
|
230
|
+
this.listeners.clear();
|
|
231
|
+
}
|
|
232
|
+
// ── Private ──
|
|
233
|
+
clearSession() {
|
|
234
|
+
this.tokens = null;
|
|
235
|
+
this.user = null;
|
|
236
|
+
this.clearRefreshTimer();
|
|
237
|
+
if (this.storage) {
|
|
238
|
+
this.storage.removeItem(STORAGE_KEY).catch(() => {
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
clearRefreshTimer() {
|
|
243
|
+
if (this.refreshTimer) {
|
|
244
|
+
clearTimeout(this.refreshTimer);
|
|
245
|
+
this.refreshTimer = null;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/** Schedule auto-refresh 60 seconds before token expiry (like JS SDK) */
|
|
249
|
+
scheduleRefresh(expiresAt) {
|
|
250
|
+
this.clearRefreshTimer();
|
|
251
|
+
const refreshIn = Math.max(expiresAt - Date.now() - 6e4, 3e4);
|
|
252
|
+
this.refreshTimer = setTimeout(() => {
|
|
253
|
+
this.refreshToken().catch(() => {
|
|
254
|
+
});
|
|
255
|
+
}, refreshIn);
|
|
256
|
+
}
|
|
128
257
|
async persistTokens() {
|
|
129
258
|
if (this.storage && this.tokens) {
|
|
130
259
|
await this.storage.setItem(STORAGE_KEY, JSON.stringify(this.tokens));
|
|
@@ -152,7 +281,8 @@ var AuthonMobileClient = class {
|
|
|
152
281
|
});
|
|
153
282
|
if (!res.ok) {
|
|
154
283
|
const error = await res.json().catch(() => ({ message: res.statusText }));
|
|
155
|
-
|
|
284
|
+
const msg = Array.isArray(error.message) ? error.message[0] : error.message || `Request failed with status ${res.status}`;
|
|
285
|
+
throw new Error(msg);
|
|
156
286
|
}
|
|
157
287
|
const text = await res.text();
|
|
158
288
|
return text ? JSON.parse(text) : void 0;
|
|
@@ -172,6 +302,8 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
172
302
|
accessToken: null
|
|
173
303
|
});
|
|
174
304
|
const [user, setUser] = (0, import_react.useState)(null);
|
|
305
|
+
const [providers, setProviders] = (0, import_react.useState)([]);
|
|
306
|
+
const [branding, setBranding] = (0, import_react.useState)(null);
|
|
175
307
|
if (!clientRef.current) {
|
|
176
308
|
clientRef.current = new AuthonMobileClient(config);
|
|
177
309
|
}
|
|
@@ -180,7 +312,13 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
180
312
|
if (storage) {
|
|
181
313
|
client.setStorage(storage);
|
|
182
314
|
}
|
|
183
|
-
|
|
315
|
+
const init = async () => {
|
|
316
|
+
const tokens = await client.initialize();
|
|
317
|
+
await client.ensureInitialized();
|
|
318
|
+
const p = await client.getProviders();
|
|
319
|
+
const b = await client.getBranding();
|
|
320
|
+
setProviders(p);
|
|
321
|
+
setBranding(b);
|
|
184
322
|
if (tokens) {
|
|
185
323
|
const u = await client.getUser();
|
|
186
324
|
setUser(u);
|
|
@@ -194,11 +332,33 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
194
332
|
} else {
|
|
195
333
|
setAuthState((prev) => ({ ...prev, isLoaded: true }));
|
|
196
334
|
}
|
|
197
|
-
}
|
|
335
|
+
};
|
|
336
|
+
init();
|
|
337
|
+
const unsubs = [
|
|
338
|
+
client.on("signedOut", () => {
|
|
339
|
+
setUser(null);
|
|
340
|
+
setAuthState({
|
|
341
|
+
isLoaded: true,
|
|
342
|
+
isSignedIn: false,
|
|
343
|
+
userId: null,
|
|
344
|
+
sessionId: null,
|
|
345
|
+
accessToken: null
|
|
346
|
+
});
|
|
347
|
+
}),
|
|
348
|
+
client.on("tokenRefreshed", () => {
|
|
349
|
+
const token = client.getAccessToken();
|
|
350
|
+
if (token) {
|
|
351
|
+
setAuthState((prev) => ({ ...prev, accessToken: token }));
|
|
352
|
+
}
|
|
353
|
+
})
|
|
354
|
+
];
|
|
355
|
+
return () => {
|
|
356
|
+
unsubs.forEach((fn) => fn());
|
|
357
|
+
client.destroy();
|
|
358
|
+
};
|
|
198
359
|
}, []);
|
|
199
360
|
const signIn = (0, import_react.useCallback)(async (params) => {
|
|
200
|
-
const tokens = await client.signIn(params);
|
|
201
|
-
const u = await client.getUser();
|
|
361
|
+
const { tokens, user: u } = await client.signIn(params);
|
|
202
362
|
setUser(u);
|
|
203
363
|
setAuthState({
|
|
204
364
|
isLoaded: true,
|
|
@@ -209,8 +369,7 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
209
369
|
});
|
|
210
370
|
}, [client]);
|
|
211
371
|
const signUp = (0, import_react.useCallback)(async (params) => {
|
|
212
|
-
const tokens = await client.signUp(params);
|
|
213
|
-
const u = await client.getUser();
|
|
372
|
+
const { tokens, user: u } = await client.signUp(params);
|
|
214
373
|
setUser(u);
|
|
215
374
|
setAuthState({
|
|
216
375
|
isLoaded: true,
|
|
@@ -222,18 +381,37 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
222
381
|
}, [client]);
|
|
223
382
|
const signOut = (0, import_react.useCallback)(async () => {
|
|
224
383
|
await client.signOut();
|
|
225
|
-
setUser(null);
|
|
226
|
-
setAuthState({
|
|
227
|
-
isLoaded: true,
|
|
228
|
-
isSignedIn: false,
|
|
229
|
-
userId: null,
|
|
230
|
-
sessionId: null,
|
|
231
|
-
accessToken: null
|
|
232
|
-
});
|
|
233
384
|
}, [client]);
|
|
234
385
|
const getToken = (0, import_react.useCallback)(() => {
|
|
235
386
|
return client.getAccessToken();
|
|
236
387
|
}, [client]);
|
|
388
|
+
const startOAuth = (0, import_react.useCallback)(
|
|
389
|
+
async (provider, redirectUri) => {
|
|
390
|
+
const uri = redirectUri || `${client.getApiUrl()}/v1/auth/oauth/redirect`;
|
|
391
|
+
return client.getOAuthUrl(provider, uri);
|
|
392
|
+
},
|
|
393
|
+
[client]
|
|
394
|
+
);
|
|
395
|
+
const completeOAuthCb = (0, import_react.useCallback)(
|
|
396
|
+
async (state) => {
|
|
397
|
+
const { tokens, user: u } = await client.completeOAuth(state);
|
|
398
|
+
setUser(u);
|
|
399
|
+
setAuthState({
|
|
400
|
+
isLoaded: true,
|
|
401
|
+
isSignedIn: true,
|
|
402
|
+
userId: u?.id || null,
|
|
403
|
+
sessionId: null,
|
|
404
|
+
accessToken: tokens.accessToken
|
|
405
|
+
});
|
|
406
|
+
},
|
|
407
|
+
[client]
|
|
408
|
+
);
|
|
409
|
+
const on = (0, import_react.useCallback)(
|
|
410
|
+
(event, listener) => {
|
|
411
|
+
return client.on(event, listener);
|
|
412
|
+
},
|
|
413
|
+
[client]
|
|
414
|
+
);
|
|
237
415
|
const value = (0, import_react.useMemo)(
|
|
238
416
|
() => ({
|
|
239
417
|
...authState,
|
|
@@ -241,9 +419,15 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
241
419
|
signIn,
|
|
242
420
|
signUp,
|
|
243
421
|
signOut,
|
|
244
|
-
getToken
|
|
422
|
+
getToken,
|
|
423
|
+
providers,
|
|
424
|
+
branding,
|
|
425
|
+
startOAuth,
|
|
426
|
+
completeOAuth: completeOAuthCb,
|
|
427
|
+
on,
|
|
428
|
+
client
|
|
245
429
|
}),
|
|
246
|
-
[authState, user, signIn, signUp, signOut, getToken]
|
|
430
|
+
[authState, user, signIn, signUp, signOut, getToken, providers, branding, startOAuth, completeOAuthCb, on, client]
|
|
247
431
|
);
|
|
248
432
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthonContext.Provider, { value, children });
|
|
249
433
|
}
|
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"],"sourcesContent":["export { AuthonProvider, AuthonContext } from './AuthonProvider';\nexport type { AuthonContextValue } from './AuthonProvider';\nexport { useAuthon } from './useAuthon';\nexport { useUser } from './useUser';\nexport { AuthonMobileClient } from './client';\nexport type {\n AuthonReactNativeConfig,\n AuthState,\n AuthonUser,\n SignInParams,\n SignUpParams,\n} from './types';\n","import React, { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AuthonMobileClient } from './client';\nimport type { AuthState, AuthonReactNativeConfig, AuthonUser, SignInParams, SignUpParams } 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}\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\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 client.initialize().then(async (tokens) => {\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\n const signIn = useCallback(async (params: SignInParams) => {\n const tokens = await client.signIn(params);\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 }, [client]);\n\n const signUp = useCallback(async (params: SignUpParams) => {\n const tokens = await client.signUp(params);\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 }, [client]);\n\n const signOut = useCallback(async () => {\n await client.signOut();\n setUser(null);\n setAuthState({\n isLoaded: true,\n isSignedIn: false,\n userId: null,\n sessionId: null,\n accessToken: null,\n });\n }, [client]);\n\n const getToken = useCallback(() => {\n return client.getAccessToken();\n }, [client]);\n\n const value = useMemo<AuthonContextValue>(\n () => ({\n ...authState,\n user,\n signIn,\n signUp,\n signOut,\n getToken,\n }),\n [authState, user, signIn, signUp, signOut, getToken],\n );\n\n return <AuthonContext.Provider value={value}>{children}</AuthonContext.Provider>;\n}\n","import type { AuthonReactNativeConfig, AuthonUser, SignInParams, SignUpParams } from './types';\n\nconst DEFAULT_API_URL = 'https://api.authon.dev';\n\ninterface TokenPair {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n}\n\ninterface ApiAuthResponse {\n accessToken: string;\n refreshToken: string;\n expiresIn: number;\n user: AuthonUser;\n}\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\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 storage: TokenStorage | null = null;\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 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 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 async signIn(params: SignInParams): Promise<TokenPair> {\n const res = (await this.request('POST', '/v1/auth/signin', params)) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n await this.persistTokens();\n return this.tokens;\n }\n\n async signUp(params: SignUpParams): Promise<TokenPair> {\n const res = (await this.request('POST', '/v1/auth/signup', params)) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n await this.persistTokens();\n return this.tokens;\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.tokens = null;\n if (this.storage) {\n await this.storage.removeItem(STORAGE_KEY);\n }\n }\n\n async getUser(): Promise<AuthonUser | null> {\n if (!this.tokens) return null;\n try {\n return (await this.request('GET', '/v1/auth/me')) as AuthonUser;\n } catch {\n return null;\n }\n }\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.tokens = null;\n if (this.storage) await this.storage.removeItem(STORAGE_KEY);\n return null;\n }\n\n const data = (await res.json()) as ApiAuthResponse;\n this.tokens = this.toTokenPair(data);\n await this.persistTokens();\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 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 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 throw new Error(error.message || `Request failed with status ${res.status}`);\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"],"mappings":"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","names":["import_react"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/AuthonProvider.tsx","../src/client.ts","../src/useAuthon.ts","../src/useUser.ts"],"sourcesContent":["export { AuthonProvider, AuthonContext } from './AuthonProvider';\nexport type { AuthonContextValue } from './AuthonProvider';\nexport { useAuthon } from './useAuthon';\nexport { useUser } from './useUser';\nexport { AuthonMobileClient } from './client';\nexport type {\n AuthonReactNativeConfig,\n AuthState,\n AuthonUser,\n SignInParams,\n SignUpParams,\n AuthonEventType,\n AuthonEvents,\n BrandingConfig,\n OAuthProviderType,\n TokenPair,\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 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: (provider: OAuthProviderType, redirectUri?: string) => 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, redirectUri?: string) => {\n const uri = redirectUri || `${client.getApiUrl()}/v1/auth/oauth/redirect`;\n return client.getOAuthUrl(provider, uri);\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 { BrandingConfig, OAuthProviderType } from '@authon/shared';\nimport type {\n AuthonReactNativeConfig,\n AuthonUser,\n SignInParams,\n SignUpParams,\n TokenPair,\n ApiAuthResponse,\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\ntype OAuthFlowMode = 'popup' | 'redirect' | 'auto';\n\ninterface ProvidersResponse {\n providers: OAuthProviderType[];\n providerConfigs?: Partial<Record<OAuthProviderType, { oauthFlow?: OAuthFlowMode }>>;\n}\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 redirectUri: string,\n ): Promise<{ url: string; state: string }> {\n const params = new URLSearchParams({ redirectUri, flow: 'redirect' });\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<ApiAuthResponse | 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 ApiAuthResponse;\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 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 // ── 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 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"],"mappings":"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","names":["import_react"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { AuthonUser as AuthonUser$1, OAuthProviderType, BrandingConfig } from '@authon/shared';
|
|
4
|
+
export { BrandingConfig, OAuthProviderType } from '@authon/shared';
|
|
3
5
|
|
|
6
|
+
type AuthonUser = AuthonUser$1;
|
|
4
7
|
interface AuthonReactNativeConfig {
|
|
5
8
|
publishableKey: string;
|
|
6
9
|
apiUrl?: string;
|
|
@@ -12,22 +15,6 @@ interface AuthState {
|
|
|
12
15
|
sessionId: string | null;
|
|
13
16
|
accessToken: string | null;
|
|
14
17
|
}
|
|
15
|
-
interface AuthonUser {
|
|
16
|
-
id: string;
|
|
17
|
-
projectId: string;
|
|
18
|
-
email: string | null;
|
|
19
|
-
displayName: string | null;
|
|
20
|
-
avatarUrl: string | null;
|
|
21
|
-
phone: string | null;
|
|
22
|
-
emailVerified: boolean;
|
|
23
|
-
phoneVerified: boolean;
|
|
24
|
-
isBanned: boolean;
|
|
25
|
-
publicMetadata: Record<string, unknown> | null;
|
|
26
|
-
lastSignInAt: string | null;
|
|
27
|
-
signInCount: number;
|
|
28
|
-
createdAt: string;
|
|
29
|
-
updatedAt: string;
|
|
30
|
-
}
|
|
31
18
|
interface SignInParams {
|
|
32
19
|
strategy: 'email_password' | 'oauth';
|
|
33
20
|
email?: string;
|
|
@@ -39,38 +26,25 @@ interface SignUpParams {
|
|
|
39
26
|
password: string;
|
|
40
27
|
displayName?: string;
|
|
41
28
|
}
|
|
42
|
-
|
|
43
|
-
interface
|
|
44
|
-
user: AuthonUser
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
getToken: () => string | null;
|
|
29
|
+
type AuthonEventType = 'signedIn' | 'signedOut' | 'error' | 'tokenRefreshed';
|
|
30
|
+
interface AuthonEvents {
|
|
31
|
+
signedIn: (user: AuthonUser) => void;
|
|
32
|
+
signedOut: () => void;
|
|
33
|
+
error: (error: Error) => void;
|
|
34
|
+
tokenRefreshed: () => void;
|
|
49
35
|
}
|
|
50
|
-
declare const AuthonContext: React.Context<AuthonContextValue | null>;
|
|
51
|
-
interface AuthonProviderProps extends AuthonReactNativeConfig {
|
|
52
|
-
children: React.ReactNode;
|
|
53
|
-
storage?: {
|
|
54
|
-
getItem(key: string): Promise<string | null>;
|
|
55
|
-
setItem(key: string, value: string): Promise<void>;
|
|
56
|
-
removeItem(key: string): Promise<void>;
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
declare function AuthonProvider({ children, storage, ...config }: AuthonProviderProps): react_jsx_runtime.JSX.Element;
|
|
60
|
-
|
|
61
|
-
declare function useAuthon(): AuthonContextValue;
|
|
62
|
-
|
|
63
|
-
declare function useUser(): {
|
|
64
|
-
isLoaded: boolean;
|
|
65
|
-
isSignedIn: boolean;
|
|
66
|
-
user: AuthonUser | null;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
36
|
interface TokenPair {
|
|
70
37
|
accessToken: string;
|
|
71
38
|
refreshToken: string;
|
|
72
39
|
expiresAt: number;
|
|
73
40
|
}
|
|
41
|
+
interface ApiAuthResponse {
|
|
42
|
+
accessToken: string;
|
|
43
|
+
refreshToken: string;
|
|
44
|
+
expiresIn: number;
|
|
45
|
+
user: AuthonUser;
|
|
46
|
+
}
|
|
47
|
+
|
|
74
48
|
type TokenStorage = {
|
|
75
49
|
getItem(key: string): Promise<string | null>;
|
|
76
50
|
setItem(key: string, value: string): Promise<void>;
|
|
@@ -80,20 +54,96 @@ declare class AuthonMobileClient {
|
|
|
80
54
|
private apiUrl;
|
|
81
55
|
private publishableKey;
|
|
82
56
|
private tokens;
|
|
57
|
+
private user;
|
|
83
58
|
private storage;
|
|
59
|
+
private refreshTimer;
|
|
60
|
+
private listeners;
|
|
61
|
+
private _providers;
|
|
62
|
+
private _branding;
|
|
63
|
+
private _initialized;
|
|
84
64
|
constructor(config: AuthonReactNativeConfig);
|
|
85
65
|
setStorage(storage: TokenStorage): void;
|
|
86
66
|
initialize(): Promise<TokenPair | null>;
|
|
87
|
-
|
|
88
|
-
|
|
67
|
+
/** Fetch providers + branding from API (lazy, cached) */
|
|
68
|
+
ensureInitialized(): Promise<void>;
|
|
69
|
+
signIn(params: SignInParams): Promise<{
|
|
70
|
+
tokens: TokenPair;
|
|
71
|
+
user: AuthonUser;
|
|
72
|
+
}>;
|
|
73
|
+
signUp(params: SignUpParams): Promise<{
|
|
74
|
+
tokens: TokenPair;
|
|
75
|
+
user: AuthonUser;
|
|
76
|
+
}>;
|
|
89
77
|
signOut(): Promise<void>;
|
|
90
78
|
getUser(): Promise<AuthonUser | null>;
|
|
79
|
+
getCachedUser(): AuthonUser | null;
|
|
91
80
|
refreshToken(refreshToken?: string): Promise<TokenPair | null>;
|
|
92
81
|
getAccessToken(): string | null;
|
|
93
82
|
isAuthenticated(): boolean;
|
|
83
|
+
getProviders(): Promise<OAuthProviderType[]>;
|
|
84
|
+
getBranding(): Promise<BrandingConfig | null>;
|
|
85
|
+
getOAuthUrl(provider: string, redirectUri: string): Promise<{
|
|
86
|
+
url: string;
|
|
87
|
+
state: string;
|
|
88
|
+
}>;
|
|
89
|
+
pollOAuth(state: string): Promise<ApiAuthResponse | null>;
|
|
90
|
+
/** Poll for OAuth completion (3 minute timeout, matching JS SDK) */
|
|
91
|
+
completeOAuth(state: string): Promise<{
|
|
92
|
+
tokens: TokenPair;
|
|
93
|
+
user: AuthonUser;
|
|
94
|
+
}>;
|
|
95
|
+
getApiUrl(): string;
|
|
96
|
+
on<K extends AuthonEventType>(event: K, listener: AuthonEvents[K]): () => void;
|
|
97
|
+
private emit;
|
|
98
|
+
destroy(): void;
|
|
99
|
+
private clearSession;
|
|
100
|
+
private clearRefreshTimer;
|
|
101
|
+
/** Schedule auto-refresh 60 seconds before token expiry (like JS SDK) */
|
|
102
|
+
private scheduleRefresh;
|
|
94
103
|
private persistTokens;
|
|
95
104
|
private toTokenPair;
|
|
96
105
|
private request;
|
|
97
106
|
}
|
|
98
107
|
|
|
99
|
-
|
|
108
|
+
interface AuthonContextValue extends AuthState {
|
|
109
|
+
user: AuthonUser | null;
|
|
110
|
+
signIn: (params: SignInParams) => Promise<void>;
|
|
111
|
+
signUp: (params: SignUpParams) => Promise<void>;
|
|
112
|
+
signOut: () => Promise<void>;
|
|
113
|
+
getToken: () => string | null;
|
|
114
|
+
/** Available OAuth providers (fetched from API) */
|
|
115
|
+
providers: OAuthProviderType[];
|
|
116
|
+
/** Branding config (fetched from API) */
|
|
117
|
+
branding: BrandingConfig | null;
|
|
118
|
+
/** Start OAuth flow — returns { url, state }. Open url in browser, then call completeOAuth(state) */
|
|
119
|
+
startOAuth: (provider: OAuthProviderType, redirectUri?: string) => Promise<{
|
|
120
|
+
url: string;
|
|
121
|
+
state: string;
|
|
122
|
+
}>;
|
|
123
|
+
/** Poll for OAuth result after user completes browser flow */
|
|
124
|
+
completeOAuth: (state: string) => Promise<void>;
|
|
125
|
+
/** Subscribe to auth events */
|
|
126
|
+
on: <K extends AuthonEventType>(event: K, listener: AuthonEvents[K]) => () => void;
|
|
127
|
+
/** Get the underlying client instance */
|
|
128
|
+
client: AuthonMobileClient;
|
|
129
|
+
}
|
|
130
|
+
declare const AuthonContext: React.Context<AuthonContextValue | null>;
|
|
131
|
+
interface AuthonProviderProps extends AuthonReactNativeConfig {
|
|
132
|
+
children: React.ReactNode;
|
|
133
|
+
storage?: {
|
|
134
|
+
getItem(key: string): Promise<string | null>;
|
|
135
|
+
setItem(key: string, value: string): Promise<void>;
|
|
136
|
+
removeItem(key: string): Promise<void>;
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
declare function AuthonProvider({ children, storage, ...config }: AuthonProviderProps): react_jsx_runtime.JSX.Element;
|
|
140
|
+
|
|
141
|
+
declare function useAuthon(): AuthonContextValue;
|
|
142
|
+
|
|
143
|
+
declare function useUser(): {
|
|
144
|
+
isLoaded: boolean;
|
|
145
|
+
isSignedIn: boolean;
|
|
146
|
+
user: AuthonUser | null;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export { type AuthState, AuthonContext, type AuthonContextValue, type AuthonEventType, type AuthonEvents, AuthonMobileClient, AuthonProvider, type AuthonReactNativeConfig, type AuthonUser, type SignInParams, type SignUpParams, type TokenPair, useAuthon, useUser };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { AuthonUser as AuthonUser$1, OAuthProviderType, BrandingConfig } from '@authon/shared';
|
|
4
|
+
export { BrandingConfig, OAuthProviderType } from '@authon/shared';
|
|
3
5
|
|
|
6
|
+
type AuthonUser = AuthonUser$1;
|
|
4
7
|
interface AuthonReactNativeConfig {
|
|
5
8
|
publishableKey: string;
|
|
6
9
|
apiUrl?: string;
|
|
@@ -12,22 +15,6 @@ interface AuthState {
|
|
|
12
15
|
sessionId: string | null;
|
|
13
16
|
accessToken: string | null;
|
|
14
17
|
}
|
|
15
|
-
interface AuthonUser {
|
|
16
|
-
id: string;
|
|
17
|
-
projectId: string;
|
|
18
|
-
email: string | null;
|
|
19
|
-
displayName: string | null;
|
|
20
|
-
avatarUrl: string | null;
|
|
21
|
-
phone: string | null;
|
|
22
|
-
emailVerified: boolean;
|
|
23
|
-
phoneVerified: boolean;
|
|
24
|
-
isBanned: boolean;
|
|
25
|
-
publicMetadata: Record<string, unknown> | null;
|
|
26
|
-
lastSignInAt: string | null;
|
|
27
|
-
signInCount: number;
|
|
28
|
-
createdAt: string;
|
|
29
|
-
updatedAt: string;
|
|
30
|
-
}
|
|
31
18
|
interface SignInParams {
|
|
32
19
|
strategy: 'email_password' | 'oauth';
|
|
33
20
|
email?: string;
|
|
@@ -39,38 +26,25 @@ interface SignUpParams {
|
|
|
39
26
|
password: string;
|
|
40
27
|
displayName?: string;
|
|
41
28
|
}
|
|
42
|
-
|
|
43
|
-
interface
|
|
44
|
-
user: AuthonUser
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
getToken: () => string | null;
|
|
29
|
+
type AuthonEventType = 'signedIn' | 'signedOut' | 'error' | 'tokenRefreshed';
|
|
30
|
+
interface AuthonEvents {
|
|
31
|
+
signedIn: (user: AuthonUser) => void;
|
|
32
|
+
signedOut: () => void;
|
|
33
|
+
error: (error: Error) => void;
|
|
34
|
+
tokenRefreshed: () => void;
|
|
49
35
|
}
|
|
50
|
-
declare const AuthonContext: React.Context<AuthonContextValue | null>;
|
|
51
|
-
interface AuthonProviderProps extends AuthonReactNativeConfig {
|
|
52
|
-
children: React.ReactNode;
|
|
53
|
-
storage?: {
|
|
54
|
-
getItem(key: string): Promise<string | null>;
|
|
55
|
-
setItem(key: string, value: string): Promise<void>;
|
|
56
|
-
removeItem(key: string): Promise<void>;
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
declare function AuthonProvider({ children, storage, ...config }: AuthonProviderProps): react_jsx_runtime.JSX.Element;
|
|
60
|
-
|
|
61
|
-
declare function useAuthon(): AuthonContextValue;
|
|
62
|
-
|
|
63
|
-
declare function useUser(): {
|
|
64
|
-
isLoaded: boolean;
|
|
65
|
-
isSignedIn: boolean;
|
|
66
|
-
user: AuthonUser | null;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
36
|
interface TokenPair {
|
|
70
37
|
accessToken: string;
|
|
71
38
|
refreshToken: string;
|
|
72
39
|
expiresAt: number;
|
|
73
40
|
}
|
|
41
|
+
interface ApiAuthResponse {
|
|
42
|
+
accessToken: string;
|
|
43
|
+
refreshToken: string;
|
|
44
|
+
expiresIn: number;
|
|
45
|
+
user: AuthonUser;
|
|
46
|
+
}
|
|
47
|
+
|
|
74
48
|
type TokenStorage = {
|
|
75
49
|
getItem(key: string): Promise<string | null>;
|
|
76
50
|
setItem(key: string, value: string): Promise<void>;
|
|
@@ -80,20 +54,96 @@ declare class AuthonMobileClient {
|
|
|
80
54
|
private apiUrl;
|
|
81
55
|
private publishableKey;
|
|
82
56
|
private tokens;
|
|
57
|
+
private user;
|
|
83
58
|
private storage;
|
|
59
|
+
private refreshTimer;
|
|
60
|
+
private listeners;
|
|
61
|
+
private _providers;
|
|
62
|
+
private _branding;
|
|
63
|
+
private _initialized;
|
|
84
64
|
constructor(config: AuthonReactNativeConfig);
|
|
85
65
|
setStorage(storage: TokenStorage): void;
|
|
86
66
|
initialize(): Promise<TokenPair | null>;
|
|
87
|
-
|
|
88
|
-
|
|
67
|
+
/** Fetch providers + branding from API (lazy, cached) */
|
|
68
|
+
ensureInitialized(): Promise<void>;
|
|
69
|
+
signIn(params: SignInParams): Promise<{
|
|
70
|
+
tokens: TokenPair;
|
|
71
|
+
user: AuthonUser;
|
|
72
|
+
}>;
|
|
73
|
+
signUp(params: SignUpParams): Promise<{
|
|
74
|
+
tokens: TokenPair;
|
|
75
|
+
user: AuthonUser;
|
|
76
|
+
}>;
|
|
89
77
|
signOut(): Promise<void>;
|
|
90
78
|
getUser(): Promise<AuthonUser | null>;
|
|
79
|
+
getCachedUser(): AuthonUser | null;
|
|
91
80
|
refreshToken(refreshToken?: string): Promise<TokenPair | null>;
|
|
92
81
|
getAccessToken(): string | null;
|
|
93
82
|
isAuthenticated(): boolean;
|
|
83
|
+
getProviders(): Promise<OAuthProviderType[]>;
|
|
84
|
+
getBranding(): Promise<BrandingConfig | null>;
|
|
85
|
+
getOAuthUrl(provider: string, redirectUri: string): Promise<{
|
|
86
|
+
url: string;
|
|
87
|
+
state: string;
|
|
88
|
+
}>;
|
|
89
|
+
pollOAuth(state: string): Promise<ApiAuthResponse | null>;
|
|
90
|
+
/** Poll for OAuth completion (3 minute timeout, matching JS SDK) */
|
|
91
|
+
completeOAuth(state: string): Promise<{
|
|
92
|
+
tokens: TokenPair;
|
|
93
|
+
user: AuthonUser;
|
|
94
|
+
}>;
|
|
95
|
+
getApiUrl(): string;
|
|
96
|
+
on<K extends AuthonEventType>(event: K, listener: AuthonEvents[K]): () => void;
|
|
97
|
+
private emit;
|
|
98
|
+
destroy(): void;
|
|
99
|
+
private clearSession;
|
|
100
|
+
private clearRefreshTimer;
|
|
101
|
+
/** Schedule auto-refresh 60 seconds before token expiry (like JS SDK) */
|
|
102
|
+
private scheduleRefresh;
|
|
94
103
|
private persistTokens;
|
|
95
104
|
private toTokenPair;
|
|
96
105
|
private request;
|
|
97
106
|
}
|
|
98
107
|
|
|
99
|
-
|
|
108
|
+
interface AuthonContextValue extends AuthState {
|
|
109
|
+
user: AuthonUser | null;
|
|
110
|
+
signIn: (params: SignInParams) => Promise<void>;
|
|
111
|
+
signUp: (params: SignUpParams) => Promise<void>;
|
|
112
|
+
signOut: () => Promise<void>;
|
|
113
|
+
getToken: () => string | null;
|
|
114
|
+
/** Available OAuth providers (fetched from API) */
|
|
115
|
+
providers: OAuthProviderType[];
|
|
116
|
+
/** Branding config (fetched from API) */
|
|
117
|
+
branding: BrandingConfig | null;
|
|
118
|
+
/** Start OAuth flow — returns { url, state }. Open url in browser, then call completeOAuth(state) */
|
|
119
|
+
startOAuth: (provider: OAuthProviderType, redirectUri?: string) => Promise<{
|
|
120
|
+
url: string;
|
|
121
|
+
state: string;
|
|
122
|
+
}>;
|
|
123
|
+
/** Poll for OAuth result after user completes browser flow */
|
|
124
|
+
completeOAuth: (state: string) => Promise<void>;
|
|
125
|
+
/** Subscribe to auth events */
|
|
126
|
+
on: <K extends AuthonEventType>(event: K, listener: AuthonEvents[K]) => () => void;
|
|
127
|
+
/** Get the underlying client instance */
|
|
128
|
+
client: AuthonMobileClient;
|
|
129
|
+
}
|
|
130
|
+
declare const AuthonContext: React.Context<AuthonContextValue | null>;
|
|
131
|
+
interface AuthonProviderProps extends AuthonReactNativeConfig {
|
|
132
|
+
children: React.ReactNode;
|
|
133
|
+
storage?: {
|
|
134
|
+
getItem(key: string): Promise<string | null>;
|
|
135
|
+
setItem(key: string, value: string): Promise<void>;
|
|
136
|
+
removeItem(key: string): Promise<void>;
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
declare function AuthonProvider({ children, storage, ...config }: AuthonProviderProps): react_jsx_runtime.JSX.Element;
|
|
140
|
+
|
|
141
|
+
declare function useAuthon(): AuthonContextValue;
|
|
142
|
+
|
|
143
|
+
declare function useUser(): {
|
|
144
|
+
isLoaded: boolean;
|
|
145
|
+
isSignedIn: boolean;
|
|
146
|
+
user: AuthonUser | null;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export { type AuthState, AuthonContext, type AuthonContextValue, type AuthonEventType, type AuthonEvents, AuthonMobileClient, AuthonProvider, type AuthonReactNativeConfig, type AuthonUser, type SignInParams, type SignUpParams, type TokenPair, useAuthon, useUser };
|
package/dist/index.js
CHANGED
|
@@ -3,12 +3,19 @@ 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
|
-
var STORAGE_KEY = "
|
|
6
|
+
var STORAGE_KEY = "authon-tokens";
|
|
7
7
|
var AuthonMobileClient = class {
|
|
8
8
|
apiUrl;
|
|
9
9
|
publishableKey;
|
|
10
10
|
tokens = null;
|
|
11
|
+
user = null;
|
|
11
12
|
storage = null;
|
|
13
|
+
refreshTimer = null;
|
|
14
|
+
listeners = /* @__PURE__ */ new Map();
|
|
15
|
+
// Cached provider/branding data
|
|
16
|
+
_providers = [];
|
|
17
|
+
_branding = null;
|
|
18
|
+
_initialized = false;
|
|
12
19
|
constructor(config) {
|
|
13
20
|
this.publishableKey = config.publishableKey;
|
|
14
21
|
this.apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\/$/, "");
|
|
@@ -16,6 +23,7 @@ var AuthonMobileClient = class {
|
|
|
16
23
|
setStorage(storage) {
|
|
17
24
|
this.storage = storage;
|
|
18
25
|
}
|
|
26
|
+
// ── Initialization ──
|
|
19
27
|
async initialize() {
|
|
20
28
|
if (!this.storage) return null;
|
|
21
29
|
const stored = await this.storage.getItem(STORAGE_KEY);
|
|
@@ -24,6 +32,7 @@ var AuthonMobileClient = class {
|
|
|
24
32
|
const tokens = JSON.parse(stored);
|
|
25
33
|
if (tokens.expiresAt > Date.now()) {
|
|
26
34
|
this.tokens = tokens;
|
|
35
|
+
this.scheduleRefresh(tokens.expiresAt);
|
|
27
36
|
return tokens;
|
|
28
37
|
}
|
|
29
38
|
return await this.refreshToken(tokens.refreshToken);
|
|
@@ -32,17 +41,39 @@ var AuthonMobileClient = class {
|
|
|
32
41
|
return null;
|
|
33
42
|
}
|
|
34
43
|
}
|
|
44
|
+
/** Fetch providers + branding from API (lazy, cached) */
|
|
45
|
+
async ensureInitialized() {
|
|
46
|
+
if (this._initialized) return;
|
|
47
|
+
try {
|
|
48
|
+
const [branding, providersRes] = await Promise.all([
|
|
49
|
+
this.request("GET", "/v1/auth/branding"),
|
|
50
|
+
this.request("GET", "/v1/auth/providers")
|
|
51
|
+
]);
|
|
52
|
+
this._branding = branding;
|
|
53
|
+
this._providers = providersRes.providers;
|
|
54
|
+
this._initialized = true;
|
|
55
|
+
} catch (err) {
|
|
56
|
+
this.emit("error", err instanceof Error ? err : new Error(String(err)));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// ── Auth ──
|
|
35
60
|
async signIn(params) {
|
|
36
61
|
const res = await this.request("POST", "/v1/auth/signin", params);
|
|
37
62
|
this.tokens = this.toTokenPair(res);
|
|
63
|
+
this.user = res.user;
|
|
38
64
|
await this.persistTokens();
|
|
39
|
-
|
|
65
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
66
|
+
this.emit("signedIn", res.user);
|
|
67
|
+
return { tokens: this.tokens, user: res.user };
|
|
40
68
|
}
|
|
41
69
|
async signUp(params) {
|
|
42
70
|
const res = await this.request("POST", "/v1/auth/signup", params);
|
|
43
71
|
this.tokens = this.toTokenPair(res);
|
|
72
|
+
this.user = res.user;
|
|
44
73
|
await this.persistTokens();
|
|
45
|
-
|
|
74
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
75
|
+
this.emit("signedIn", res.user);
|
|
76
|
+
return { tokens: this.tokens, user: res.user };
|
|
46
77
|
}
|
|
47
78
|
async signOut() {
|
|
48
79
|
if (this.tokens) {
|
|
@@ -51,19 +82,23 @@ var AuthonMobileClient = class {
|
|
|
51
82
|
} catch {
|
|
52
83
|
}
|
|
53
84
|
}
|
|
54
|
-
this.
|
|
55
|
-
|
|
56
|
-
await this.storage.removeItem(STORAGE_KEY);
|
|
57
|
-
}
|
|
85
|
+
this.clearSession();
|
|
86
|
+
this.emit("signedOut");
|
|
58
87
|
}
|
|
59
88
|
async getUser() {
|
|
60
89
|
if (!this.tokens) return null;
|
|
61
90
|
try {
|
|
62
|
-
|
|
91
|
+
const user = await this.request("GET", "/v1/auth/me");
|
|
92
|
+
this.user = user;
|
|
93
|
+
return user;
|
|
63
94
|
} catch {
|
|
64
95
|
return null;
|
|
65
96
|
}
|
|
66
97
|
}
|
|
98
|
+
getCachedUser() {
|
|
99
|
+
return this.user;
|
|
100
|
+
}
|
|
101
|
+
// ── Token management ──
|
|
67
102
|
async refreshToken(refreshToken) {
|
|
68
103
|
const token = refreshToken || this.tokens?.refreshToken;
|
|
69
104
|
if (!token) return null;
|
|
@@ -77,13 +112,15 @@ var AuthonMobileClient = class {
|
|
|
77
112
|
body: JSON.stringify({ refreshToken: token })
|
|
78
113
|
});
|
|
79
114
|
if (!res.ok) {
|
|
80
|
-
this.
|
|
81
|
-
if (this.storage) await this.storage.removeItem(STORAGE_KEY);
|
|
115
|
+
this.clearSession();
|
|
82
116
|
return null;
|
|
83
117
|
}
|
|
84
118
|
const data = await res.json();
|
|
85
119
|
this.tokens = this.toTokenPair(data);
|
|
120
|
+
this.user = data.user;
|
|
86
121
|
await this.persistTokens();
|
|
122
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
123
|
+
this.emit("tokenRefreshed");
|
|
87
124
|
return this.tokens;
|
|
88
125
|
} catch {
|
|
89
126
|
return null;
|
|
@@ -95,6 +132,98 @@ var AuthonMobileClient = class {
|
|
|
95
132
|
isAuthenticated() {
|
|
96
133
|
return this.tokens !== null && this.tokens.expiresAt > Date.now();
|
|
97
134
|
}
|
|
135
|
+
// ── OAuth ──
|
|
136
|
+
async getProviders() {
|
|
137
|
+
await this.ensureInitialized();
|
|
138
|
+
return this._providers;
|
|
139
|
+
}
|
|
140
|
+
async getBranding() {
|
|
141
|
+
await this.ensureInitialized();
|
|
142
|
+
return this._branding;
|
|
143
|
+
}
|
|
144
|
+
async getOAuthUrl(provider, redirectUri) {
|
|
145
|
+
const params = new URLSearchParams({ redirectUri, flow: "redirect" });
|
|
146
|
+
return await this.request(
|
|
147
|
+
"GET",
|
|
148
|
+
`/v1/auth/oauth/${provider}/url?${params.toString()}`
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
async pollOAuth(state) {
|
|
152
|
+
try {
|
|
153
|
+
const res = await fetch(
|
|
154
|
+
`${this.apiUrl}/v1/auth/oauth/poll?state=${encodeURIComponent(state)}`,
|
|
155
|
+
{ headers: { "x-api-key": this.publishableKey } }
|
|
156
|
+
);
|
|
157
|
+
if (!res.ok) return null;
|
|
158
|
+
const data = await res.json();
|
|
159
|
+
if (data.status === "completed" && data.accessToken) {
|
|
160
|
+
return data;
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
} catch {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/** Poll for OAuth completion (3 minute timeout, matching JS SDK) */
|
|
168
|
+
async completeOAuth(state) {
|
|
169
|
+
const maxAttempts = 360;
|
|
170
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
171
|
+
const result = await this.pollOAuth(state);
|
|
172
|
+
if (result) {
|
|
173
|
+
this.tokens = this.toTokenPair(result);
|
|
174
|
+
this.user = result.user;
|
|
175
|
+
await this.persistTokens();
|
|
176
|
+
this.scheduleRefresh(this.tokens.expiresAt);
|
|
177
|
+
this.emit("signedIn", result.user);
|
|
178
|
+
return { tokens: this.tokens, user: result.user };
|
|
179
|
+
}
|
|
180
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
181
|
+
}
|
|
182
|
+
throw new Error("OAuth timeout");
|
|
183
|
+
}
|
|
184
|
+
getApiUrl() {
|
|
185
|
+
return this.apiUrl;
|
|
186
|
+
}
|
|
187
|
+
// ── Event system ──
|
|
188
|
+
on(event, listener) {
|
|
189
|
+
if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
190
|
+
const set = this.listeners.get(event);
|
|
191
|
+
set.add(listener);
|
|
192
|
+
return () => set.delete(listener);
|
|
193
|
+
}
|
|
194
|
+
emit(event, ...args) {
|
|
195
|
+
this.listeners.get(event)?.forEach((fn) => fn(...args));
|
|
196
|
+
}
|
|
197
|
+
// ── Cleanup ──
|
|
198
|
+
destroy() {
|
|
199
|
+
this.clearRefreshTimer();
|
|
200
|
+
this.listeners.clear();
|
|
201
|
+
}
|
|
202
|
+
// ── Private ──
|
|
203
|
+
clearSession() {
|
|
204
|
+
this.tokens = null;
|
|
205
|
+
this.user = null;
|
|
206
|
+
this.clearRefreshTimer();
|
|
207
|
+
if (this.storage) {
|
|
208
|
+
this.storage.removeItem(STORAGE_KEY).catch(() => {
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
clearRefreshTimer() {
|
|
213
|
+
if (this.refreshTimer) {
|
|
214
|
+
clearTimeout(this.refreshTimer);
|
|
215
|
+
this.refreshTimer = null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/** Schedule auto-refresh 60 seconds before token expiry (like JS SDK) */
|
|
219
|
+
scheduleRefresh(expiresAt) {
|
|
220
|
+
this.clearRefreshTimer();
|
|
221
|
+
const refreshIn = Math.max(expiresAt - Date.now() - 6e4, 3e4);
|
|
222
|
+
this.refreshTimer = setTimeout(() => {
|
|
223
|
+
this.refreshToken().catch(() => {
|
|
224
|
+
});
|
|
225
|
+
}, refreshIn);
|
|
226
|
+
}
|
|
98
227
|
async persistTokens() {
|
|
99
228
|
if (this.storage && this.tokens) {
|
|
100
229
|
await this.storage.setItem(STORAGE_KEY, JSON.stringify(this.tokens));
|
|
@@ -122,7 +251,8 @@ var AuthonMobileClient = class {
|
|
|
122
251
|
});
|
|
123
252
|
if (!res.ok) {
|
|
124
253
|
const error = await res.json().catch(() => ({ message: res.statusText }));
|
|
125
|
-
|
|
254
|
+
const msg = Array.isArray(error.message) ? error.message[0] : error.message || `Request failed with status ${res.status}`;
|
|
255
|
+
throw new Error(msg);
|
|
126
256
|
}
|
|
127
257
|
const text = await res.text();
|
|
128
258
|
return text ? JSON.parse(text) : void 0;
|
|
@@ -142,6 +272,8 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
142
272
|
accessToken: null
|
|
143
273
|
});
|
|
144
274
|
const [user, setUser] = useState(null);
|
|
275
|
+
const [providers, setProviders] = useState([]);
|
|
276
|
+
const [branding, setBranding] = useState(null);
|
|
145
277
|
if (!clientRef.current) {
|
|
146
278
|
clientRef.current = new AuthonMobileClient(config);
|
|
147
279
|
}
|
|
@@ -150,7 +282,13 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
150
282
|
if (storage) {
|
|
151
283
|
client.setStorage(storage);
|
|
152
284
|
}
|
|
153
|
-
|
|
285
|
+
const init = async () => {
|
|
286
|
+
const tokens = await client.initialize();
|
|
287
|
+
await client.ensureInitialized();
|
|
288
|
+
const p = await client.getProviders();
|
|
289
|
+
const b = await client.getBranding();
|
|
290
|
+
setProviders(p);
|
|
291
|
+
setBranding(b);
|
|
154
292
|
if (tokens) {
|
|
155
293
|
const u = await client.getUser();
|
|
156
294
|
setUser(u);
|
|
@@ -164,11 +302,33 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
164
302
|
} else {
|
|
165
303
|
setAuthState((prev) => ({ ...prev, isLoaded: true }));
|
|
166
304
|
}
|
|
167
|
-
}
|
|
305
|
+
};
|
|
306
|
+
init();
|
|
307
|
+
const unsubs = [
|
|
308
|
+
client.on("signedOut", () => {
|
|
309
|
+
setUser(null);
|
|
310
|
+
setAuthState({
|
|
311
|
+
isLoaded: true,
|
|
312
|
+
isSignedIn: false,
|
|
313
|
+
userId: null,
|
|
314
|
+
sessionId: null,
|
|
315
|
+
accessToken: null
|
|
316
|
+
});
|
|
317
|
+
}),
|
|
318
|
+
client.on("tokenRefreshed", () => {
|
|
319
|
+
const token = client.getAccessToken();
|
|
320
|
+
if (token) {
|
|
321
|
+
setAuthState((prev) => ({ ...prev, accessToken: token }));
|
|
322
|
+
}
|
|
323
|
+
})
|
|
324
|
+
];
|
|
325
|
+
return () => {
|
|
326
|
+
unsubs.forEach((fn) => fn());
|
|
327
|
+
client.destroy();
|
|
328
|
+
};
|
|
168
329
|
}, []);
|
|
169
330
|
const signIn = useCallback(async (params) => {
|
|
170
|
-
const tokens = await client.signIn(params);
|
|
171
|
-
const u = await client.getUser();
|
|
331
|
+
const { tokens, user: u } = await client.signIn(params);
|
|
172
332
|
setUser(u);
|
|
173
333
|
setAuthState({
|
|
174
334
|
isLoaded: true,
|
|
@@ -179,8 +339,7 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
179
339
|
});
|
|
180
340
|
}, [client]);
|
|
181
341
|
const signUp = useCallback(async (params) => {
|
|
182
|
-
const tokens = await client.signUp(params);
|
|
183
|
-
const u = await client.getUser();
|
|
342
|
+
const { tokens, user: u } = await client.signUp(params);
|
|
184
343
|
setUser(u);
|
|
185
344
|
setAuthState({
|
|
186
345
|
isLoaded: true,
|
|
@@ -192,18 +351,37 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
192
351
|
}, [client]);
|
|
193
352
|
const signOut = useCallback(async () => {
|
|
194
353
|
await client.signOut();
|
|
195
|
-
setUser(null);
|
|
196
|
-
setAuthState({
|
|
197
|
-
isLoaded: true,
|
|
198
|
-
isSignedIn: false,
|
|
199
|
-
userId: null,
|
|
200
|
-
sessionId: null,
|
|
201
|
-
accessToken: null
|
|
202
|
-
});
|
|
203
354
|
}, [client]);
|
|
204
355
|
const getToken = useCallback(() => {
|
|
205
356
|
return client.getAccessToken();
|
|
206
357
|
}, [client]);
|
|
358
|
+
const startOAuth = useCallback(
|
|
359
|
+
async (provider, redirectUri) => {
|
|
360
|
+
const uri = redirectUri || `${client.getApiUrl()}/v1/auth/oauth/redirect`;
|
|
361
|
+
return client.getOAuthUrl(provider, uri);
|
|
362
|
+
},
|
|
363
|
+
[client]
|
|
364
|
+
);
|
|
365
|
+
const completeOAuthCb = useCallback(
|
|
366
|
+
async (state) => {
|
|
367
|
+
const { tokens, user: u } = await client.completeOAuth(state);
|
|
368
|
+
setUser(u);
|
|
369
|
+
setAuthState({
|
|
370
|
+
isLoaded: true,
|
|
371
|
+
isSignedIn: true,
|
|
372
|
+
userId: u?.id || null,
|
|
373
|
+
sessionId: null,
|
|
374
|
+
accessToken: tokens.accessToken
|
|
375
|
+
});
|
|
376
|
+
},
|
|
377
|
+
[client]
|
|
378
|
+
);
|
|
379
|
+
const on = useCallback(
|
|
380
|
+
(event, listener) => {
|
|
381
|
+
return client.on(event, listener);
|
|
382
|
+
},
|
|
383
|
+
[client]
|
|
384
|
+
);
|
|
207
385
|
const value = useMemo(
|
|
208
386
|
() => ({
|
|
209
387
|
...authState,
|
|
@@ -211,9 +389,15 @@ function AuthonProvider({ children, storage, ...config }) {
|
|
|
211
389
|
signIn,
|
|
212
390
|
signUp,
|
|
213
391
|
signOut,
|
|
214
|
-
getToken
|
|
392
|
+
getToken,
|
|
393
|
+
providers,
|
|
394
|
+
branding,
|
|
395
|
+
startOAuth,
|
|
396
|
+
completeOAuth: completeOAuthCb,
|
|
397
|
+
on,
|
|
398
|
+
client
|
|
215
399
|
}),
|
|
216
|
-
[authState, user, signIn, signUp, signOut, getToken]
|
|
400
|
+
[authState, user, signIn, signUp, signOut, getToken, providers, branding, startOAuth, completeOAuthCb, on, client]
|
|
217
401
|
);
|
|
218
402
|
return /* @__PURE__ */ jsx(AuthonContext.Provider, { value, children });
|
|
219
403
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/AuthonProvider.tsx","../src/client.ts","../src/useAuthon.ts","../src/useUser.ts"],"sourcesContent":["import React, { createContext, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AuthonMobileClient } from './client';\nimport type { AuthState, AuthonReactNativeConfig, AuthonUser, SignInParams, SignUpParams } 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}\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\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 client.initialize().then(async (tokens) => {\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\n const signIn = useCallback(async (params: SignInParams) => {\n const tokens = await client.signIn(params);\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 }, [client]);\n\n const signUp = useCallback(async (params: SignUpParams) => {\n const tokens = await client.signUp(params);\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 }, [client]);\n\n const signOut = useCallback(async () => {\n await client.signOut();\n setUser(null);\n setAuthState({\n isLoaded: true,\n isSignedIn: false,\n userId: null,\n sessionId: null,\n accessToken: null,\n });\n }, [client]);\n\n const getToken = useCallback(() => {\n return client.getAccessToken();\n }, [client]);\n\n const value = useMemo<AuthonContextValue>(\n () => ({\n ...authState,\n user,\n signIn,\n signUp,\n signOut,\n getToken,\n }),\n [authState, user, signIn, signUp, signOut, getToken],\n );\n\n return <AuthonContext.Provider value={value}>{children}</AuthonContext.Provider>;\n}\n","import type { AuthonReactNativeConfig, AuthonUser, SignInParams, SignUpParams } from './types';\n\nconst DEFAULT_API_URL = 'https://api.authon.dev';\n\ninterface TokenPair {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n}\n\ninterface ApiAuthResponse {\n accessToken: string;\n refreshToken: string;\n expiresIn: number;\n user: AuthonUser;\n}\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\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 storage: TokenStorage | null = null;\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 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 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 async signIn(params: SignInParams): Promise<TokenPair> {\n const res = (await this.request('POST', '/v1/auth/signin', params)) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n await this.persistTokens();\n return this.tokens;\n }\n\n async signUp(params: SignUpParams): Promise<TokenPair> {\n const res = (await this.request('POST', '/v1/auth/signup', params)) as ApiAuthResponse;\n this.tokens = this.toTokenPair(res);\n await this.persistTokens();\n return this.tokens;\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.tokens = null;\n if (this.storage) {\n await this.storage.removeItem(STORAGE_KEY);\n }\n }\n\n async getUser(): Promise<AuthonUser | null> {\n if (!this.tokens) return null;\n try {\n return (await this.request('GET', '/v1/auth/me')) as AuthonUser;\n } catch {\n return null;\n }\n }\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.tokens = null;\n if (this.storage) await this.storage.removeItem(STORAGE_KEY);\n return null;\n }\n\n const data = (await res.json()) as ApiAuthResponse;\n this.tokens = this.toTokenPair(data);\n await this.persistTokens();\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 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 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 throw new Error(error.message || `Request failed with status ${res.status}`);\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"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/AuthonProvider.tsx","../src/client.ts","../src/useAuthon.ts","../src/useUser.ts"],"sourcesContent":["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 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: (provider: OAuthProviderType, redirectUri?: string) => 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, redirectUri?: string) => {\n const uri = redirectUri || `${client.getApiUrl()}/v1/auth/oauth/redirect`;\n return client.getOAuthUrl(provider, uri);\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 { BrandingConfig, OAuthProviderType } from '@authon/shared';\nimport type {\n AuthonReactNativeConfig,\n AuthonUser,\n SignInParams,\n SignUpParams,\n TokenPair,\n ApiAuthResponse,\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\ntype OAuthFlowMode = 'popup' | 'redirect' | 'auto';\n\ninterface ProvidersResponse {\n providers: OAuthProviderType[];\n providerConfigs?: Partial<Record<OAuthProviderType, { oauthFlow?: OAuthFlowMode }>>;\n}\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 redirectUri: string,\n ): Promise<{ url: string; state: string }> {\n const params = new URLSearchParams({ redirectUri, flow: 'redirect' });\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<ApiAuthResponse | 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 ApiAuthResponse;\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 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 // ── 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 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"],"mappings":";AAAA,SAAgB,eAAe,aAAa,WAAW,SAAS,QAAQ,gBAAgB;;;ACYxF,IAAM,kBAAkB;AAexB,IAAM,cAAc;AAEb,IAAM,qBAAN,MAAyB;AAAA,EACtB;AAAA,EACA;AAAA,EACA,SAA2B;AAAA,EAC3B,OAA0B;AAAA,EAC1B,UAA+B;AAAA,EAC/B,eAAqD;AAAA,EACrD,YAA4D,oBAAI,IAAI;AAAA;AAAA,EAGpE,aAAkC,CAAC;AAAA,EACnC,YAAmC;AAAA,EACnC,eAAe;AAAA,EAEvB,YAAY,QAAiC;AAC3C,SAAK,iBAAiB,OAAO;AAC7B,SAAK,UAAU,OAAO,UAAU,iBAAiB,QAAQ,OAAO,EAAE;AAAA,EACpE;AAAA,EAEA,WAAW,SAAuB;AAChC,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA,EAIA,MAAM,aAAwC;AAC5C,QAAI,CAAC,KAAK,QAAS,QAAO;AAE1B,UAAM,SAAS,MAAM,KAAK,QAAQ,QAAQ,WAAW;AACrD,QAAI,CAAC,OAAQ,QAAO;AAEpB,QAAI;AACF,YAAM,SAAoB,KAAK,MAAM,MAAM;AAC3C,UAAI,OAAO,YAAY,KAAK,IAAI,GAAG;AACjC,aAAK,SAAS;AACd,aAAK,gBAAgB,OAAO,SAAS;AACrC,eAAO;AAAA,MACT;AAEA,aAAO,MAAM,KAAK,aAAa,OAAO,YAAY;AAAA,IACpD,QAAQ;AACN,YAAM,KAAK,QAAQ,WAAW,WAAW;AACzC,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,oBAAmC;AACvC,QAAI,KAAK,aAAc;AACvB,QAAI;AACF,YAAM,CAAC,UAAU,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,QACjD,KAAK,QAAQ,OAAO,mBAAmB;AAAA,QACvC,KAAK,QAAQ,OAAO,oBAAoB;AAAA,MAC1C,CAAC;AACD,WAAK,YAAY;AACjB,WAAK,aAAa,aAAa;AAC/B,WAAK,eAAe;AAAA,IACtB,SAAS,KAAK;AACZ,WAAK,KAAK,SAAS,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,CAAC;AAAA,IACxE;AAAA,EACF;AAAA;AAAA,EAIA,MAAM,OAAO,QAAwE;AACnF,UAAM,MAAO,MAAM,KAAK,QAAQ,QAAQ,mBAAmB,MAAM;AACjE,SAAK,SAAS,KAAK,YAAY,GAAG;AAClC,SAAK,OAAO,IAAI;AAChB,UAAM,KAAK,cAAc;AACzB,SAAK,gBAAgB,KAAK,OAAO,SAAS;AAC1C,SAAK,KAAK,YAAY,IAAI,IAAI;AAC9B,WAAO,EAAE,QAAQ,KAAK,QAAQ,MAAM,IAAI,KAAK;AAAA,EAC/C;AAAA,EAEA,MAAM,OAAO,QAAwE;AACnF,UAAM,MAAO,MAAM,KAAK,QAAQ,QAAQ,mBAAmB,MAAM;AACjE,SAAK,SAAS,KAAK,YAAY,GAAG;AAClC,SAAK,OAAO,IAAI;AAChB,UAAM,KAAK,cAAc;AACzB,SAAK,gBAAgB,KAAK,OAAO,SAAS;AAC1C,SAAK,KAAK,YAAY,IAAI,IAAI;AAC9B,WAAO,EAAE,QAAQ,KAAK,QAAQ,MAAM,IAAI,KAAK;AAAA,EAC/C;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI,KAAK,QAAQ;AACf,UAAI;AACF,cAAM,KAAK,QAAQ,QAAQ,oBAAoB,MAAS;AAAA,MAC1D,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,aAAa;AAClB,SAAK,KAAK,WAAW;AAAA,EACvB;AAAA,EAEA,MAAM,UAAsC;AAC1C,QAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,QAAI;AACF,YAAM,OAAQ,MAAM,KAAK,QAAQ,OAAO,aAAa;AACrD,WAAK,OAAO;AACZ,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,gBAAmC;AACjC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAIA,MAAM,aAAa,cAAkD;AACnE,UAAM,QAAQ,gBAAgB,KAAK,QAAQ;AAC3C,QAAI,CAAC,MAAO,QAAO;AAEnB,QAAI;AACF,YAAM,MAAM,MAAM,MAAM,GAAG,KAAK,MAAM,0BAA0B;AAAA,QAC9D,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,aAAa,KAAK;AAAA,QACpB;AAAA,QACA,MAAM,KAAK,UAAU,EAAE,cAAc,MAAM,CAAC;AAAA,MAC9C,CAAC;AAED,UAAI,CAAC,IAAI,IAAI;AACX,aAAK,aAAa;AAClB,eAAO;AAAA,MACT;AAEA,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,WAAK,SAAS,KAAK,YAAY,IAAI;AACnC,WAAK,OAAO,KAAK;AACjB,YAAM,KAAK,cAAc;AACzB,WAAK,gBAAgB,KAAK,OAAO,SAAS;AAC1C,WAAK,KAAK,gBAAgB;AAC1B,aAAO,KAAK;AAAA,IACd,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,iBAAgC;AAC9B,WAAO,KAAK,QAAQ,eAAe;AAAA,EACrC;AAAA,EAEA,kBAA2B;AACzB,WAAO,KAAK,WAAW,QAAQ,KAAK,OAAO,YAAY,KAAK,IAAI;AAAA,EAClE;AAAA;AAAA,EAIA,MAAM,eAA6C;AACjD,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,cAA8C;AAClD,UAAM,KAAK,kBAAkB;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,YACJ,UACA,aACyC;AACzC,UAAM,SAAS,IAAI,gBAAgB,EAAE,aAAa,MAAM,WAAW,CAAC;AACpE,WAAQ,MAAM,KAAK;AAAA,MACjB;AAAA,MACA,kBAAkB,QAAQ,QAAQ,OAAO,SAAS,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,OAAgD;AAC9D,QAAI;AACF,YAAM,MAAM,MAAM;AAAA,QAChB,GAAG,KAAK,MAAM,6BAA6B,mBAAmB,KAAK,CAAC;AAAA,QACpE,EAAE,SAAS,EAAE,aAAa,KAAK,eAAe,EAAE;AAAA,MAClD;AACA,UAAI,CAAC,IAAI,GAAI,QAAO;AACpB,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,UAAI,KAAK,WAAW,eAAe,KAAK,aAAa;AACnD,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,cAAc,OAAiE;AACnF,UAAM,cAAc;AACpB,aAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,YAAM,SAAS,MAAM,KAAK,UAAU,KAAK;AACzC,UAAI,QAAQ;AACV,aAAK,SAAS,KAAK,YAAY,MAAM;AACrC,aAAK,OAAO,OAAO;AACnB,cAAM,KAAK,cAAc;AACzB,aAAK,gBAAgB,KAAK,OAAO,SAAS;AAC1C,aAAK,KAAK,YAAY,OAAO,IAAI;AACjC,eAAO,EAAE,QAAQ,KAAK,QAAQ,MAAM,OAAO,KAAK;AAAA,MAClD;AACA,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAAA,IAC7C;AACA,UAAM,IAAI,MAAM,eAAe;AAAA,EACjC;AAAA,EAEA,YAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAIA,GAA8B,OAAU,UAAuC;AAC7E,QAAI,CAAC,KAAK,UAAU,IAAI,KAAK,EAAG,MAAK,UAAU,IAAI,OAAO,oBAAI,IAAI,CAAC;AACnE,UAAM,MAAM,KAAK,UAAU,IAAI,KAAK;AACpC,QAAI,IAAI,QAAwC;AAChD,WAAO,MAAM,IAAI,OAAO,QAAwC;AAAA,EAClE;AAAA,EAEQ,KAAK,UAAkB,MAAuB;AACpD,SAAK,UAAU,IAAI,KAAK,GAAG,QAAQ,CAAC,OAAO,GAAG,GAAG,IAAI,CAAC;AAAA,EACxD;AAAA;AAAA,EAIA,UAAgB;AACd,SAAK,kBAAkB;AACvB,SAAK,UAAU,MAAM;AAAA,EACvB;AAAA;AAAA,EAIQ,eAAqB;AAC3B,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,kBAAkB;AACvB,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,WAAW,WAAW,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEQ,oBAA0B;AAChC,QAAI,KAAK,cAAc;AACrB,mBAAa,KAAK,YAAY;AAC9B,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA;AAAA,EAGQ,gBAAgB,WAAyB;AAC/C,SAAK,kBAAkB;AACvB,UAAM,YAAY,KAAK,IAAI,YAAY,KAAK,IAAI,IAAI,KAAQ,GAAM;AAClE,SAAK,eAAe,WAAW,MAAM;AACnC,WAAK,aAAa,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACpC,GAAG,SAAS;AAAA,EACd;AAAA,EAEA,MAAc,gBAA+B;AAC3C,QAAI,KAAK,WAAW,KAAK,QAAQ;AAC/B,YAAM,KAAK,QAAQ,QAAQ,aAAa,KAAK,UAAU,KAAK,MAAM,CAAC;AAAA,IACrE;AAAA,EACF;AAAA,EAEQ,YAAY,KAAiC;AACnD,WAAO;AAAA,MACL,aAAa,IAAI;AAAA,MACjB,cAAc,IAAI;AAAA,MAClB,WAAW,KAAK,IAAI,IAAI,IAAI,YAAY;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,MAAc,QAAQ,QAAgB,MAAc,MAAkC;AACpF,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,aAAa,KAAK;AAAA,IACpB;AAEA,QAAI,KAAK,QAAQ,aAAa;AAC5B,cAAQ,eAAe,IAAI,UAAU,KAAK,OAAO,WAAW;AAAA,IAC9D;AAEA,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,MAAM,GAAG,IAAI,IAAI;AAAA,MAC/C;AAAA,MACA;AAAA,MACA,MAAM,OAAO,KAAK,UAAU,IAAI,IAAI;AAAA,IACtC,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,QAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE;AACxE,YAAM,MAAM,MAAM,QAAQ,MAAM,OAAO,IACnC,MAAM,QAAQ,CAAC,IACf,MAAM,WAAW,8BAA8B,IAAI,MAAM;AAC7D,YAAM,IAAI,MAAM,GAAG;AAAA,IACrB;AAEA,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,OAAO,KAAK,MAAM,IAAI,IAAI;AAAA,EACnC;AACF;;;ADhIS;AA1KF,IAAM,gBAAgB,cAAyC,IAAI;AAWnE,SAAS,eAAe,EAAE,UAAU,SAAS,GAAG,OAAO,GAAwB;AACpF,QAAM,YAAY,OAAkC,IAAI;AACxD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAoB;AAAA,IACpD,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,aAAa;AAAA,EACf,CAAC;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAA4B,IAAI;AACxD,QAAM,CAAC,WAAW,YAAY,IAAI,SAA8B,CAAC,CAAC;AAClE,QAAM,CAAC,UAAU,WAAW,IAAI,SAAgC,IAAI;AAEpE,MAAI,CAAC,UAAU,SAAS;AACtB,cAAU,UAAU,IAAI,mBAAmB,MAAM;AAAA,EACnD;AAEA,QAAM,SAAS,UAAU;AAEzB,YAAU,MAAM;AACd,QAAI,SAAS;AACX,aAAO,WAAW,OAAO;AAAA,IAC3B;AAEA,UAAM,OAAO,YAAY;AAEvB,YAAM,SAAS,MAAM,OAAO,WAAW;AAGvC,YAAM,OAAO,kBAAkB;AAC/B,YAAM,IAAI,MAAM,OAAO,aAAa;AACpC,YAAM,IAAI,MAAM,OAAO,YAAY;AACnC,mBAAa,CAAC;AACd,kBAAY,CAAC;AAEb,UAAI,QAAQ;AACV,cAAM,IAAI,MAAM,OAAO,QAAQ;AAC/B,gBAAQ,CAAC;AACT,qBAAa;AAAA,UACX,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,QAAQ,GAAG,MAAM;AAAA,UACjB,WAAW;AAAA,UACX,aAAa,OAAO;AAAA,QACtB,CAAC;AAAA,MACH,OAAO;AACL,qBAAa,CAAC,UAAU,EAAE,GAAG,MAAM,UAAU,KAAK,EAAE;AAAA,MACtD;AAAA,IACF;AAEA,SAAK;AAGL,UAAM,SAAS;AAAA,MACb,OAAO,GAAG,aAAa,MAAM;AAC3B,gBAAQ,IAAI;AACZ,qBAAa;AAAA,UACX,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,aAAa;AAAA,QACf,CAAC;AAAA,MACH,CAAC;AAAA,MACD,OAAO,GAAG,kBAAkB,MAAM;AAChC,cAAM,QAAQ,OAAO,eAAe;AACpC,YAAI,OAAO;AACT,uBAAa,CAAC,UAAU,EAAE,GAAG,MAAM,aAAa,MAAM,EAAE;AAAA,QAC1D;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO,MAAM;AACX,aAAO,QAAQ,CAAC,OAAO,GAAG,CAAC;AAC3B,aAAO,QAAQ;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,SAAS,YAAY,OAAO,WAAyB;AACzD,UAAM,EAAE,QAAQ,MAAM,EAAE,IAAI,MAAM,OAAO,OAAO,MAAM;AACtD,YAAQ,CAAC;AACT,iBAAa;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,QAAQ,GAAG,MAAM;AAAA,MACjB,WAAW;AAAA,MACX,aAAa,OAAO;AAAA,IACtB,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,SAAS,YAAY,OAAO,WAAyB;AACzD,UAAM,EAAE,QAAQ,MAAM,EAAE,IAAI,MAAM,OAAO,OAAO,MAAM;AACtD,YAAQ,CAAC;AACT,iBAAa;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,QAAQ,GAAG,MAAM;AAAA,MACjB,WAAW;AAAA,MACX,aAAa,OAAO;AAAA,IACtB,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,UAAU,YAAY,YAAY;AACtC,UAAM,OAAO,QAAQ;AAAA,EAEvB,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,WAAW,YAAY,MAAM;AACjC,WAAO,OAAO,eAAe;AAAA,EAC/B,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,aAAa;AAAA,IACjB,OAAO,UAA6B,gBAAyB;AAC3D,YAAM,MAAM,eAAe,GAAG,OAAO,UAAU,CAAC;AAChD,aAAO,OAAO,YAAY,UAAU,GAAG;AAAA,IACzC;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,kBAAkB;AAAA,IACtB,OAAO,UAAkB;AACvB,YAAM,EAAE,QAAQ,MAAM,EAAE,IAAI,MAAM,OAAO,cAAc,KAAK;AAC5D,cAAQ,CAAC;AACT,mBAAa;AAAA,QACX,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,QAAQ,GAAG,MAAM;AAAA,QACjB,WAAW;AAAA,QACX,aAAa,OAAO;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,KAAK;AAAA,IACT,CAA4B,OAAU,aAA8B;AAClE,aAAO,OAAO,GAAG,OAAO,QAAQ;AAAA,IAClC;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe;AAAA,MACf;AAAA,MACA;AAAA,IACF;AAAA,IACA,CAAC,WAAW,MAAM,QAAQ,QAAQ,SAAS,UAAU,WAAW,UAAU,YAAY,iBAAiB,IAAI,MAAM;AAAA,EACnH;AAEA,SAAO,oBAAC,cAAc,UAAd,EAAuB,OAAe,UAAS;AACzD;;;AE5MA,SAAS,kBAAkB;AAGpB,SAAS,YAAgC;AAC9C,QAAM,UAAU,WAAW,aAAa;AACxC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AACA,SAAO;AACT;;;ACNO,SAAS,UAId;AACA,QAAM,EAAE,UAAU,YAAY,KAAK,IAAI,UAAU;AACjD,SAAO,EAAE,UAAU,YAAY,KAAK;AACtC;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@authon/react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Authon React Native SDK — mobile authentication",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"auth"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@authon/shared": "^0.
|
|
39
|
+
"@authon/shared": "^0.2.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"react": "^18.0.0 || ^19.0.0",
|