@tern-secure/nextjs 3.2.33 → 3.2.35
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/cjs/boundary/TernSecureClientProvider.js +25 -8
- package/dist/cjs/boundary/TernSecureClientProvider.js.map +1 -1
- package/dist/cjs/boundary/hooks/useAuth.js.map +1 -1
- package/dist/esm/boundary/TernSecureClientProvider.js +26 -9
- package/dist/esm/boundary/TernSecureClientProvider.js.map +1 -1
- package/dist/esm/boundary/hooks/useAuth.js.map +1 -1
- package/dist/types/boundary/TernSecureClientProvider.d.ts.map +1 -1
- package/package.json +2 -1
|
@@ -37,6 +37,7 @@ function TernSecureClientProvider({
|
|
|
37
37
|
const auth = (0, import_react.useMemo)(() => import_client_init.ternSecureAuth, []);
|
|
38
38
|
const router = (0, import_navigation.useRouter)();
|
|
39
39
|
const pathname = (0, import_navigation.usePathname)();
|
|
40
|
+
const intervalRef = (0, import_react.useRef)(null);
|
|
40
41
|
const [authState, setAuthState] = (0, import_react.useState)(() => ({
|
|
41
42
|
userId: null,
|
|
42
43
|
isLoaded: false,
|
|
@@ -45,6 +46,10 @@ function TernSecureClientProvider({
|
|
|
45
46
|
token: null
|
|
46
47
|
}));
|
|
47
48
|
const handleSignOut = (0, import_react.useCallback)(async (error) => {
|
|
49
|
+
if (intervalRef.current) {
|
|
50
|
+
clearInterval(intervalRef.current);
|
|
51
|
+
intervalRef.current = null;
|
|
52
|
+
}
|
|
48
53
|
await auth.signOut();
|
|
49
54
|
setAuthState({
|
|
50
55
|
isLoaded: true,
|
|
@@ -72,6 +77,16 @@ function TernSecureClientProvider({
|
|
|
72
77
|
}
|
|
73
78
|
return { isValid: false, token: null, userId: null };
|
|
74
79
|
}, [handleSignOut]);
|
|
80
|
+
const startTokenCheckInterval = (0, import_react.useCallback)(() => {
|
|
81
|
+
if (intervalRef.current) {
|
|
82
|
+
clearInterval(intervalRef.current);
|
|
83
|
+
}
|
|
84
|
+
if (pathname !== loginPath) {
|
|
85
|
+
intervalRef.current = setInterval(() => {
|
|
86
|
+
checkTokenValidity(auth.currentUser);
|
|
87
|
+
}, 3e4);
|
|
88
|
+
}
|
|
89
|
+
}, [auth, checkTokenValidity, loginPath, pathname]);
|
|
75
90
|
const handleAuthStateChange = (0, import_react.useCallback)(async (user) => {
|
|
76
91
|
const { isValid, token, userId } = await checkTokenValidity(user);
|
|
77
92
|
setAuthState({
|
|
@@ -87,15 +102,20 @@ function TernSecureClientProvider({
|
|
|
87
102
|
if (!isValid && pathname !== loginPath) {
|
|
88
103
|
router.push(loginPath);
|
|
89
104
|
}
|
|
90
|
-
|
|
105
|
+
if (user && isValid) {
|
|
106
|
+
startTokenCheckInterval();
|
|
107
|
+
} else if (intervalRef.current) {
|
|
108
|
+
clearInterval(intervalRef.current);
|
|
109
|
+
intervalRef.current = null;
|
|
110
|
+
}
|
|
111
|
+
}, [checkTokenValidity, onUserChanged, router, loginPath, pathname, startTokenCheckInterval]);
|
|
91
112
|
(0, import_react.useEffect)(() => {
|
|
92
113
|
const unsubscribeAuthState = (0, import_auth.onAuthStateChanged)(auth, handleAuthStateChange);
|
|
93
|
-
const intervalId = setInterval(() => {
|
|
94
|
-
handleAuthStateChange(auth.currentUser);
|
|
95
|
-
}, 6e4);
|
|
96
114
|
return () => {
|
|
97
115
|
unsubscribeAuthState();
|
|
98
|
-
|
|
116
|
+
if (intervalRef.current) {
|
|
117
|
+
clearInterval(intervalRef.current);
|
|
118
|
+
}
|
|
99
119
|
};
|
|
100
120
|
}, [auth, handleAuthStateChange]);
|
|
101
121
|
const contextValue = (0, import_react.useMemo)(() => ({
|
|
@@ -103,9 +123,6 @@ function TernSecureClientProvider({
|
|
|
103
123
|
checkTokenValidity: () => handleAuthStateChange(auth.currentUser),
|
|
104
124
|
signOut: handleSignOut
|
|
105
125
|
}), [authState, handleAuthStateChange, auth, handleSignOut]);
|
|
106
|
-
if (!authState.isLoaded) {
|
|
107
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TernSecureCtx.TernSecureCtx.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "aria-live": "polite", "aria-busy": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: "Loading authentication state..." }) }) });
|
|
108
|
-
}
|
|
109
126
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TernSecureCtx.TernSecureCtx.Provider, { value: contextValue, children });
|
|
110
127
|
}
|
|
111
128
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useEffect, useMemo, useCallback } from 'react'\r\nimport { ternSecureAuth } from '../utils/client-init'\r\nimport { User, onAuthStateChanged } from \"firebase/auth\"\r\nimport { TernSecureCtx, TernSecureState, TernSecureCtxValue } from './TernSecureCtx'\r\nimport { useRouter, usePathname } from 'next/navigation'\r\nimport { verifyTernIdToken } from '../app-router/server/sessionTernSecure'\r\n\r\ninterface TernSecureClientProviderProps {\r\n children: React.ReactNode;\r\n onUserChanged?: (user: User | null) => Promise<void>;\r\n loginPath?: string;\r\n}\r\n\r\nexport function TernSecureClientProvider({ \r\n children, \r\n onUserChanged,\r\n loginPath = '/sign-in'\r\n}: TernSecureClientProviderProps) {\r\n const auth = useMemo(() => ternSecureAuth, []);\r\n const router = useRouter();\r\n const pathname = usePathname();\r\n\r\n const [authState, setAuthState] = useState<TernSecureState>(() => ({\r\n userId: null,\r\n isLoaded: false,\r\n error: null,\r\n isValid: false,\r\n token: null\r\n }));\r\n\r\n const handleSignOut = useCallback(async (error?: Error) => {\r\n await auth.signOut();\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n error: error || null,\r\n isValid: false,\r\n token: null\r\n });\r\n router.push(loginPath);\r\n }, [auth, router, loginPath]);\r\n\r\n const checkTokenValidity = useCallback(async (user: User | null) => {\r\n if (user) {\r\n try {\r\n
|
|
1
|
+
{"version":3,"sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useEffect, useMemo, useCallback, useRef } from 'react'\r\nimport { ternSecureAuth } from '../utils/client-init'\r\nimport { User, onAuthStateChanged } from \"firebase/auth\"\r\nimport { TernSecureCtx, TernSecureState, TernSecureCtxValue } from './TernSecureCtx'\r\nimport { useRouter, usePathname } from 'next/navigation'\r\nimport { verifyTernIdToken } from '../app-router/server/sessionTernSecure'\r\n\r\ninterface TernSecureClientProviderProps {\r\n children: React.ReactNode;\r\n onUserChanged?: (user: User | null) => Promise<void>;\r\n loginPath?: string;\r\n}\r\n\r\nexport function TernSecureClientProvider({ \r\n children, \r\n onUserChanged,\r\n loginPath = '/sign-in'\r\n}: TernSecureClientProviderProps) {\r\n const auth = useMemo(() => ternSecureAuth, []);\r\n const router = useRouter();\r\n const pathname = usePathname();\r\n const intervalRef = useRef<NodeJS.Timeout | null>(null);\r\n\r\n const [authState, setAuthState] = useState<TernSecureState>(() => ({\r\n userId: null,\r\n isLoaded: false,\r\n error: null,\r\n isValid: false,\r\n token: null\r\n }));\r\n\r\n const handleSignOut = useCallback(async (error?: Error) => {\r\n if (intervalRef.current) {\r\n clearInterval(intervalRef.current);\r\n intervalRef.current = null;\r\n }\r\n await auth.signOut();\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n error: error || null,\r\n isValid: false,\r\n token: null\r\n });\r\n router.push(loginPath);\r\n }, [auth, router, loginPath]);\r\n\r\n const checkTokenValidity = useCallback(async (user: User | null) => {\r\n if (user) {\r\n try {\r\n const token = await user.getIdToken(true);\r\n const decodedToken = await verifyTernIdToken(token);\r\n const isValid = decodedToken.valid\r\n\r\n if(isValid) {\r\n return { isValid: true, token, userId: user.uid };\r\n }\r\n } catch (error) {\r\n console.error('Token validation error:', error);\r\n await handleSignOut(error instanceof Error ? error : new Error('Authentication token is invalid'));\r\n return { isValid: false, token: null, userId: null };\r\n }\r\n }\r\n return { isValid: false, token: null, userId: null };\r\n }, [handleSignOut]);\r\n\r\n const startTokenCheckInterval = useCallback(() => {\r\n if (intervalRef.current) {\r\n clearInterval(intervalRef.current);\r\n }\r\n if (pathname !== loginPath) {\r\n intervalRef.current = setInterval(() => {\r\n checkTokenValidity(auth.currentUser);\r\n }, 30000); // Check every 30 seconds\r\n }\r\n }, [auth, checkTokenValidity, loginPath, pathname]);\r\n\r\n const handleAuthStateChange = useCallback(async (user: User | null) => {\r\n const { isValid, token, userId } = await checkTokenValidity(user);\r\n \r\n setAuthState({\r\n isLoaded: true,\r\n userId,\r\n isValid,\r\n token,\r\n error: null\r\n });\r\n\r\n if (onUserChanged) {\r\n await onUserChanged(user);\r\n }\r\n\r\n if (!isValid && pathname !== loginPath) {\r\n router.push(loginPath);\r\n }\r\n\r\n if (user && isValid) {\r\n startTokenCheckInterval();\r\n } else if (intervalRef.current) {\r\n clearInterval(intervalRef.current);\r\n intervalRef.current = null;\r\n }\r\n }, [checkTokenValidity, onUserChanged, router, loginPath, pathname, startTokenCheckInterval]);\r\n\r\n useEffect(() => {\r\n const unsubscribeAuthState = onAuthStateChanged(auth, handleAuthStateChange);\r\n \r\n return () => {\r\n unsubscribeAuthState();\r\n if (intervalRef.current) {\r\n clearInterval(intervalRef.current);\r\n }\r\n };\r\n }, [auth, handleAuthStateChange]);\r\n\r\n const contextValue: TernSecureCtxValue = useMemo(() => ({\r\n ...authState,\r\n checkTokenValidity: () => handleAuthStateChange(auth.currentUser),\r\n signOut: handleSignOut,\r\n }), [authState, handleAuthStateChange, auth, handleSignOut]);\r\n\r\n return (\r\n <TernSecureCtx.Provider value={contextValue}>\r\n {children}\r\n </TernSecureCtx.Provider>\r\n );\r\n}\r\n\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/boundary/hooks/useAuth.ts"],"sourcesContent":["\"use client\"\r\n\r\nimport { useCallback } from 'react'\r\nimport { useTernSecure } from '../TernSecureCtx'\r\nimport { User } from 'firebase/auth'\r\nimport { TernSecureUser } from '../TernSecureCtx'\r\n\r\nexport function useAuth() {\r\n const {\r\n userId,\r\n isLoaded,\r\n error,\r\n isValid,\r\n token,\r\n checkTokenValidity,\r\n signOut\r\n } = useTernSecure('useAuth')\r\n\r\n const user: User | null = TernSecureUser()\r\n\r\n const refreshToken = useCallback(async () => {\r\n await checkTokenValidity()\r\n }, [checkTokenValidity])\r\n\r\n return {\r\n user,\r\n userId,\r\n isLoaded,\r\n error,\r\n isAuthenticated: isValid,\r\n token,\r\n refreshToken,\r\n signOut\r\n }\r\n}\r\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/boundary/hooks/useAuth.ts"],"sourcesContent":["\"use client\"\r\n\r\nimport { useCallback } from 'react'\r\nimport { useTernSecure } from '../TernSecureCtx'\r\nimport { User } from 'firebase/auth'\r\nimport { TernSecureUser } from '../TernSecureCtx'\r\n\r\nexport function useAuth() {\r\n const {\r\n userId,\r\n isLoaded,\r\n error,\r\n isValid,\r\n token,\r\n checkTokenValidity,\r\n signOut\r\n } = useTernSecure('useAuth')\r\n\r\n const user: User | null = TernSecureUser()\r\n\r\n const refreshToken = useCallback(async () => {\r\n await checkTokenValidity()\r\n }, [checkTokenValidity])\r\n\r\n return {\r\n user,\r\n userId,\r\n isLoaded,\r\n error,\r\n isAuthenticated: isValid,\r\n token,\r\n refreshToken,\r\n signOut\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAA4B;AAC5B,2BAA8B;AAE9B,IAAAA,wBAA+B;AAExB,SAAS,UAAU;AACxB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,QAAI,oCAAc,SAAS;AAE3B,QAAM,WAAoB,sCAAe;AAEzC,QAAM,mBAAe,0BAAY,YAAY;AAC3C,UAAM,mBAAmB;AAAA,EAC3B,GAAG,CAAC,kBAAkB,CAAC;AAEvB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["import_TernSecureCtx"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useEffect, useMemo, useCallback } from "react";
|
|
3
|
+
import { useState, useEffect, useMemo, useCallback, useRef } from "react";
|
|
4
4
|
import { ternSecureAuth } from "../utils/client-init";
|
|
5
5
|
import { onAuthStateChanged } from "firebase/auth";
|
|
6
6
|
import { TernSecureCtx } from "./TernSecureCtx";
|
|
@@ -14,6 +14,7 @@ function TernSecureClientProvider({
|
|
|
14
14
|
const auth = useMemo(() => ternSecureAuth, []);
|
|
15
15
|
const router = useRouter();
|
|
16
16
|
const pathname = usePathname();
|
|
17
|
+
const intervalRef = useRef(null);
|
|
17
18
|
const [authState, setAuthState] = useState(() => ({
|
|
18
19
|
userId: null,
|
|
19
20
|
isLoaded: false,
|
|
@@ -22,6 +23,10 @@ function TernSecureClientProvider({
|
|
|
22
23
|
token: null
|
|
23
24
|
}));
|
|
24
25
|
const handleSignOut = useCallback(async (error) => {
|
|
26
|
+
if (intervalRef.current) {
|
|
27
|
+
clearInterval(intervalRef.current);
|
|
28
|
+
intervalRef.current = null;
|
|
29
|
+
}
|
|
25
30
|
await auth.signOut();
|
|
26
31
|
setAuthState({
|
|
27
32
|
isLoaded: true,
|
|
@@ -49,6 +54,16 @@ function TernSecureClientProvider({
|
|
|
49
54
|
}
|
|
50
55
|
return { isValid: false, token: null, userId: null };
|
|
51
56
|
}, [handleSignOut]);
|
|
57
|
+
const startTokenCheckInterval = useCallback(() => {
|
|
58
|
+
if (intervalRef.current) {
|
|
59
|
+
clearInterval(intervalRef.current);
|
|
60
|
+
}
|
|
61
|
+
if (pathname !== loginPath) {
|
|
62
|
+
intervalRef.current = setInterval(() => {
|
|
63
|
+
checkTokenValidity(auth.currentUser);
|
|
64
|
+
}, 3e4);
|
|
65
|
+
}
|
|
66
|
+
}, [auth, checkTokenValidity, loginPath, pathname]);
|
|
52
67
|
const handleAuthStateChange = useCallback(async (user) => {
|
|
53
68
|
const { isValid, token, userId } = await checkTokenValidity(user);
|
|
54
69
|
setAuthState({
|
|
@@ -64,15 +79,20 @@ function TernSecureClientProvider({
|
|
|
64
79
|
if (!isValid && pathname !== loginPath) {
|
|
65
80
|
router.push(loginPath);
|
|
66
81
|
}
|
|
67
|
-
|
|
82
|
+
if (user && isValid) {
|
|
83
|
+
startTokenCheckInterval();
|
|
84
|
+
} else if (intervalRef.current) {
|
|
85
|
+
clearInterval(intervalRef.current);
|
|
86
|
+
intervalRef.current = null;
|
|
87
|
+
}
|
|
88
|
+
}, [checkTokenValidity, onUserChanged, router, loginPath, pathname, startTokenCheckInterval]);
|
|
68
89
|
useEffect(() => {
|
|
69
90
|
const unsubscribeAuthState = onAuthStateChanged(auth, handleAuthStateChange);
|
|
70
|
-
const intervalId = setInterval(() => {
|
|
71
|
-
handleAuthStateChange(auth.currentUser);
|
|
72
|
-
}, 6e4);
|
|
73
91
|
return () => {
|
|
74
92
|
unsubscribeAuthState();
|
|
75
|
-
|
|
93
|
+
if (intervalRef.current) {
|
|
94
|
+
clearInterval(intervalRef.current);
|
|
95
|
+
}
|
|
76
96
|
};
|
|
77
97
|
}, [auth, handleAuthStateChange]);
|
|
78
98
|
const contextValue = useMemo(() => ({
|
|
@@ -80,9 +100,6 @@ function TernSecureClientProvider({
|
|
|
80
100
|
checkTokenValidity: () => handleAuthStateChange(auth.currentUser),
|
|
81
101
|
signOut: handleSignOut
|
|
82
102
|
}), [authState, handleAuthStateChange, auth, handleSignOut]);
|
|
83
|
-
if (!authState.isLoaded) {
|
|
84
|
-
return /* @__PURE__ */ jsx(TernSecureCtx.Provider, { value: contextValue, children: /* @__PURE__ */ jsx("div", { "aria-live": "polite", "aria-busy": "true", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading authentication state..." }) }) });
|
|
85
|
-
}
|
|
86
103
|
return /* @__PURE__ */ jsx(TernSecureCtx.Provider, { value: contextValue, children });
|
|
87
104
|
}
|
|
88
105
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useEffect, useMemo, useCallback } from 'react'\r\nimport { ternSecureAuth } from '../utils/client-init'\r\nimport { User, onAuthStateChanged } from \"firebase/auth\"\r\nimport { TernSecureCtx, TernSecureState, TernSecureCtxValue } from './TernSecureCtx'\r\nimport { useRouter, usePathname } from 'next/navigation'\r\nimport { verifyTernIdToken } from '../app-router/server/sessionTernSecure'\r\n\r\ninterface TernSecureClientProviderProps {\r\n children: React.ReactNode;\r\n onUserChanged?: (user: User | null) => Promise<void>;\r\n loginPath?: string;\r\n}\r\n\r\nexport function TernSecureClientProvider({ \r\n children, \r\n onUserChanged,\r\n loginPath = '/sign-in'\r\n}: TernSecureClientProviderProps) {\r\n const auth = useMemo(() => ternSecureAuth, []);\r\n const router = useRouter();\r\n const pathname = usePathname();\r\n\r\n const [authState, setAuthState] = useState<TernSecureState>(() => ({\r\n userId: null,\r\n isLoaded: false,\r\n error: null,\r\n isValid: false,\r\n token: null\r\n }));\r\n\r\n const handleSignOut = useCallback(async (error?: Error) => {\r\n await auth.signOut();\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n error: error || null,\r\n isValid: false,\r\n token: null\r\n });\r\n router.push(loginPath);\r\n }, [auth, router, loginPath]);\r\n\r\n const checkTokenValidity = useCallback(async (user: User | null) => {\r\n if (user) {\r\n try {\r\n
|
|
1
|
+
{"version":3,"sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useEffect, useMemo, useCallback, useRef } from 'react'\r\nimport { ternSecureAuth } from '../utils/client-init'\r\nimport { User, onAuthStateChanged } from \"firebase/auth\"\r\nimport { TernSecureCtx, TernSecureState, TernSecureCtxValue } from './TernSecureCtx'\r\nimport { useRouter, usePathname } from 'next/navigation'\r\nimport { verifyTernIdToken } from '../app-router/server/sessionTernSecure'\r\n\r\ninterface TernSecureClientProviderProps {\r\n children: React.ReactNode;\r\n onUserChanged?: (user: User | null) => Promise<void>;\r\n loginPath?: string;\r\n}\r\n\r\nexport function TernSecureClientProvider({ \r\n children, \r\n onUserChanged,\r\n loginPath = '/sign-in'\r\n}: TernSecureClientProviderProps) {\r\n const auth = useMemo(() => ternSecureAuth, []);\r\n const router = useRouter();\r\n const pathname = usePathname();\r\n const intervalRef = useRef<NodeJS.Timeout | null>(null);\r\n\r\n const [authState, setAuthState] = useState<TernSecureState>(() => ({\r\n userId: null,\r\n isLoaded: false,\r\n error: null,\r\n isValid: false,\r\n token: null\r\n }));\r\n\r\n const handleSignOut = useCallback(async (error?: Error) => {\r\n if (intervalRef.current) {\r\n clearInterval(intervalRef.current);\r\n intervalRef.current = null;\r\n }\r\n await auth.signOut();\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n error: error || null,\r\n isValid: false,\r\n token: null\r\n });\r\n router.push(loginPath);\r\n }, [auth, router, loginPath]);\r\n\r\n const checkTokenValidity = useCallback(async (user: User | null) => {\r\n if (user) {\r\n try {\r\n const token = await user.getIdToken(true);\r\n const decodedToken = await verifyTernIdToken(token);\r\n const isValid = decodedToken.valid\r\n\r\n if(isValid) {\r\n return { isValid: true, token, userId: user.uid };\r\n }\r\n } catch (error) {\r\n console.error('Token validation error:', error);\r\n await handleSignOut(error instanceof Error ? error : new Error('Authentication token is invalid'));\r\n return { isValid: false, token: null, userId: null };\r\n }\r\n }\r\n return { isValid: false, token: null, userId: null };\r\n }, [handleSignOut]);\r\n\r\n const startTokenCheckInterval = useCallback(() => {\r\n if (intervalRef.current) {\r\n clearInterval(intervalRef.current);\r\n }\r\n if (pathname !== loginPath) {\r\n intervalRef.current = setInterval(() => {\r\n checkTokenValidity(auth.currentUser);\r\n }, 30000); // Check every 30 seconds\r\n }\r\n }, [auth, checkTokenValidity, loginPath, pathname]);\r\n\r\n const handleAuthStateChange = useCallback(async (user: User | null) => {\r\n const { isValid, token, userId } = await checkTokenValidity(user);\r\n \r\n setAuthState({\r\n isLoaded: true,\r\n userId,\r\n isValid,\r\n token,\r\n error: null\r\n });\r\n\r\n if (onUserChanged) {\r\n await onUserChanged(user);\r\n }\r\n\r\n if (!isValid && pathname !== loginPath) {\r\n router.push(loginPath);\r\n }\r\n\r\n if (user && isValid) {\r\n startTokenCheckInterval();\r\n } else if (intervalRef.current) {\r\n clearInterval(intervalRef.current);\r\n intervalRef.current = null;\r\n }\r\n }, [checkTokenValidity, onUserChanged, router, loginPath, pathname, startTokenCheckInterval]);\r\n\r\n useEffect(() => {\r\n const unsubscribeAuthState = onAuthStateChanged(auth, handleAuthStateChange);\r\n \r\n return () => {\r\n unsubscribeAuthState();\r\n if (intervalRef.current) {\r\n clearInterval(intervalRef.current);\r\n }\r\n };\r\n }, [auth, handleAuthStateChange]);\r\n\r\n const contextValue: TernSecureCtxValue = useMemo(() => ({\r\n ...authState,\r\n checkTokenValidity: () => handleAuthStateChange(auth.currentUser),\r\n signOut: handleSignOut,\r\n }), [authState, handleAuthStateChange, auth, handleSignOut]);\r\n\r\n return (\r\n <TernSecureCtx.Provider value={contextValue}>\r\n {children}\r\n </TernSecureCtx.Provider>\r\n );\r\n}\r\n\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/boundary/hooks/useAuth.ts"],"sourcesContent":["\"use client\"\r\n\r\nimport { useCallback } from 'react'\r\nimport { useTernSecure } from '../TernSecureCtx'\r\nimport { User } from 'firebase/auth'\r\nimport { TernSecureUser } from '../TernSecureCtx'\r\n\r\nexport function useAuth() {\r\n const {\r\n userId,\r\n isLoaded,\r\n error,\r\n isValid,\r\n token,\r\n checkTokenValidity,\r\n signOut\r\n } = useTernSecure('useAuth')\r\n\r\n const user: User | null = TernSecureUser()\r\n\r\n const refreshToken = useCallback(async () => {\r\n await checkTokenValidity()\r\n }, [checkTokenValidity])\r\n\r\n return {\r\n user,\r\n userId,\r\n isLoaded,\r\n error,\r\n isAuthenticated: isValid,\r\n token,\r\n refreshToken,\r\n signOut\r\n }\r\n}\r\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/boundary/hooks/useAuth.ts"],"sourcesContent":["\"use client\"\r\n\r\nimport { useCallback } from 'react'\r\nimport { useTernSecure } from '../TernSecureCtx'\r\nimport { User } from 'firebase/auth'\r\nimport { TernSecureUser } from '../TernSecureCtx'\r\n\r\nexport function useAuth() {\r\n const {\r\n userId,\r\n isLoaded,\r\n error,\r\n isValid,\r\n token,\r\n checkTokenValidity,\r\n signOut\r\n } = useTernSecure('useAuth')\r\n\r\n const user: User | null = TernSecureUser()\r\n\r\n const refreshToken = useCallback(async () => {\r\n await checkTokenValidity()\r\n }, [checkTokenValidity])\r\n\r\n return {\r\n user,\r\n userId,\r\n isLoaded,\r\n error,\r\n isAuthenticated: isValid,\r\n token,\r\n refreshToken,\r\n signOut\r\n }\r\n}\r\n"],"mappings":";AAEA,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAE9B,SAAS,sBAAsB;AAExB,SAAS,UAAU;AACxB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,cAAc,SAAS;AAE3B,QAAM,OAAoB,eAAe;AAEzC,QAAM,eAAe,YAAY,YAAY;AAC3C,UAAM,mBAAmB;AAAA,EAC3B,GAAG,CAAC,kBAAkB,CAAC;AAEvB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TernSecureClientProvider.d.ts","sourceRoot":"","sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"TernSecureClientProvider.d.ts","sourceRoot":"","sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4D,MAAM,OAAO,CAAA;AAEhF,OAAO,EAAE,IAAI,EAAsB,MAAM,eAAe,CAAA;AAKxD,UAAU,6BAA6B;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,aAAa,EACb,SAAsB,EACvB,EAAE,6BAA6B,2CA6G/B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tern-secure/nextjs",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.35",
|
|
4
4
|
"packageManager": "npm@10.9.0",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"prettier": "^3.3.3",
|
|
36
36
|
"rimraf": "^6.0.1",
|
|
37
37
|
"tsup": "^8.3.5",
|
|
38
|
+
"turbo": "^2.3.3",
|
|
38
39
|
"typescript": "^5.7.2"
|
|
39
40
|
},
|
|
40
41
|
"types": "./dist/types/index.d.ts",
|