@civic/auth 0.9.0 → 0.9.1-alpha.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 (101) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/lib/logger.d.ts +6 -0
  3. package/dist/lib/logger.d.ts.map +1 -1
  4. package/dist/lib/logger.js +7 -0
  5. package/dist/lib/logger.js.map +1 -1
  6. package/dist/nextjs/config.d.ts +2 -4
  7. package/dist/nextjs/config.d.ts.map +1 -1
  8. package/dist/nextjs/config.js +4 -57
  9. package/dist/nextjs/config.js.map +1 -1
  10. package/dist/react-router-7/components/UserButton.d.ts +15 -0
  11. package/dist/react-router-7/components/UserButton.d.ts.map +1 -0
  12. package/dist/react-router-7/components/UserButton.js +112 -0
  13. package/dist/react-router-7/components/UserButton.js.map +1 -0
  14. package/dist/react-router-7/components/UserButtonPresentation.d.ts +10 -0
  15. package/dist/react-router-7/components/UserButtonPresentation.d.ts.map +1 -0
  16. package/dist/react-router-7/components/UserButtonPresentation.js +19 -0
  17. package/dist/react-router-7/components/UserButtonPresentation.js.map +1 -0
  18. package/dist/react-router-7/config.d.ts +111 -0
  19. package/dist/react-router-7/config.d.ts.map +1 -0
  20. package/dist/react-router-7/config.js +88 -0
  21. package/dist/react-router-7/config.js.map +1 -0
  22. package/dist/react-router-7/cookies.d.ts +41 -0
  23. package/dist/react-router-7/cookies.d.ts.map +1 -0
  24. package/dist/react-router-7/cookies.js +188 -0
  25. package/dist/react-router-7/cookies.js.map +1 -0
  26. package/dist/react-router-7/index.d.ts +10 -0
  27. package/dist/react-router-7/index.d.ts.map +1 -0
  28. package/dist/react-router-7/index.js +12 -0
  29. package/dist/react-router-7/index.js.map +1 -0
  30. package/dist/react-router-7/routeHandler.d.ts +54 -0
  31. package/dist/react-router-7/routeHandler.d.ts.map +1 -0
  32. package/dist/react-router-7/routeHandler.js +394 -0
  33. package/dist/react-router-7/routeHandler.js.map +1 -0
  34. package/dist/react-router-7/useUser.d.ts +38 -0
  35. package/dist/react-router-7/useUser.d.ts.map +1 -0
  36. package/dist/react-router-7/useUser.js +92 -0
  37. package/dist/react-router-7/useUser.js.map +1 -0
  38. package/dist/reactjs/core/GlobalAuthManager.d.ts +6 -4
  39. package/dist/reactjs/core/GlobalAuthManager.d.ts.map +1 -1
  40. package/dist/reactjs/core/GlobalAuthManager.js +16 -6
  41. package/dist/reactjs/core/GlobalAuthManager.js.map +1 -1
  42. package/dist/reactjs/hooks/useUser.js.map +1 -1
  43. package/dist/server/ServerAuthenticationResolver.d.ts.map +1 -1
  44. package/dist/server/ServerAuthenticationResolver.js +4 -0
  45. package/dist/server/ServerAuthenticationResolver.js.map +1 -1
  46. package/dist/server/config.d.ts +11 -3
  47. package/dist/server/config.d.ts.map +1 -1
  48. package/dist/server/config.js.map +1 -1
  49. package/dist/server/login.d.ts.map +1 -1
  50. package/dist/server/login.js +5 -0
  51. package/dist/server/login.js.map +1 -1
  52. package/dist/server/logout.d.ts.map +1 -1
  53. package/dist/server/logout.js +5 -0
  54. package/dist/server/logout.js.map +1 -1
  55. package/dist/server/session.d.ts.map +1 -1
  56. package/dist/server/session.js +5 -0
  57. package/dist/server/session.js.map +1 -1
  58. package/dist/services/AuthenticationService.d.ts.map +1 -1
  59. package/dist/services/AuthenticationService.js +0 -5
  60. package/dist/services/AuthenticationService.js.map +1 -1
  61. package/dist/services/PKCE.d.ts.map +1 -1
  62. package/dist/services/PKCE.js +4 -1
  63. package/dist/services/PKCE.js.map +1 -1
  64. package/dist/shared/hooks/useCivicAuthConfig.d.ts +1 -1
  65. package/dist/shared/hooks/useCivicAuthConfig.d.ts.map +1 -1
  66. package/dist/shared/lib/AuthenticationRefresherImpl.d.ts.map +1 -1
  67. package/dist/shared/lib/AuthenticationRefresherImpl.js +4 -0
  68. package/dist/shared/lib/AuthenticationRefresherImpl.js.map +1 -1
  69. package/dist/shared/lib/cookieConfig.d.ts +46 -0
  70. package/dist/shared/lib/cookieConfig.d.ts.map +1 -0
  71. package/dist/shared/lib/cookieConfig.js +99 -0
  72. package/dist/shared/lib/cookieConfig.js.map +1 -0
  73. package/dist/shared/lib/util.d.ts +5 -0
  74. package/dist/shared/lib/util.d.ts.map +1 -1
  75. package/dist/shared/lib/util.js +65 -3
  76. package/dist/shared/lib/util.js.map +1 -1
  77. package/dist/shared/version.d.ts +1 -1
  78. package/dist/shared/version.d.ts.map +1 -1
  79. package/dist/shared/version.js +1 -1
  80. package/dist/shared/version.js.map +1 -1
  81. package/dist/tsconfig.tsbuildinfo +1 -0
  82. package/dist/types.d.ts +1 -1
  83. package/dist/types.d.ts.map +1 -1
  84. package/dist/types.js.map +1 -1
  85. package/dist/vanillajs/auth/CivicAuth.d.ts +1 -1
  86. package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -1
  87. package/dist/vanillajs/auth/CivicAuth.js +36 -9
  88. package/dist/vanillajs/auth/CivicAuth.js.map +1 -1
  89. package/dist/vanillajs/auth/config/ConfigProcessor.d.ts.map +1 -1
  90. package/dist/vanillajs/auth/config/ConfigProcessor.js +17 -3
  91. package/dist/vanillajs/auth/config/ConfigProcessor.js.map +1 -1
  92. package/dist/vanillajs/auth/handlers/MessageHandler.d.ts.map +1 -1
  93. package/dist/vanillajs/auth/handlers/MessageHandler.js +3 -0
  94. package/dist/vanillajs/auth/handlers/MessageHandler.js.map +1 -1
  95. package/dist/vanillajs/auth/types/AuthTypes.d.ts +31 -12
  96. package/dist/vanillajs/auth/types/AuthTypes.d.ts.map +1 -1
  97. package/dist/vanillajs/auth/types/AuthTypes.js.map +1 -1
  98. package/dist/vanillajs/iframe/IframeManager.d.ts.map +1 -1
  99. package/dist/vanillajs/iframe/IframeManager.js +12 -0
  100. package/dist/vanillajs/iframe/IframeManager.js.map +1 -1
  101. package/package.json +8 -1
@@ -0,0 +1,394 @@
1
+ import { redirect } from "react-router";
2
+ import { CivicAuth } from "@civic/auth/server";
3
+ import { ReactRouterCookieStorage } from "./cookies.js";
4
+ import { resolveAuthConfig } from "./config.js";
5
+ import { getProtocolFromRequest } from "../shared/lib/util.js";
6
+ /**
7
+ * Fields that are safe to expose to the frontend
8
+ */
9
+ const WHITELISTED_FRONTEND_FIELDS = [
10
+ "clientId",
11
+ "oauthServer",
12
+ "callbackUrl",
13
+ "logoutCallbackUrl",
14
+ "loginUrl",
15
+ "baseUrl",
16
+ "logoutUrl",
17
+ ];
18
+ /**
19
+ * Create auth route handlers for React Router - backend endpoints compatible with VanillaJS frontend integration
20
+ * These routes work similar to the Express example, using server-side CivicAuth SDK
21
+ */
22
+ export function createRouteHandlers(configOverrides = {}) {
23
+ const config = resolveAuthConfig(configOverrides);
24
+ /**
25
+ * Gets a default base URL when no baseUrl is configured
26
+ * Uses request headers to determine protocol when possible
27
+ */
28
+ const getDefaultBaseUrl = (request) => {
29
+ const protocol = getProtocolFromRequest(request);
30
+ const host = request ? new URL(request.url).host : "localhost:5191";
31
+ return `${protocol}//${host}`;
32
+ };
33
+ /**
34
+ * Resolves configuration with proper fallbacks based on request context
35
+ * @param request - The request object to extract host for fallbacks
36
+ * @returns Resolved configuration with all fallbacks applied
37
+ */
38
+ const resolveConfigWithFallbacks = (request) => {
39
+ const host = request
40
+ ? `${getProtocolFromRequest(request)}//${new URL(request.url).host}`
41
+ : (config.baseUrl ?? getDefaultBaseUrl(request));
42
+ return {
43
+ clientId: config.clientId,
44
+ oauthServer: config.oauthServer,
45
+ callbackUrl: config.callbackUrl ?? `${host}/auth/callback`,
46
+ logoutCallbackUrl: config.logoutCallbackUrl ?? `${host}/auth/logout`,
47
+ loginUrl: config.loginUrl ?? `${host}/auth/login`,
48
+ baseUrl: config.baseUrl ?? host,
49
+ loginSuccessUrl: config.loginSuccessUrl ?? `${host}`,
50
+ logoutUrl: config.logoutUrl ?? `${host}`,
51
+ };
52
+ };
53
+ /**
54
+ * Gets the whitelisted frontend configuration with proper fallbacks
55
+ * Only exposes fields that are safe for frontend consumption
56
+ * @param request - The request object to extract host for fallbacks
57
+ * @returns The whitelisted configuration object with fallbacks applied
58
+ */
59
+ const getWhitelistedFrontEndConfig = (request) => {
60
+ const resolved = resolveConfigWithFallbacks(request);
61
+ // Filter resolved config to only include whitelisted fields
62
+ return WHITELISTED_FRONTEND_FIELDS.reduce((acc, key) => {
63
+ acc[key] = resolved[key];
64
+ return acc;
65
+ }, {});
66
+ };
67
+ /**
68
+ * Helper to create CivicAuth instance for a request
69
+ */
70
+ const createCivicAuth = (request) => {
71
+ const cookieStorage = new ReactRouterCookieStorage(request);
72
+ const resolvedConfig = resolveConfigWithFallbacks(request);
73
+ const civicAuth = new CivicAuth(cookieStorage, {
74
+ clientId: resolvedConfig.clientId,
75
+ redirectUrl: resolvedConfig.callbackUrl,
76
+ oauthServer: resolvedConfig.oauthServer,
77
+ postLogoutRedirectUrl: resolvedConfig.logoutCallbackUrl,
78
+ loginSuccessUrl: resolvedConfig.loginSuccessUrl,
79
+ loginUrl: resolvedConfig.loginUrl,
80
+ });
81
+ return {
82
+ civicAuth,
83
+ // Use the original cookieStorage instance that we properly configured with setRequest()
84
+ cookieStorage,
85
+ };
86
+ };
87
+ /**
88
+ * Helper to create response with cookie headers
89
+ * Following React Router pattern: add serialized cookies as "Set-Cookie" headers
90
+ */
91
+ const createResponseWithCookies = (body, init, cookieStorage) => {
92
+ const headers = new Headers(init.headers);
93
+ // Add cookie headers from storage - each one is a complete "Set-Cookie" header from cookie.serialize()
94
+ const cookieHeaders = cookieStorage.getCookieHeaders();
95
+ cookieHeaders.forEach((cookieHeader) => {
96
+ headers.append("Set-Cookie", cookieHeader);
97
+ });
98
+ return new Response(body, {
99
+ ...init,
100
+ headers,
101
+ });
102
+ };
103
+ /**
104
+ * Helper to create redirect with cookie headers
105
+ * Following React Router pattern: add serialized cookies as "Set-Cookie" headers
106
+ */
107
+ const redirectWithCookies = (url, cookieStorage, init) => {
108
+ const headers = new Headers(init?.headers);
109
+ // Add cookie headers from storage - each one is a complete "Set-Cookie" header from cookie.serialize()
110
+ const cookieHeaders = cookieStorage.getCookieHeaders();
111
+ cookieHeaders.forEach((cookieHeader) => {
112
+ headers.append("Set-Cookie", cookieHeader);
113
+ });
114
+ // Set Location header for proper redirect
115
+ headers.set("Location", url);
116
+ return new Response(null, {
117
+ ...init,
118
+ status: 302,
119
+ headers,
120
+ });
121
+ };
122
+ const handlers = {
123
+ /**
124
+ * Login loader - backend OAuth login initiation endpoint
125
+ * Uses CivicAuth.buildLoginUrl() like Express example
126
+ */
127
+ loginLoader: async ({ request }) => {
128
+ const incomingUrl = new URL(request.url);
129
+ const frontendState = incomingUrl.searchParams.get("state");
130
+ // const returnTo = incomingUrl.searchParams.get("returnTo") || "/";
131
+ try {
132
+ const { civicAuth, cookieStorage } = createCivicAuth(request);
133
+ const url = await civicAuth.buildLoginUrl({
134
+ state: frontendState || undefined,
135
+ });
136
+ const response = redirectWithCookies(url.toString(), cookieStorage);
137
+ return response;
138
+ }
139
+ catch (error) {
140
+ console.error("[LOGIN_HANDLER] Backend login error:", error);
141
+ return redirect("/?error=login_failed");
142
+ }
143
+ },
144
+ /**
145
+ * Callback loader - backend OAuth callback endpoint
146
+ * Uses CivicAuth.handleCallback() like Express example
147
+ */
148
+ callbackLoader: async ({ request }) => {
149
+ try {
150
+ const url = new URL(request.url);
151
+ const code = url.searchParams.get("code");
152
+ const state = url.searchParams.get("state");
153
+ const error = url.searchParams.get("error");
154
+ if (error) {
155
+ console.error("OAuth error in callback:", error);
156
+ return redirect("/?error=oauth_error");
157
+ }
158
+ if (!code || !state) {
159
+ throw new Error("Missing code or state parameter");
160
+ }
161
+ const { civicAuth, cookieStorage } = createCivicAuth(request);
162
+ // Convert React Router request to the format expected by handleCallback
163
+ const handleCallbackRequest = {
164
+ headers: Object.fromEntries(request.headers.entries()),
165
+ };
166
+ // For non-iframe requests, use the original handleCallback logic
167
+ const result = await civicAuth.handleCallback({
168
+ code,
169
+ state,
170
+ req: handleCallbackRequest,
171
+ });
172
+ if (result.redirectTo) {
173
+ return redirectWithCookies(result.redirectTo, cookieStorage);
174
+ }
175
+ if (result.content) {
176
+ // Handle both string content and object content
177
+ if (typeof result.content === "string") {
178
+ return createResponseWithCookies(result.content, {
179
+ status: 200,
180
+ headers: {
181
+ "Content-Type": "text/html",
182
+ },
183
+ }, cookieStorage);
184
+ }
185
+ else {
186
+ // Object content (JSON response)
187
+ return createResponseWithCookies(JSON.stringify(result.content), {
188
+ status: 200,
189
+ headers: {
190
+ "Content-Type": "application/json",
191
+ },
192
+ }, cookieStorage);
193
+ }
194
+ }
195
+ // Fallback redirect
196
+ return redirectWithCookies("/", cookieStorage);
197
+ }
198
+ catch (error) {
199
+ console.error("[CALLBACK_HANDLER] OAuth callback error:", error);
200
+ return redirect("/?error=callback_failed");
201
+ }
202
+ },
203
+ /**
204
+ * Logout loader - backend logout endpoint
205
+ * Uses CivicAuth.buildLogoutRedirectUrl() and clearTokens() like Express example
206
+ */
207
+ logoutLoader: async ({ request }) => {
208
+ try {
209
+ const { civicAuth, cookieStorage } = createCivicAuth(request);
210
+ const logoutUrl = await civicAuth.buildLogoutRedirectUrl();
211
+ await civicAuth.clearTokens();
212
+ const url = new URL(logoutUrl.toString());
213
+ // Remove the state parameter to avoid it showing up in the frontend URL
214
+ url.searchParams.delete("state");
215
+ return redirectWithCookies(url.toString(), cookieStorage);
216
+ }
217
+ catch (error) {
218
+ console.error("[LOGOUT_HANDLER] Logout error:", error);
219
+ // If logout URL generation fails, clear tokens and redirect to home (Express pattern)
220
+ try {
221
+ const { civicAuth, cookieStorage } = createCivicAuth(request);
222
+ await civicAuth.clearTokens();
223
+ return redirectWithCookies("/", cookieStorage);
224
+ }
225
+ catch (clearError) {
226
+ console.error("[LOGOUT_HANDLER] Failed to clear tokens:", clearError);
227
+ return redirect("/");
228
+ }
229
+ }
230
+ },
231
+ /**
232
+ * User endpoint - returns current user data as JSON
233
+ * Uses CivicAuth.isLoggedIn() and getUser() like Express example
234
+ */
235
+ userLoader: async ({ request }) => {
236
+ try {
237
+ const { civicAuth, cookieStorage } = createCivicAuth(request);
238
+ const isLoggedIn = await civicAuth.isLoggedIn();
239
+ if (!isLoggedIn) {
240
+ return createResponseWithCookies(JSON.stringify({ error: "Not authenticated" }), {
241
+ status: 401,
242
+ headers: { "Content-Type": "application/json" },
243
+ }, cookieStorage);
244
+ }
245
+ const user = await civicAuth.getUser();
246
+ return createResponseWithCookies(JSON.stringify({ user }), {
247
+ status: 200,
248
+ headers: { "Content-Type": "application/json" },
249
+ }, cookieStorage);
250
+ }
251
+ catch (error) {
252
+ console.error("[USER_HANDLER] User endpoint error:", error);
253
+ return new Response(JSON.stringify({ error: "Internal server error" }), {
254
+ status: 500,
255
+ headers: { "Content-Type": "application/json" },
256
+ });
257
+ }
258
+ },
259
+ /**
260
+ * Refresh endpoint - refreshes access tokens
261
+ * Uses CivicAuth.refreshTokens() like Express example
262
+ */
263
+ refreshLoader: async ({ request }) => {
264
+ try {
265
+ const { civicAuth, cookieStorage } = createCivicAuth(request);
266
+ const isLoggedIn = await civicAuth.isLoggedIn();
267
+ if (!isLoggedIn) {
268
+ return createResponseWithCookies(JSON.stringify({ error: "Not authenticated" }), {
269
+ status: 401,
270
+ headers: { "Content-Type": "application/json" },
271
+ }, cookieStorage);
272
+ }
273
+ await civicAuth.refreshTokens();
274
+ return createResponseWithCookies(JSON.stringify({ success: true, message: "Tokens refreshed" }), {
275
+ status: 200,
276
+ headers: { "Content-Type": "application/json" },
277
+ }, cookieStorage);
278
+ }
279
+ catch (error) {
280
+ console.error("[REFRESH_HANDLER] Token refresh error:", error);
281
+ return new Response(JSON.stringify({ error: "Token refresh failed" }), {
282
+ status: 500,
283
+ headers: { "Content-Type": "application/json" },
284
+ });
285
+ }
286
+ },
287
+ /**
288
+ * Get user data from session (for SSR)
289
+ * Uses CivicAuth.isLoggedIn() and getUser() like Express example
290
+ */
291
+ getUser: async (request) => {
292
+ try {
293
+ const { civicAuth } = createCivicAuth(request);
294
+ const isLoggedIn = await civicAuth.isLoggedIn();
295
+ if (!isLoggedIn) {
296
+ return null;
297
+ }
298
+ return await civicAuth.getUser();
299
+ }
300
+ catch (error) {
301
+ console.error("[GETUSER_HANDLER] getUser error:", error);
302
+ return null;
303
+ }
304
+ },
305
+ /**
306
+ * Get auth data including user and config (for SSR)
307
+ * Returns user data, config, and other auth-related data needed by the app under a civic key
308
+ */
309
+ getAuthData: async (request) => {
310
+ try {
311
+ const { civicAuth } = createCivicAuth(request);
312
+ const isLoggedIn = await civicAuth.isLoggedIn();
313
+ const user = isLoggedIn ? await civicAuth.getUser() : null;
314
+ // Get the whitelisted config with proper fallbacks using the request
315
+ const configWithFallbacks = getWhitelistedFrontEndConfig(request);
316
+ return {
317
+ civic: {
318
+ user,
319
+ config: configWithFallbacks,
320
+ isLoggedIn,
321
+ },
322
+ };
323
+ }
324
+ catch (error) {
325
+ console.error("[GETAUTHDATA_HANDLER] getAuthData error:", error);
326
+ // Even in error cases, provide config with fallbacks
327
+ const configWithFallbacks = getWhitelistedFrontEndConfig(request);
328
+ return {
329
+ civic: {
330
+ user: null,
331
+ config: configWithFallbacks,
332
+ isLoggedIn: false,
333
+ },
334
+ };
335
+ }
336
+ },
337
+ };
338
+ /**
339
+ * Creates a loader function that handles all auth routes
340
+ * @example
341
+ * // In your auth.$.tsx route file:
342
+ * export const loader = createAuthLoader();
343
+ */
344
+ const createAuthLoader = () => {
345
+ return async (args) => {
346
+ // Get the auth path from the URL
347
+ const authPath = args.params["*"];
348
+ // Route to the appropriate handler
349
+ switch (authPath) {
350
+ case "login":
351
+ return handlers.loginLoader(args);
352
+ case "callback":
353
+ return handlers.callbackLoader(args);
354
+ case "refresh":
355
+ return handlers.refreshLoader(args);
356
+ case "logout":
357
+ return handlers.logoutLoader(args);
358
+ case "user":
359
+ return handlers.userLoader(args);
360
+ default:
361
+ // Return 404 for unknown auth paths
362
+ return new Response("Not Found", { status: 404 });
363
+ }
364
+ };
365
+ };
366
+ /**
367
+ * Creates an action function that handles POST requests to auth routes
368
+ * @example
369
+ * // In your auth.$.tsx route file:
370
+ * export const action = createAuthAction();
371
+ */
372
+ const createAuthAction = () => {
373
+ return async (args) => {
374
+ // Get the auth path from the URL
375
+ const authPath = args.params["*"];
376
+ // Route to the appropriate handler for POST requests
377
+ switch (authPath) {
378
+ case "refresh":
379
+ return handlers.refreshLoader(args); // Same logic for refresh regardless of GET/POST
380
+ default:
381
+ // Return 405 Method Not Allowed for unsupported POST paths
382
+ return new Response("Method Not Allowed", { status: 405 });
383
+ }
384
+ };
385
+ };
386
+ return {
387
+ ...handlers,
388
+ createAuthLoader,
389
+ createAuthAction,
390
+ resolveConfigWithFallbacks,
391
+ getWhitelistedFrontEndConfig,
392
+ };
393
+ }
394
+ //# sourceMappingURL=routeHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routeHandler.js","sourceRoot":"","sources":["../../src/react-router-7/routeHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { redirect, type LoaderFunctionArgs } from \"react-router\";\nimport { CivicAuth } from \"@civic/auth/server\";\nimport { ReactRouterCookieStorage } from \"./cookies.js\";\nimport { resolveAuthConfig } from \"./config.js\";\nimport type {\n AuthConfig,\n ResolvedAuthConfig,\n WhitelistedFrontEndConfig,\n} from \"./config.js\";\nimport { getProtocolFromRequest } from \"@/shared/lib/util.js\";\n\n/**\n * Fields that are safe to expose to the frontend\n */\nconst WHITELISTED_FRONTEND_FIELDS = [\n \"clientId\",\n \"oauthServer\",\n \"callbackUrl\",\n \"logoutCallbackUrl\",\n \"loginUrl\",\n \"baseUrl\",\n \"logoutUrl\",\n] as const;\n\n/**\n * Create auth route handlers for React Router - backend endpoints compatible with VanillaJS frontend integration\n * These routes work similar to the Express example, using server-side CivicAuth SDK\n */\nexport function createRouteHandlers(configOverrides: Partial<AuthConfig> = {}) {\n const config = resolveAuthConfig(configOverrides);\n\n /**\n * Gets a default base URL when no baseUrl is configured\n * Uses request headers to determine protocol when possible\n */\n const getDefaultBaseUrl = (request?: Request): string => {\n const protocol = getProtocolFromRequest(request);\n const host = request ? new URL(request.url).host : \"localhost:5191\";\n\n return `${protocol}//${host}`;\n };\n\n /**\n * Resolves configuration with proper fallbacks based on request context\n * @param request - The request object to extract host for fallbacks\n * @returns Resolved configuration with all fallbacks applied\n */\n const resolveConfigWithFallbacks = (\n request?: Request,\n ): ResolvedAuthConfig => {\n const host = request\n ? `${getProtocolFromRequest(request)}//${new URL(request.url).host}`\n : (config.baseUrl ?? getDefaultBaseUrl(request));\n\n return {\n clientId: config.clientId,\n oauthServer: config.oauthServer,\n callbackUrl: config.callbackUrl ?? `${host}/auth/callback`,\n logoutCallbackUrl: config.logoutCallbackUrl ?? `${host}/auth/logout`,\n loginUrl: config.loginUrl ?? `${host}/auth/login`,\n baseUrl: config.baseUrl ?? host,\n loginSuccessUrl: config.loginSuccessUrl ?? `${host}`,\n logoutUrl: config.logoutUrl ?? `${host}`,\n };\n };\n\n /**\n * Gets the whitelisted frontend configuration with proper fallbacks\n * Only exposes fields that are safe for frontend consumption\n * @param request - The request object to extract host for fallbacks\n * @returns The whitelisted configuration object with fallbacks applied\n */\n const getWhitelistedFrontEndConfig = (\n request?: Request,\n ): WhitelistedFrontEndConfig => {\n const resolved = resolveConfigWithFallbacks(request);\n\n // Filter resolved config to only include whitelisted fields\n return WHITELISTED_FRONTEND_FIELDS.reduce((acc, key) => {\n acc[key] = resolved[key];\n return acc;\n }, {} as WhitelistedFrontEndConfig);\n };\n\n /**\n * Helper to create CivicAuth instance for a request\n */\n const createCivicAuth = (request: Request) => {\n const cookieStorage = new ReactRouterCookieStorage(request);\n\n const resolvedConfig = resolveConfigWithFallbacks(request);\n\n const civicAuth = new CivicAuth(cookieStorage, {\n clientId: resolvedConfig.clientId,\n redirectUrl: resolvedConfig.callbackUrl,\n oauthServer: resolvedConfig.oauthServer,\n postLogoutRedirectUrl: resolvedConfig.logoutCallbackUrl,\n loginSuccessUrl: resolvedConfig.loginSuccessUrl,\n loginUrl: resolvedConfig.loginUrl,\n });\n\n return {\n civicAuth,\n // Use the original cookieStorage instance that we properly configured with setRequest()\n cookieStorage,\n };\n };\n\n /**\n * Helper to create response with cookie headers\n * Following React Router pattern: add serialized cookies as \"Set-Cookie\" headers\n */\n const createResponseWithCookies = (\n body: string,\n init: ResponseInit,\n cookieStorage: ReactRouterCookieStorage,\n ): Response => {\n const headers = new Headers(init.headers);\n\n // Add cookie headers from storage - each one is a complete \"Set-Cookie\" header from cookie.serialize()\n const cookieHeaders = cookieStorage.getCookieHeaders();\n\n cookieHeaders.forEach((cookieHeader) => {\n headers.append(\"Set-Cookie\", cookieHeader);\n });\n\n return new Response(body, {\n ...init,\n headers,\n });\n };\n\n /**\n * Helper to create redirect with cookie headers\n * Following React Router pattern: add serialized cookies as \"Set-Cookie\" headers\n */\n const redirectWithCookies = (\n url: string,\n cookieStorage: ReactRouterCookieStorage,\n init?: ResponseInit,\n ): Response => {\n const headers = new Headers(init?.headers);\n\n // Add cookie headers from storage - each one is a complete \"Set-Cookie\" header from cookie.serialize()\n const cookieHeaders = cookieStorage.getCookieHeaders();\n\n cookieHeaders.forEach((cookieHeader) => {\n headers.append(\"Set-Cookie\", cookieHeader);\n });\n\n // Set Location header for proper redirect\n headers.set(\"Location\", url);\n\n return new Response(null, {\n ...init,\n status: 302,\n headers,\n });\n };\n\n const handlers = {\n /**\n * Login loader - backend OAuth login initiation endpoint\n * Uses CivicAuth.buildLoginUrl() like Express example\n */\n loginLoader: async ({ request }: LoaderFunctionArgs) => {\n const incomingUrl = new URL(request.url);\n const frontendState = incomingUrl.searchParams.get(\"state\");\n // const returnTo = incomingUrl.searchParams.get(\"returnTo\") || \"/\";\n\n try {\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n\n const url = await civicAuth.buildLoginUrl({\n state: frontendState || undefined,\n });\n\n const response = redirectWithCookies(url.toString(), cookieStorage);\n\n return response;\n } catch (error) {\n console.error(\"[LOGIN_HANDLER] Backend login error:\", error);\n return redirect(\"/?error=login_failed\");\n }\n },\n\n /**\n * Callback loader - backend OAuth callback endpoint\n * Uses CivicAuth.handleCallback() like Express example\n */\n callbackLoader: async ({ request }: LoaderFunctionArgs) => {\n try {\n const url = new URL(request.url);\n const code = url.searchParams.get(\"code\");\n const state = url.searchParams.get(\"state\");\n const error = url.searchParams.get(\"error\");\n\n if (error) {\n console.error(\"OAuth error in callback:\", error);\n return redirect(\"/?error=oauth_error\");\n }\n\n if (!code || !state) {\n throw new Error(\"Missing code or state parameter\");\n }\n\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n\n // Convert React Router request to the format expected by handleCallback\n const handleCallbackRequest = {\n headers: Object.fromEntries(request.headers.entries()),\n };\n\n // For non-iframe requests, use the original handleCallback logic\n const result = await civicAuth.handleCallback({\n code,\n state,\n req: handleCallbackRequest,\n });\n\n if (result.redirectTo) {\n return redirectWithCookies(result.redirectTo, cookieStorage);\n }\n\n if (result.content) {\n // Handle both string content and object content\n if (typeof result.content === \"string\") {\n return createResponseWithCookies(\n result.content,\n {\n status: 200,\n headers: {\n \"Content-Type\": \"text/html\",\n },\n },\n cookieStorage,\n );\n } else {\n // Object content (JSON response)\n return createResponseWithCookies(\n JSON.stringify(result.content),\n {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n },\n cookieStorage,\n );\n }\n }\n\n // Fallback redirect\n return redirectWithCookies(\"/\", cookieStorage);\n } catch (error) {\n console.error(\"[CALLBACK_HANDLER] OAuth callback error:\", error);\n return redirect(\"/?error=callback_failed\");\n }\n },\n\n /**\n * Logout loader - backend logout endpoint\n * Uses CivicAuth.buildLogoutRedirectUrl() and clearTokens() like Express example\n */\n logoutLoader: async ({ request }: LoaderFunctionArgs) => {\n try {\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n\n const logoutUrl = await civicAuth.buildLogoutRedirectUrl();\n await civicAuth.clearTokens();\n\n const url = new URL(logoutUrl.toString());\n // Remove the state parameter to avoid it showing up in the frontend URL\n url.searchParams.delete(\"state\");\n\n return redirectWithCookies(url.toString(), cookieStorage);\n } catch (error) {\n console.error(\"[LOGOUT_HANDLER] Logout error:\", error);\n // If logout URL generation fails, clear tokens and redirect to home (Express pattern)\n try {\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n await civicAuth.clearTokens();\n return redirectWithCookies(\"/\", cookieStorage);\n } catch (clearError) {\n console.error(\"[LOGOUT_HANDLER] Failed to clear tokens:\", clearError);\n return redirect(\"/\");\n }\n }\n },\n\n /**\n * User endpoint - returns current user data as JSON\n * Uses CivicAuth.isLoggedIn() and getUser() like Express example\n */\n userLoader: async ({ request }: LoaderFunctionArgs) => {\n try {\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n\n const isLoggedIn = await civicAuth.isLoggedIn();\n\n if (!isLoggedIn) {\n return createResponseWithCookies(\n JSON.stringify({ error: \"Not authenticated\" }),\n {\n status: 401,\n headers: { \"Content-Type\": \"application/json\" },\n },\n cookieStorage,\n );\n }\n\n const user = await civicAuth.getUser();\n\n return createResponseWithCookies(\n JSON.stringify({ user }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n },\n cookieStorage,\n );\n } catch (error) {\n console.error(\"[USER_HANDLER] User endpoint error:\", error);\n return new Response(\n JSON.stringify({ error: \"Internal server error\" }),\n {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n }\n },\n\n /**\n * Refresh endpoint - refreshes access tokens\n * Uses CivicAuth.refreshTokens() like Express example\n */\n refreshLoader: async ({ request }: LoaderFunctionArgs) => {\n try {\n const { civicAuth, cookieStorage } = createCivicAuth(request);\n\n const isLoggedIn = await civicAuth.isLoggedIn();\n if (!isLoggedIn) {\n return createResponseWithCookies(\n JSON.stringify({ error: \"Not authenticated\" }),\n {\n status: 401,\n headers: { \"Content-Type\": \"application/json\" },\n },\n cookieStorage,\n );\n }\n\n await civicAuth.refreshTokens();\n\n return createResponseWithCookies(\n JSON.stringify({ success: true, message: \"Tokens refreshed\" }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n },\n cookieStorage,\n );\n } catch (error) {\n console.error(\"[REFRESH_HANDLER] Token refresh error:\", error);\n return new Response(JSON.stringify({ error: \"Token refresh failed\" }), {\n status: 500,\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n },\n\n /**\n * Get user data from session (for SSR)\n * Uses CivicAuth.isLoggedIn() and getUser() like Express example\n */\n getUser: async (request: Request) => {\n try {\n const { civicAuth } = createCivicAuth(request);\n\n const isLoggedIn = await civicAuth.isLoggedIn();\n if (!isLoggedIn) {\n return null;\n }\n\n return await civicAuth.getUser();\n } catch (error) {\n console.error(\"[GETUSER_HANDLER] getUser error:\", error);\n return null;\n }\n },\n\n /**\n * Get auth data including user and config (for SSR)\n * Returns user data, config, and other auth-related data needed by the app under a civic key\n */\n getAuthData: async (request: Request) => {\n try {\n const { civicAuth } = createCivicAuth(request);\n\n const isLoggedIn = await civicAuth.isLoggedIn();\n const user = isLoggedIn ? await civicAuth.getUser() : null;\n\n // Get the whitelisted config with proper fallbacks using the request\n const configWithFallbacks = getWhitelistedFrontEndConfig(request);\n\n return {\n civic: {\n user,\n config: configWithFallbacks,\n isLoggedIn,\n },\n };\n } catch (error) {\n console.error(\"[GETAUTHDATA_HANDLER] getAuthData error:\", error);\n // Even in error cases, provide config with fallbacks\n const configWithFallbacks = getWhitelistedFrontEndConfig(request);\n return {\n civic: {\n user: null,\n config: configWithFallbacks,\n isLoggedIn: false,\n },\n };\n }\n },\n };\n\n /**\n * Creates a loader function that handles all auth routes\n * @example\n * // In your auth.$.tsx route file:\n * export const loader = createAuthLoader();\n */\n const createAuthLoader = () => {\n return async (args: LoaderFunctionArgs) => {\n // Get the auth path from the URL\n const authPath = args.params[\"*\"];\n\n // Route to the appropriate handler\n switch (authPath) {\n case \"login\":\n return handlers.loginLoader(args);\n\n case \"callback\":\n return handlers.callbackLoader(args);\n\n case \"refresh\":\n return handlers.refreshLoader(args);\n\n case \"logout\":\n return handlers.logoutLoader(args);\n\n case \"user\":\n return handlers.userLoader(args);\n\n default:\n // Return 404 for unknown auth paths\n return new Response(\"Not Found\", { status: 404 });\n }\n };\n };\n\n /**\n * Creates an action function that handles POST requests to auth routes\n * @example\n * // In your auth.$.tsx route file:\n * export const action = createAuthAction();\n */\n const createAuthAction = () => {\n return async (args: LoaderFunctionArgs) => {\n // Get the auth path from the URL\n const authPath = args.params[\"*\"];\n\n // Route to the appropriate handler for POST requests\n switch (authPath) {\n case \"refresh\":\n return handlers.refreshLoader(args); // Same logic for refresh regardless of GET/POST\n\n default:\n // Return 405 Method Not Allowed for unsupported POST paths\n return new Response(\"Method Not Allowed\", { status: 405 });\n }\n };\n };\n\n return {\n ...handlers,\n createAuthLoader,\n createAuthAction,\n resolveConfigWithFallbacks,\n getWhitelistedFrontEndConfig,\n };\n}\n"]}
@@ -0,0 +1,38 @@
1
+ import { type AuthResult, type CivicAuthClientConfig, type User } from "@civic/auth/vanillajs";
2
+ import type { AuthConfig } from "./config.js";
3
+ export type SignInConfig = Pick<CivicAuthClientConfig, "displayMode" | "clientId" | "redirectUrl" | "logoutRedirectUrl" | "targetContainerElement">;
4
+ export interface CivicAuthData {
5
+ user: User | null;
6
+ isLoggedIn: boolean;
7
+ config: AuthConfig;
8
+ }
9
+ export interface RootLoaderData {
10
+ civic: CivicAuthData;
11
+ }
12
+ export interface AuthData {
13
+ isLoggedIn: boolean;
14
+ user: User | null;
15
+ loginUrl: string;
16
+ logoutUrl: string;
17
+ signIn: (config?: SignInConfig) => Promise<AuthResult>;
18
+ signOut: (baseUrl?: string) => Promise<void>;
19
+ }
20
+ /**
21
+ * Hook to access auth data from the root loader
22
+ * @returns CivicAuthData - The civic auth data from the root loader
23
+ */
24
+ export declare function useAuthData(): CivicAuthData | undefined;
25
+ /**
26
+ * Hook to access authentication state and user information (SSR pattern)
27
+ * This is the primary hook for React Router 7 applications using server-side rendering
28
+ * Enhanced with GlobalAuthManager for better state management
29
+ * @returns Authentication state and user information from server-side rendering
30
+ */
31
+ export declare function useUser(): {
32
+ user: import("../types.js").BaseUser | null;
33
+ isLoggedIn: boolean;
34
+ signIn: (config?: SignInConfig) => Promise<AuthResult>;
35
+ signOut: () => Promise<void>;
36
+ config: AuthConfig;
37
+ };
38
+ //# sourceMappingURL=useUser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useUser.d.ts","sourceRoot":"","sources":["../../src/react-router-7/useUser.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,IAAI,EACV,MAAM,uBAAuB,CAAC;AAM/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,MAAM,MAAM,YAAY,GAAG,IAAI,CAC7B,qBAAqB,EACnB,aAAa,GACb,UAAU,GACV,aAAa,GACb,mBAAmB,GACnB,wBAAwB,CAC3B,CAAC;AAGF,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;CACpB;AAGD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,aAAa,CAAC;CACtB;AAGD,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACvD,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,aAAa,GAAG,SAAS,CAKvD;AAED;;;;;GAKG;AACH,wBAAgB,OAAO;;;sBAuCU,YAAY;;YA1EnC,UAAU;EAgHnB"}
@@ -0,0 +1,92 @@
1
+ import { useMatches, useRevalidator } from "react-router";
2
+ import {} from "@civic/auth/vanillajs";
3
+ import { GlobalAuthManager, } from "../reactjs/core/GlobalAuthManager.js";
4
+ import { useEffect, useMemo, useState } from "react";
5
+ /**
6
+ * Hook to access auth data from the root loader
7
+ * @returns CivicAuthData - The civic auth data from the root loader
8
+ */
9
+ export function useAuthData() {
10
+ const matches = useMatches();
11
+ const rootMatch = matches.find((match) => match.id === "root");
12
+ const data = rootMatch?.data;
13
+ return data?.civic;
14
+ }
15
+ /**
16
+ * Hook to access authentication state and user information (SSR pattern)
17
+ * This is the primary hook for React Router 7 applications using server-side rendering
18
+ * Enhanced with GlobalAuthManager for better state management
19
+ * @returns Authentication state and user information from server-side rendering
20
+ */
21
+ export function useUser() {
22
+ const authData = useAuthData();
23
+ const revalidator = useRevalidator();
24
+ const [authManager] = useState(() => GlobalAuthManager.getInstance());
25
+ if (!authData) {
26
+ throw new Error("Auth data not found. Make sure to use createRootAuthLoader in your root route.");
27
+ }
28
+ const initialConfig = useMemo(() => {
29
+ return {
30
+ clientId: authData.config.clientId,
31
+ loginUrl: authData.config.loginUrl,
32
+ displayMode: "iframe",
33
+ framework: "react-router",
34
+ config: {
35
+ oauthServer: authData.config.oauthServer,
36
+ },
37
+ onSignIn: (error) => {
38
+ if (!error) {
39
+ revalidator.revalidate();
40
+ }
41
+ },
42
+ onSignOut: () => {
43
+ revalidator.revalidate();
44
+ },
45
+ };
46
+ }, [revalidator, authData]);
47
+ useEffect(() => {
48
+ const initialize = async () => {
49
+ await authManager.initialize(initialConfig);
50
+ };
51
+ initialize();
52
+ }, [authManager, initialConfig]);
53
+ // Create signIn function that leverages GlobalAuthManager
54
+ const signIn = async (config) => {
55
+ try {
56
+ if (config) {
57
+ await authManager.initialize({
58
+ ...initialConfig,
59
+ ...config,
60
+ });
61
+ }
62
+ const result = await authManager.signIn();
63
+ // Return in AuthResult format for compatibility
64
+ return result;
65
+ }
66
+ catch (error) {
67
+ console.error("Sign-in failed:", error);
68
+ throw error;
69
+ }
70
+ };
71
+ // Create signOut function that leverages GlobalAuthManager
72
+ const signOut = async () => {
73
+ try {
74
+ await authManager.signOut();
75
+ // The onSignOut callback will handle revalidation
76
+ }
77
+ catch (error) {
78
+ console.error("Sign-out failed:", error);
79
+ // Still try redirecting to logout URL as fallback
80
+ window.location.href = "/auth/logout";
81
+ }
82
+ };
83
+ // Ensure we have a valid user object or null
84
+ return {
85
+ ...authData,
86
+ user: authData.user || null,
87
+ isLoggedIn: !!authData.user,
88
+ signIn,
89
+ signOut,
90
+ };
91
+ }
92
+ //# sourceMappingURL=useUser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useUser.js","sourceRoot":"","sources":["../../src/react-router-7/useUser.ts"],"names":[],"mappings":"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","sourcesContent":["import { useMatches, useRevalidator } from \"react-router\";\nimport {\n type AuthResult,\n type CivicAuthClientConfig,\n type User,\n} from \"@civic/auth/vanillajs\";\nimport {\n GlobalAuthManager,\n type GlobalAuthConfig,\n} from \"../reactjs/core/GlobalAuthManager.js\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { AuthConfig } from \"./config.js\";\n\n// Configuration type for signIn function\nexport type SignInConfig = Pick<\n CivicAuthClientConfig,\n | \"displayMode\"\n | \"clientId\"\n | \"redirectUrl\"\n | \"logoutRedirectUrl\"\n | \"targetContainerElement\"\n>;\n\n// Type for the civic auth data structure from the root loader\nexport interface CivicAuthData {\n user: User | null;\n isLoggedIn: boolean;\n config: AuthConfig;\n}\n\n// Type for the complete root loader data structure\nexport interface RootLoaderData {\n civic: CivicAuthData;\n}\n\n// Type for the auth data that will be available in the root loader (SSR pattern)\nexport interface AuthData {\n isLoggedIn: boolean;\n user: User | null;\n loginUrl: string;\n logoutUrl: string;\n signIn: (config?: SignInConfig) => Promise<AuthResult>;\n signOut: (baseUrl?: string) => Promise<void>;\n}\n\n/**\n * Hook to access auth data from the root loader\n * @returns CivicAuthData - The civic auth data from the root loader\n */\nexport function useAuthData(): CivicAuthData | undefined {\n const matches = useMatches();\n const rootMatch = matches.find((match) => match.id === \"root\");\n const data = rootMatch?.data as RootLoaderData | undefined;\n return data?.civic;\n}\n\n/**\n * Hook to access authentication state and user information (SSR pattern)\n * This is the primary hook for React Router 7 applications using server-side rendering\n * Enhanced with GlobalAuthManager for better state management\n * @returns Authentication state and user information from server-side rendering\n */\nexport function useUser() {\n const authData = useAuthData();\n const revalidator = useRevalidator();\n const [authManager] = useState(() => GlobalAuthManager.getInstance());\n\n if (!authData) {\n throw new Error(\n \"Auth data not found. Make sure to use createRootAuthLoader in your root route.\",\n );\n }\n\n const initialConfig: GlobalAuthConfig = useMemo(() => {\n return {\n clientId: authData.config.clientId,\n loginUrl: authData.config.loginUrl,\n displayMode: \"iframe\",\n framework: \"react-router\",\n config: {\n oauthServer: authData.config.oauthServer,\n },\n onSignIn: (error) => {\n if (!error) {\n revalidator.revalidate();\n }\n },\n onSignOut: () => {\n revalidator.revalidate();\n },\n };\n }, [revalidator, authData]);\n\n useEffect(() => {\n const initialize = async () => {\n await authManager.initialize(initialConfig);\n };\n initialize();\n }, [authManager, initialConfig]);\n\n // Create signIn function that leverages GlobalAuthManager\n const signIn = async (config?: SignInConfig) => {\n try {\n if (config) {\n await authManager.initialize({\n ...initialConfig,\n ...config,\n });\n }\n const result = await authManager.signIn();\n\n // Return in AuthResult format for compatibility\n return result as AuthResult;\n } catch (error) {\n console.error(\"Sign-in failed:\", error);\n throw error;\n }\n };\n\n // Create signOut function that leverages GlobalAuthManager\n const signOut = async () => {\n try {\n await authManager.signOut();\n // The onSignOut callback will handle revalidation\n } catch (error) {\n console.error(\"Sign-out failed:\", error);\n // Still try redirecting to logout URL as fallback\n window.location.href = \"/auth/logout\";\n }\n };\n\n // Ensure we have a valid user object or null\n return {\n ...authData,\n user: authData.user || null,\n isLoggedIn: !!authData.user,\n signIn,\n signOut,\n };\n}\n"]}
@@ -27,15 +27,17 @@
27
27
  * - Server-side rendering scenarios where providers might be problematic
28
28
  */
29
29
  import type { User, Session } from "../../vanillajs/index.js";
30
- import type { DisplayMode, FrameworkType } from "../../types.js";
30
+ import type { FrameworkType } from "../../types.js";
31
+ import type { VanillaJSDisplayMode } from "../../vanillajs/auth/types/AuthTypes.js";
31
32
  import type { LoggingConfig } from "../../vanillajs/auth/types/AuthTypes.js";
32
33
  export interface GlobalAuthConfig {
33
- clientId: string;
34
+ clientId?: string;
34
35
  redirectUrl?: string;
36
+ loginUrl?: string;
35
37
  config?: {
36
38
  oauthServer?: string;
37
39
  };
38
- displayMode?: DisplayMode;
40
+ displayMode?: VanillaJSDisplayMode;
39
41
  iframeMode?: "modal" | "embedded";
40
42
  nonce?: string;
41
43
  logoutRedirectUrl?: string;
@@ -56,7 +58,7 @@ export interface GlobalAuthState {
56
58
  isLoading: boolean;
57
59
  authStatus: AuthStatus;
58
60
  error: Error | null;
59
- displayMode?: DisplayMode;
61
+ displayMode?: VanillaJSDisplayMode;
60
62
  isPreloaded?: boolean;
61
63
  }
62
64
  type StateListener = (state: GlobalAuthState) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"GlobalAuthManager.d.ts","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAOH,OAAO,KAAK,EACV,IAAI,EACJ,OAAO,EAER,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAQzE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE;QACP,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED,MAAM,MAAM,UAAU,GAClB,eAAe,GACf,iBAAiB,GACjB,gBAAgB,GAChB,OAAO,GACP,aAAa,CAAC;AAElB,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAEtD;;;GAGG;AACH,cAAM,iBAAiB;IACrB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkC;IACzD,OAAO,CAAC,IAAI,CAA0B;IACtC,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,SAAS,CAGV;IACP,OAAO,CAAC,qBAAqB,CAA8B;IAE3D,OAAO,CAAC,KAAK,CAOX;IAEF,OAAO;IAIP,MAAM,CAAC,WAAW,IAAI,iBAAiB;IAOvC;;;OAGG;IACG,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBzD;;OAEG;YACW,aAAa;IAgF3B;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,IAAI;IAK9C;;OAEG;IACH,QAAQ,IAAI,eAAe;IAI3B;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAC;IAiBvC;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAa9B;;;OAGG;IACH,yBAAyB,IAAI,OAAO;IAIpC;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOzC;;OAEG;IACH,iBAAiB,IAAI,OAAO;IAI5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAYpB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAwD3B;;OAEG;YACW,qBAAqB;IAiBnC;;OAEG;IACH,OAAO,CAAC,QAAQ;IAKhB;;OAEG;YACW,OAAO;CAStB;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"GlobalAuthManager.d.ts","sourceRoot":"","sources":["../../../src/reactjs/core/GlobalAuthManager.ts"],"names":[],"mappings":"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"}