transactional-auth-react 0.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.
package/README.md ADDED
@@ -0,0 +1,223 @@
1
+ # transactional-auth-react
2
+
3
+ React SDK for Transactional Auth - OpenID Connect authentication for React applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install transactional-auth-react
9
+ # or
10
+ yarn add transactional-auth-react
11
+ # or
12
+ pnpm add transactional-auth-react
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ### 1. Configure the Provider
18
+
19
+ Wrap your application with the `TransactionalAuthProvider`:
20
+
21
+ ```tsx
22
+ import { TransactionalAuthProvider } from 'transactional-auth-react';
23
+
24
+ function App() {
25
+ return (
26
+ <TransactionalAuthProvider
27
+ domain="auth.usetransactional.com"
28
+ clientId="your-client-id"
29
+ redirectUri={window.location.origin}
30
+ >
31
+ <YourApp />
32
+ </TransactionalAuthProvider>
33
+ );
34
+ }
35
+ ```
36
+
37
+ ### 2. Add Login/Logout
38
+
39
+ Use the `useAuth` hook to access authentication state and methods:
40
+
41
+ ```tsx
42
+ import { useAuth } from 'transactional-auth-react';
43
+
44
+ function LoginButton() {
45
+ const { isAuthenticated, isLoading, loginWithRedirect, logout, user } = useAuth();
46
+
47
+ if (isLoading) {
48
+ return <div>Loading...</div>;
49
+ }
50
+
51
+ if (isAuthenticated) {
52
+ return (
53
+ <div>
54
+ <span>Welcome, {user?.name}</span>
55
+ <button onClick={() => logout()}>Logout</button>
56
+ </div>
57
+ );
58
+ }
59
+
60
+ return <button onClick={() => loginWithRedirect()}>Login</button>;
61
+ }
62
+ ```
63
+
64
+ ### 3. Protect Routes
65
+
66
+ Use the `AuthGuard` component or `withAuthenticationRequired` HOC:
67
+
68
+ ```tsx
69
+ import { AuthGuard } from 'transactional-auth-react';
70
+
71
+ function ProtectedPage() {
72
+ return (
73
+ <AuthGuard fallback={<div>Loading...</div>}>
74
+ <div>This content is only visible to authenticated users</div>
75
+ </AuthGuard>
76
+ );
77
+ }
78
+ ```
79
+
80
+ Or with the HOC:
81
+
82
+ ```tsx
83
+ import { withAuthenticationRequired } from 'transactional-auth-react';
84
+
85
+ function Dashboard() {
86
+ return <div>Dashboard content</div>;
87
+ }
88
+
89
+ export default withAuthenticationRequired(Dashboard);
90
+ ```
91
+
92
+ ## API Reference
93
+
94
+ ### TransactionalAuthProvider
95
+
96
+ The main provider component that wraps your application.
97
+
98
+ | Prop | Type | Default | Description |
99
+ |------|------|---------|-------------|
100
+ | `domain` | `string` | Required | Auth domain (e.g., 'auth.usetransactional.com') |
101
+ | `clientId` | `string` | Required | Your application's client ID |
102
+ | `redirectUri` | `string` | `window.location.origin` | Redirect URI after authentication |
103
+ | `scope` | `string` | `'openid profile email'` | Scopes to request |
104
+ | `audience` | `string` | - | API audience for access token |
105
+ | `cacheLocation` | `'memory' \| 'localstorage'` | `'localstorage'` | Where to store tokens |
106
+ | `useRefreshTokens` | `boolean` | `true` | Use refresh tokens for silent renewal |
107
+ | `onRedirectCallback` | `(appState?) => void` | - | Callback after redirect from login |
108
+
109
+ ### useAuth Hook
110
+
111
+ Returns the authentication context with state and methods.
112
+
113
+ ```tsx
114
+ const {
115
+ // State
116
+ isAuthenticated, // boolean - Whether user is authenticated
117
+ isLoading, // boolean - Whether auth state is loading
118
+ user, // TransactionalAuthUser | null
119
+ error, // Error | null
120
+
121
+ // Methods
122
+ loginWithRedirect, // (options?) => Promise<void>
123
+ loginWithPopup, // (options?) => Promise<void>
124
+ logout, // (options?) => Promise<void>
125
+ getAccessToken, // () => Promise<string | undefined>
126
+ getIdTokenClaims, // () => Promise<object | undefined>
127
+ hasPermission, // (permission: string) => boolean
128
+ hasRole, // (role: string) => boolean
129
+ } = useAuth();
130
+ ```
131
+
132
+ ### useUser Hook
133
+
134
+ Returns the current authenticated user.
135
+
136
+ ```tsx
137
+ const { user, isLoading } = useUser();
138
+ ```
139
+
140
+ ### useAccessToken Hook
141
+
142
+ Returns the current access token (or null if not authenticated).
143
+
144
+ ```tsx
145
+ const accessToken = useAccessToken();
146
+ ```
147
+
148
+ ### AuthGuard Component
149
+
150
+ Protects content that requires authentication.
151
+
152
+ ```tsx
153
+ <AuthGuard
154
+ fallback={<Loading />} // Shown while loading
155
+ onUnauthenticated={() => {}} // Called when not authenticated
156
+ autoRedirect={true} // Auto-redirect to login
157
+ >
158
+ <ProtectedContent />
159
+ </AuthGuard>
160
+ ```
161
+
162
+ ### withAuthenticationRequired HOC
163
+
164
+ Higher-order component for protecting components.
165
+
166
+ ```tsx
167
+ export default withAuthenticationRequired(Component, {
168
+ fallback: <Loading />,
169
+ onUnauthenticated: () => {},
170
+ returnTo: '/dashboard',
171
+ });
172
+ ```
173
+
174
+ ## Making API Calls
175
+
176
+ Use the access token to authenticate API requests:
177
+
178
+ ```tsx
179
+ import { useAuth } from 'transactional-auth-react';
180
+
181
+ function ApiExample() {
182
+ const { getAccessToken } = useAuth();
183
+
184
+ async function fetchData() {
185
+ const token = await getAccessToken();
186
+
187
+ const response = await fetch('https://api.example.com/data', {
188
+ headers: {
189
+ Authorization: `Bearer ${token}`,
190
+ },
191
+ });
192
+
193
+ return response.json();
194
+ }
195
+
196
+ // ...
197
+ }
198
+ ```
199
+
200
+ ## Next.js App Router
201
+
202
+ For Next.js 13+ with the App Router, mark components as client components:
203
+
204
+ ```tsx
205
+ 'use client';
206
+
207
+ import { TransactionalAuthProvider } from 'transactional-auth-react';
208
+
209
+ export function AuthProvider({ children }: { children: React.ReactNode }) {
210
+ return (
211
+ <TransactionalAuthProvider
212
+ domain="auth.usetransactional.com"
213
+ clientId="your-client-id"
214
+ >
215
+ {children}
216
+ </TransactionalAuthProvider>
217
+ );
218
+ }
219
+ ```
220
+
221
+ ## License
222
+
223
+ MIT
@@ -0,0 +1,252 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React$1 from 'react';
3
+
4
+ /**
5
+ * Transactional Auth React - Types
6
+ */
7
+ interface TransactionalAuthUser {
8
+ sub: string;
9
+ email?: string;
10
+ emailVerified?: boolean;
11
+ name?: string;
12
+ givenName?: string;
13
+ familyName?: string;
14
+ picture?: string;
15
+ phoneNumber?: string;
16
+ phoneNumberVerified?: boolean;
17
+ }
18
+ interface TransactionalAuthState {
19
+ isAuthenticated: boolean;
20
+ isLoading: boolean;
21
+ user: TransactionalAuthUser | null;
22
+ error: Error | null;
23
+ }
24
+ interface LoginOptions {
25
+ /** Return URL after login */
26
+ returnTo?: string;
27
+ /** State to pass through the authentication flow */
28
+ appState?: Record<string, unknown>;
29
+ /** Force specific connection (e.g., 'google', 'github') */
30
+ connection?: string;
31
+ /** Login hint (pre-fill email) */
32
+ loginHint?: string;
33
+ /** UI locales */
34
+ uiLocales?: string;
35
+ }
36
+ interface LogoutOptions {
37
+ /** Return URL after logout */
38
+ returnTo?: string;
39
+ /** Whether to logout from the identity provider as well */
40
+ federated?: boolean;
41
+ }
42
+ interface TransactionalAuthContextValue extends TransactionalAuthState {
43
+ /** Redirect to login page */
44
+ loginWithRedirect: (options?: LoginOptions) => Promise<void>;
45
+ /** Open login popup */
46
+ loginWithPopup: (options?: LoginOptions) => Promise<void>;
47
+ /** Logout the user */
48
+ logout: (options?: LogoutOptions) => Promise<void>;
49
+ /** Get the access token (silently refreshes if needed) */
50
+ getAccessToken: () => Promise<string | undefined>;
51
+ /** Get ID token claims */
52
+ getIdTokenClaims: () => Promise<Record<string, unknown> | undefined>;
53
+ /** Check if user has specific permission */
54
+ hasPermission: (permission: string) => boolean;
55
+ /** Check if user has specific role */
56
+ hasRole: (role: string) => boolean;
57
+ }
58
+ interface TransactionalAuthProviderProps {
59
+ /** Auth domain (e.g., 'auth.usetransactional.com' or 'myapp.auth.usetransactional.com') */
60
+ domain: string;
61
+ /** Client ID of your application */
62
+ clientId: string;
63
+ /** Redirect URI after authentication (defaults to window.location.origin) */
64
+ redirectUri?: string;
65
+ /** Scopes to request (defaults to 'openid profile email') */
66
+ scope?: string;
67
+ /** API audience for access token */
68
+ audience?: string;
69
+ /** Where to store tokens: 'memory' or 'localstorage' */
70
+ cacheLocation?: 'memory' | 'localstorage';
71
+ /** Use refresh tokens for silent renewal */
72
+ useRefreshTokens?: boolean;
73
+ /** Callback after redirect from login */
74
+ onRedirectCallback?: (appState?: Record<string, unknown>) => void;
75
+ /** Children components */
76
+ children: React.ReactNode;
77
+ }
78
+
79
+ /**
80
+ * TransactionalAuthProvider Component
81
+ *
82
+ * Provides authentication context to your React application.
83
+ *
84
+ * @example
85
+ * ```tsx
86
+ * import { TransactionalAuthProvider } from 'transactional-auth-react';
87
+ *
88
+ * function App() {
89
+ * return (
90
+ * <TransactionalAuthProvider
91
+ * domain="auth.usetransactional.com"
92
+ * clientId="your-client-id"
93
+ * redirectUri={window.location.origin}
94
+ * >
95
+ * <YourApp />
96
+ * </TransactionalAuthProvider>
97
+ * );
98
+ * }
99
+ * ```
100
+ */
101
+ declare function TransactionalAuthProvider({ domain, clientId, redirectUri, scope, audience, cacheLocation, useRefreshTokens, onRedirectCallback, children, }: TransactionalAuthProviderProps): react_jsx_runtime.JSX.Element;
102
+
103
+ declare const TransactionalAuthContext: React$1.Context<TransactionalAuthContextValue>;
104
+
105
+ /**
106
+ * Transactional Auth React - useAuth Hook
107
+ */
108
+
109
+ /**
110
+ * Hook to access authentication state and methods.
111
+ *
112
+ * @example
113
+ * ```tsx
114
+ * import { useAuth } from 'transactional-auth-react';
115
+ *
116
+ * function LoginButton() {
117
+ * const { isAuthenticated, loginWithRedirect, logout, user } = useAuth();
118
+ *
119
+ * if (isAuthenticated) {
120
+ * return (
121
+ * <div>
122
+ * <span>Welcome, {user?.name}</span>
123
+ * <button onClick={() => logout()}>Logout</button>
124
+ * </div>
125
+ * );
126
+ * }
127
+ *
128
+ * return <button onClick={() => loginWithRedirect()}>Login</button>;
129
+ * }
130
+ * ```
131
+ */
132
+ declare function useAuth(): TransactionalAuthContextValue;
133
+
134
+ /**
135
+ * Transactional Auth React - useUser Hook
136
+ */
137
+
138
+ interface UseUserResult {
139
+ user: TransactionalAuthUser | null;
140
+ isLoading: boolean;
141
+ }
142
+ /**
143
+ * Hook to access the current authenticated user.
144
+ *
145
+ * @example
146
+ * ```tsx
147
+ * import { useUser } from 'transactional-auth-react';
148
+ *
149
+ * function Profile() {
150
+ * const { user, isLoading } = useUser();
151
+ *
152
+ * if (isLoading) return <div>Loading...</div>;
153
+ * if (!user) return <div>Not logged in</div>;
154
+ *
155
+ * return (
156
+ * <div>
157
+ * <img src={user.picture} alt={user.name} />
158
+ * <h1>{user.name}</h1>
159
+ * <p>{user.email}</p>
160
+ * </div>
161
+ * );
162
+ * }
163
+ * ```
164
+ */
165
+ declare function useUser(): UseUserResult;
166
+
167
+ /**
168
+ * Transactional Auth React - useAccessToken Hook
169
+ */
170
+ /**
171
+ * Hook to get the current access token.
172
+ *
173
+ * @example
174
+ * ```tsx
175
+ * import { useAccessToken } from 'transactional-auth-react';
176
+ *
177
+ * function ApiComponent() {
178
+ * const accessToken = useAccessToken();
179
+ *
180
+ * useEffect(() => {
181
+ * if (accessToken) {
182
+ * fetch('/api/data', {
183
+ * headers: { Authorization: `Bearer ${accessToken}` }
184
+ * });
185
+ * }
186
+ * }, [accessToken]);
187
+ *
188
+ * return <div>...</div>;
189
+ * }
190
+ * ```
191
+ */
192
+ declare function useAccessToken(): string | null;
193
+
194
+ interface AuthGuardProps {
195
+ /** Content to show while authenticated */
196
+ children: React$1.ReactNode;
197
+ /** Content to show while loading */
198
+ fallback?: React$1.ReactNode;
199
+ /** Callback when user is not authenticated */
200
+ onUnauthenticated?: () => void;
201
+ /** Whether to automatically redirect to login */
202
+ autoRedirect?: boolean;
203
+ }
204
+ /**
205
+ * Component that guards content for authenticated users only.
206
+ *
207
+ * @example
208
+ * ```tsx
209
+ * import { AuthGuard } from 'transactional-auth-react';
210
+ *
211
+ * function ProtectedPage() {
212
+ * return (
213
+ * <AuthGuard fallback={<div>Loading...</div>}>
214
+ * <div>Protected content</div>
215
+ * </AuthGuard>
216
+ * );
217
+ * }
218
+ * ```
219
+ */
220
+ declare function AuthGuard({ children, fallback, onUnauthenticated, autoRedirect, }: AuthGuardProps): react_jsx_runtime.JSX.Element | null;
221
+
222
+ /**
223
+ * Transactional Auth React - withAuthenticationRequired HOC
224
+ */
225
+
226
+ interface WithAuthenticationRequiredOptions {
227
+ /** Content to show while loading */
228
+ fallback?: React$1.ReactNode;
229
+ /** Callback when user is not authenticated */
230
+ onUnauthenticated?: () => void;
231
+ /** Return URL after login */
232
+ returnTo?: string;
233
+ }
234
+ /**
235
+ * Higher-order component that wraps a component to require authentication.
236
+ *
237
+ * @example
238
+ * ```tsx
239
+ * import { withAuthenticationRequired } from 'transactional-auth-react';
240
+ *
241
+ * function Dashboard() {
242
+ * return <div>Dashboard content</div>;
243
+ * }
244
+ *
245
+ * export default withAuthenticationRequired(Dashboard, {
246
+ * fallback: <div>Loading...</div>,
247
+ * });
248
+ * ```
249
+ */
250
+ declare function withAuthenticationRequired<P extends object>(Component: React$1.ComponentType<P>, options?: WithAuthenticationRequiredOptions): React$1.ComponentType<P>;
251
+
252
+ export { AuthGuard, type LoginOptions, type LogoutOptions, TransactionalAuthContext, type TransactionalAuthContextValue, TransactionalAuthProvider, type TransactionalAuthProviderProps, type TransactionalAuthState, type TransactionalAuthUser, useAccessToken, useAuth, useUser, withAuthenticationRequired };
@@ -0,0 +1,252 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React$1 from 'react';
3
+
4
+ /**
5
+ * Transactional Auth React - Types
6
+ */
7
+ interface TransactionalAuthUser {
8
+ sub: string;
9
+ email?: string;
10
+ emailVerified?: boolean;
11
+ name?: string;
12
+ givenName?: string;
13
+ familyName?: string;
14
+ picture?: string;
15
+ phoneNumber?: string;
16
+ phoneNumberVerified?: boolean;
17
+ }
18
+ interface TransactionalAuthState {
19
+ isAuthenticated: boolean;
20
+ isLoading: boolean;
21
+ user: TransactionalAuthUser | null;
22
+ error: Error | null;
23
+ }
24
+ interface LoginOptions {
25
+ /** Return URL after login */
26
+ returnTo?: string;
27
+ /** State to pass through the authentication flow */
28
+ appState?: Record<string, unknown>;
29
+ /** Force specific connection (e.g., 'google', 'github') */
30
+ connection?: string;
31
+ /** Login hint (pre-fill email) */
32
+ loginHint?: string;
33
+ /** UI locales */
34
+ uiLocales?: string;
35
+ }
36
+ interface LogoutOptions {
37
+ /** Return URL after logout */
38
+ returnTo?: string;
39
+ /** Whether to logout from the identity provider as well */
40
+ federated?: boolean;
41
+ }
42
+ interface TransactionalAuthContextValue extends TransactionalAuthState {
43
+ /** Redirect to login page */
44
+ loginWithRedirect: (options?: LoginOptions) => Promise<void>;
45
+ /** Open login popup */
46
+ loginWithPopup: (options?: LoginOptions) => Promise<void>;
47
+ /** Logout the user */
48
+ logout: (options?: LogoutOptions) => Promise<void>;
49
+ /** Get the access token (silently refreshes if needed) */
50
+ getAccessToken: () => Promise<string | undefined>;
51
+ /** Get ID token claims */
52
+ getIdTokenClaims: () => Promise<Record<string, unknown> | undefined>;
53
+ /** Check if user has specific permission */
54
+ hasPermission: (permission: string) => boolean;
55
+ /** Check if user has specific role */
56
+ hasRole: (role: string) => boolean;
57
+ }
58
+ interface TransactionalAuthProviderProps {
59
+ /** Auth domain (e.g., 'auth.usetransactional.com' or 'myapp.auth.usetransactional.com') */
60
+ domain: string;
61
+ /** Client ID of your application */
62
+ clientId: string;
63
+ /** Redirect URI after authentication (defaults to window.location.origin) */
64
+ redirectUri?: string;
65
+ /** Scopes to request (defaults to 'openid profile email') */
66
+ scope?: string;
67
+ /** API audience for access token */
68
+ audience?: string;
69
+ /** Where to store tokens: 'memory' or 'localstorage' */
70
+ cacheLocation?: 'memory' | 'localstorage';
71
+ /** Use refresh tokens for silent renewal */
72
+ useRefreshTokens?: boolean;
73
+ /** Callback after redirect from login */
74
+ onRedirectCallback?: (appState?: Record<string, unknown>) => void;
75
+ /** Children components */
76
+ children: React.ReactNode;
77
+ }
78
+
79
+ /**
80
+ * TransactionalAuthProvider Component
81
+ *
82
+ * Provides authentication context to your React application.
83
+ *
84
+ * @example
85
+ * ```tsx
86
+ * import { TransactionalAuthProvider } from 'transactional-auth-react';
87
+ *
88
+ * function App() {
89
+ * return (
90
+ * <TransactionalAuthProvider
91
+ * domain="auth.usetransactional.com"
92
+ * clientId="your-client-id"
93
+ * redirectUri={window.location.origin}
94
+ * >
95
+ * <YourApp />
96
+ * </TransactionalAuthProvider>
97
+ * );
98
+ * }
99
+ * ```
100
+ */
101
+ declare function TransactionalAuthProvider({ domain, clientId, redirectUri, scope, audience, cacheLocation, useRefreshTokens, onRedirectCallback, children, }: TransactionalAuthProviderProps): react_jsx_runtime.JSX.Element;
102
+
103
+ declare const TransactionalAuthContext: React$1.Context<TransactionalAuthContextValue>;
104
+
105
+ /**
106
+ * Transactional Auth React - useAuth Hook
107
+ */
108
+
109
+ /**
110
+ * Hook to access authentication state and methods.
111
+ *
112
+ * @example
113
+ * ```tsx
114
+ * import { useAuth } from 'transactional-auth-react';
115
+ *
116
+ * function LoginButton() {
117
+ * const { isAuthenticated, loginWithRedirect, logout, user } = useAuth();
118
+ *
119
+ * if (isAuthenticated) {
120
+ * return (
121
+ * <div>
122
+ * <span>Welcome, {user?.name}</span>
123
+ * <button onClick={() => logout()}>Logout</button>
124
+ * </div>
125
+ * );
126
+ * }
127
+ *
128
+ * return <button onClick={() => loginWithRedirect()}>Login</button>;
129
+ * }
130
+ * ```
131
+ */
132
+ declare function useAuth(): TransactionalAuthContextValue;
133
+
134
+ /**
135
+ * Transactional Auth React - useUser Hook
136
+ */
137
+
138
+ interface UseUserResult {
139
+ user: TransactionalAuthUser | null;
140
+ isLoading: boolean;
141
+ }
142
+ /**
143
+ * Hook to access the current authenticated user.
144
+ *
145
+ * @example
146
+ * ```tsx
147
+ * import { useUser } from 'transactional-auth-react';
148
+ *
149
+ * function Profile() {
150
+ * const { user, isLoading } = useUser();
151
+ *
152
+ * if (isLoading) return <div>Loading...</div>;
153
+ * if (!user) return <div>Not logged in</div>;
154
+ *
155
+ * return (
156
+ * <div>
157
+ * <img src={user.picture} alt={user.name} />
158
+ * <h1>{user.name}</h1>
159
+ * <p>{user.email}</p>
160
+ * </div>
161
+ * );
162
+ * }
163
+ * ```
164
+ */
165
+ declare function useUser(): UseUserResult;
166
+
167
+ /**
168
+ * Transactional Auth React - useAccessToken Hook
169
+ */
170
+ /**
171
+ * Hook to get the current access token.
172
+ *
173
+ * @example
174
+ * ```tsx
175
+ * import { useAccessToken } from 'transactional-auth-react';
176
+ *
177
+ * function ApiComponent() {
178
+ * const accessToken = useAccessToken();
179
+ *
180
+ * useEffect(() => {
181
+ * if (accessToken) {
182
+ * fetch('/api/data', {
183
+ * headers: { Authorization: `Bearer ${accessToken}` }
184
+ * });
185
+ * }
186
+ * }, [accessToken]);
187
+ *
188
+ * return <div>...</div>;
189
+ * }
190
+ * ```
191
+ */
192
+ declare function useAccessToken(): string | null;
193
+
194
+ interface AuthGuardProps {
195
+ /** Content to show while authenticated */
196
+ children: React$1.ReactNode;
197
+ /** Content to show while loading */
198
+ fallback?: React$1.ReactNode;
199
+ /** Callback when user is not authenticated */
200
+ onUnauthenticated?: () => void;
201
+ /** Whether to automatically redirect to login */
202
+ autoRedirect?: boolean;
203
+ }
204
+ /**
205
+ * Component that guards content for authenticated users only.
206
+ *
207
+ * @example
208
+ * ```tsx
209
+ * import { AuthGuard } from 'transactional-auth-react';
210
+ *
211
+ * function ProtectedPage() {
212
+ * return (
213
+ * <AuthGuard fallback={<div>Loading...</div>}>
214
+ * <div>Protected content</div>
215
+ * </AuthGuard>
216
+ * );
217
+ * }
218
+ * ```
219
+ */
220
+ declare function AuthGuard({ children, fallback, onUnauthenticated, autoRedirect, }: AuthGuardProps): react_jsx_runtime.JSX.Element | null;
221
+
222
+ /**
223
+ * Transactional Auth React - withAuthenticationRequired HOC
224
+ */
225
+
226
+ interface WithAuthenticationRequiredOptions {
227
+ /** Content to show while loading */
228
+ fallback?: React$1.ReactNode;
229
+ /** Callback when user is not authenticated */
230
+ onUnauthenticated?: () => void;
231
+ /** Return URL after login */
232
+ returnTo?: string;
233
+ }
234
+ /**
235
+ * Higher-order component that wraps a component to require authentication.
236
+ *
237
+ * @example
238
+ * ```tsx
239
+ * import { withAuthenticationRequired } from 'transactional-auth-react';
240
+ *
241
+ * function Dashboard() {
242
+ * return <div>Dashboard content</div>;
243
+ * }
244
+ *
245
+ * export default withAuthenticationRequired(Dashboard, {
246
+ * fallback: <div>Loading...</div>,
247
+ * });
248
+ * ```
249
+ */
250
+ declare function withAuthenticationRequired<P extends object>(Component: React$1.ComponentType<P>, options?: WithAuthenticationRequiredOptions): React$1.ComponentType<P>;
251
+
252
+ export { AuthGuard, type LoginOptions, type LogoutOptions, TransactionalAuthContext, type TransactionalAuthContextValue, TransactionalAuthProvider, type TransactionalAuthProviderProps, type TransactionalAuthState, type TransactionalAuthUser, useAccessToken, useAuth, useUser, withAuthenticationRequired };
package/dist/index.js ADDED
@@ -0,0 +1,333 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ AuthGuard: () => AuthGuard,
34
+ TransactionalAuthContext: () => TransactionalAuthContext,
35
+ TransactionalAuthProvider: () => TransactionalAuthProvider,
36
+ useAccessToken: () => useAccessToken,
37
+ useAuth: () => useAuth,
38
+ useUser: () => useUser,
39
+ withAuthenticationRequired: () => withAuthenticationRequired
40
+ });
41
+ module.exports = __toCommonJS(index_exports);
42
+
43
+ // src/TransactionalAuthProvider.tsx
44
+ var React = __toESM(require("react"));
45
+ var import_oidc_client_ts = require("oidc-client-ts");
46
+
47
+ // src/context.ts
48
+ var import_react = require("react");
49
+ var defaultContext = {
50
+ isAuthenticated: false,
51
+ isLoading: true,
52
+ user: null,
53
+ error: null,
54
+ loginWithRedirect: async () => {
55
+ throw new Error("TransactionalAuthProvider not found");
56
+ },
57
+ loginWithPopup: async () => {
58
+ throw new Error("TransactionalAuthProvider not found");
59
+ },
60
+ logout: async () => {
61
+ throw new Error("TransactionalAuthProvider not found");
62
+ },
63
+ getAccessToken: async () => {
64
+ throw new Error("TransactionalAuthProvider not found");
65
+ },
66
+ getIdTokenClaims: async () => {
67
+ throw new Error("TransactionalAuthProvider not found");
68
+ },
69
+ hasPermission: () => false,
70
+ hasRole: () => false
71
+ };
72
+ var TransactionalAuthContext = (0, import_react.createContext)(defaultContext);
73
+
74
+ // src/TransactionalAuthProvider.tsx
75
+ var import_jsx_runtime = require("react/jsx-runtime");
76
+ function mapUser(user) {
77
+ return {
78
+ sub: user.profile.sub,
79
+ email: user.profile.email,
80
+ emailVerified: user.profile.email_verified,
81
+ name: user.profile.name,
82
+ givenName: user.profile.given_name,
83
+ familyName: user.profile.family_name,
84
+ picture: user.profile.picture,
85
+ phoneNumber: user.profile.phone_number,
86
+ phoneNumberVerified: user.profile.phone_number_verified
87
+ };
88
+ }
89
+ function TransactionalAuthProvider({
90
+ domain,
91
+ clientId,
92
+ redirectUri,
93
+ scope = "openid profile email",
94
+ audience,
95
+ cacheLocation = "localstorage",
96
+ useRefreshTokens = true,
97
+ onRedirectCallback,
98
+ children
99
+ }) {
100
+ const [state, setState] = React.useState({
101
+ isAuthenticated: false,
102
+ isLoading: true,
103
+ user: null,
104
+ error: null
105
+ });
106
+ const userManagerRef = React.useRef(null);
107
+ const [permissions, setPermissions] = React.useState([]);
108
+ const [roles, setRoles] = React.useState([]);
109
+ React.useEffect(() => {
110
+ const effectiveRedirectUri = redirectUri || (typeof window !== "undefined" ? window.location.origin : "");
111
+ const effectiveScope = useRefreshTokens ? `${scope} offline_access` : scope;
112
+ const manager = new import_oidc_client_ts.UserManager({
113
+ authority: `https://${domain}`,
114
+ client_id: clientId,
115
+ redirect_uri: effectiveRedirectUri,
116
+ post_logout_redirect_uri: effectiveRedirectUri,
117
+ scope: effectiveScope,
118
+ response_type: "code",
119
+ automaticSilentRenew: useRefreshTokens,
120
+ userStore: typeof window !== "undefined" ? cacheLocation === "localstorage" ? new import_oidc_client_ts.WebStorageStateStore({ store: window.localStorage }) : new import_oidc_client_ts.WebStorageStateStore({ store: window.sessionStorage }) : void 0,
121
+ extraQueryParams: audience ? { audience } : void 0
122
+ });
123
+ userManagerRef.current = manager;
124
+ manager.getUser().then((user) => {
125
+ if (user && !user.expired) {
126
+ setState({
127
+ isAuthenticated: true,
128
+ isLoading: false,
129
+ user: mapUser(user),
130
+ error: null
131
+ });
132
+ const accessToken = user.access_token;
133
+ if (accessToken) {
134
+ try {
135
+ const payload = JSON.parse(atob(accessToken.split(".")[1]));
136
+ setRoles(payload.roles || []);
137
+ setPermissions(payload.permissions || []);
138
+ } catch {
139
+ }
140
+ }
141
+ } else {
142
+ setState((s) => ({ ...s, isLoading: false }));
143
+ }
144
+ }).catch((error) => {
145
+ setState((s) => ({ ...s, isLoading: false, error }));
146
+ });
147
+ if (typeof window !== "undefined") {
148
+ const params = new URLSearchParams(window.location.search);
149
+ if (params.has("code") || params.has("error")) {
150
+ manager.signinRedirectCallback().then((user) => {
151
+ setState({
152
+ isAuthenticated: true,
153
+ isLoading: false,
154
+ user: mapUser(user),
155
+ error: null
156
+ });
157
+ onRedirectCallback?.(user.state);
158
+ window.history.replaceState({}, "", window.location.pathname);
159
+ }).catch((error) => {
160
+ setState((s) => ({ ...s, isLoading: false, error }));
161
+ });
162
+ }
163
+ }
164
+ const handleUserLoaded = (user) => {
165
+ setState({
166
+ isAuthenticated: true,
167
+ isLoading: false,
168
+ user: mapUser(user),
169
+ error: null
170
+ });
171
+ };
172
+ const handleUserUnloaded = () => {
173
+ setState({
174
+ isAuthenticated: false,
175
+ isLoading: false,
176
+ user: null,
177
+ error: null
178
+ });
179
+ setRoles([]);
180
+ setPermissions([]);
181
+ };
182
+ const handleSilentRenewError = (error) => {
183
+ console.error("Silent renew error:", error);
184
+ };
185
+ manager.events.addUserLoaded(handleUserLoaded);
186
+ manager.events.addUserUnloaded(handleUserUnloaded);
187
+ manager.events.addSilentRenewError(handleSilentRenewError);
188
+ return () => {
189
+ manager.events.removeUserLoaded(handleUserLoaded);
190
+ manager.events.removeUserUnloaded(handleUserUnloaded);
191
+ manager.events.removeSilentRenewError(handleSilentRenewError);
192
+ };
193
+ }, [domain, clientId, redirectUri, scope, audience, cacheLocation, useRefreshTokens, onRedirectCallback]);
194
+ const contextValue = React.useMemo(
195
+ () => ({
196
+ ...state,
197
+ loginWithRedirect: async (options) => {
198
+ await userManagerRef.current?.signinRedirect({
199
+ state: options?.appState,
200
+ extraQueryParams: {
201
+ ...options?.connection ? { connection: options.connection } : {},
202
+ ...options?.loginHint ? { login_hint: options.loginHint } : {},
203
+ ...options?.uiLocales ? { ui_locales: options.uiLocales } : {}
204
+ },
205
+ redirect_uri: options?.returnTo
206
+ });
207
+ },
208
+ loginWithPopup: async (options) => {
209
+ const user = await userManagerRef.current?.signinPopup({
210
+ extraQueryParams: {
211
+ ...options?.connection ? { connection: options.connection } : {},
212
+ ...options?.loginHint ? { login_hint: options.loginHint } : {}
213
+ }
214
+ });
215
+ if (user) {
216
+ setState({
217
+ isAuthenticated: true,
218
+ isLoading: false,
219
+ user: mapUser(user),
220
+ error: null
221
+ });
222
+ }
223
+ },
224
+ logout: async (options) => {
225
+ await userManagerRef.current?.signoutRedirect({
226
+ post_logout_redirect_uri: options?.returnTo
227
+ });
228
+ },
229
+ getAccessToken: async () => {
230
+ const user = await userManagerRef.current?.getUser();
231
+ return user?.access_token;
232
+ },
233
+ getIdTokenClaims: async () => {
234
+ const user = await userManagerRef.current?.getUser();
235
+ return user?.profile;
236
+ },
237
+ hasPermission: (permission) => {
238
+ return permissions.includes(permission);
239
+ },
240
+ hasRole: (role) => {
241
+ return roles.includes(role);
242
+ }
243
+ }),
244
+ [state, permissions, roles]
245
+ );
246
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TransactionalAuthContext.Provider, { value: contextValue, children });
247
+ }
248
+
249
+ // src/hooks/useAuth.ts
250
+ var import_react2 = require("react");
251
+ function useAuth() {
252
+ const context = (0, import_react2.useContext)(TransactionalAuthContext);
253
+ if (!context) {
254
+ throw new Error("useAuth must be used within a TransactionalAuthProvider");
255
+ }
256
+ return context;
257
+ }
258
+
259
+ // src/hooks/useUser.ts
260
+ function useUser() {
261
+ const { user, isLoading } = useAuth();
262
+ return { user, isLoading };
263
+ }
264
+
265
+ // src/hooks/useAccessToken.ts
266
+ var import_react3 = require("react");
267
+ function useAccessToken() {
268
+ const { getAccessToken, isAuthenticated } = useAuth();
269
+ const [token, setToken] = (0, import_react3.useState)(null);
270
+ (0, import_react3.useEffect)(() => {
271
+ if (isAuthenticated) {
272
+ getAccessToken().then((t) => setToken(t || null));
273
+ } else {
274
+ setToken(null);
275
+ }
276
+ }, [getAccessToken, isAuthenticated]);
277
+ return token;
278
+ }
279
+
280
+ // src/components/AuthGuard.tsx
281
+ var React2 = __toESM(require("react"));
282
+ var import_jsx_runtime2 = require("react/jsx-runtime");
283
+ function AuthGuard({
284
+ children,
285
+ fallback,
286
+ onUnauthenticated,
287
+ autoRedirect = true
288
+ }) {
289
+ const { isAuthenticated, isLoading, loginWithRedirect } = useAuth();
290
+ React2.useEffect(() => {
291
+ if (!isLoading && !isAuthenticated) {
292
+ if (onUnauthenticated) {
293
+ onUnauthenticated();
294
+ } else if (autoRedirect && typeof window !== "undefined") {
295
+ loginWithRedirect({ returnTo: window.location.pathname });
296
+ }
297
+ }
298
+ }, [isLoading, isAuthenticated, onUnauthenticated, autoRedirect, loginWithRedirect]);
299
+ if (isLoading) {
300
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback ?? null });
301
+ }
302
+ if (!isAuthenticated) {
303
+ return null;
304
+ }
305
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
306
+ }
307
+
308
+ // src/components/withAuthenticationRequired.tsx
309
+ var import_jsx_runtime3 = require("react/jsx-runtime");
310
+ function withAuthenticationRequired(Component, options) {
311
+ const WrappedComponent = function WithAuthenticationRequired(props) {
312
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
313
+ AuthGuard,
314
+ {
315
+ fallback: options?.fallback,
316
+ onUnauthenticated: options?.onUnauthenticated,
317
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Component, { ...props })
318
+ }
319
+ );
320
+ };
321
+ WrappedComponent.displayName = `withAuthenticationRequired(${Component.displayName || Component.name || "Component"})`;
322
+ return WrappedComponent;
323
+ }
324
+ // Annotate the CommonJS export names for ESM import in node:
325
+ 0 && (module.exports = {
326
+ AuthGuard,
327
+ TransactionalAuthContext,
328
+ TransactionalAuthProvider,
329
+ useAccessToken,
330
+ useAuth,
331
+ useUser,
332
+ withAuthenticationRequired
333
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,290 @@
1
+ // src/TransactionalAuthProvider.tsx
2
+ import * as React from "react";
3
+ import { UserManager, WebStorageStateStore } from "oidc-client-ts";
4
+
5
+ // src/context.ts
6
+ import { createContext } from "react";
7
+ var defaultContext = {
8
+ isAuthenticated: false,
9
+ isLoading: true,
10
+ user: null,
11
+ error: null,
12
+ loginWithRedirect: async () => {
13
+ throw new Error("TransactionalAuthProvider not found");
14
+ },
15
+ loginWithPopup: async () => {
16
+ throw new Error("TransactionalAuthProvider not found");
17
+ },
18
+ logout: async () => {
19
+ throw new Error("TransactionalAuthProvider not found");
20
+ },
21
+ getAccessToken: async () => {
22
+ throw new Error("TransactionalAuthProvider not found");
23
+ },
24
+ getIdTokenClaims: async () => {
25
+ throw new Error("TransactionalAuthProvider not found");
26
+ },
27
+ hasPermission: () => false,
28
+ hasRole: () => false
29
+ };
30
+ var TransactionalAuthContext = createContext(defaultContext);
31
+
32
+ // src/TransactionalAuthProvider.tsx
33
+ import { jsx } from "react/jsx-runtime";
34
+ function mapUser(user) {
35
+ return {
36
+ sub: user.profile.sub,
37
+ email: user.profile.email,
38
+ emailVerified: user.profile.email_verified,
39
+ name: user.profile.name,
40
+ givenName: user.profile.given_name,
41
+ familyName: user.profile.family_name,
42
+ picture: user.profile.picture,
43
+ phoneNumber: user.profile.phone_number,
44
+ phoneNumberVerified: user.profile.phone_number_verified
45
+ };
46
+ }
47
+ function TransactionalAuthProvider({
48
+ domain,
49
+ clientId,
50
+ redirectUri,
51
+ scope = "openid profile email",
52
+ audience,
53
+ cacheLocation = "localstorage",
54
+ useRefreshTokens = true,
55
+ onRedirectCallback,
56
+ children
57
+ }) {
58
+ const [state, setState] = React.useState({
59
+ isAuthenticated: false,
60
+ isLoading: true,
61
+ user: null,
62
+ error: null
63
+ });
64
+ const userManagerRef = React.useRef(null);
65
+ const [permissions, setPermissions] = React.useState([]);
66
+ const [roles, setRoles] = React.useState([]);
67
+ React.useEffect(() => {
68
+ const effectiveRedirectUri = redirectUri || (typeof window !== "undefined" ? window.location.origin : "");
69
+ const effectiveScope = useRefreshTokens ? `${scope} offline_access` : scope;
70
+ const manager = new UserManager({
71
+ authority: `https://${domain}`,
72
+ client_id: clientId,
73
+ redirect_uri: effectiveRedirectUri,
74
+ post_logout_redirect_uri: effectiveRedirectUri,
75
+ scope: effectiveScope,
76
+ response_type: "code",
77
+ automaticSilentRenew: useRefreshTokens,
78
+ userStore: typeof window !== "undefined" ? cacheLocation === "localstorage" ? new WebStorageStateStore({ store: window.localStorage }) : new WebStorageStateStore({ store: window.sessionStorage }) : void 0,
79
+ extraQueryParams: audience ? { audience } : void 0
80
+ });
81
+ userManagerRef.current = manager;
82
+ manager.getUser().then((user) => {
83
+ if (user && !user.expired) {
84
+ setState({
85
+ isAuthenticated: true,
86
+ isLoading: false,
87
+ user: mapUser(user),
88
+ error: null
89
+ });
90
+ const accessToken = user.access_token;
91
+ if (accessToken) {
92
+ try {
93
+ const payload = JSON.parse(atob(accessToken.split(".")[1]));
94
+ setRoles(payload.roles || []);
95
+ setPermissions(payload.permissions || []);
96
+ } catch {
97
+ }
98
+ }
99
+ } else {
100
+ setState((s) => ({ ...s, isLoading: false }));
101
+ }
102
+ }).catch((error) => {
103
+ setState((s) => ({ ...s, isLoading: false, error }));
104
+ });
105
+ if (typeof window !== "undefined") {
106
+ const params = new URLSearchParams(window.location.search);
107
+ if (params.has("code") || params.has("error")) {
108
+ manager.signinRedirectCallback().then((user) => {
109
+ setState({
110
+ isAuthenticated: true,
111
+ isLoading: false,
112
+ user: mapUser(user),
113
+ error: null
114
+ });
115
+ onRedirectCallback?.(user.state);
116
+ window.history.replaceState({}, "", window.location.pathname);
117
+ }).catch((error) => {
118
+ setState((s) => ({ ...s, isLoading: false, error }));
119
+ });
120
+ }
121
+ }
122
+ const handleUserLoaded = (user) => {
123
+ setState({
124
+ isAuthenticated: true,
125
+ isLoading: false,
126
+ user: mapUser(user),
127
+ error: null
128
+ });
129
+ };
130
+ const handleUserUnloaded = () => {
131
+ setState({
132
+ isAuthenticated: false,
133
+ isLoading: false,
134
+ user: null,
135
+ error: null
136
+ });
137
+ setRoles([]);
138
+ setPermissions([]);
139
+ };
140
+ const handleSilentRenewError = (error) => {
141
+ console.error("Silent renew error:", error);
142
+ };
143
+ manager.events.addUserLoaded(handleUserLoaded);
144
+ manager.events.addUserUnloaded(handleUserUnloaded);
145
+ manager.events.addSilentRenewError(handleSilentRenewError);
146
+ return () => {
147
+ manager.events.removeUserLoaded(handleUserLoaded);
148
+ manager.events.removeUserUnloaded(handleUserUnloaded);
149
+ manager.events.removeSilentRenewError(handleSilentRenewError);
150
+ };
151
+ }, [domain, clientId, redirectUri, scope, audience, cacheLocation, useRefreshTokens, onRedirectCallback]);
152
+ const contextValue = React.useMemo(
153
+ () => ({
154
+ ...state,
155
+ loginWithRedirect: async (options) => {
156
+ await userManagerRef.current?.signinRedirect({
157
+ state: options?.appState,
158
+ extraQueryParams: {
159
+ ...options?.connection ? { connection: options.connection } : {},
160
+ ...options?.loginHint ? { login_hint: options.loginHint } : {},
161
+ ...options?.uiLocales ? { ui_locales: options.uiLocales } : {}
162
+ },
163
+ redirect_uri: options?.returnTo
164
+ });
165
+ },
166
+ loginWithPopup: async (options) => {
167
+ const user = await userManagerRef.current?.signinPopup({
168
+ extraQueryParams: {
169
+ ...options?.connection ? { connection: options.connection } : {},
170
+ ...options?.loginHint ? { login_hint: options.loginHint } : {}
171
+ }
172
+ });
173
+ if (user) {
174
+ setState({
175
+ isAuthenticated: true,
176
+ isLoading: false,
177
+ user: mapUser(user),
178
+ error: null
179
+ });
180
+ }
181
+ },
182
+ logout: async (options) => {
183
+ await userManagerRef.current?.signoutRedirect({
184
+ post_logout_redirect_uri: options?.returnTo
185
+ });
186
+ },
187
+ getAccessToken: async () => {
188
+ const user = await userManagerRef.current?.getUser();
189
+ return user?.access_token;
190
+ },
191
+ getIdTokenClaims: async () => {
192
+ const user = await userManagerRef.current?.getUser();
193
+ return user?.profile;
194
+ },
195
+ hasPermission: (permission) => {
196
+ return permissions.includes(permission);
197
+ },
198
+ hasRole: (role) => {
199
+ return roles.includes(role);
200
+ }
201
+ }),
202
+ [state, permissions, roles]
203
+ );
204
+ return /* @__PURE__ */ jsx(TransactionalAuthContext.Provider, { value: contextValue, children });
205
+ }
206
+
207
+ // src/hooks/useAuth.ts
208
+ import { useContext } from "react";
209
+ function useAuth() {
210
+ const context = useContext(TransactionalAuthContext);
211
+ if (!context) {
212
+ throw new Error("useAuth must be used within a TransactionalAuthProvider");
213
+ }
214
+ return context;
215
+ }
216
+
217
+ // src/hooks/useUser.ts
218
+ function useUser() {
219
+ const { user, isLoading } = useAuth();
220
+ return { user, isLoading };
221
+ }
222
+
223
+ // src/hooks/useAccessToken.ts
224
+ import { useState as useState2, useEffect as useEffect2 } from "react";
225
+ function useAccessToken() {
226
+ const { getAccessToken, isAuthenticated } = useAuth();
227
+ const [token, setToken] = useState2(null);
228
+ useEffect2(() => {
229
+ if (isAuthenticated) {
230
+ getAccessToken().then((t) => setToken(t || null));
231
+ } else {
232
+ setToken(null);
233
+ }
234
+ }, [getAccessToken, isAuthenticated]);
235
+ return token;
236
+ }
237
+
238
+ // src/components/AuthGuard.tsx
239
+ import * as React2 from "react";
240
+ import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
241
+ function AuthGuard({
242
+ children,
243
+ fallback,
244
+ onUnauthenticated,
245
+ autoRedirect = true
246
+ }) {
247
+ const { isAuthenticated, isLoading, loginWithRedirect } = useAuth();
248
+ React2.useEffect(() => {
249
+ if (!isLoading && !isAuthenticated) {
250
+ if (onUnauthenticated) {
251
+ onUnauthenticated();
252
+ } else if (autoRedirect && typeof window !== "undefined") {
253
+ loginWithRedirect({ returnTo: window.location.pathname });
254
+ }
255
+ }
256
+ }, [isLoading, isAuthenticated, onUnauthenticated, autoRedirect, loginWithRedirect]);
257
+ if (isLoading) {
258
+ return /* @__PURE__ */ jsx2(Fragment, { children: fallback ?? null });
259
+ }
260
+ if (!isAuthenticated) {
261
+ return null;
262
+ }
263
+ return /* @__PURE__ */ jsx2(Fragment, { children });
264
+ }
265
+
266
+ // src/components/withAuthenticationRequired.tsx
267
+ import { jsx as jsx3 } from "react/jsx-runtime";
268
+ function withAuthenticationRequired(Component, options) {
269
+ const WrappedComponent = function WithAuthenticationRequired(props) {
270
+ return /* @__PURE__ */ jsx3(
271
+ AuthGuard,
272
+ {
273
+ fallback: options?.fallback,
274
+ onUnauthenticated: options?.onUnauthenticated,
275
+ children: /* @__PURE__ */ jsx3(Component, { ...props })
276
+ }
277
+ );
278
+ };
279
+ WrappedComponent.displayName = `withAuthenticationRequired(${Component.displayName || Component.name || "Component"})`;
280
+ return WrappedComponent;
281
+ }
282
+ export {
283
+ AuthGuard,
284
+ TransactionalAuthContext,
285
+ TransactionalAuthProvider,
286
+ useAccessToken,
287
+ useAuth,
288
+ useUser,
289
+ withAuthenticationRequired
290
+ };
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "transactional-auth-react",
3
+ "version": "0.1.0",
4
+ "description": "React SDK for Transactional Auth - OpenID Connect authentication for React applications",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.mjs",
11
+ "require": "./dist/index.js",
12
+ "types": "./dist/index.d.ts"
13
+ }
14
+ },
15
+ "sideEffects": false,
16
+ "files": [
17
+ "dist",
18
+ "README.md"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
22
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
23
+ "typecheck": "tsc --noEmit",
24
+ "lint": "eslint src --ext .ts,.tsx",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "keywords": [
28
+ "react",
29
+ "auth",
30
+ "authentication",
31
+ "oidc",
32
+ "openid-connect",
33
+ "oauth2",
34
+ "transactional"
35
+ ],
36
+ "author": "Transactional",
37
+ "license": "MIT",
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "https://github.com/TransactionalHQ/transactional-auth-react"
41
+ },
42
+ "homepage": "https://github.com/TransactionalHQ/transactional-auth-react#readme",
43
+ "bugs": {
44
+ "url": "https://github.com/TransactionalHQ/transactional-auth-react/issues"
45
+ },
46
+ "peerDependencies": {
47
+ "react": "^18.0.0 || ^19.0.0"
48
+ },
49
+ "dependencies": {
50
+ "oidc-client-ts": "^3.0.1"
51
+ },
52
+ "devDependencies": {
53
+ "@types/react": "^18.2.0",
54
+ "react": "^18.2.0",
55
+ "tsup": "^8.0.0",
56
+ "typescript": "^5.5.0"
57
+ }
58
+ }