@civic/auth 0.7.0-beta.1 → 0.7.1-beta.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.
Files changed (163) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +19 -1
  3. package/dist/nextjs/config.d.ts +1 -0
  4. package/dist/nextjs/config.d.ts.map +1 -1
  5. package/dist/nextjs/config.js +2 -4
  6. package/dist/nextjs/config.js.map +1 -1
  7. package/dist/nextjs/hooks/useRefresh.d.ts.map +1 -1
  8. package/dist/nextjs/hooks/useRefresh.js +7 -1
  9. package/dist/nextjs/hooks/useRefresh.js.map +1 -1
  10. package/dist/nextjs/hooks/useUserCookie.d.ts.map +1 -1
  11. package/dist/nextjs/hooks/useUserCookie.js.map +1 -1
  12. package/dist/nextjs/providers/NextAuthProvider.d.ts.map +1 -1
  13. package/dist/nextjs/providers/NextAuthProvider.js +4 -3
  14. package/dist/nextjs/providers/NextAuthProvider.js.map +1 -1
  15. package/dist/nextjs/routeHandler.d.ts.map +1 -1
  16. package/dist/nextjs/routeHandler.js +7 -0
  17. package/dist/nextjs/routeHandler.js.map +1 -1
  18. package/dist/reactjs/components/SignInButton.d.ts.map +1 -1
  19. package/dist/reactjs/components/SignInButton.js +8 -3
  20. package/dist/reactjs/components/SignInButton.js.map +1 -1
  21. package/dist/reactjs/components/SignOutButton.d.ts.map +1 -1
  22. package/dist/reactjs/components/SignOutButton.js +3 -1
  23. package/dist/reactjs/components/SignOutButton.js.map +1 -1
  24. package/dist/reactjs/components/UserButton.d.ts.map +1 -1
  25. package/dist/reactjs/components/UserButton.js +11 -6
  26. package/dist/reactjs/components/UserButton.js.map +1 -1
  27. package/dist/reactjs/components/index.d.ts +5 -5
  28. package/dist/reactjs/components/index.d.ts.map +1 -1
  29. package/dist/reactjs/components/index.js +5 -5
  30. package/dist/reactjs/components/index.js.map +1 -1
  31. package/dist/reactjs/core/GlobalAuthManager.d.ts +120 -0
  32. package/dist/reactjs/core/GlobalAuthManager.d.ts.map +1 -0
  33. package/dist/reactjs/core/GlobalAuthManager.js +296 -0
  34. package/dist/reactjs/core/GlobalAuthManager.js.map +1 -0
  35. package/dist/reactjs/hooks/index.d.ts +2 -2
  36. package/dist/reactjs/hooks/index.d.ts.map +1 -1
  37. package/dist/reactjs/hooks/index.js +2 -2
  38. package/dist/reactjs/hooks/index.js.map +1 -1
  39. package/dist/reactjs/hooks/useToken.d.ts +13 -0
  40. package/dist/reactjs/hooks/useToken.d.ts.map +1 -0
  41. package/dist/reactjs/hooks/useToken.js +48 -0
  42. package/dist/reactjs/hooks/useToken.js.map +1 -0
  43. package/dist/reactjs/hooks/useUser.d.ts +20 -2
  44. package/dist/reactjs/hooks/useUser.d.ts.map +1 -1
  45. package/dist/reactjs/hooks/useUser.js +163 -7
  46. package/dist/reactjs/hooks/useUser.js.map +1 -1
  47. package/dist/reactjs/index.d.ts +6 -2
  48. package/dist/reactjs/index.d.ts.map +1 -1
  49. package/dist/reactjs/index.js +7 -1
  50. package/dist/reactjs/index.js.map +1 -1
  51. package/dist/reactjs/providers/CivicAuthContext.d.ts +40 -0
  52. package/dist/reactjs/providers/CivicAuthContext.d.ts.map +1 -0
  53. package/dist/reactjs/providers/CivicAuthContext.js +303 -0
  54. package/dist/reactjs/providers/CivicAuthContext.js.map +1 -0
  55. package/dist/reactjs/providers/CivicAuthProvider.d.ts +20 -4
  56. package/dist/reactjs/providers/CivicAuthProvider.d.ts.map +1 -1
  57. package/dist/reactjs/providers/CivicAuthProvider.js +46 -24
  58. package/dist/reactjs/providers/CivicAuthProvider.js.map +1 -1
  59. package/dist/reactjs/providers/index.d.ts +2 -2
  60. package/dist/reactjs/providers/index.d.ts.map +1 -1
  61. package/dist/reactjs/providers/index.js +4 -2
  62. package/dist/reactjs/providers/index.js.map +1 -1
  63. package/dist/server/ServerAuthenticationResolver.d.ts.map +1 -1
  64. package/dist/server/ServerAuthenticationResolver.js +28 -11
  65. package/dist/server/ServerAuthenticationResolver.js.map +1 -1
  66. package/dist/server/config.d.ts +2 -0
  67. package/dist/server/config.d.ts.map +1 -1
  68. package/dist/server/config.js.map +1 -1
  69. package/dist/server/login.d.ts +2 -2
  70. package/dist/server/login.d.ts.map +1 -1
  71. package/dist/server/login.js +7 -2
  72. package/dist/server/login.js.map +1 -1
  73. package/dist/services/AuthenticationService.d.ts +1 -1
  74. package/dist/services/AuthenticationService.d.ts.map +1 -1
  75. package/dist/services/AuthenticationService.js +2 -2
  76. package/dist/services/AuthenticationService.js.map +1 -1
  77. package/dist/shared/components/CivicAuthIframe.js +1 -1
  78. package/dist/shared/components/CivicAuthIframe.js.map +1 -1
  79. package/dist/shared/components/CivicAuthIframeContainer.js +2 -2
  80. package/dist/shared/components/CivicAuthIframeContainer.js.map +1 -1
  81. package/dist/shared/hooks/index.d.ts +1 -2
  82. package/dist/shared/hooks/index.d.ts.map +1 -1
  83. package/dist/shared/hooks/index.js +1 -2
  84. package/dist/shared/hooks/index.js.map +1 -1
  85. package/dist/shared/hooks/useClientTokenExchangeSession.d.ts +7 -0
  86. package/dist/shared/hooks/useClientTokenExchangeSession.d.ts.map +1 -0
  87. package/dist/shared/hooks/useClientTokenExchangeSession.js +17 -0
  88. package/dist/shared/hooks/useClientTokenExchangeSession.js.map +1 -0
  89. package/dist/shared/hooks/useSignIn.d.ts +4 -9
  90. package/dist/shared/hooks/useSignIn.d.ts.map +1 -1
  91. package/dist/shared/hooks/useSignIn.js +42 -75
  92. package/dist/shared/hooks/useSignIn.js.map +1 -1
  93. package/dist/shared/lib/BrowserAuthenticationRefresher.js +3 -3
  94. package/dist/shared/lib/BrowserAuthenticationRefresher.js.map +1 -1
  95. package/dist/shared/lib/types.d.ts +1 -1
  96. package/dist/shared/lib/types.js +1 -1
  97. package/dist/shared/lib/types.js.map +1 -1
  98. package/dist/shared/lib/util.d.ts +5 -6
  99. package/dist/shared/lib/util.d.ts.map +1 -1
  100. package/dist/shared/lib/util.js +66 -75
  101. package/dist/shared/lib/util.js.map +1 -1
  102. package/dist/shared/providers/AuthContext.d.ts +2 -7
  103. package/dist/shared/providers/AuthContext.d.ts.map +1 -1
  104. package/dist/shared/providers/AuthContext.js.map +1 -1
  105. package/dist/shared/providers/CivicAuthConfigContext.d.ts +2 -2
  106. package/dist/shared/providers/CivicAuthConfigContext.d.ts.map +1 -1
  107. package/dist/shared/providers/CivicAuthConfigContext.js +1 -1
  108. package/dist/shared/providers/CivicAuthConfigContext.js.map +1 -1
  109. package/dist/shared/providers/TokenProvider.d.ts.map +1 -1
  110. package/dist/shared/providers/TokenProvider.js +4 -7
  111. package/dist/shared/providers/TokenProvider.js.map +1 -1
  112. package/dist/shared/providers/UserProvider.d.ts +1 -5
  113. package/dist/shared/providers/UserProvider.d.ts.map +1 -1
  114. package/dist/shared/providers/UserProvider.js.map +1 -1
  115. package/dist/shared/version.d.ts +1 -1
  116. package/dist/shared/version.js +1 -1
  117. package/dist/shared/version.js.map +1 -1
  118. package/dist/types.d.ts +2 -2
  119. package/dist/types.js.map +1 -1
  120. package/dist/utils.d.ts +8 -0
  121. package/dist/utils.d.ts.map +1 -1
  122. package/dist/utils.js +23 -0
  123. package/dist/utils.js.map +1 -1
  124. package/dist/vanillajs/auth/CivicAuth.d.ts +12 -0
  125. package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
  126. package/dist/vanillajs/auth/CivicAuth.js +88 -5
  127. package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
  128. package/dist/vanillajs/auth/SessionManager.d.ts +7 -1
  129. package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -1
  130. package/dist/vanillajs/auth/SessionManager.js +34 -3
  131. package/dist/vanillajs/auth/SessionManager.js.map +1 -1
  132. package/dist/vanillajs/auth/TokenRefresher.js +2 -2
  133. package/dist/vanillajs/auth/TokenRefresher.js.map +1 -1
  134. package/dist/vanillajs/auth/config/ConfigProcessor.d.ts.map +1 -1
  135. package/dist/vanillajs/auth/config/ConfigProcessor.js +7 -2
  136. package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -1
  137. package/dist/vanillajs/auth/types/AuthTypes.d.ts +3 -0
  138. package/dist/vanillajs/auth/types/AuthTypes.d.ts.map +1 -1
  139. package/dist/vanillajs/auth/types/AuthTypes.js.map +1 -1
  140. package/dist/vanillajs/index.d.ts +2 -0
  141. package/dist/vanillajs/index.d.ts.map +1 -1
  142. package/dist/vanillajs/index.js +2 -0
  143. package/dist/vanillajs/index.js.map +1 -1
  144. package/dist/vanillajs/types/index.d.ts +1 -1
  145. package/dist/vanillajs/types/index.d.ts.map +1 -1
  146. package/dist/vanillajs/types/index.js.map +1 -1
  147. package/dist/vanillajs/utils/auth-utils.d.ts +14 -0
  148. package/dist/vanillajs/utils/auth-utils.d.ts.map +1 -1
  149. package/dist/vanillajs/utils/auth-utils.js +39 -0
  150. package/dist/vanillajs/utils/auth-utils.js.map +1 -1
  151. package/package.json +1 -1
  152. package/dist/reactjs/hooks/useClientTokenExchangeSession.d.ts +0 -3
  153. package/dist/reactjs/hooks/useClientTokenExchangeSession.d.ts.map +0 -1
  154. package/dist/reactjs/hooks/useClientTokenExchangeSession.js +0 -13
  155. package/dist/reactjs/hooks/useClientTokenExchangeSession.js.map +0 -1
  156. package/dist/reactjs/providers/AuthProvider.d.ts +0 -10
  157. package/dist/reactjs/providers/AuthProvider.d.ts.map +0 -1
  158. package/dist/reactjs/providers/AuthProvider.js +0 -79
  159. package/dist/reactjs/providers/AuthProvider.js.map +0 -1
  160. package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts +0 -17
  161. package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.d.ts.map +0 -1
  162. package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.js +0 -190
  163. package/dist/reactjs/providers/ClientTokenExchangeSessionProvider.js.map +0 -1
@@ -0,0 +1,296 @@
1
+ /**
2
+ * GlobalAuthManager - Singleton Authentication State Manager
3
+ *
4
+ * This module provides a global singleton that manages authentication state across a React application
5
+ * without requiring React Context providers or prop drilling. It acts as a centralized authentication
6
+ * manager that wraps the CivicAuth vanilla JavaScript library and provides a React-friendly interface.
7
+ *
8
+ * Key Features:
9
+ * - Singleton pattern ensures single auth instance across the entire app
10
+ * - Eliminates need for React Context providers and reduces bundle size
11
+ * - Manages authentication state (user, session, loading, errors)
12
+ * - Handles sign-in/sign-out flows with event-driven updates
13
+ * - Provides idempotent initialization (safe to call multiple times)
14
+ * - Supports multiple React hooks subscribing to the same auth state
15
+ * - Automatic session refresh and user data synchronization
16
+ *
17
+ * Usage:
18
+ * - Initialize once in your app with authentication configuration
19
+ * - Use React hooks (useCivicAuth, useAuth, etc.) to access auth state
20
+ * - The manager handles all underlying CivicAuth SDK interactions
21
+ * - State updates are automatically propagated to all subscribed components
22
+ *
23
+ * This design pattern is particularly useful for:
24
+ * - Large applications with many components needing auth state
25
+ * - Avoiding provider wrapper hell in React component trees
26
+ * - Ensuring consistent auth state across disconnected component hierarchies
27
+ * - Server-side rendering scenarios where providers might be problematic
28
+ */
29
+ import { CivicAuth, AuthenticationEvents, AuthEvent, } from "../../vanillajs/index.js";
30
+ /**
31
+ * Global singleton that manages CivicAuth instance for React hooks
32
+ * Eliminates the need for React providers
33
+ */
34
+ class GlobalAuthManager {
35
+ static instance = null;
36
+ auth = null;
37
+ events = null;
38
+ config = null;
39
+ listeners = new Set();
40
+ callbacks = {};
41
+ initializationPromise = null;
42
+ state = {
43
+ user: null,
44
+ session: null,
45
+ isLoading: false,
46
+ authStatus: "unauthenticated",
47
+ error: null,
48
+ displayMode: undefined,
49
+ };
50
+ constructor() {
51
+ // Private constructor for singleton
52
+ }
53
+ static getInstance() {
54
+ if (!GlobalAuthManager.instance) {
55
+ GlobalAuthManager.instance = new GlobalAuthManager();
56
+ }
57
+ return GlobalAuthManager.instance;
58
+ }
59
+ /**
60
+ * Initialize auth with config (idempotent)
61
+ * Returns the same promise for concurrent calls with same config
62
+ */
63
+ async initialize(config) {
64
+ // If we have a promise and same config, return existing promise
65
+ if (this.initializationPromise &&
66
+ this.config &&
67
+ this.isSameConfig(config)) {
68
+ return this.initializationPromise;
69
+ }
70
+ // If different config, reset everything
71
+ if (this.config && !this.isSameConfig(config)) {
72
+ this.initializationPromise = null;
73
+ await this.cleanup();
74
+ }
75
+ // Create new initialization promise if needed
76
+ if (!this.initializationPromise) {
77
+ this.initializationPromise = this._doInitialize(config);
78
+ }
79
+ return this.initializationPromise;
80
+ }
81
+ /**
82
+ * Private method that does the actual initialization work
83
+ */
84
+ async _doInitialize(config) {
85
+ this.config = config;
86
+ this.callbacks = {
87
+ onSignIn: config.onSignIn,
88
+ onSignOut: config.onSignOut,
89
+ };
90
+ this.setState({ isLoading: true, error: null });
91
+ try {
92
+ this.events = new AuthenticationEvents();
93
+ this.setupEventListeners();
94
+ const authConfig = {
95
+ clientId: config.clientId,
96
+ oauthServerBaseUrl: config.config?.oauthServer,
97
+ scopes: config.scopes || [
98
+ "openid",
99
+ "profile",
100
+ "email",
101
+ "offline_access",
102
+ ],
103
+ displayMode: config.displayMode || "iframe",
104
+ iframeDisplayMode: config.iframeMode || "modal",
105
+ nonce: config.nonce,
106
+ authProcessTimeout: config.authProcessTimeout || 120000,
107
+ events: this.events,
108
+ logging: {
109
+ enabled: true,
110
+ level: "debug",
111
+ },
112
+ };
113
+ // Only add redirectUrl if provided
114
+ if (config.redirectUrl) {
115
+ authConfig.redirectUrl = config.redirectUrl;
116
+ }
117
+ // Only add logoutRedirectUrl if provided
118
+ if (config.logoutRedirectUrl) {
119
+ authConfig.logoutRedirectUrl = config.logoutRedirectUrl;
120
+ }
121
+ this.auth = await CivicAuth.create(authConfig);
122
+ // Check initial auth state
123
+ const isAuthenticated = await this.auth.isAuthenticated();
124
+ if (isAuthenticated) {
125
+ await this.refreshUserAndSession();
126
+ this.setState({ authStatus: "authenticated" });
127
+ }
128
+ else {
129
+ this.setState({ authStatus: "unauthenticated" });
130
+ }
131
+ this.setState({
132
+ isLoading: false,
133
+ displayMode: config.displayMode,
134
+ });
135
+ }
136
+ catch (error) {
137
+ // Reset promise on error so it can be retried
138
+ this.initializationPromise = null;
139
+ const authError = error instanceof Error
140
+ ? error
141
+ : new Error("Auth initialization failed");
142
+ this.setState({
143
+ error: authError,
144
+ authStatus: "error",
145
+ isLoading: false,
146
+ });
147
+ throw authError;
148
+ }
149
+ }
150
+ /**
151
+ * Subscribe to state changes
152
+ */
153
+ subscribe(listener) {
154
+ this.listeners.add(listener);
155
+ return () => this.listeners.delete(listener);
156
+ }
157
+ /**
158
+ * Get current state
159
+ */
160
+ getState() {
161
+ return { ...this.state };
162
+ }
163
+ /**
164
+ * Sign in
165
+ */
166
+ async signIn() {
167
+ if (!this.auth) {
168
+ throw new Error("Auth not initialized");
169
+ }
170
+ const { user } = await this.auth.startAuthentication();
171
+ await this.refreshUserAndSession();
172
+ // Ensure we have a user to return
173
+ if (!user) {
174
+ throw new Error("Authentication succeeded but no user was returned");
175
+ }
176
+ // Return the user object
177
+ return { user };
178
+ }
179
+ /**
180
+ * Sign out
181
+ */
182
+ async signOut() {
183
+ if (!this.auth) {
184
+ throw new Error("Auth not initialized");
185
+ }
186
+ await this.auth.logout();
187
+ this.setState({
188
+ user: null,
189
+ session: null,
190
+ authStatus: "unauthenticated",
191
+ });
192
+ }
193
+ /**
194
+ * Check if config is the same (for idempotent initialization)
195
+ */
196
+ isSameConfig(newConfig) {
197
+ if (!this.config)
198
+ return false;
199
+ return (this.config.clientId === newConfig.clientId &&
200
+ this.config.config?.oauthServer === newConfig.config?.oauthServer &&
201
+ this.config.displayMode === newConfig.displayMode &&
202
+ this.config.nonce === newConfig.nonce);
203
+ }
204
+ /**
205
+ * Setup event listeners for auth state changes
206
+ */
207
+ setupEventListeners() {
208
+ if (!this.events)
209
+ return;
210
+ this.events.on(AuthEvent.SIGN_IN_STARTED, () => {
211
+ this.setState({
212
+ isLoading: true,
213
+ authStatus: "authenticating",
214
+ error: null,
215
+ });
216
+ });
217
+ this.events.on(AuthEvent.SIGN_IN_COMPLETE, () => {
218
+ this.setState({
219
+ isLoading: false,
220
+ authStatus: "authenticated",
221
+ error: null,
222
+ });
223
+ this.refreshUserAndSession();
224
+ this.callbacks.onSignIn?.();
225
+ });
226
+ this.events.on(AuthEvent.SIGN_IN_ERROR, (event) => {
227
+ const errorDetail = event?.detail || "Authentication failed";
228
+ const authError = new Error(errorDetail);
229
+ this.setState({
230
+ isLoading: false,
231
+ authStatus: "error",
232
+ error: authError,
233
+ });
234
+ this.callbacks.onSignIn?.(authError);
235
+ });
236
+ this.events.on(AuthEvent.SIGN_OUT_STARTED, () => {
237
+ this.setState({
238
+ isLoading: true,
239
+ authStatus: "signing_out",
240
+ error: null,
241
+ });
242
+ });
243
+ this.events.on(AuthEvent.SIGN_OUT_COMPLETE, () => {
244
+ this.setState({
245
+ isLoading: false,
246
+ authStatus: "unauthenticated",
247
+ user: null,
248
+ session: null,
249
+ error: null,
250
+ });
251
+ this.callbacks.onSignOut?.();
252
+ });
253
+ this.events.on(AuthEvent.USER_SESSION_CHANGED, () => {
254
+ this.refreshUserAndSession();
255
+ });
256
+ }
257
+ /**
258
+ * Refresh user and session data
259
+ */
260
+ async refreshUserAndSession() {
261
+ if (!this.auth)
262
+ return;
263
+ try {
264
+ const [session, user] = await Promise.all([
265
+ this.auth.getCurrentSession(),
266
+ this.auth.getCurrentUser(),
267
+ ]);
268
+ this.setState({ session, user });
269
+ }
270
+ catch (error) {
271
+ const sessionError = error instanceof Error ? error : new Error("Failed to get session");
272
+ this.setState({ error: sessionError });
273
+ }
274
+ }
275
+ /**
276
+ * Update state and notify listeners
277
+ */
278
+ setState(updates) {
279
+ this.state = { ...this.state, ...updates };
280
+ this.listeners.forEach((listener) => listener(this.state));
281
+ }
282
+ /**
283
+ * Cleanup auth instance
284
+ */
285
+ async cleanup() {
286
+ if (this.auth) {
287
+ await this.auth.destroy();
288
+ this.auth = null;
289
+ }
290
+ this.events = null;
291
+ this.config = null;
292
+ this.initializationPromise = null; // Reset promise for clean re-initialization
293
+ }
294
+ }
295
+ export { GlobalAuthManager };
296
+ //# sourceMappingURL=GlobalAuthManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GlobalAuthManager.js","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GlobalAuthManager - Singleton Authentication State Manager\n *\n * This module provides a global singleton that manages authentication state across a React application\n * without requiring React Context providers or prop drilling. It acts as a centralized authentication\n * manager that wraps the CivicAuth vanilla JavaScript library and provides a React-friendly interface.\n *\n * Key Features:\n * - Singleton pattern ensures single auth instance across the entire app\n * - Eliminates need for React Context providers and reduces bundle size\n * - Manages authentication state (user, session, loading, errors)\n * - Handles sign-in/sign-out flows with event-driven updates\n * - Provides idempotent initialization (safe to call multiple times)\n * - Supports multiple React hooks subscribing to the same auth state\n * - Automatic session refresh and user data synchronization\n *\n * Usage:\n * - Initialize once in your app with authentication configuration\n * - Use React hooks (useCivicAuth, useAuth, etc.) to access auth state\n * - The manager handles all underlying CivicAuth SDK interactions\n * - State updates are automatically propagated to all subscribed components\n *\n * This design pattern is particularly useful for:\n * - Large applications with many components needing auth state\n * - Avoiding provider wrapper hell in React component trees\n * - Ensuring consistent auth state across disconnected component hierarchies\n * - Server-side rendering scenarios where providers might be problematic\n */\n\nimport {\n CivicAuth,\n AuthenticationEvents,\n AuthEvent,\n} from \"../../vanillajs/index.js\";\nimport type {\n User,\n Session,\n CivicAuthClientConfig,\n} from \"../../vanillajs/index.js\";\nimport type { DisplayMode } from \"../../types.js\";\n\n// Event payload interfaces\ninterface SignInErrorEvent {\n detail: string;\n}\n\nexport interface GlobalAuthConfig {\n clientId: string;\n redirectUrl?: string;\n config?: {\n oauthServer?: string;\n };\n displayMode?: DisplayMode;\n iframeMode?: \"modal\" | \"embedded\";\n nonce?: string;\n logoutRedirectUrl?: string;\n scopes?: string[];\n authProcessTimeout?: number;\n onSignIn?: (error?: Error) => void;\n onSignOut?: () => void;\n}\n\nexport type AuthStatus =\n | \"authenticated\"\n | \"unauthenticated\"\n | \"authenticating\"\n | \"error\"\n | \"signing_out\";\n\nexport interface GlobalAuthState {\n user: User | null;\n session: Session | null;\n isLoading: boolean;\n authStatus: AuthStatus;\n error: Error | null;\n displayMode?: DisplayMode;\n}\n\ntype StateListener = (state: GlobalAuthState) => void;\n\n/**\n * Global singleton that manages CivicAuth instance for React hooks\n * Eliminates the need for React providers\n */\nclass GlobalAuthManager {\n private static instance: GlobalAuthManager | null = null;\n private auth: CivicAuth | null = null;\n private events: AuthenticationEvents | null = null;\n private config: GlobalAuthConfig | null = null;\n private listeners = new Set<StateListener>();\n private callbacks: {\n onSignIn?: (error?: Error) => void;\n onSignOut?: () => void;\n } = {};\n private initializationPromise: Promise<void> | null = null;\n\n private state: GlobalAuthState = {\n user: null,\n session: null,\n isLoading: false,\n authStatus: \"unauthenticated\",\n error: null,\n displayMode: undefined,\n };\n\n private constructor() {\n // Private constructor for singleton\n }\n\n static getInstance(): GlobalAuthManager {\n if (!GlobalAuthManager.instance) {\n GlobalAuthManager.instance = new GlobalAuthManager();\n }\n return GlobalAuthManager.instance;\n }\n\n /**\n * Initialize auth with config (idempotent)\n * Returns the same promise for concurrent calls with same config\n */\n async initialize(config: GlobalAuthConfig): Promise<void> {\n // If we have a promise and same config, return existing promise\n if (\n this.initializationPromise &&\n this.config &&\n this.isSameConfig(config)\n ) {\n return this.initializationPromise;\n }\n\n // If different config, reset everything\n if (this.config && !this.isSameConfig(config)) {\n this.initializationPromise = null;\n await this.cleanup();\n }\n\n // Create new initialization promise if needed\n if (!this.initializationPromise) {\n this.initializationPromise = this._doInitialize(config);\n }\n\n return this.initializationPromise;\n }\n\n /**\n * Private method that does the actual initialization work\n */\n private async _doInitialize(config: GlobalAuthConfig): Promise<void> {\n this.config = config;\n this.callbacks = {\n onSignIn: config.onSignIn,\n onSignOut: config.onSignOut,\n };\n this.setState({ isLoading: true, error: null });\n\n try {\n this.events = new AuthenticationEvents();\n this.setupEventListeners();\n\n const authConfig: CivicAuthClientConfig = {\n clientId: config.clientId,\n oauthServerBaseUrl: config.config?.oauthServer,\n scopes: config.scopes || [\n \"openid\",\n \"profile\",\n \"email\",\n \"offline_access\",\n ],\n displayMode: config.displayMode || \"iframe\",\n iframeDisplayMode: config.iframeMode || \"modal\",\n nonce: config.nonce,\n authProcessTimeout: config.authProcessTimeout || 120000,\n events: this.events,\n logging: {\n enabled: true,\n level: \"debug\" as const,\n },\n };\n\n // Only add redirectUrl if provided\n if (config.redirectUrl) {\n authConfig.redirectUrl = config.redirectUrl;\n }\n\n // Only add logoutRedirectUrl if provided\n if (config.logoutRedirectUrl) {\n authConfig.logoutRedirectUrl = config.logoutRedirectUrl;\n }\n\n this.auth = await CivicAuth.create(authConfig);\n\n // Check initial auth state\n const isAuthenticated = await this.auth.isAuthenticated();\n if (isAuthenticated) {\n await this.refreshUserAndSession();\n this.setState({ authStatus: \"authenticated\" });\n } else {\n this.setState({ authStatus: \"unauthenticated\" });\n }\n\n this.setState({\n isLoading: false,\n displayMode: config.displayMode,\n });\n } catch (error) {\n // Reset promise on error so it can be retried\n this.initializationPromise = null;\n\n const authError =\n error instanceof Error\n ? error\n : new Error(\"Auth initialization failed\");\n this.setState({\n error: authError,\n authStatus: \"error\",\n isLoading: false,\n });\n throw authError;\n }\n }\n\n /**\n * Subscribe to state changes\n */\n subscribe(listener: StateListener): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n /**\n * Get current state\n */\n getState(): GlobalAuthState {\n return { ...this.state };\n }\n\n /**\n * Sign in\n */\n async signIn(): Promise<{ user: User }> {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n\n const { user } = await this.auth.startAuthentication();\n await this.refreshUserAndSession();\n\n // Ensure we have a user to return\n if (!user) {\n throw new Error(\"Authentication succeeded but no user was returned\");\n }\n\n // Return the user object\n return { user };\n }\n\n /**\n * Sign out\n */\n async signOut(): Promise<void> {\n if (!this.auth) {\n throw new Error(\"Auth not initialized\");\n }\n\n await this.auth.logout();\n this.setState({\n user: null,\n session: null,\n authStatus: \"unauthenticated\",\n });\n }\n\n /**\n * Check if config is the same (for idempotent initialization)\n */\n private isSameConfig(newConfig: GlobalAuthConfig): boolean {\n if (!this.config) return false;\n return (\n this.config.clientId === newConfig.clientId &&\n this.config.config?.oauthServer === newConfig.config?.oauthServer &&\n this.config.displayMode === newConfig.displayMode &&\n this.config.nonce === newConfig.nonce\n );\n }\n\n /**\n * Setup event listeners for auth state changes\n */\n private setupEventListeners(): void {\n if (!this.events) return;\n\n this.events.on(AuthEvent.SIGN_IN_STARTED, () => {\n this.setState({\n isLoading: true,\n authStatus: \"authenticating\",\n error: null,\n });\n });\n\n this.events.on(AuthEvent.SIGN_IN_COMPLETE, () => {\n this.setState({\n isLoading: false,\n authStatus: \"authenticated\",\n error: null,\n });\n this.refreshUserAndSession();\n this.callbacks.onSignIn?.();\n });\n\n this.events.on(AuthEvent.SIGN_IN_ERROR, (event?: SignInErrorEvent) => {\n const errorDetail = event?.detail || \"Authentication failed\";\n const authError = new Error(errorDetail);\n this.setState({\n isLoading: false,\n authStatus: \"error\",\n error: authError,\n });\n this.callbacks.onSignIn?.(authError);\n });\n\n this.events.on(AuthEvent.SIGN_OUT_STARTED, () => {\n this.setState({\n isLoading: true,\n authStatus: \"signing_out\",\n error: null,\n });\n });\n\n this.events.on(AuthEvent.SIGN_OUT_COMPLETE, () => {\n this.setState({\n isLoading: false,\n authStatus: \"unauthenticated\",\n user: null,\n session: null,\n error: null,\n });\n this.callbacks.onSignOut?.();\n });\n\n this.events.on(AuthEvent.USER_SESSION_CHANGED, () => {\n this.refreshUserAndSession();\n });\n }\n\n /**\n * Refresh user and session data\n */\n private async refreshUserAndSession(): Promise<void> {\n if (!this.auth) return;\n\n try {\n const [session, user] = await Promise.all([\n this.auth.getCurrentSession(),\n this.auth.getCurrentUser(),\n ]);\n\n this.setState({ session, user });\n } catch (error) {\n const sessionError =\n error instanceof Error ? error : new Error(\"Failed to get session\");\n this.setState({ error: sessionError });\n }\n }\n\n /**\n * Update state and notify listeners\n */\n private setState(updates: Partial<GlobalAuthState>): void {\n this.state = { ...this.state, ...updates };\n this.listeners.forEach((listener) => listener(this.state));\n }\n\n /**\n * Cleanup auth instance\n */\n private async cleanup(): Promise<void> {\n if (this.auth) {\n await this.auth.destroy();\n this.auth = null;\n }\n this.events = null;\n this.config = null;\n this.initializationPromise = null; // Reset promise for clean re-initialization\n }\n}\n\nexport { GlobalAuthManager };\n"]}
@@ -1,3 +1,3 @@
1
- export { useUser } from "../../reactjs/hooks/useUser.js";
2
- export { useToken } from "../../shared/hooks/useToken.js";
1
+ export { useUser, type UserContextType } from "./useUser.js";
2
+ export { useToken, type TokenContextType } from "./useToken.js";
3
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/reactjs/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/reactjs/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC"}
@@ -1,3 +1,3 @@
1
- export { useUser } from "../../reactjs/hooks/useUser.js";
2
- export { useToken } from "../../shared/hooks/useToken.js";
1
+ export { useUser } from "./useUser.js";
2
+ export { useToken } from "./useToken.js";
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/reactjs/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC","sourcesContent":["export { useUser } from \"@/reactjs/hooks/useUser.js\";\nexport { useToken } from \"@/shared/hooks/useToken.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/reactjs/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAwB,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAyB,MAAM,eAAe,CAAC","sourcesContent":["export { useUser, type UserContextType } from \"./useUser.js\";\nexport { useToken, type TokenContextType } from \"./useToken.js\";\n"]}
@@ -0,0 +1,13 @@
1
+ import type { ForwardedTokens } from "../../types.js";
2
+ import type { GlobalAuthConfig } from "../core/GlobalAuthManager.js";
3
+ export interface TokenContextType {
4
+ idToken?: string | null;
5
+ accessToken?: string | null;
6
+ refreshToken?: string | null;
7
+ forwardedTokens?: ForwardedTokens;
8
+ isLoading: boolean;
9
+ error: Error | null;
10
+ }
11
+ declare const useToken: (config?: GlobalAuthConfig) => TokenContextType;
12
+ export { useToken };
13
+ //# sourceMappingURL=useToken.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToken.d.ts","sourceRoot":"","sources":["../../../src/reactjs/hooks/useToken.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED,QAAA,MAAM,QAAQ,YAAa,gBAAgB,KAAG,gBAuB7C,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * useToken Hook
3
+ *
4
+ * A backwards-compatible token hook that extracts token-related properties from useUser.
5
+ * This hook provides access to authentication tokens without user profile information.
6
+ *
7
+ * Use this hook when you:
8
+ * - Only need access to tokens (idToken, accessToken, refreshToken, forwardedTokens)
9
+ * - Want to maintain backwards compatibility with existing code
10
+ * - Don't need user profile information
11
+ *
12
+ * This hook supports the same authentication patterns as useUser with automatic fallback:
13
+ * 1. Provider-based (legacy): Uses CivicAuthProvider or CivicNextAuthProvider
14
+ * 2. Provider-free (modern): Direct configuration via useToken(config)
15
+ *
16
+ * Usage Examples:
17
+ *
18
+ * // With provider (existing approach)
19
+ * <CivicAuthProvider clientId="..." config={{ oauthServer: "..." }}>
20
+ * const { accessToken, idToken, forwardedTokens } = useToken();
21
+ * </CivicAuthProvider>
22
+ *
23
+ * // Without provider (new approach) - direct configuration
24
+ * const { accessToken, idToken, refreshToken } = useToken({
25
+ * clientId: "your-client-id",
26
+ * config: { oauthServer: "https://auth.civic.com/oauth/" },
27
+ * displayMode: "iframe",
28
+ * scopes: ["openid", "profile", "email"]
29
+ * });
30
+ */
31
+ "use client";
32
+ import { useMemo } from "react";
33
+ import { useUser } from "./useUser.js";
34
+ const useToken = (config) => {
35
+ // Leverage the existing useUser hook which handles all the fallback logic
36
+ const { idToken, accessToken, refreshToken, forwardedTokens, isLoading, error, } = useUser(config);
37
+ // Return only token-related properties for backwards compatibility
38
+ return useMemo(() => ({
39
+ idToken,
40
+ accessToken,
41
+ refreshToken,
42
+ forwardedTokens,
43
+ isLoading,
44
+ error,
45
+ }), [idToken, accessToken, refreshToken, forwardedTokens, isLoading, error]);
46
+ };
47
+ export { useToken };
48
+ //# sourceMappingURL=useToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useToken.js","sourceRoot":"","sources":["../../../src/reactjs/hooks/useToken.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,YAAY,CAAC;AACb,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAavC,MAAM,QAAQ,GAAG,CAAC,MAAyB,EAAoB,EAAE;IAC/D,0EAA0E;IAC1E,MAAM,EACJ,OAAO,EACP,WAAW,EACX,YAAY,EACZ,eAAe,EACf,SAAS,EACT,KAAK,GACN,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEpB,mEAAmE;IACnE,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,CAAC;QACL,OAAO;QACP,WAAW;QACX,YAAY;QACZ,eAAe;QACf,SAAS;QACT,KAAK;KACN,CAAC,EACF,CAAC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,KAAK,CAAC,CACxE,CAAC;AACJ,CAAC,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC","sourcesContent":["/**\n * useToken Hook\n *\n * A backwards-compatible token hook that extracts token-related properties from useUser.\n * This hook provides access to authentication tokens without user profile information.\n *\n * Use this hook when you:\n * - Only need access to tokens (idToken, accessToken, refreshToken, forwardedTokens)\n * - Want to maintain backwards compatibility with existing code\n * - Don't need user profile information\n *\n * This hook supports the same authentication patterns as useUser with automatic fallback:\n * 1. Provider-based (legacy): Uses CivicAuthProvider or CivicNextAuthProvider\n * 2. Provider-free (modern): Direct configuration via useToken(config)\n *\n * Usage Examples:\n *\n * // With provider (existing approach)\n * <CivicAuthProvider clientId=\"...\" config={{ oauthServer: \"...\" }}>\n * const { accessToken, idToken, forwardedTokens } = useToken();\n * </CivicAuthProvider>\n *\n * // Without provider (new approach) - direct configuration\n * const { accessToken, idToken, refreshToken } = useToken({\n * clientId: \"your-client-id\",\n * config: { oauthServer: \"https://auth.civic.com/oauth/\" },\n * displayMode: \"iframe\",\n * scopes: [\"openid\", \"profile\", \"email\"]\n * });\n */\n\"use client\";\nimport { useMemo } from \"react\";\nimport { useUser } from \"./useUser.js\";\nimport type { ForwardedTokens } from \"../../types.js\";\nimport type { GlobalAuthConfig } from \"../core/GlobalAuthManager.js\";\n\nexport interface TokenContextType {\n idToken?: string | null;\n accessToken?: string | null;\n refreshToken?: string | null;\n forwardedTokens?: ForwardedTokens;\n isLoading: boolean;\n error: Error | null;\n}\n\nconst useToken = (config?: GlobalAuthConfig): TokenContextType => {\n // Leverage the existing useUser hook which handles all the fallback logic\n const {\n idToken,\n accessToken,\n refreshToken,\n forwardedTokens,\n isLoading,\n error,\n } = useUser(config);\n\n // Return only token-related properties for backwards compatibility\n return useMemo(\n () => ({\n idToken,\n accessToken,\n refreshToken,\n forwardedTokens,\n isLoading,\n error,\n }),\n [idToken, accessToken, refreshToken, forwardedTokens, isLoading, error],\n );\n};\n\nexport { useToken };\n"]}
@@ -1,4 +1,22 @@
1
- import { type UserContextType } from "../../shared/providers/UserProvider.js";
2
- declare const useUser: <T extends Record<string, unknown> = Record<string, never>>() => UserContextType<T>;
1
+ import type { User, ForwardedTokens } from "../../types.js";
2
+ import type { AuthStatus } from "../../types.js";
3
+ import type { DisplayMode } from "../../types.js";
4
+ import { type GlobalAuthConfig } from "../core/GlobalAuthManager.js";
5
+ export interface UserContextType<T extends Record<string, unknown> = Record<string, never>> {
6
+ user: User<T> | null;
7
+ idToken?: string | null;
8
+ accessToken?: string | null;
9
+ refreshToken?: string | null;
10
+ forwardedTokens?: ForwardedTokens;
11
+ isLoading: boolean;
12
+ authStatus: AuthStatus;
13
+ error: Error | null;
14
+ signIn: () => Promise<{
15
+ user: User<T>;
16
+ }>;
17
+ signOut: () => Promise<void>;
18
+ displayMode?: DisplayMode;
19
+ }
20
+ declare const useUser: <T extends Record<string, unknown> = Record<string, never>>(config?: GlobalAuthConfig) => UserContextType<T>;
3
21
  export { useUser };
4
22
  //# sourceMappingURL=useUser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useUser.d.ts","sourceRoot":"","sources":["../../../src/reactjs/hooks/useUser.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,oCAAoC,CAAC;AAE5C,QAAA,MAAM,OAAO,GACX,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,+BAC9B,eAAe,CAAC,CAAC,CAQrB,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"useUser.d.ts","sourceRoot":"","sources":["../../../src/reactjs/hooks/useUser.ts"],"names":[],"mappings":"AAyCA,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAEL,KAAK,gBAAgB,EAEtB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,WAAW,eAAe,CAC9B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC;IAEzD,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;KAAE,CAAC,CAAC;IACzC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,QAAA,MAAM,OAAO,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,mCACvC,gBAAgB,KACxB,eAAe,CAAC,CAAC,CA2InB,CAAC;AAEF,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -1,12 +1,168 @@
1
+ /**
2
+ * useUser Hook
3
+ *
4
+ * A comprehensive user session hook that provides full user data including profile information,
5
+ * authentication tokens, and authentication state. Supports generic typing for custom user data.
6
+ *
7
+ * Use this hook when you:
8
+ * - Need access to user profile information (user object)
9
+ * - Need authentication tokens (JWT, access, refresh tokens)
10
+ * - Are working with custom user data types
11
+ * - Need comprehensive user session data
12
+ * - Want backward compatibility with legacy UserContext
13
+ *
14
+ * This hook supports two authentication patterns with automatic fallback:
15
+ * 1. Provider-based (legacy): Uses CivicAuthProvider or CivicNextAuthProvider
16
+ * 2. Provider-free (modern): Direct configuration via useUser(config)
17
+ *
18
+ * Usage Examples:
19
+ *
20
+ * // With provider (existing approach - NextJS/React providers)
21
+ * <CivicAuthProvider clientId="..." config={{ oauthServer: "..." }}>
22
+ * const { user, isLoading, signIn } = useUser();
23
+ * </CivicAuthProvider>
24
+ *
25
+ * // Without provider (new approach) - direct configuration
26
+ * const { user, authStatus, signOut } = useUser({
27
+ * clientId: "your-client-id",
28
+ * config: { oauthServer: "https://auth.civic.com/oauth/" },
29
+ * displayMode: "iframe", // or "redirect", "popup", etc.
30
+ * scopes: ["openid", "profile", "email"],
31
+ * onSignIn: (error) => console.log("Sign in completed", error),
32
+ * onSignOut: () => console.log("Sign out completed")
33
+ * });
34
+ *
35
+ * // Generic typing for custom user data
36
+ * interface CustomUser { customField: string; }
37
+ * const { user } = useUser<CustomUser>(); // user will be User<CustomUser> | null
38
+ */
1
39
  "use client";
2
- import { useContext } from "react";
3
- import { UserContext, } from "../../shared/providers/UserProvider.js";
4
- const useUser = () => {
5
- const context = useContext(UserContext);
6
- if (!context) {
7
- throw new Error("useUser must be used within a UserProvider");
40
+ import { useContext, useState, useEffect, useCallback, useMemo } from "react";
41
+ import { UserContext } from "../../shared/providers/UserProvider.js";
42
+ import { GlobalAuthManager, } from "../core/GlobalAuthManager.js";
43
+ import { extractTokensFromSession } from "../../vanillajs/utils/auth-utils.js";
44
+ const useUser = (config) => {
45
+ // Always call context hooks unconditionally (rules of hooks)
46
+ const sharedContext = useContext(UserContext);
47
+ // State for global manager approach
48
+ const [globalState, setGlobalState] = useState(null);
49
+ // Determine which approach to use
50
+ const hasProviderContext = sharedContext;
51
+ const shouldUseGlobal = !hasProviderContext;
52
+ // Initialize global manager if no provider context
53
+ useEffect(() => {
54
+ if (!shouldUseGlobal)
55
+ return;
56
+ const manager = GlobalAuthManager.getInstance();
57
+ // If config is provided, initialize with it
58
+ if (config) {
59
+ const initializeAuth = async () => {
60
+ try {
61
+ await manager.initialize(config);
62
+ }
63
+ catch (error) {
64
+ console.error("Failed to initialize auth:", error);
65
+ }
66
+ };
67
+ initializeAuth();
68
+ }
69
+ // Subscribe to state changes
70
+ const unsubscribe = manager.subscribe((newState) => {
71
+ setGlobalState(newState);
72
+ });
73
+ // Get current state
74
+ setGlobalState(manager.getState());
75
+ return unsubscribe;
76
+ }, [shouldUseGlobal, config]);
77
+ // Global manager sign in/out functions
78
+ const globalSignIn = useCallback(async () => {
79
+ const manager = GlobalAuthManager.getInstance();
80
+ await manager.signIn();
81
+ // Get the user after sign in
82
+ const state = manager.getState();
83
+ if (!state.user) {
84
+ throw new Error("Authentication succeeded but no user was returned");
85
+ }
86
+ return { user: state.user };
87
+ }, []);
88
+ const globalSignOut = useCallback(async () => {
89
+ const manager = GlobalAuthManager.getInstance();
90
+ await manager.signOut();
91
+ }, []);
92
+ // Extract tokens from global state
93
+ const globalTokens = useMemo(() => {
94
+ return extractTokensFromSession(globalState?.session || null);
95
+ }, [globalState?.session]);
96
+ // Create wrapper functions for different signIn signatures
97
+ const wrapSharedSignIn = useCallback(async () => {
98
+ if (sharedContext) {
99
+ await sharedContext.signIn(); // This returns void
100
+ // Get user from context after sign in
101
+ if (sharedContext.user) {
102
+ return { user: sharedContext.user };
103
+ }
104
+ // We don't return a user yet in nextjs until the next refactor
105
+ return { user: null };
106
+ }
107
+ throw new Error("Shared context not available");
108
+ }, [sharedContext]);
109
+ // ========================================================================
110
+ // FALLBACK PRIORITY SYSTEM - Two authentication context approaches
111
+ // ========================================================================
112
+ // 1. DEPRECATED UserContext (ACTIVE - Used by NextJS)
113
+ // Framework-agnostic shared context from UserProvider
114
+ // Location: shared/providers/UserProvider.tsx
115
+ // Usage: NextJS example uses CivicNextAuthProvider → UserProvider → UserContext
116
+ if (sharedContext) {
117
+ return {
118
+ user: sharedContext.user,
119
+ idToken: sharedContext.idToken,
120
+ accessToken: sharedContext.accessToken,
121
+ refreshToken: undefined, // Not available in shared context
122
+ forwardedTokens: sharedContext.forwardedTokens,
123
+ isLoading: sharedContext.isLoading,
124
+ authStatus: sharedContext.authStatus,
125
+ error: sharedContext.error,
126
+ signIn: wrapSharedSignIn,
127
+ signOut: sharedContext.signOut,
128
+ displayMode: sharedContext.displayMode,
129
+ };
8
130
  }
9
- return context;
131
+ // 2. GlobalAuthManager (MODERN - Provider-free approach)
132
+ // Singleton-based state management, eliminates need for React providers
133
+ // Location: reactjs/core/GlobalAuthManager.ts
134
+ // Usage: React example uses CivicAuthProvider → GlobalAuthManager internally
135
+ // Can also be used directly: useUser({ clientId: "...", config: {...} })
136
+ if (globalState) {
137
+ return {
138
+ user: globalState.user,
139
+ idToken: globalTokens.idToken,
140
+ accessToken: globalTokens.accessToken,
141
+ refreshToken: globalTokens.refreshToken,
142
+ forwardedTokens: globalTokens.forwardedTokens,
143
+ isLoading: globalState.isLoading,
144
+ authStatus: globalState.authStatus,
145
+ error: globalState.error,
146
+ signIn: globalSignIn,
147
+ signOut: globalSignOut,
148
+ displayMode: globalState.displayMode,
149
+ };
150
+ }
151
+ // If no context and no global state, provide default loading state
152
+ // This happens when CivicAuthProvider is present but GlobalAuthManager hasn't initialized yet
153
+ return {
154
+ user: null,
155
+ idToken: null,
156
+ accessToken: null,
157
+ refreshToken: null,
158
+ forwardedTokens: undefined,
159
+ isLoading: true,
160
+ authStatus: "unauthenticated",
161
+ error: null,
162
+ signIn: globalSignIn,
163
+ signOut: globalSignOut,
164
+ displayMode: config?.displayMode,
165
+ };
10
166
  };
11
167
  export { useUser };
12
168
  //# sourceMappingURL=useUser.js.map