say-auth 1.1.0 → 1.1.1

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.d.mts CHANGED
@@ -290,6 +290,29 @@ interface AuthProviderProps {
290
290
  }
291
291
  declare function AuthProvider({ children, apiUrl, onError, onSessionExpired, onLogin, onLogout, autoRefresh, refreshThreshold }: AuthProviderProps): react_jsx_runtime.JSX.Element;
292
292
  declare function useAuthContext(): AuthContextValue;
293
+ declare function withAuth<P extends object>(Component: React__default.ComponentType<P>): React__default.FC<P & {
294
+ auth?: AuthContextValue;
295
+ }>;
296
+ interface RoleBasedProps {
297
+ children: React__default.ReactNode;
298
+ roles: string | string[];
299
+ fallback?: React__default.ReactNode;
300
+ }
301
+ declare function RoleBased({ children, roles, fallback }: RoleBasedProps): react_jsx_runtime.JSX.Element;
302
+ interface MFARequiredProps {
303
+ children: React__default.ReactNode;
304
+ redirectTo?: string;
305
+ }
306
+ declare function MFARequired({ children, redirectTo }: MFARequiredProps): react_jsx_runtime.JSX.Element | null;
307
+ declare function AuthStatus(): react_jsx_runtime.JSX.Element;
308
+ declare function SessionTimer(): react_jsx_runtime.JSX.Element | null;
309
+ declare function AuthDebug(): react_jsx_runtime.JSX.Element | null;
310
+ declare function SessionMonitor(): null;
311
+ interface SessionExpiryWarningProps {
312
+ warningMinutes?: number[];
313
+ onExtend?: () => void;
314
+ }
315
+ declare function SessionExpiryWarning({ warningMinutes, onExtend }: SessionExpiryWarningProps): react_jsx_runtime.JSX.Element | null;
293
316
 
294
317
  interface ProtectedRouteProps {
295
318
  children: React.ReactNode;
@@ -379,4 +402,4 @@ declare const securityHeaders: {
379
402
  };
380
403
  declare function applySecurityHeaders(response: Response): Response;
381
404
 
382
- export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthProvider, AuthService, type AuthState, type AuthTokens, DeviceFingerprint, type LoginCredentials, LoginForm, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, STORAGE_KEYS, SessionManager, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, applySecurityHeaders, cn, errorTracker, formatDate, generateRandomString, getErrorMessage, initErrorTracker, isValidEmail, securityHeaders, setupAuthInterceptors, useAuth, useAuthContext, useProtectedRoute, validateEnvironment };
405
+ export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthDebug, AuthProvider, AuthService, type AuthState, AuthStatus, type AuthTokens, DeviceFingerprint, type LoginCredentials, LoginForm, MFARequired, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, RoleBased, STORAGE_KEYS, SessionExpiryWarning, SessionManager, SessionMonitor, SessionTimer, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, applySecurityHeaders, cn, errorTracker, formatDate, generateRandomString, getErrorMessage, initErrorTracker, isValidEmail, securityHeaders, setupAuthInterceptors, useAuth, useAuthContext, useProtectedRoute, validateEnvironment, withAuth };
package/dist/index.d.ts CHANGED
@@ -290,6 +290,29 @@ interface AuthProviderProps {
290
290
  }
291
291
  declare function AuthProvider({ children, apiUrl, onError, onSessionExpired, onLogin, onLogout, autoRefresh, refreshThreshold }: AuthProviderProps): react_jsx_runtime.JSX.Element;
292
292
  declare function useAuthContext(): AuthContextValue;
293
+ declare function withAuth<P extends object>(Component: React__default.ComponentType<P>): React__default.FC<P & {
294
+ auth?: AuthContextValue;
295
+ }>;
296
+ interface RoleBasedProps {
297
+ children: React__default.ReactNode;
298
+ roles: string | string[];
299
+ fallback?: React__default.ReactNode;
300
+ }
301
+ declare function RoleBased({ children, roles, fallback }: RoleBasedProps): react_jsx_runtime.JSX.Element;
302
+ interface MFARequiredProps {
303
+ children: React__default.ReactNode;
304
+ redirectTo?: string;
305
+ }
306
+ declare function MFARequired({ children, redirectTo }: MFARequiredProps): react_jsx_runtime.JSX.Element | null;
307
+ declare function AuthStatus(): react_jsx_runtime.JSX.Element;
308
+ declare function SessionTimer(): react_jsx_runtime.JSX.Element | null;
309
+ declare function AuthDebug(): react_jsx_runtime.JSX.Element | null;
310
+ declare function SessionMonitor(): null;
311
+ interface SessionExpiryWarningProps {
312
+ warningMinutes?: number[];
313
+ onExtend?: () => void;
314
+ }
315
+ declare function SessionExpiryWarning({ warningMinutes, onExtend }: SessionExpiryWarningProps): react_jsx_runtime.JSX.Element | null;
293
316
 
294
317
  interface ProtectedRouteProps {
295
318
  children: React.ReactNode;
@@ -379,4 +402,4 @@ declare const securityHeaders: {
379
402
  };
380
403
  declare function applySecurityHeaders(response: Response): Response;
381
404
 
382
- export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthProvider, AuthService, type AuthState, type AuthTokens, DeviceFingerprint, type LoginCredentials, LoginForm, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, STORAGE_KEYS, SessionManager, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, applySecurityHeaders, cn, errorTracker, formatDate, generateRandomString, getErrorMessage, initErrorTracker, isValidEmail, securityHeaders, setupAuthInterceptors, useAuth, useAuthContext, useProtectedRoute, validateEnvironment };
405
+ export { API_ENDPOINTS, AUTH_CONFIG, AuditAction, type AuditEntry$1 as AuditEntry, AuditLogger, AuthDebug, AuthProvider, AuthService, type AuthState, AuthStatus, type AuthTokens, DeviceFingerprint, type LoginCredentials, LoginForm, MFARequired, MFAService, MFASetup, MFAVerification, type MFAVerify, ProtectedRoute, RateLimiter, type RegisterData, RoleBased, STORAGE_KEYS, SessionExpiryWarning, SessionManager, SessionMonitor, SessionTimer, SessionWarning, TokenBlacklist, type TokenBlacklistEntry, TokenManager, SecureTokenStorage as TokenStorage, type User, applySecurityHeaders, cn, errorTracker, formatDate, generateRandomString, getErrorMessage, initErrorTracker, isValidEmail, securityHeaders, setupAuthInterceptors, useAuth, useAuthContext, useProtectedRoute, validateEnvironment, withAuth };
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ var CryptoJS = require('crypto-js');
5
5
  var OTPAuth = require('otpauth');
6
6
  var QRCode = require('qrcode');
7
7
  var rfc4648 = require('rfc4648');
8
- var react = require('react');
8
+ var React = require('react');
9
9
  var navigation = require('next/navigation');
10
10
  var jsxRuntime = require('react/jsx-runtime');
11
11
  var lucideReact = require('lucide-react');
@@ -34,6 +34,7 @@ var axios__default = /*#__PURE__*/_interopDefault(axios);
34
34
  var CryptoJS__default = /*#__PURE__*/_interopDefault(CryptoJS);
35
35
  var OTPAuth__namespace = /*#__PURE__*/_interopNamespace(OTPAuth);
36
36
  var QRCode__default = /*#__PURE__*/_interopDefault(QRCode);
37
+ var React__default = /*#__PURE__*/_interopDefault(React);
37
38
 
38
39
  // src/utils/constants.ts
39
40
  var AUTH_CONFIG = {
@@ -1017,8 +1018,8 @@ var AuthService = class _AuthService {
1017
1018
  }
1018
1019
  };
1019
1020
  function useAuth(apiUrl) {
1020
- const [state, setState] = react.useState(AuthService.getInstance(apiUrl).getState());
1021
- react.useEffect(() => {
1021
+ const [state, setState] = React.useState(AuthService.getInstance(apiUrl).getState());
1022
+ React.useEffect(() => {
1022
1023
  const unsubscribe = AuthService.getInstance(apiUrl).subscribe(setState);
1023
1024
  return unsubscribe;
1024
1025
  }, [apiUrl]);
@@ -1053,7 +1054,7 @@ function useAuth(apiUrl) {
1053
1054
  function useProtectedRoute(redirectTo = "/login", requiredRole) {
1054
1055
  const { isAuthenticated, isLoading, hasRole } = useAuth();
1055
1056
  const router = navigation.useRouter();
1056
- react.useEffect(() => {
1057
+ React.useEffect(() => {
1057
1058
  if (!isLoading && !isAuthenticated) {
1058
1059
  router.push(redirectTo);
1059
1060
  }
@@ -1063,7 +1064,7 @@ function useProtectedRoute(redirectTo = "/login", requiredRole) {
1063
1064
  }, [isAuthenticated, isLoading, router, redirectTo, requiredRole, hasRole]);
1064
1065
  return { isAuthenticated, isLoading };
1065
1066
  }
1066
- var AuthContext = react.createContext(null);
1067
+ var AuthContext = React.createContext(null);
1067
1068
  function AuthProvider({
1068
1069
  children,
1069
1070
  apiUrl,
@@ -1074,17 +1075,17 @@ function AuthProvider({
1074
1075
  autoRefresh = true,
1075
1076
  refreshThreshold = AUTH_CONFIG.tokenRefreshThreshold
1076
1077
  }) {
1077
- const [state, setState] = react.useState({
1078
+ const [state, setState] = React.useState({
1078
1079
  user: null,
1079
1080
  tokens: null,
1080
1081
  isAuthenticated: false,
1081
1082
  isLoading: true,
1082
1083
  error: null
1083
1084
  });
1084
- const [refreshTimeout, setRefreshTimeout] = react.useState(null);
1085
- const [sessionTimeout, setSessionTimeout] = react.useState(null);
1086
- const authService = react.useMemo(() => AuthService.getInstance(apiUrl), [apiUrl]);
1087
- react.useEffect(() => {
1085
+ const [refreshTimeout, setRefreshTimeout] = React.useState(null);
1086
+ const [sessionTimeout, setSessionTimeout] = React.useState(null);
1087
+ const authService = React.useMemo(() => AuthService.getInstance(apiUrl), [apiUrl]);
1088
+ React.useEffect(() => {
1088
1089
  const unsubscribe = authService.subscribe((newState) => {
1089
1090
  setState(newState);
1090
1091
  if (!newState.isAuthenticated && newState.error === "Session expired") {
@@ -1105,7 +1106,7 @@ function AuthProvider({
1105
1106
  if (sessionTimeout) clearTimeout(sessionTimeout);
1106
1107
  };
1107
1108
  }, [authService, onError, onSessionExpired, onLogin, onLogout]);
1108
- react.useEffect(() => {
1109
+ React.useEffect(() => {
1109
1110
  if (!autoRefresh || !state.tokens?.accessToken || !state.isAuthenticated) {
1110
1111
  return;
1111
1112
  }
@@ -1128,7 +1129,7 @@ function AuthProvider({
1128
1129
  if (refreshTimeout) clearTimeout(refreshTimeout);
1129
1130
  };
1130
1131
  }, [state.tokens?.accessToken, state.isAuthenticated, autoRefresh, refreshThreshold]);
1131
- react.useEffect(() => {
1132
+ React.useEffect(() => {
1132
1133
  if (!state.isAuthenticated || !state.tokens?.accessToken) {
1133
1134
  return;
1134
1135
  }
@@ -1150,7 +1151,7 @@ function AuthProvider({
1150
1151
  if (sessionTimeout) clearTimeout(sessionTimeout);
1151
1152
  };
1152
1153
  }, [state.tokens?.accessToken, state.isAuthenticated]);
1153
- const getTokenExpiry = react.useCallback((token) => {
1154
+ const getTokenExpiry = React.useCallback((token) => {
1154
1155
  try {
1155
1156
  const payload = JSON.parse(atob(token.split(".")[1]));
1156
1157
  return payload.exp ? new Date(payload.exp * 1e3) : null;
@@ -1158,12 +1159,12 @@ function AuthProvider({
1158
1159
  return null;
1159
1160
  }
1160
1161
  }, []);
1161
- const handleSessionExpired = react.useCallback(async () => {
1162
+ const handleSessionExpired = React.useCallback(async () => {
1162
1163
  console.warn("Session expired");
1163
1164
  await authService.logout("security");
1164
1165
  onSessionExpired?.();
1165
1166
  }, [authService, onSessionExpired]);
1166
- const login = react.useCallback(async (credentials) => {
1167
+ const login = React.useCallback(async (credentials) => {
1167
1168
  try {
1168
1169
  const result = await authService.login(credentials);
1169
1170
  return result;
@@ -1172,7 +1173,7 @@ function AuthProvider({
1172
1173
  throw new Error(errorMessage);
1173
1174
  }
1174
1175
  }, [authService]);
1175
- const register = react.useCallback(async (data) => {
1176
+ const register = React.useCallback(async (data) => {
1176
1177
  try {
1177
1178
  const user = await authService.register(data);
1178
1179
  return user;
@@ -1181,14 +1182,14 @@ function AuthProvider({
1181
1182
  throw new Error(errorMessage);
1182
1183
  }
1183
1184
  }, [authService]);
1184
- const logout = react.useCallback(async () => {
1185
+ const logout = React.useCallback(async () => {
1185
1186
  try {
1186
1187
  await authService.logout("logout");
1187
1188
  } catch (error) {
1188
1189
  console.error("Logout error:", error);
1189
1190
  }
1190
1191
  }, [authService]);
1191
- const logoutAllDevices = react.useCallback(async () => {
1192
+ const logoutAllDevices = React.useCallback(async () => {
1192
1193
  try {
1193
1194
  await authService.logoutAllDevices();
1194
1195
  } catch (error) {
@@ -1196,14 +1197,14 @@ function AuthProvider({
1196
1197
  throw error;
1197
1198
  }
1198
1199
  }, [authService]);
1199
- const refreshSession = react.useCallback(async () => {
1200
+ const refreshSession = React.useCallback(async () => {
1200
1201
  try {
1201
1202
  await authService.refreshSession();
1202
1203
  } catch (error) {
1203
1204
  console.error("Session refresh failed:", error);
1204
1205
  }
1205
1206
  }, [authService]);
1206
- const changePassword = react.useCallback(async (currentPassword, newPassword) => {
1207
+ const changePassword = React.useCallback(async (currentPassword, newPassword) => {
1207
1208
  try {
1208
1209
  await authService.changePassword(currentPassword, newPassword);
1209
1210
  } catch (error) {
@@ -1211,7 +1212,7 @@ function AuthProvider({
1211
1212
  throw new Error(errorMessage);
1212
1213
  }
1213
1214
  }, [authService]);
1214
- const verifyMFA = react.useCallback(async (code, trustDevice) => {
1215
+ const verifyMFA = React.useCallback(async (code, trustDevice) => {
1215
1216
  try {
1216
1217
  const user = await authService.verifyMFA(code, trustDevice || false);
1217
1218
  return user;
@@ -1220,7 +1221,7 @@ function AuthProvider({
1220
1221
  throw new Error(errorMessage);
1221
1222
  }
1222
1223
  }, [authService]);
1223
- const setupMFA = react.useCallback(async () => {
1224
+ const setupMFA = React.useCallback(async () => {
1224
1225
  try {
1225
1226
  const response = await authService.getAxiosInstance().post("/auth/mfa/setup");
1226
1227
  return response.data;
@@ -1229,7 +1230,7 @@ function AuthProvider({
1229
1230
  throw new Error(errorMessage);
1230
1231
  }
1231
1232
  }, [authService]);
1232
- const disableMFA = react.useCallback(async (code) => {
1233
+ const disableMFA = React.useCallback(async (code) => {
1233
1234
  try {
1234
1235
  await authService.getAxiosInstance().post("/auth/mfa/disable", { code });
1235
1236
  if (state.user) {
@@ -1243,16 +1244,16 @@ function AuthProvider({
1243
1244
  throw new Error(errorMessage);
1244
1245
  }
1245
1246
  }, [authService, state.user]);
1246
- const hasRole = react.useCallback((role) => {
1247
+ const hasRole = React.useCallback((role) => {
1247
1248
  return authService.hasRole(role);
1248
1249
  }, [authService]);
1249
- const getAxiosInstance = react.useCallback(() => {
1250
+ const getAxiosInstance = React.useCallback(() => {
1250
1251
  return authService.getAxiosInstance();
1251
1252
  }, [authService]);
1252
- const getUser = react.useCallback(() => {
1253
+ const getUser = React.useCallback(() => {
1253
1254
  return authService.getUser();
1254
1255
  }, [authService]);
1255
- const updateUser = react.useCallback(async (userData) => {
1256
+ const updateUser = React.useCallback(async (userData) => {
1256
1257
  try {
1257
1258
  const updatedUser = await authService.getAxiosInstance().put("/users/profile", userData);
1258
1259
  setState((prev) => ({ ...prev, user: updatedUser.data }));
@@ -1261,34 +1262,34 @@ function AuthProvider({
1261
1262
  throw new Error(errorMessage);
1262
1263
  }
1263
1264
  }, [authService]);
1264
- const clearError = react.useCallback(() => {
1265
+ const clearError = React.useCallback(() => {
1265
1266
  setState((prev) => ({ ...prev, error: null }));
1266
1267
  }, []);
1267
- const isTokenExpired = react.useCallback(() => {
1268
+ const isTokenExpired = React.useCallback(() => {
1268
1269
  if (!state.tokens?.accessToken) return true;
1269
1270
  const expiry = getTokenExpiry(state.tokens.accessToken);
1270
1271
  if (!expiry) return true;
1271
1272
  return expiry.getTime() <= Date.now();
1272
1273
  }, [state.tokens?.accessToken, getTokenExpiry]);
1273
- const getAccessToken = react.useCallback(() => {
1274
+ const getAccessToken = React.useCallback(() => {
1274
1275
  return state.tokens?.accessToken || null;
1275
1276
  }, [state.tokens?.accessToken]);
1276
- const healthCheck = react.useCallback(async () => {
1277
+ const healthCheck = React.useCallback(async () => {
1277
1278
  return await authService.healthCheckWithRetry();
1278
1279
  }, [authService]);
1279
- const refreshTokens = react.useCallback(async () => {
1280
+ const refreshTokens = React.useCallback(async () => {
1280
1281
  await authService.refreshSession();
1281
1282
  }, [authService]);
1282
- const getRemainingSessionTime = react.useCallback(() => {
1283
+ const getRemainingSessionTime = React.useCallback(() => {
1283
1284
  if (!state.tokens?.accessToken) return 0;
1284
1285
  const expiry = getTokenExpiry(state.tokens.accessToken);
1285
1286
  if (!expiry) return 0;
1286
1287
  return Math.max(expiry.getTime() - Date.now(), 0);
1287
1288
  }, [state.tokens?.accessToken, getTokenExpiry]);
1288
- const extendSession = react.useCallback(async () => {
1289
+ const extendSession = React.useCallback(async () => {
1289
1290
  await refreshSession();
1290
1291
  }, [refreshSession]);
1291
- const value = react.useMemo(() => ({
1292
+ const value = React.useMemo(() => ({
1292
1293
  ...state,
1293
1294
  login,
1294
1295
  register,
@@ -1336,12 +1337,218 @@ function AuthProvider({
1336
1337
  return /* @__PURE__ */ jsxRuntime.jsx(AuthContext.Provider, { value, children });
1337
1338
  }
1338
1339
  function useAuthContext() {
1339
- const context = react.useContext(AuthContext);
1340
+ const context = React.useContext(AuthContext);
1340
1341
  if (!context) {
1341
1342
  throw new Error("useAuthContext must be used within AuthProvider");
1342
1343
  }
1343
1344
  return context;
1344
1345
  }
1346
+ function withAuth(Component) {
1347
+ return function WithAuthComponent(props) {
1348
+ const auth = useAuthContext();
1349
+ return React__default.default.createElement(Component, { ...props, auth });
1350
+ };
1351
+ }
1352
+ function RoleBased({ children, roles, fallback = null }) {
1353
+ const { hasRole, isAuthenticated } = useAuthContext();
1354
+ if (isAuthenticated && hasRole(roles)) {
1355
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
1356
+ }
1357
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallback });
1358
+ }
1359
+ function MFARequired({ children, redirectTo = "/mfa/setup" }) {
1360
+ const { user, isAuthenticated, isLoading } = useAuthContext();
1361
+ if (isLoading) {
1362
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Loading..." });
1363
+ }
1364
+ if (!isAuthenticated) {
1365
+ return null;
1366
+ }
1367
+ if (!user?.mfaEnabled) {
1368
+ if (typeof window !== "undefined") {
1369
+ window.location.href = redirectTo;
1370
+ }
1371
+ return null;
1372
+ }
1373
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
1374
+ }
1375
+ function AuthStatus() {
1376
+ const { user, isAuthenticated, isLoading, getRemainingSessionTime } = useAuthContext();
1377
+ if (isLoading) return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Checking authentication..." });
1378
+ if (!isAuthenticated) return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Not authenticated" });
1379
+ const remainingTime = getRemainingSessionTime();
1380
+ const remainingMinutes = Math.floor(remainingTime / 6e4);
1381
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm", children: [
1382
+ "Logged in as: ",
1383
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: user?.name }),
1384
+ " (",
1385
+ user?.email,
1386
+ ")",
1387
+ user?.role && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 text-blue-600", children: [
1388
+ "Role: ",
1389
+ user.role
1390
+ ] }),
1391
+ user?.mfaEnabled && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-green-600", children: "\u2713 MFA" }),
1392
+ remainingMinutes > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 text-gray-500", children: [
1393
+ "Session: ",
1394
+ remainingMinutes,
1395
+ "min"
1396
+ ] })
1397
+ ] });
1398
+ }
1399
+ function SessionTimer() {
1400
+ const { getRemainingSessionTime, extendSession, logout } = useAuthContext();
1401
+ const [timeLeft, setTimeLeft] = React.useState(getRemainingSessionTime());
1402
+ React.useEffect(() => {
1403
+ const interval = setInterval(() => {
1404
+ const remaining = getRemainingSessionTime();
1405
+ setTimeLeft(remaining);
1406
+ if (remaining <= 5 * 60 * 1e3 && remaining > 0) {
1407
+ const shouldExtend = window.confirm(
1408
+ `Your session will expire in ${Math.floor(remaining / 6e4)} minutes. Would you like to extend it?`
1409
+ );
1410
+ if (shouldExtend) {
1411
+ extendSession();
1412
+ }
1413
+ }
1414
+ if (remaining <= 0) {
1415
+ logout();
1416
+ }
1417
+ }, 1e3);
1418
+ return () => clearInterval(interval);
1419
+ }, [getRemainingSessionTime, extendSession, logout]);
1420
+ if (timeLeft <= 0) return null;
1421
+ const minutes = Math.floor(timeLeft / 6e4);
1422
+ const seconds = Math.floor(timeLeft % 6e4 / 1e3);
1423
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed bottom-4 left-4 bg-gray-900 text-white px-3 py-1 rounded text-xs font-mono", children: [
1424
+ "Session: ",
1425
+ minutes,
1426
+ ":",
1427
+ seconds.toString().padStart(2, "0")
1428
+ ] });
1429
+ }
1430
+ function AuthDebug() {
1431
+ const auth = useAuthContext();
1432
+ if (process.env.NODE_ENV !== "development") {
1433
+ return null;
1434
+ }
1435
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed bottom-4 right-4 bg-black text-white p-4 rounded-lg text-xs font-mono z-50 max-w-md overflow-auto shadow-xl", children: /* @__PURE__ */ jsxRuntime.jsxs("details", { children: [
1436
+ /* @__PURE__ */ jsxRuntime.jsx("summary", { className: "cursor-pointer font-bold hover:text-gray-300", children: "\u{1F510} Auth Debug Info" }),
1437
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 space-y-1", children: [
1438
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1439
+ "\u2705 Authenticated: ",
1440
+ auth.isAuthenticated ? "Yes" : "No"
1441
+ ] }),
1442
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1443
+ "\u23F3 Loading: ",
1444
+ auth.isLoading ? "Yes" : "No"
1445
+ ] }),
1446
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1447
+ "\u{1F464} User: ",
1448
+ auth.user?.email || "None"
1449
+ ] }),
1450
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1451
+ "\u{1F4DB} Name: ",
1452
+ auth.user?.name || "None"
1453
+ ] }),
1454
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1455
+ "\u{1F3AD} Role: ",
1456
+ auth.user?.role || "None"
1457
+ ] }),
1458
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1459
+ "\u{1F510} MFA: ",
1460
+ auth.user?.mfaEnabled ? "Enabled" : "Disabled"
1461
+ ] }),
1462
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1463
+ "\u23F0 Token Expired: ",
1464
+ auth.isTokenExpired() ? "Yes" : "No"
1465
+ ] }),
1466
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1467
+ "\u{1F3AB} Has Token: ",
1468
+ auth.getAccessToken() ? "Yes" : "No"
1469
+ ] }),
1470
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1471
+ "\u23F1\uFE0F Session Time: ",
1472
+ Math.floor(auth.getRemainingSessionTime() / 1e3),
1473
+ "s"
1474
+ ] }),
1475
+ auth.error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-red-500", children: [
1476
+ "\u274C Error: ",
1477
+ auth.error
1478
+ ] })
1479
+ ] })
1480
+ ] }) });
1481
+ }
1482
+ function SessionMonitor() {
1483
+ const { isAuthenticated, refreshSession } = useAuthContext();
1484
+ React.useEffect(() => {
1485
+ if (!isAuthenticated) return;
1486
+ const interval = setInterval(async () => {
1487
+ try {
1488
+ await refreshSession();
1489
+ } catch (error) {
1490
+ console.error("Session health check failed:", error);
1491
+ }
1492
+ }, 5 * 60 * 1e3);
1493
+ return () => clearInterval(interval);
1494
+ }, [isAuthenticated, refreshSession]);
1495
+ return null;
1496
+ }
1497
+ function SessionExpiryWarning({
1498
+ warningMinutes = [5, 2, 1],
1499
+ onExtend
1500
+ }) {
1501
+ const { getRemainingSessionTime, extendSession } = useAuthContext();
1502
+ const [showWarning, setShowWarning] = React.useState(false);
1503
+ const [timeLeft, setTimeLeft] = React.useState(0);
1504
+ React.useEffect(() => {
1505
+ const interval = setInterval(() => {
1506
+ const remaining = getRemainingSessionTime();
1507
+ setTimeLeft(remaining);
1508
+ const shouldShow = warningMinutes.some(
1509
+ (minutes2) => Math.abs(remaining - minutes2 * 60 * 1e3) < 1e3
1510
+ );
1511
+ setShowWarning(shouldShow && remaining > 0);
1512
+ }, 1e3);
1513
+ return () => clearInterval(interval);
1514
+ }, [getRemainingSessionTime, warningMinutes]);
1515
+ const handleExtend = async () => {
1516
+ await extendSession();
1517
+ setShowWarning(false);
1518
+ onExtend?.();
1519
+ };
1520
+ if (!showWarning) return null;
1521
+ const minutes = Math.floor(timeLeft / 6e4);
1522
+ const seconds = Math.floor(timeLeft % 6e4 / 1e3);
1523
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg p-6 max-w-md mx-4", children: [
1524
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-2", children: "Session Expiring Soon" }),
1525
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-gray-600 mb-4", children: [
1526
+ "Your session will expire in ",
1527
+ minutes,
1528
+ ":",
1529
+ seconds.toString().padStart(2, "0"),
1530
+ " minutes. Would you like to extend it?"
1531
+ ] }),
1532
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
1533
+ /* @__PURE__ */ jsxRuntime.jsx(
1534
+ "button",
1535
+ {
1536
+ onClick: handleExtend,
1537
+ className: "bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600",
1538
+ children: "Extend Session"
1539
+ }
1540
+ ),
1541
+ /* @__PURE__ */ jsxRuntime.jsx(
1542
+ "button",
1543
+ {
1544
+ onClick: () => setShowWarning(false),
1545
+ className: "bg-gray-300 text-gray-700 px-4 py-2 rounded hover:bg-gray-400",
1546
+ children: "Dismiss"
1547
+ }
1548
+ )
1549
+ ] })
1550
+ ] }) });
1551
+ }
1345
1552
  function ProtectedRoute({
1346
1553
  children,
1347
1554
  requiredRole,
@@ -1389,11 +1596,11 @@ function generateRandomString(length) {
1389
1596
  return result;
1390
1597
  }
1391
1598
  function LoginForm({ onSubmit, isLoading = false, error, className }) {
1392
- const [email, setEmail] = react.useState("");
1393
- const [password, setPassword] = react.useState("");
1394
- const [showPassword, setShowPassword] = react.useState(false);
1395
- const [rememberMe, setRememberMe] = react.useState(false);
1396
- const [localError, setLocalError] = react.useState("");
1599
+ const [email, setEmail] = React.useState("");
1600
+ const [password, setPassword] = React.useState("");
1601
+ const [showPassword, setShowPassword] = React.useState(false);
1602
+ const [rememberMe, setRememberMe] = React.useState(false);
1603
+ const [localError, setLocalError] = React.useState("");
1397
1604
  const handleSubmit = async (e) => {
1398
1605
  e.preventDefault();
1399
1606
  setLocalError("");
@@ -1494,13 +1701,13 @@ function LoginForm({ onSubmit, isLoading = false, error, className }) {
1494
1701
  ] }) }) });
1495
1702
  }
1496
1703
  function MFASetup({ userId, email, onComplete, onCancel }) {
1497
- const [step, setStep] = react.useState("setup");
1498
- const [qrCode, setQrCode] = react.useState("");
1499
- const [backupCodes, setBackupCodes] = react.useState([]);
1500
- const [verificationCode, setVerificationCode] = react.useState("");
1501
- const [error, setError] = react.useState("");
1502
- const [copied, setCopied] = react.useState(false);
1503
- const [isLoading, setIsLoading] = react.useState(false);
1704
+ const [step, setStep] = React.useState("setup");
1705
+ const [qrCode, setQrCode] = React.useState("");
1706
+ const [backupCodes, setBackupCodes] = React.useState([]);
1707
+ const [verificationCode, setVerificationCode] = React.useState("");
1708
+ const [error, setError] = React.useState("");
1709
+ const [copied, setCopied] = React.useState(false);
1710
+ const [isLoading, setIsLoading] = React.useState(false);
1504
1711
  const handleSetup = async () => {
1505
1712
  setIsLoading(true);
1506
1713
  try {
@@ -1641,10 +1848,10 @@ function MFASetup({ userId, email, onComplete, onCancel }) {
1641
1848
  ] });
1642
1849
  }
1643
1850
  function MFAVerification({ onSubmit, onBack }) {
1644
- const [code, setCode] = react.useState("");
1645
- const [trustDevice, setTrustDevice] = react.useState(false);
1646
- const [error, setError] = react.useState("");
1647
- const [isLoading, setIsLoading] = react.useState(false);
1851
+ const [code, setCode] = React.useState("");
1852
+ const [trustDevice, setTrustDevice] = React.useState(false);
1853
+ const [error, setError] = React.useState("");
1854
+ const [isLoading, setIsLoading] = React.useState(false);
1648
1855
  const handleSubmit = async (e) => {
1649
1856
  e.preventDefault();
1650
1857
  if (code.length !== 6) {
@@ -1721,9 +1928,9 @@ function MFAVerification({ onSubmit, onBack }) {
1721
1928
  }
1722
1929
  function SessionWarning({ warningMinutes = 2 }) {
1723
1930
  const { refreshSession } = useAuth();
1724
- const [showWarning, setShowWarning] = react.useState(false);
1725
- const [timeLeft, setTimeLeft] = react.useState(0);
1726
- react.useEffect(() => {
1931
+ const [showWarning, setShowWarning] = React.useState(false);
1932
+ const [timeLeft, setTimeLeft] = React.useState(0);
1933
+ React.useEffect(() => {
1727
1934
  const checkSession = () => {
1728
1935
  const tokens = localStorage.getItem("auth_tokens_encrypted");
1729
1936
  if (!tokens) return;
@@ -1903,17 +2110,24 @@ exports.API_ENDPOINTS = API_ENDPOINTS;
1903
2110
  exports.AUTH_CONFIG = AUTH_CONFIG;
1904
2111
  exports.AuditAction = AuditAction;
1905
2112
  exports.AuditLogger = AuditLogger;
2113
+ exports.AuthDebug = AuthDebug;
1906
2114
  exports.AuthProvider = AuthProvider;
1907
2115
  exports.AuthService = AuthService;
2116
+ exports.AuthStatus = AuthStatus;
1908
2117
  exports.DeviceFingerprint = DeviceFingerprint;
1909
2118
  exports.LoginForm = LoginForm;
2119
+ exports.MFARequired = MFARequired;
1910
2120
  exports.MFAService = MFAService;
1911
2121
  exports.MFASetup = MFASetup;
1912
2122
  exports.MFAVerification = MFAVerification;
1913
2123
  exports.ProtectedRoute = ProtectedRoute;
1914
2124
  exports.RateLimiter = RateLimiter;
2125
+ exports.RoleBased = RoleBased;
1915
2126
  exports.STORAGE_KEYS = STORAGE_KEYS;
2127
+ exports.SessionExpiryWarning = SessionExpiryWarning;
1916
2128
  exports.SessionManager = SessionManager;
2129
+ exports.SessionMonitor = SessionMonitor;
2130
+ exports.SessionTimer = SessionTimer;
1917
2131
  exports.SessionWarning = SessionWarning;
1918
2132
  exports.TokenBlacklist = TokenBlacklist;
1919
2133
  exports.TokenManager = TokenManager;
@@ -1931,5 +2145,6 @@ exports.useAuth = useAuth;
1931
2145
  exports.useAuthContext = useAuthContext;
1932
2146
  exports.useProtectedRoute = useProtectedRoute;
1933
2147
  exports.validateEnvironment = validateEnvironment;
2148
+ exports.withAuth = withAuth;
1934
2149
  //# sourceMappingURL=index.js.map
1935
2150
  //# sourceMappingURL=index.js.map