@oxyhq/auth 1.0.0 → 1.1.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.
@@ -45,30 +45,21 @@ function WebOxyProvider({ children, baseURL, authWebUrl, onAuthStateChange, onEr
45
45
  const [isLoading, setIsLoading] = (0, react_1.useState)(!skipAutoCheck);
46
46
  const [error, setError] = (0, react_1.useState)(null);
47
47
  const [activeSessionId, setActiveSessionId] = (0, react_1.useState)(null);
48
- const [sessions, setSessions] = (0, react_1.useState)([]);
48
+ // Sessions array kept as constant empty for API compatibility.
49
+ // Multi-session management is handled by @oxyhq/services (OxyContext) for RN apps.
50
+ const sessions = [];
49
51
  const isAuthenticated = !!user;
50
52
  const handleAuthSuccess = (0, react_1.useCallback)(async (session, method = 'credentials') => {
51
53
  await authManager.handleAuthSuccess(session, method);
52
- // Set active session
53
54
  if (session.sessionId) {
54
55
  setActiveSessionId(session.sessionId);
55
56
  }
56
- // Fetch full user profile
57
- try {
58
- const fullUser = await oxyServices.getCurrentUser();
59
- if (fullUser) {
60
- setUser(fullUser);
61
- }
62
- else {
63
- setUser(session.user);
64
- }
65
- }
66
- catch {
67
- setUser(session.user);
68
- }
57
+ // Use the session user directly to avoid an extra API round-trip.
58
+ // The session already contains user data from the auth exchange.
59
+ setUser(session.user);
69
60
  setError(null);
70
61
  setIsLoading(false);
71
- }, [authManager, oxyServices]);
62
+ }, [authManager]);
72
63
  const handleAuthError = (0, react_1.useCallback)((err) => {
73
64
  const errorMessage = err instanceof Error ? err.message : 'Authentication failed';
74
65
  setError(errorMessage);
@@ -119,8 +110,18 @@ function WebOxyProvider({ children, baseURL, authWebUrl, onAuthStateChange, onEr
119
110
  setIsLoading(false);
120
111
  }
121
112
  };
122
- initAuth();
123
- return () => { mounted = false; };
113
+ // Safety timeout: if all auth methods stall, stop loading
114
+ const INIT_TIMEOUT_MS = 15000;
115
+ const timeoutId = setTimeout(() => {
116
+ if (mounted) {
117
+ setIsLoading(false);
118
+ }
119
+ }, INIT_TIMEOUT_MS);
120
+ initAuth().finally(() => clearTimeout(timeoutId));
121
+ return () => {
122
+ mounted = false;
123
+ clearTimeout(timeoutId);
124
+ };
124
125
  }, [oxyServices, crossDomainAuth, authManager, skipAutoCheck, handleAuthSuccess]);
125
126
  (0, react_1.useEffect)(() => {
126
127
  onAuthStateChange?.(user);
@@ -184,7 +185,6 @@ function WebOxyProvider({ children, baseURL, authWebUrl, onAuthStateChange, onEr
184
185
  await authManager.signOut();
185
186
  setUser(null);
186
187
  setActiveSessionId(null);
187
- setSessions([]);
188
188
  }
189
189
  catch (err) {
190
190
  const errorMessage = err instanceof Error ? err.message : 'Sign out failed';
@@ -210,7 +210,6 @@ function WebOxyProvider({ children, baseURL, authWebUrl, onAuthStateChange, onEr
210
210
  await authManager.signOut();
211
211
  setUser(null);
212
212
  setActiveSessionId(null);
213
- setSessions([]);
214
213
  }, [authManager]);
215
214
  (0, react_1.useEffect)(() => {
216
215
  return () => { authManager.destroy(); };
@@ -57,7 +57,7 @@ function useWebSSO({ oxyServices, onSessionFound, onSSOUnavailable, onError, ena
57
57
  const isCheckingRef = (0, react_1.useRef)(false);
58
58
  const hasCheckedRef = (0, react_1.useRef)(false);
59
59
  // Check FedCM support once
60
- const fedCMSupported = isWebBrowser() && oxyServices.isFedCMSupported?.();
60
+ const fedCMSupported = isWebBrowser() && oxyServices.isFedCMSupported();
61
61
  const checkSSO = (0, react_1.useCallback)(async () => {
62
62
  if (!isWebBrowser() || isCheckingRef.current) {
63
63
  return null;
@@ -74,7 +74,7 @@ function useWebSSO({ oxyServices, onSessionFound, onSSOUnavailable, onError, ena
74
74
  }
75
75
  isCheckingRef.current = true;
76
76
  try {
77
- const session = await oxyServices.silentSignInWithFedCM?.();
77
+ const session = await oxyServices.silentSignInWithFedCM();
78
78
  if (session) {
79
79
  await onSessionFound(session);
80
80
  return session;
@@ -106,7 +106,7 @@ function useWebSSO({ oxyServices, onSessionFound, onSSOUnavailable, onError, ena
106
106
  }
107
107
  isCheckingRef.current = true;
108
108
  try {
109
- const session = await oxyServices.signInWithFedCM?.();
109
+ const session = await oxyServices.signInWithFedCM();
110
110
  if (session) {
111
111
  await onSessionFound(session);
112
112
  return session;
@@ -106,7 +106,9 @@ const createNativeStorage = async () => {
106
106
  return asyncStorageInstance;
107
107
  }
108
108
  try {
109
- const asyncStorageModule = await Promise.resolve().then(() => __importStar(require('@react-native-async-storage/async-storage')));
109
+ // Variable indirection prevents bundlers (Vite, webpack) from statically resolving this
110
+ const moduleName = '@react-native-async-storage/async-storage';
111
+ const asyncStorageModule = await Promise.resolve(`${moduleName}`).then(s => __importStar(require(s)));
110
112
  asyncStorageInstance = asyncStorageModule.default;
111
113
  return asyncStorageInstance;
112
114
  }
@@ -40,30 +40,21 @@ export function WebOxyProvider({ children, baseURL, authWebUrl, onAuthStateChang
40
40
  const [isLoading, setIsLoading] = useState(!skipAutoCheck);
41
41
  const [error, setError] = useState(null);
42
42
  const [activeSessionId, setActiveSessionId] = useState(null);
43
- const [sessions, setSessions] = useState([]);
43
+ // Sessions array kept as constant empty for API compatibility.
44
+ // Multi-session management is handled by @oxyhq/services (OxyContext) for RN apps.
45
+ const sessions = [];
44
46
  const isAuthenticated = !!user;
45
47
  const handleAuthSuccess = useCallback(async (session, method = 'credentials') => {
46
48
  await authManager.handleAuthSuccess(session, method);
47
- // Set active session
48
49
  if (session.sessionId) {
49
50
  setActiveSessionId(session.sessionId);
50
51
  }
51
- // Fetch full user profile
52
- try {
53
- const fullUser = await oxyServices.getCurrentUser();
54
- if (fullUser) {
55
- setUser(fullUser);
56
- }
57
- else {
58
- setUser(session.user);
59
- }
60
- }
61
- catch {
62
- setUser(session.user);
63
- }
52
+ // Use the session user directly to avoid an extra API round-trip.
53
+ // The session already contains user data from the auth exchange.
54
+ setUser(session.user);
64
55
  setError(null);
65
56
  setIsLoading(false);
66
- }, [authManager, oxyServices]);
57
+ }, [authManager]);
67
58
  const handleAuthError = useCallback((err) => {
68
59
  const errorMessage = err instanceof Error ? err.message : 'Authentication failed';
69
60
  setError(errorMessage);
@@ -114,8 +105,18 @@ export function WebOxyProvider({ children, baseURL, authWebUrl, onAuthStateChang
114
105
  setIsLoading(false);
115
106
  }
116
107
  };
117
- initAuth();
118
- return () => { mounted = false; };
108
+ // Safety timeout: if all auth methods stall, stop loading
109
+ const INIT_TIMEOUT_MS = 15000;
110
+ const timeoutId = setTimeout(() => {
111
+ if (mounted) {
112
+ setIsLoading(false);
113
+ }
114
+ }, INIT_TIMEOUT_MS);
115
+ initAuth().finally(() => clearTimeout(timeoutId));
116
+ return () => {
117
+ mounted = false;
118
+ clearTimeout(timeoutId);
119
+ };
119
120
  }, [oxyServices, crossDomainAuth, authManager, skipAutoCheck, handleAuthSuccess]);
120
121
  useEffect(() => {
121
122
  onAuthStateChange?.(user);
@@ -179,7 +180,6 @@ export function WebOxyProvider({ children, baseURL, authWebUrl, onAuthStateChang
179
180
  await authManager.signOut();
180
181
  setUser(null);
181
182
  setActiveSessionId(null);
182
- setSessions([]);
183
183
  }
184
184
  catch (err) {
185
185
  const errorMessage = err instanceof Error ? err.message : 'Sign out failed';
@@ -205,7 +205,6 @@ export function WebOxyProvider({ children, baseURL, authWebUrl, onAuthStateChang
205
205
  await authManager.signOut();
206
206
  setUser(null);
207
207
  setActiveSessionId(null);
208
- setSessions([]);
209
208
  }, [authManager]);
210
209
  useEffect(() => {
211
210
  return () => { authManager.destroy(); };
@@ -53,7 +53,7 @@ export function useWebSSO({ oxyServices, onSessionFound, onSSOUnavailable, onErr
53
53
  const isCheckingRef = useRef(false);
54
54
  const hasCheckedRef = useRef(false);
55
55
  // Check FedCM support once
56
- const fedCMSupported = isWebBrowser() && oxyServices.isFedCMSupported?.();
56
+ const fedCMSupported = isWebBrowser() && oxyServices.isFedCMSupported();
57
57
  const checkSSO = useCallback(async () => {
58
58
  if (!isWebBrowser() || isCheckingRef.current) {
59
59
  return null;
@@ -70,7 +70,7 @@ export function useWebSSO({ oxyServices, onSessionFound, onSSOUnavailable, onErr
70
70
  }
71
71
  isCheckingRef.current = true;
72
72
  try {
73
- const session = await oxyServices.silentSignInWithFedCM?.();
73
+ const session = await oxyServices.silentSignInWithFedCM();
74
74
  if (session) {
75
75
  await onSessionFound(session);
76
76
  return session;
@@ -102,7 +102,7 @@ export function useWebSSO({ oxyServices, onSessionFound, onSSOUnavailable, onErr
102
102
  }
103
103
  isCheckingRef.current = true;
104
104
  try {
105
- const session = await oxyServices.signInWithFedCM?.();
105
+ const session = await oxyServices.signInWithFedCM();
106
106
  if (session) {
107
107
  await onSessionFound(session);
108
108
  return session;
@@ -70,7 +70,9 @@ const createNativeStorage = async () => {
70
70
  return asyncStorageInstance;
71
71
  }
72
72
  try {
73
- const asyncStorageModule = await import('@react-native-async-storage/async-storage');
73
+ // Variable indirection prevents bundlers (Vite, webpack) from statically resolving this
74
+ const moduleName = '@react-native-async-storage/async-storage';
75
+ const asyncStorageModule = await import(moduleName);
74
76
  asyncStorageInstance = asyncStorageModule.default;
75
77
  return asyncStorageInstance;
76
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/auth",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "OxyHQ Web Authentication SDK — headless auth with React hooks for Next.js, Vite, and web apps",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -105,7 +105,10 @@ export function WebOxyProvider({
105
105
  const [isLoading, setIsLoading] = useState(!skipAutoCheck);
106
106
  const [error, setError] = useState<string | null>(null);
107
107
  const [activeSessionId, setActiveSessionId] = useState<string | null>(null);
108
- const [sessions, setSessions] = useState<ClientSession[]>([]);
108
+
109
+ // Sessions array kept as constant empty for API compatibility.
110
+ // Multi-session management is handled by @oxyhq/services (OxyContext) for RN apps.
111
+ const sessions: ClientSession[] = [];
109
112
 
110
113
  const isAuthenticated = !!user;
111
114
 
@@ -115,26 +118,16 @@ export function WebOxyProvider({
115
118
  ) => {
116
119
  await authManager.handleAuthSuccess(session, method);
117
120
 
118
- // Set active session
119
121
  if (session.sessionId) {
120
122
  setActiveSessionId(session.sessionId);
121
123
  }
122
124
 
123
- // Fetch full user profile
124
- try {
125
- const fullUser = await oxyServices.getCurrentUser();
126
- if (fullUser) {
127
- setUser(fullUser);
128
- } else {
129
- setUser(session.user as User);
130
- }
131
- } catch {
132
- setUser(session.user as User);
133
- }
134
-
125
+ // Use the session user directly to avoid an extra API round-trip.
126
+ // The session already contains user data from the auth exchange.
127
+ setUser(session.user as User);
135
128
  setError(null);
136
129
  setIsLoading(false);
137
- }, [authManager, oxyServices]);
130
+ }, [authManager]);
138
131
 
139
132
  const handleAuthError = useCallback((err: unknown) => {
140
133
  const errorMessage = err instanceof Error ? err.message : 'Authentication failed';
@@ -187,8 +180,20 @@ export function WebOxyProvider({
187
180
  }
188
181
  };
189
182
 
190
- initAuth();
191
- return () => { mounted = false; };
183
+ // Safety timeout: if all auth methods stall, stop loading
184
+ const INIT_TIMEOUT_MS = 15_000;
185
+ const timeoutId = setTimeout(() => {
186
+ if (mounted) {
187
+ setIsLoading(false);
188
+ }
189
+ }, INIT_TIMEOUT_MS);
190
+
191
+ initAuth().finally(() => clearTimeout(timeoutId));
192
+
193
+ return () => {
194
+ mounted = false;
195
+ clearTimeout(timeoutId);
196
+ };
192
197
  }, [oxyServices, crossDomainAuth, authManager, skipAutoCheck, handleAuthSuccess]);
193
198
 
194
199
  useEffect(() => {
@@ -258,7 +263,6 @@ export function WebOxyProvider({
258
263
  await authManager.signOut();
259
264
  setUser(null);
260
265
  setActiveSessionId(null);
261
- setSessions([]);
262
266
  } catch (err) {
263
267
  const errorMessage = err instanceof Error ? err.message : 'Sign out failed';
264
268
  setError(errorMessage);
@@ -283,7 +287,6 @@ export function WebOxyProvider({
283
287
  await authManager.signOut();
284
288
  setUser(null);
285
289
  setActiveSessionId(null);
286
- setSessions([]);
287
290
  }, [authManager]);
288
291
 
289
292
  useEffect(() => {
@@ -84,7 +84,7 @@ export function useWebSSO({
84
84
  const hasCheckedRef = useRef(false);
85
85
 
86
86
  // Check FedCM support once
87
- const fedCMSupported = isWebBrowser() && (oxyServices as any).isFedCMSupported?.();
87
+ const fedCMSupported = isWebBrowser() && oxyServices.isFedCMSupported();
88
88
 
89
89
  const checkSSO = useCallback(async (): Promise<SessionLoginResponse | null> => {
90
90
  if (!isWebBrowser() || isCheckingRef.current) {
@@ -106,7 +106,7 @@ export function useWebSSO({
106
106
  isCheckingRef.current = true;
107
107
 
108
108
  try {
109
- const session = await (oxyServices as any).silentSignInWithFedCM?.();
109
+ const session = await oxyServices.silentSignInWithFedCM();
110
110
 
111
111
  if (session) {
112
112
  await onSessionFound(session);
@@ -142,7 +142,7 @@ export function useWebSSO({
142
142
  isCheckingRef.current = true;
143
143
 
144
144
  try {
145
- const session = await (oxyServices as any).signInWithFedCM?.();
145
+ const session = await oxyServices.signInWithFedCM();
146
146
 
147
147
  if (session) {
148
148
  await onSessionFound(session);
@@ -85,7 +85,9 @@ const createNativeStorage = async (): Promise<StorageInterface> => {
85
85
  }
86
86
 
87
87
  try {
88
- const asyncStorageModule = await import('@react-native-async-storage/async-storage');
88
+ // Variable indirection prevents bundlers (Vite, webpack) from statically resolving this
89
+ const moduleName = '@react-native-async-storage/async-storage';
90
+ const asyncStorageModule = await import(moduleName);
89
91
  asyncStorageInstance = asyncStorageModule.default as unknown as StorageInterface;
90
92
  return asyncStorageInstance;
91
93
  } catch (error) {