@thunderid/nextjs 1.2.3 → 1.3.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 (128) hide show
  1. package/dist/ThunderIDNextClient.d.ts +33 -1
  2. package/dist/ThunderIDNextClient.d.ts.map +1 -1
  3. package/dist/ThunderIDNextClient.js +28 -1
  4. package/dist/ThunderIDNextClient.js.map +1 -1
  5. package/dist/cjs/ThunderIDNextClient.cjs +28 -1
  6. package/dist/cjs/ThunderIDNextClient.cjs.map +1 -1
  7. package/dist/cjs/client/components/presentation/AuthFlowSelect/AuthFlowSelect.cjs +25 -0
  8. package/dist/cjs/client/components/presentation/AuthFlowSelect/AuthFlowSelect.cjs.map +1 -0
  9. package/dist/cjs/client/components/presentation/SignIn/SignIn.cjs.map +1 -1
  10. package/dist/cjs/client/components/presentation/SignUp/SignUp.cjs +3 -2
  11. package/dist/cjs/client/components/presentation/SignUp/SignUp.cjs.map +1 -1
  12. package/dist/cjs/client/components/presentation/UserSelect/UserSelect.cjs +25 -0
  13. package/dist/cjs/client/components/presentation/UserSelect/UserSelect.cjs.map +1 -0
  14. package/dist/cjs/client/components/presentation/UserTypeSelect/UserTypeSelect.cjs +25 -0
  15. package/dist/cjs/client/components/presentation/UserTypeSelect/UserTypeSelect.cjs.map +1 -0
  16. package/dist/cjs/client/contexts/ThunderID/ThunderIDProvider.cjs +3 -2
  17. package/dist/cjs/client/contexts/ThunderID/ThunderIDProvider.cjs.map +1 -1
  18. package/dist/cjs/client/fetchAuthFlowsFromServer.cjs +18 -0
  19. package/dist/cjs/client/fetchAuthFlowsFromServer.cjs.map +1 -0
  20. package/dist/cjs/client/fetchFlowMetaFromServer.cjs +22 -0
  21. package/dist/cjs/client/fetchFlowMetaFromServer.cjs.map +1 -0
  22. package/dist/cjs/client/fetchUserTypesFromServer.cjs +18 -0
  23. package/dist/cjs/client/fetchUserTypesFromServer.cjs.map +1 -0
  24. package/dist/cjs/client/fetchUsersFromServer.cjs +18 -0
  25. package/dist/cjs/client/fetchUsersFromServer.cjs.map +1 -0
  26. package/dist/cjs/client/index.cjs +3 -0
  27. package/dist/cjs/client/loadPageFromAction.cjs +19 -0
  28. package/dist/cjs/client/loadPageFromAction.cjs.map +1 -0
  29. package/dist/cjs/index.cjs +6 -0
  30. package/dist/cjs/server/ThunderIDProvider.cjs +0 -2
  31. package/dist/cjs/server/ThunderIDProvider.cjs.map +1 -1
  32. package/dist/cjs/server/actions/getAuthFlowsAction.cjs +28 -0
  33. package/dist/cjs/server/actions/getAuthFlowsAction.cjs.map +1 -0
  34. package/dist/cjs/server/actions/getFlowMetaAction.cjs +30 -12
  35. package/dist/cjs/server/actions/getFlowMetaAction.cjs.map +1 -1
  36. package/dist/cjs/server/actions/getUserTypesAction.cjs +27 -0
  37. package/dist/cjs/server/actions/getUserTypesAction.cjs.map +1 -0
  38. package/dist/cjs/server/actions/getUsersAction.cjs +28 -0
  39. package/dist/cjs/server/actions/getUsersAction.cjs.map +1 -0
  40. package/dist/cjs/server/actions/handleOAuthCallbackAction.cjs +1 -0
  41. package/dist/cjs/server/actions/handleOAuthCallbackAction.cjs.map +1 -1
  42. package/dist/cjs/server/actions/runSelectPageAction.cjs +47 -0
  43. package/dist/cjs/server/actions/runSelectPageAction.cjs.map +1 -0
  44. package/dist/cjs/server/proxy/createRouteMatcher.cjs +21 -4
  45. package/dist/cjs/server/proxy/createRouteMatcher.cjs.map +1 -1
  46. package/dist/cjs/utils/SessionManager.cjs +11 -7
  47. package/dist/cjs/utils/SessionManager.cjs.map +1 -1
  48. package/dist/client/components/presentation/AuthFlowSelect/AuthFlowSelect.d.ts +11 -0
  49. package/dist/client/components/presentation/AuthFlowSelect/AuthFlowSelect.d.ts.map +1 -0
  50. package/dist/client/components/presentation/AuthFlowSelect/AuthFlowSelect.js +22 -0
  51. package/dist/client/components/presentation/AuthFlowSelect/AuthFlowSelect.js.map +1 -0
  52. package/dist/client/components/presentation/SignIn/SignIn.d.ts +1 -1
  53. package/dist/client/components/presentation/SignIn/SignIn.d.ts.map +1 -1
  54. package/dist/client/components/presentation/SignIn/SignIn.js.map +1 -1
  55. package/dist/client/components/presentation/SignUp/SignUp.d.ts.map +1 -1
  56. package/dist/client/components/presentation/SignUp/SignUp.js +3 -2
  57. package/dist/client/components/presentation/SignUp/SignUp.js.map +1 -1
  58. package/dist/client/components/presentation/UserSelect/UserSelect.d.ts +11 -0
  59. package/dist/client/components/presentation/UserSelect/UserSelect.d.ts.map +1 -0
  60. package/dist/client/components/presentation/UserSelect/UserSelect.js +22 -0
  61. package/dist/client/components/presentation/UserSelect/UserSelect.js.map +1 -0
  62. package/dist/client/components/presentation/UserTypeSelect/UserTypeSelect.d.ts +11 -0
  63. package/dist/client/components/presentation/UserTypeSelect/UserTypeSelect.d.ts.map +1 -0
  64. package/dist/client/components/presentation/UserTypeSelect/UserTypeSelect.js +22 -0
  65. package/dist/client/components/presentation/UserTypeSelect/UserTypeSelect.js.map +1 -0
  66. package/dist/client/contexts/ThunderID/ThunderIDProvider.d.ts +0 -11
  67. package/dist/client/contexts/ThunderID/ThunderIDProvider.d.ts.map +1 -1
  68. package/dist/client/contexts/ThunderID/ThunderIDProvider.js +3 -2
  69. package/dist/client/contexts/ThunderID/ThunderIDProvider.js.map +1 -1
  70. package/dist/client/fetchAuthFlowsFromServer.d.ts +9 -0
  71. package/dist/client/fetchAuthFlowsFromServer.d.ts.map +1 -0
  72. package/dist/client/fetchAuthFlowsFromServer.js +18 -0
  73. package/dist/client/fetchAuthFlowsFromServer.js.map +1 -0
  74. package/dist/client/fetchFlowMetaFromServer.d.ts +12 -0
  75. package/dist/client/fetchFlowMetaFromServer.d.ts.map +1 -0
  76. package/dist/client/fetchFlowMetaFromServer.js +20 -0
  77. package/dist/client/fetchFlowMetaFromServer.js.map +1 -0
  78. package/dist/client/fetchUserTypesFromServer.d.ts +9 -0
  79. package/dist/client/fetchUserTypesFromServer.d.ts.map +1 -0
  80. package/dist/client/fetchUserTypesFromServer.js +18 -0
  81. package/dist/client/fetchUserTypesFromServer.js.map +1 -0
  82. package/dist/client/fetchUsersFromServer.d.ts +8 -0
  83. package/dist/client/fetchUsersFromServer.d.ts.map +1 -0
  84. package/dist/client/fetchUsersFromServer.js +18 -0
  85. package/dist/client/fetchUsersFromServer.js.map +1 -0
  86. package/dist/client/index.d.ts +6 -0
  87. package/dist/client/index.d.ts.map +1 -1
  88. package/dist/client/index.js +3 -0
  89. package/dist/client/loadPageFromAction.d.ts +9 -0
  90. package/dist/client/loadPageFromAction.d.ts.map +1 -0
  91. package/dist/client/loadPageFromAction.js +17 -0
  92. package/dist/client/loadPageFromAction.js.map +1 -0
  93. package/dist/index.js +4 -1
  94. package/dist/server/ThunderIDProvider.d.ts.map +1 -1
  95. package/dist/server/ThunderIDProvider.js +0 -2
  96. package/dist/server/ThunderIDProvider.js.map +1 -1
  97. package/dist/server/actions/getAuthFlowsAction.d.ts +19 -0
  98. package/dist/server/actions/getAuthFlowsAction.d.ts.map +1 -0
  99. package/dist/server/actions/getAuthFlowsAction.js +26 -0
  100. package/dist/server/actions/getAuthFlowsAction.js.map +1 -0
  101. package/dist/server/actions/getFlowMetaAction.d.ts +16 -1
  102. package/dist/server/actions/getFlowMetaAction.d.ts.map +1 -1
  103. package/dist/server/actions/getFlowMetaAction.js +31 -13
  104. package/dist/server/actions/getFlowMetaAction.js.map +1 -1
  105. package/dist/server/actions/getUserTypesAction.d.ts +18 -0
  106. package/dist/server/actions/getUserTypesAction.d.ts.map +1 -0
  107. package/dist/server/actions/getUserTypesAction.js +25 -0
  108. package/dist/server/actions/getUserTypesAction.js.map +1 -0
  109. package/dist/server/actions/getUsersAction.d.ts +18 -0
  110. package/dist/server/actions/getUsersAction.d.ts.map +1 -0
  111. package/dist/server/actions/getUsersAction.js +26 -0
  112. package/dist/server/actions/getUsersAction.js.map +1 -0
  113. package/dist/server/actions/handleOAuthCallbackAction.d.ts.map +1 -1
  114. package/dist/server/actions/handleOAuthCallbackAction.js +1 -0
  115. package/dist/server/actions/handleOAuthCallbackAction.js.map +1 -1
  116. package/dist/server/actions/runSelectPageAction.d.ts +28 -0
  117. package/dist/server/actions/runSelectPageAction.d.ts.map +1 -0
  118. package/dist/server/actions/runSelectPageAction.js +45 -0
  119. package/dist/server/actions/runSelectPageAction.js.map +1 -0
  120. package/dist/server/proxy/createRouteMatcher.d.ts +0 -19
  121. package/dist/server/proxy/createRouteMatcher.d.ts.map +1 -1
  122. package/dist/server/proxy/createRouteMatcher.js +21 -4
  123. package/dist/server/proxy/createRouteMatcher.js.map +1 -1
  124. package/dist/utils/SessionManager.d.ts +1 -1
  125. package/dist/utils/SessionManager.d.ts.map +1 -1
  126. package/dist/utils/SessionManager.js +3 -1
  127. package/dist/utils/SessionManager.js.map +1 -1
  128. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"ThunderIDProvider.cjs","names":["ThunderIDClientProvider: FC<PropsWithChildren<ThunderIDClientProviderProps>>","reRenderCheckRef: RefObject<boolean>","router: AppRouterInstance","searchParams: ReadonlyURLSearchParams","code: string | null","state: string | null","result: {error?: string; redirectUrl?: string; success: boolean}","ThunderIDRuntimeError","result: any","contextValue: ThunderIDContextProps","reactContextValue: ReactThunderIDContextProps","ThunderIDContext","ReactThunderIDContext","I18nProvider","FlowMetaProvider","ThemeProvider","FlowProvider","UserProvider"],"sources":["../../../../../src/client/contexts/ThunderID/ThunderIDProvider.tsx"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use client';\n\nimport {\n AttributeSchema,\n EmbeddedFlowExecuteRequestConfig,\n FlowMetadataResponse,\n generateFlattenedUserProfile,\n UpdateMeProfileConfig,\n User,\n UserProfile,\n ThunderIDRuntimeError,\n getVendorPrefix,\n} from '@thunderid/node';\nimport {\n I18nProvider,\n FlowMetaProvider,\n FlowProvider,\n UserProvider,\n ThemeProvider,\n ThunderIDContext as ReactThunderIDContext,\n ThunderIDContextProps as ReactThunderIDContextProps,\n ThunderIDProviderProps,\n} from '@thunderid/react';\nimport {ReadonlyURLSearchParams} from 'next/dist/client/components/navigation.react-server';\nimport {AppRouterInstance} from 'next/dist/shared/lib/app-router-context.shared-runtime';\nimport {useRouter, useSearchParams} from 'next/navigation';\nimport {FC, PropsWithChildren, RefObject, useEffect, useMemo, useRef, useState} from 'react';\nimport ThunderIDContext, {ThunderIDContextProps} from './ThunderIDContext';\nimport {RefreshResult} from '../../../server/actions/refreshToken';\nimport logger from '../../../utils/logger';\n\n/**\n * Props interface of {@link ThunderIDClientProvider}\n */\nexport type ThunderIDClientProviderProps = Partial<Omit<ThunderIDProviderProps, 'baseUrl' | 'clientId'>> &\n Pick<ThunderIDProviderProps, 'baseUrl' | 'clientId'> & {\n applicationId: ThunderIDContextProps['applicationId'];\n clearSession: () => Promise<void>;\n /**\n * Server Action that fetches `GET /flow/meta` server-side, passed down to `FlowMetaProvider` so\n * it never calls `baseUrl` directly from the browser — avoiding the CORS requirement that a\n * direct client-side fetch to the ThunderID server would otherwise impose. Used for both the\n * initial fetch (when `initialMeta` isn't seeded, e.g. it failed server-side) and subsequent\n * `switchLanguage()` calls.\n */\n fetchMeta?: (params: {applicationId?: string; language?: string}) => Promise<FlowMetadataResponse>;\n handleOAuthCallback: (\n code: string,\n state: string,\n ) => Promise<{error?: string; redirectUrl?: string; success: boolean}>;\n /**\n * Flow metadata fetched server-side ahead of time, seeding `FlowMetaProvider` so it can skip\n * its own initial client-side fetch (avoiding a flash of untranslated i18n keys).\n */\n initialMeta?: FlowMetadataResponse | null;\n isSignedIn: boolean;\n organizationHandle: ThunderIDContextProps['organizationHandle'];\n refreshToken: () => Promise<RefreshResult>;\n signIn: ThunderIDContextProps['signIn'];\n signOut: ThunderIDContextProps['signOut'];\n signUp: ThunderIDContextProps['signUp'];\n updateProfile: (\n requestConfig: UpdateMeProfileConfig,\n sessionId?: string,\n ) => Promise<{data: {user: User}; error: string; success: boolean}>;\n user: User | null;\n userProfile: UserProfile;\n userSchema?: Record<string, AttributeSchema> | null;\n };\n\nconst ThunderIDClientProvider: FC<PropsWithChildren<ThunderIDClientProviderProps>> = ({\n baseUrl,\n children,\n signIn,\n clearSession,\n refreshToken,\n signOut,\n signUp,\n handleOAuthCallback,\n preferences,\n isSignedIn,\n signInUrl,\n signUpUrl,\n user: _user,\n userProfile: _userProfile,\n userSchema: _userSchema = null,\n updateProfile,\n applicationId,\n organizationHandle,\n scopes,\n vendor,\n initialMeta = null,\n fetchMeta,\n}: PropsWithChildren<ThunderIDClientProviderProps>) => {\n const reRenderCheckRef: RefObject<boolean> = useRef(false);\n const router: AppRouterInstance = useRouter();\n const searchParams: ReadonlyURLSearchParams = useSearchParams();\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [user, setUser] = useState<User | null>(_user);\n const [userProfile, setUserProfile] = useState<UserProfile>(_userProfile);\n const [userSchema, setUserSchema] = useState<Record<string, AttributeSchema> | null>(_userSchema);\n\n useEffect(() => {\n setUserProfile(_userProfile);\n }, [_userProfile]);\n\n useEffect(() => {\n setUserSchema(_userSchema);\n }, [_userSchema]);\n\n useEffect(() => {\n setUser(_user);\n }, [_user]);\n\n // Handle OAuth callback automatically\n useEffect(() => {\n // React 18.x Strict.Mode has a new check for `Ensuring reusable state` to facilitate an upcoming react feature.\n // https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state\n // This will remount all the useEffects to ensure that there are no unexpected side effects.\n // When react remounts the signIn hook of the AuthProvider, it will cause a race condition. Hence, we have to\n // prevent the re-render of this hook as suggested in the following discussion.\n // https://github.com/reactwg/react-18/discussions/18#discussioncomment-795623\n if (reRenderCheckRef.current) {\n return;\n }\n\n reRenderCheckRef.current = true;\n\n // Don't handle callback if already signed in\n if (isSignedIn) return;\n\n (async (): Promise<void> => {\n try {\n const code: string | null = searchParams.get('code');\n const state: string | null = searchParams.get('state');\n const error: string | null = searchParams.get('error');\n\n // Check for OAuth errors first\n if (error) {\n logger.error('[ThunderIDClientProvider] An error was received for the initiated sign-in request.');\n\n return;\n }\n\n // Handle OAuth callback if code and state are present\n if (code && state) {\n setIsLoading(true);\n\n const result: {error?: string; redirectUrl?: string; success: boolean} = await handleOAuthCallback(\n code,\n state,\n );\n\n if (result.success) {\n // Redirect to the success URL\n if (result.redirectUrl) {\n router.push(result.redirectUrl);\n } else {\n // Refresh the page to update authentication state\n window.location.reload();\n }\n } else {\n logger.error(\n `[ThunderIDClientProvider] An error occurred while signing in: ${result.error || 'Authentication failed'}`,\n );\n }\n }\n } catch (error) {\n logger.error('[ThunderIDClientProvider] Failed to handle OAuth callback:', error);\n }\n })();\n }, []);\n\n useEffect(() => {\n // Set loading to false when server has resolved authentication state\n setIsLoading(false);\n }, [isSignedIn, user]);\n\n const handleSignIn = async (payload: any, request: EmbeddedFlowExecuteRequestConfig): Promise<any> => {\n if (!signIn) {\n throw new ThunderIDRuntimeError(\n '`signIn` function is not available.',\n 'ThunderIDClientProvider-handleSignIn-RuntimeError-001',\n 'nextjs',\n );\n }\n\n const result: any = await signIn(payload, request);\n\n // Redirect based flow URL is sent as `signInUrl` in the response.\n // Use window.location.href instead of router.push() — the OAuth authorization\n // endpoint is on an external server, and router.push() would send RSC fetch\n // headers that the identity provider doesn't understand, causing a CORS error.\n if (result?.data?.signInUrl) {\n window.location.href = result.data.signInUrl;\n\n return undefined;\n }\n\n // After the Embedded flow is successful, the URL to navigate next is sent as `afterSignInUrl` in the response.\n if (result?.data?.afterSignInUrl) {\n router.push(result.data.afterSignInUrl);\n\n return undefined;\n }\n\n if (result?.error) {\n throw new Error(result.error);\n }\n\n return result?.data ?? result;\n };\n\n const handleSignUp = async (payload: any, request: EmbeddedFlowExecuteRequestConfig): Promise<any> => {\n if (!signUp) {\n throw new ThunderIDRuntimeError(\n '`signUp` function is not available.',\n 'ThunderIDClientProvider-handleSignUp-RuntimeError-001',\n 'nextjs',\n );\n }\n\n const result: any = await signUp(payload, request);\n\n // Redirect based flow URL is sent as `signUpUrl` in the response.\n if (result?.data?.signUpUrl) {\n router.push(result.data.signUpUrl);\n\n return undefined;\n }\n\n // After the Embedded flow is successful, the URL to navigate next is sent as `afterSignUpUrl` in the response.\n if (result?.data?.afterSignUpUrl) {\n router.push(result.data.afterSignUpUrl);\n\n return undefined;\n }\n\n if (result?.error) {\n throw new Error(result.error);\n }\n\n return result?.data ?? result;\n };\n\n const handleSignOut = async (): Promise<any> => {\n logger.debug('[ThunderIDClientProvider][handleSignOut] `handleSignOut` called.');\n\n try {\n const result: any = await signOut();\n\n logger.debug('[ThunderIDClientProvider][handleSignOut] Sign out result:', result);\n\n if (result?.data?.afterSignOutUrl) {\n router.push(result.data.afterSignOutUrl);\n\n return {location: result.data.afterSignOutUrl, redirected: true};\n }\n\n if (result?.error) {\n logger.error(\n '[ThunderIDClientProvider][handleSignOut] Error result was returned during signing the user out with a button click:',\n result.error,\n );\n }\n\n return result?.data ?? result;\n } catch (error) {\n logger.error(\n '[ThunderIDClientProvider][handleSignOut] Error occurred during signing the user out with a button click:',\n error,\n );\n\n return undefined;\n }\n };\n\n const contextValue: ThunderIDContextProps = useMemo(\n () => ({\n applicationId,\n baseUrl,\n clearSession,\n isLoading,\n isSignedIn,\n organizationHandle,\n preferences,\n refreshToken,\n scopes,\n signIn: handleSignIn,\n signInUrl,\n signOut: handleSignOut,\n signUp: handleSignUp,\n signUpUrl,\n user,\n }),\n [\n baseUrl,\n user,\n isSignedIn,\n isLoading,\n signInUrl,\n signUpUrl,\n applicationId,\n organizationHandle,\n scopes,\n preferences,\n ],\n );\n\n const handleProfileUpdate = (payload: User): void => {\n setUser(payload);\n setUserProfile((prev: UserProfile) => ({\n ...prev,\n flattenedProfile: generateFlattenedUserProfile(payload),\n profile: payload,\n }));\n };\n\n // Bridge into @thunderid/react's own ThunderIDContext. Internal react components rendered by\n // BaseSignIn/BaseSignUp — most notably FlowMetaProvider, which fetches `/flow/meta` and injects\n // its i18n bundle — call react's `useThunderID()` directly. Without this bridge they'd only see\n // react's context default (applicationId/baseUrl undefined, isInitialized false), so the meta\n // fetch would never fire and flow labels would render as untranslated i18n keys. Fields with no\n // nextjs equivalent (token/http helpers meant for direct browser API calls) are stubbed out,\n // since nextjs routes those operations through server actions instead.\n const unsupported = (name: string): (() => Promise<never>) => {\n return () =>\n Promise.reject(\n new ThunderIDRuntimeError(\n `\\`${name}\\` is not supported in @thunderid/nextjs.`,\n `ThunderIDClientProvider-${name}-NotSupportedError-001`,\n 'nextjs',\n ),\n );\n };\n\n const reactContextValue: ReactThunderIDContextProps = useMemo(\n () => ({\n afterSignInUrl: undefined,\n applicationId,\n baseUrl,\n clearSession,\n clientId: undefined,\n discovery: {wellKnown: null},\n exchangeToken: unsupported('exchangeToken'),\n getAccessToken: unsupported('getAccessToken'),\n getDecodedIdToken: unsupported('getDecodedIdToken'),\n getIdToken: unsupported('getIdToken'),\n getStorageManager: () => Promise.resolve(null),\n http: {\n request: unsupported('http.request'),\n requestAll: unsupported('http.requestAll'),\n },\n instanceId: 0,\n isInitialized: !isLoading,\n isLoading,\n isMetaLoading: false,\n isSignedIn,\n meta: initialMeta ?? null,\n organizationHandle,\n reInitialize: unsupported('reInitialize'),\n recover: unsupported('recover'),\n resolveFlowTemplateLiterals: (text: string | undefined): string => text ?? '',\n scopes,\n signIn: handleSignIn,\n signInSilently: unsupported('signInSilently'),\n signInUrl,\n signOut: handleSignOut,\n signUp: handleSignUp,\n signUpUrl,\n user,\n userSchema,\n vendor: getVendorPrefix(vendor),\n }),\n [\n applicationId,\n baseUrl,\n clearSession,\n isLoading,\n isSignedIn,\n organizationHandle,\n scopes,\n signInUrl,\n signUpUrl,\n user,\n userSchema,\n initialMeta,\n vendor,\n ],\n );\n\n return (\n <ThunderIDContext.Provider value={contextValue}>\n <ReactThunderIDContext.Provider value={reactContextValue}>\n <I18nProvider preferences={preferences?.i18n}>\n <FlowMetaProvider\n enabled={preferences?.resolveFromMeta !== false}\n initialMeta={initialMeta}\n fetchMeta={fetchMeta}\n >\n <ThemeProvider theme={preferences?.theme?.overrides} mode={preferences?.theme?.mode}>\n <FlowProvider>\n <UserProvider\n profile={userProfile}\n userSchema={userSchema}\n onUpdateProfile={handleProfileUpdate}\n updateProfile={updateProfile}\n >\n {children}\n </UserProvider>\n </FlowProvider>\n </ThemeProvider>\n </FlowMetaProvider>\n </I18nProvider>\n </ReactThunderIDContext.Provider>\n </ThunderIDContext.Provider>\n );\n};\n\nexport default ThunderIDClientProvider;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ThunderIDProvider.cjs","names":["ThunderIDClientProvider: FC<PropsWithChildren<ThunderIDClientProviderProps>>","reRenderCheckRef: RefObject<boolean>","router: AppRouterInstance","searchParams: ReadonlyURLSearchParams","code: string | null","state: string | null","result: {error?: string; redirectUrl?: string; success: boolean}","ThunderIDRuntimeError","result: any","contextValue: ThunderIDContextProps","reactContextValue: ReactThunderIDContextProps","ThunderIDContext","ReactThunderIDContext","I18nProvider","FlowMetaProvider","fetchFlowMetaFromServer","ThemeProvider","FlowProvider","UserProvider"],"sources":["../../../../../src/client/contexts/ThunderID/ThunderIDProvider.tsx"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use client';\n\nimport {\n AttributeSchema,\n EmbeddedFlowExecuteRequestConfig,\n FlowMetadataResponse,\n generateFlattenedUserProfile,\n UpdateMeProfileConfig,\n User,\n UserProfile,\n ThunderIDRuntimeError,\n getVendorPrefix,\n} from '@thunderid/node';\nimport {\n I18nProvider,\n FlowMetaProvider,\n FlowProvider,\n UserProvider,\n ThemeProvider,\n ThunderIDContext as ReactThunderIDContext,\n ThunderIDContextProps as ReactThunderIDContextProps,\n ThunderIDProviderProps,\n} from '@thunderid/react';\nimport {ReadonlyURLSearchParams} from 'next/dist/client/components/navigation.react-server';\nimport {AppRouterInstance} from 'next/dist/shared/lib/app-router-context.shared-runtime';\nimport {useRouter, useSearchParams} from 'next/navigation';\nimport {FC, PropsWithChildren, RefObject, useEffect, useMemo, useRef, useState} from 'react';\nimport ThunderIDContext, {ThunderIDContextProps} from './ThunderIDContext';\nimport {RefreshResult} from '../../../server/actions/refreshToken';\nimport logger from '../../../utils/logger';\nimport fetchFlowMetaFromServer from '../../fetchFlowMetaFromServer';\n\n/**\n * Props interface of {@link ThunderIDClientProvider}\n */\nexport type ThunderIDClientProviderProps = Partial<Omit<ThunderIDProviderProps, 'baseUrl' | 'clientId'>> &\n Pick<ThunderIDProviderProps, 'baseUrl' | 'clientId'> & {\n applicationId: ThunderIDContextProps['applicationId'];\n clearSession: () => Promise<void>;\n handleOAuthCallback: (\n code: string,\n state: string,\n ) => Promise<{error?: string; redirectUrl?: string; success: boolean}>;\n /**\n * Flow metadata fetched server-side ahead of time, seeding `FlowMetaProvider` so it can skip\n * its own initial client-side fetch (avoiding a flash of untranslated i18n keys).\n */\n initialMeta?: FlowMetadataResponse | null;\n isSignedIn: boolean;\n organizationHandle: ThunderIDContextProps['organizationHandle'];\n refreshToken: () => Promise<RefreshResult>;\n signIn: ThunderIDContextProps['signIn'];\n signOut: ThunderIDContextProps['signOut'];\n signUp: ThunderIDContextProps['signUp'];\n updateProfile: (\n requestConfig: UpdateMeProfileConfig,\n sessionId?: string,\n ) => Promise<{data: {user: User}; error: string; success: boolean}>;\n user: User | null;\n userProfile: UserProfile;\n userSchema?: Record<string, AttributeSchema> | null;\n };\n\nconst ThunderIDClientProvider: FC<PropsWithChildren<ThunderIDClientProviderProps>> = ({\n baseUrl,\n children,\n signIn,\n clearSession,\n refreshToken,\n signOut,\n signUp,\n handleOAuthCallback,\n preferences,\n isSignedIn,\n signInUrl,\n signUpUrl,\n user: _user,\n userProfile: _userProfile,\n userSchema: _userSchema = null,\n updateProfile,\n applicationId,\n organizationHandle,\n scopes,\n vendor,\n initialMeta = null,\n}: PropsWithChildren<ThunderIDClientProviderProps>) => {\n const reRenderCheckRef: RefObject<boolean> = useRef(false);\n const router: AppRouterInstance = useRouter();\n const searchParams: ReadonlyURLSearchParams = useSearchParams();\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [user, setUser] = useState<User | null>(_user);\n const [userProfile, setUserProfile] = useState<UserProfile>(_userProfile);\n const [userSchema, setUserSchema] = useState<Record<string, AttributeSchema> | null>(_userSchema);\n\n useEffect(() => {\n setUserProfile(_userProfile);\n }, [_userProfile]);\n\n useEffect(() => {\n setUserSchema(_userSchema);\n }, [_userSchema]);\n\n useEffect(() => {\n setUser(_user);\n }, [_user]);\n\n // Handle OAuth callback automatically\n useEffect(() => {\n // React 18.x Strict.Mode has a new check for `Ensuring reusable state` to facilitate an upcoming react feature.\n // https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state\n // This will remount all the useEffects to ensure that there are no unexpected side effects.\n // When react remounts the signIn hook of the AuthProvider, it will cause a race condition. Hence, we have to\n // prevent the re-render of this hook as suggested in the following discussion.\n // https://github.com/reactwg/react-18/discussions/18#discussioncomment-795623\n if (reRenderCheckRef.current) {\n return;\n }\n\n reRenderCheckRef.current = true;\n\n // Don't handle callback if already signed in\n if (isSignedIn) return;\n\n (async (): Promise<void> => {\n try {\n const code: string | null = searchParams.get('code');\n const state: string | null = searchParams.get('state');\n const error: string | null = searchParams.get('error');\n\n // Check for OAuth errors first\n if (error) {\n logger.error('[ThunderIDClientProvider] An error was received for the initiated sign-in request.');\n\n return;\n }\n\n // Handle OAuth callback if code and state are present\n if (code && state) {\n setIsLoading(true);\n\n const result: {error?: string; redirectUrl?: string; success: boolean} = await handleOAuthCallback(\n code,\n state,\n );\n\n if (result.success) {\n // Redirect to the success URL\n if (result.redirectUrl) {\n router.push(result.redirectUrl);\n } else {\n // Refresh the page to update authentication state\n window.location.reload();\n }\n } else {\n logger.error(\n `[ThunderIDClientProvider] An error occurred while signing in: ${result.error || 'Authentication failed'}`,\n );\n }\n }\n } catch (error) {\n logger.error('[ThunderIDClientProvider] Failed to handle OAuth callback:', error);\n }\n })();\n }, []);\n\n useEffect(() => {\n // Set loading to false when server has resolved authentication state\n setIsLoading(false);\n }, [isSignedIn, user]);\n\n const handleSignIn = async (payload: any, request: EmbeddedFlowExecuteRequestConfig): Promise<any> => {\n if (!signIn) {\n throw new ThunderIDRuntimeError(\n '`signIn` function is not available.',\n 'ThunderIDClientProvider-handleSignIn-RuntimeError-001',\n 'nextjs',\n );\n }\n\n const result: any = await signIn(payload, request);\n\n // Redirect based flow URL is sent as `signInUrl` in the response.\n // Use window.location.href instead of router.push() — the OAuth authorization\n // endpoint is on an external server, and router.push() would send RSC fetch\n // headers that the identity provider doesn't understand, causing a CORS error.\n if (result?.data?.signInUrl) {\n window.location.href = result.data.signInUrl;\n\n return undefined;\n }\n\n // After the Embedded flow is successful, the URL to navigate next is sent as `afterSignInUrl` in the response.\n if (result?.data?.afterSignInUrl) {\n router.push(result.data.afterSignInUrl);\n\n return undefined;\n }\n\n if (result?.error) {\n throw new Error(result.error);\n }\n\n return result?.data ?? result;\n };\n\n const handleSignUp = async (payload: any, request: EmbeddedFlowExecuteRequestConfig): Promise<any> => {\n if (!signUp) {\n throw new ThunderIDRuntimeError(\n '`signUp` function is not available.',\n 'ThunderIDClientProvider-handleSignUp-RuntimeError-001',\n 'nextjs',\n );\n }\n\n const result: any = await signUp(payload, request);\n\n // Redirect based flow URL is sent as `signUpUrl` in the response.\n if (result?.data?.signUpUrl) {\n router.push(result.data.signUpUrl);\n\n return undefined;\n }\n\n // After the Embedded flow is successful, the URL to navigate next is sent as `afterSignUpUrl` in the response.\n if (result?.data?.afterSignUpUrl) {\n router.push(result.data.afterSignUpUrl);\n\n return undefined;\n }\n\n if (result?.error) {\n throw new Error(result.error);\n }\n\n return result?.data ?? result;\n };\n\n const handleSignOut = async (): Promise<any> => {\n logger.debug('[ThunderIDClientProvider][handleSignOut] `handleSignOut` called.');\n\n try {\n const result: any = await signOut();\n\n logger.debug('[ThunderIDClientProvider][handleSignOut] Sign out result:', result);\n\n if (result?.data?.afterSignOutUrl) {\n router.push(result.data.afterSignOutUrl);\n\n return {location: result.data.afterSignOutUrl, redirected: true};\n }\n\n if (result?.error) {\n logger.error(\n '[ThunderIDClientProvider][handleSignOut] Error result was returned during signing the user out with a button click:',\n result.error,\n );\n }\n\n return result?.data ?? result;\n } catch (error) {\n logger.error(\n '[ThunderIDClientProvider][handleSignOut] Error occurred during signing the user out with a button click:',\n error,\n );\n\n return undefined;\n }\n };\n\n const contextValue: ThunderIDContextProps = useMemo(\n () => ({\n applicationId,\n baseUrl,\n clearSession,\n isLoading,\n isSignedIn,\n organizationHandle,\n preferences,\n refreshToken,\n scopes,\n signIn: handleSignIn,\n signInUrl,\n signOut: handleSignOut,\n signUp: handleSignUp,\n signUpUrl,\n user,\n }),\n [\n baseUrl,\n user,\n isSignedIn,\n isLoading,\n signInUrl,\n signUpUrl,\n applicationId,\n organizationHandle,\n scopes,\n preferences,\n ],\n );\n\n const handleProfileUpdate = (payload: User): void => {\n setUser(payload);\n setUserProfile((prev: UserProfile) => ({\n ...prev,\n flattenedProfile: generateFlattenedUserProfile(payload),\n profile: payload,\n }));\n };\n\n // Bridge into @thunderid/react's own ThunderIDContext. Internal react components rendered by\n // BaseSignIn/BaseSignUp — most notably FlowMetaProvider, which fetches `/flow/meta` and injects\n // its i18n bundle — call react's `useThunderID()` directly. Without this bridge they'd only see\n // react's context default (applicationId/baseUrl undefined, isInitialized false), so the meta\n // fetch would never fire and flow labels would render as untranslated i18n keys. Fields with no\n // nextjs equivalent (token/http helpers meant for direct browser API calls) are stubbed out,\n // since nextjs routes those operations through server actions instead.\n const unsupported = (name: string): (() => Promise<never>) => {\n return () =>\n Promise.reject(\n new ThunderIDRuntimeError(\n `\\`${name}\\` is not supported in @thunderid/nextjs.`,\n `ThunderIDClientProvider-${name}-NotSupportedError-001`,\n 'nextjs',\n ),\n );\n };\n\n const reactContextValue: ReactThunderIDContextProps = useMemo(\n () => ({\n afterSignInUrl: undefined,\n applicationId,\n baseUrl,\n clearSession,\n clientId: undefined,\n discovery: {wellKnown: null},\n exchangeToken: unsupported('exchangeToken'),\n getAccessToken: unsupported('getAccessToken'),\n getDecodedIdToken: unsupported('getDecodedIdToken'),\n getIdToken: unsupported('getIdToken'),\n getStorageManager: () => Promise.resolve(null),\n http: {\n request: unsupported('http.request'),\n requestAll: unsupported('http.requestAll'),\n },\n instanceId: 0,\n isInitialized: !isLoading,\n isLoading,\n isMetaLoading: false,\n isSignedIn,\n meta: initialMeta ?? null,\n organizationHandle,\n reInitialize: unsupported('reInitialize'),\n recover: unsupported('recover'),\n resolveFlowTemplateLiterals: (text: string | undefined): string => text ?? '',\n scopes,\n signIn: handleSignIn,\n signInSilently: unsupported('signInSilently'),\n signInUrl,\n signOut: handleSignOut,\n signUp: handleSignUp,\n signUpUrl,\n user,\n userSchema,\n vendor: getVendorPrefix(vendor),\n }),\n [\n applicationId,\n baseUrl,\n clearSession,\n isLoading,\n isSignedIn,\n organizationHandle,\n scopes,\n signInUrl,\n signUpUrl,\n user,\n userSchema,\n initialMeta,\n vendor,\n ],\n );\n\n return (\n <ThunderIDContext.Provider value={contextValue}>\n <ReactThunderIDContext.Provider value={reactContextValue}>\n <I18nProvider preferences={preferences?.i18n}>\n <FlowMetaProvider\n enabled={preferences?.resolveFromMeta !== false}\n initialMeta={initialMeta}\n fetchMeta={fetchFlowMetaFromServer}\n >\n <ThemeProvider theme={preferences?.theme?.overrides} mode={preferences?.theme?.mode}>\n <FlowProvider>\n <UserProvider\n profile={userProfile}\n userSchema={userSchema}\n onUpdateProfile={handleProfileUpdate}\n updateProfile={updateProfile}\n >\n {children}\n </UserProvider>\n </FlowProvider>\n </ThemeProvider>\n </FlowMetaProvider>\n </I18nProvider>\n </ReactThunderIDContext.Provider>\n </ThunderIDContext.Provider>\n );\n};\n\nexport default ThunderIDClientProvider;\n"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ const require_loadPageFromAction = require('./loadPageFromAction.cjs');
2
+ const require_getAuthFlowsAction = require('../server/actions/getAuthFlowsAction.cjs');
3
+
4
+ //#region src/client/fetchAuthFlowsFromServer.ts
5
+ /**
6
+ * The loader behind `AuthFlowSelect`: loads authentication flows through {@link getAuthFlowsAction} with the
7
+ * signed-in user's server-held session. Requires an existing session. `request.signal` is not forwarded because
8
+ * an `AbortSignal` cannot cross the server action boundary.
9
+ */
10
+ const fetchAuthFlowsFromServer = async ({ limit, offset }) => require_loadPageFromAction.default(await require_getAuthFlowsAction.default({
11
+ limit,
12
+ offset
13
+ }), "getAuthFlowsAction-Error-001");
14
+ var fetchAuthFlowsFromServer_default = fetchAuthFlowsFromServer;
15
+
16
+ //#endregion
17
+ exports.default = fetchAuthFlowsFromServer_default;
18
+ //# sourceMappingURL=fetchAuthFlowsFromServer.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchAuthFlowsFromServer.cjs","names":["fetchAuthFlowsFromServer: FetchAuthFlows","loadPageFromAction","getAuthFlowsAction"],"sources":["../../../src/client/fetchAuthFlowsFromServer.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type {FetchAuthFlows, SelectPage, SelectPageRequest} from '@thunderid/node';\nimport loadPageFromAction from './loadPageFromAction';\nimport getAuthFlowsAction from '../server/actions/getAuthFlowsAction';\n\n/**\n * The loader behind `AuthFlowSelect`: loads authentication flows through {@link getAuthFlowsAction} with the\n * signed-in user's server-held session. Requires an existing session. `request.signal` is not forwarded because\n * an `AbortSignal` cannot cross the server action boundary.\n */\nconst fetchAuthFlowsFromServer: FetchAuthFlows = async ({limit, offset}: SelectPageRequest): Promise<SelectPage> =>\n loadPageFromAction(await getAuthFlowsAction({limit, offset}), 'getAuthFlowsAction-Error-001');\n\nexport default fetchAuthFlowsFromServer;\n"],"mappings":";;;;;;;;;AAYA,MAAMA,2BAA2C,OAAO,EAAC,OAAO,aAC9DC,mCAAmB,MAAMC,mCAAmB;CAAC;CAAO;CAAO,CAAC,EAAE,+BAA+B;AAE/F,uCAAe"}
@@ -0,0 +1,22 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const require_getFlowMetaAction = require('../server/actions/getFlowMetaAction.cjs');
3
+ let __thunderid_node = require("@thunderid/node");
4
+ __thunderid_node = require_rolldown_runtime.__toESM(__thunderid_node);
5
+
6
+ //#region src/client/fetchFlowMetaFromServer.ts
7
+ /**
8
+ * The `fetchMeta` behind `FlowMetaProvider`: loads flow metadata through {@link getFlowMetaAction} so the browser
9
+ * never calls `baseUrl` directly, and throws the failure the action returned as an SDK error, which
10
+ * `FlowMetaProvider` reports through its `error` state.
11
+ */
12
+ const fetchFlowMetaFromServer = async (params) => {
13
+ const result = await require_getFlowMetaAction.default(params);
14
+ if (result.success) return result.meta;
15
+ if (result.statusCode !== void 0) throw new __thunderid_node.ThunderIDAPIError(result.message, "getFlowMetaAction-Error-001", "nextjs", result.statusCode);
16
+ throw new __thunderid_node.ThunderIDRuntimeError(result.message, "getFlowMetaAction-Error-001", "nextjs");
17
+ };
18
+ var fetchFlowMetaFromServer_default = fetchFlowMetaFromServer;
19
+
20
+ //#endregion
21
+ exports.default = fetchFlowMetaFromServer_default;
22
+ //# sourceMappingURL=fetchFlowMetaFromServer.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchFlowMetaFromServer.cjs","names":["result: GetFlowMetaActionResult","getFlowMetaAction","ThunderIDAPIError","ThunderIDRuntimeError"],"sources":["../../../src/client/fetchFlowMetaFromServer.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {FlowMetadataResponse, ThunderIDAPIError, ThunderIDRuntimeError} from '@thunderid/node';\nimport getFlowMetaAction, {GetFlowMetaActionResult} from '../server/actions/getFlowMetaAction';\n\n/**\n * The `fetchMeta` behind `FlowMetaProvider`: loads flow metadata through {@link getFlowMetaAction} so the browser\n * never calls `baseUrl` directly, and throws the failure the action returned as an SDK error, which\n * `FlowMetaProvider` reports through its `error` state.\n */\nconst fetchFlowMetaFromServer = async (params: {\n applicationId?: string;\n language?: string;\n}): Promise<FlowMetadataResponse> => {\n const result: GetFlowMetaActionResult = await getFlowMetaAction(params);\n\n if (result.success) {\n return result.meta;\n }\n\n if (result.statusCode !== undefined) {\n throw new ThunderIDAPIError(result.message, 'getFlowMetaAction-Error-001', 'nextjs', result.statusCode);\n }\n\n throw new ThunderIDRuntimeError(result.message, 'getFlowMetaAction-Error-001', 'nextjs');\n};\n\nexport default fetchFlowMetaFromServer;\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,0BAA0B,OAAO,WAGF;CACnC,MAAMA,SAAkC,MAAMC,kCAAkB,OAAO;AAEvE,KAAI,OAAO,QACT,QAAO,OAAO;AAGhB,KAAI,OAAO,eAAe,OACxB,OAAM,IAAIC,mCAAkB,OAAO,SAAS,+BAA+B,UAAU,OAAO,WAAW;AAGzG,OAAM,IAAIC,uCAAsB,OAAO,SAAS,+BAA+B,SAAS;;AAG1F,sCAAe"}
@@ -0,0 +1,18 @@
1
+ const require_loadPageFromAction = require('./loadPageFromAction.cjs');
2
+ const require_getUserTypesAction = require('../server/actions/getUserTypesAction.cjs');
3
+
4
+ //#region src/client/fetchUserTypesFromServer.ts
5
+ /**
6
+ * The loader behind `UserTypeSelect`: loads user types through {@link getUserTypesAction} with the signed-in
7
+ * user's server-held session. Requires an existing session. `request.signal` is not forwarded because an
8
+ * `AbortSignal` cannot cross the server action boundary.
9
+ */
10
+ const fetchUserTypesFromServer = async ({ limit, offset }) => require_loadPageFromAction.default(await require_getUserTypesAction.default({
11
+ limit,
12
+ offset
13
+ }), "getUserTypesAction-Error-001");
14
+ var fetchUserTypesFromServer_default = fetchUserTypesFromServer;
15
+
16
+ //#endregion
17
+ exports.default = fetchUserTypesFromServer_default;
18
+ //# sourceMappingURL=fetchUserTypesFromServer.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchUserTypesFromServer.cjs","names":["fetchUserTypesFromServer: FetchUserTypes","loadPageFromAction","getUserTypesAction"],"sources":["../../../src/client/fetchUserTypesFromServer.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type {FetchUserTypes, SelectPage, SelectPageRequest} from '@thunderid/node';\nimport loadPageFromAction from './loadPageFromAction';\nimport getUserTypesAction from '../server/actions/getUserTypesAction';\n\n/**\n * The loader behind `UserTypeSelect`: loads user types through {@link getUserTypesAction} with the signed-in\n * user's server-held session. Requires an existing session. `request.signal` is not forwarded because an\n * `AbortSignal` cannot cross the server action boundary.\n */\nconst fetchUserTypesFromServer: FetchUserTypes = async ({limit, offset}: SelectPageRequest): Promise<SelectPage> =>\n loadPageFromAction(await getUserTypesAction({limit, offset}), 'getUserTypesAction-Error-001');\n\nexport default fetchUserTypesFromServer;\n"],"mappings":";;;;;;;;;AAYA,MAAMA,2BAA2C,OAAO,EAAC,OAAO,aAC9DC,mCAAmB,MAAMC,mCAAmB;CAAC;CAAO;CAAO,CAAC,EAAE,+BAA+B;AAE/F,uCAAe"}
@@ -0,0 +1,18 @@
1
+ const require_loadPageFromAction = require('./loadPageFromAction.cjs');
2
+ const require_getUsersAction = require('../server/actions/getUsersAction.cjs');
3
+
4
+ //#region src/client/fetchUsersFromServer.ts
5
+ /**
6
+ * The loader behind `UserSelect`: loads users through {@link getUsersAction} with the signed-in user's server-held session.
7
+ * Requires an existing session. `request.signal` is not forwarded because an `AbortSignal` cannot cross the server action boundary.
8
+ */
9
+ const fetchUsersFromServer = async ({ filter, limit, offset }) => require_loadPageFromAction.default(await require_getUsersAction.default({
10
+ filter,
11
+ limit,
12
+ offset
13
+ }), "getUsersAction-Error-001");
14
+ var fetchUsersFromServer_default = fetchUsersFromServer;
15
+
16
+ //#endregion
17
+ exports.default = fetchUsersFromServer_default;
18
+ //# sourceMappingURL=fetchUsersFromServer.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetchUsersFromServer.cjs","names":["fetchUsersFromServer: FetchUsers","loadPageFromAction","getUsersAction"],"sources":["../../../src/client/fetchUsersFromServer.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport type {FetchUsers, SelectPage, SelectPageRequest} from '@thunderid/node';\nimport loadPageFromAction from './loadPageFromAction';\nimport getUsersAction from '../server/actions/getUsersAction';\n\n/**\n * The loader behind `UserSelect`: loads users through {@link getUsersAction} with the signed-in user's server-held session.\n * Requires an existing session. `request.signal` is not forwarded because an `AbortSignal` cannot cross the server action boundary.\n */\nconst fetchUsersFromServer: FetchUsers = async ({filter, limit, offset}: SelectPageRequest): Promise<SelectPage> =>\n loadPageFromAction(await getUsersAction({filter, limit, offset}), 'getUsersAction-Error-001');\n\nexport default fetchUsersFromServer;\n"],"mappings":";;;;;;;;AAWA,MAAMA,uBAAmC,OAAO,EAAC,QAAQ,OAAO,aAC9DC,mCAAmB,MAAMC,+BAAe;CAAC;CAAQ;CAAO;CAAO,CAAC,EAAE,2BAA2B;AAE/F,mCAAe"}
@@ -11,3 +11,6 @@ const require_UserProfile = require('./components/presentation/UserProfile/UserP
11
11
  const require_UserDropdown = require('./components/presentation/UserDropdown/UserDropdown.cjs');
12
12
  const require_UserAvatar = require('./components/presentation/UserAvatar/UserAvatar.cjs');
13
13
  const require_ChangeCredential = require('./components/presentation/ChangeCredential/ChangeCredential.cjs');
14
+ const require_UserSelect = require('./components/presentation/UserSelect/UserSelect.cjs');
15
+ const require_AuthFlowSelect = require('./components/presentation/AuthFlowSelect/AuthFlowSelect.cjs');
16
+ const require_UserTypeSelect = require('./components/presentation/UserTypeSelect/UserTypeSelect.cjs');
@@ -0,0 +1,19 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ let __thunderid_node = require("@thunderid/node");
3
+ __thunderid_node = require_rolldown_runtime.__toESM(__thunderid_node);
4
+
5
+ //#region src/client/loadPageFromAction.ts
6
+ /**
7
+ * Turns a select page server action result into a loader page, or throws the failure it carries. The message was built
8
+ * on the server from fixed words and the status, so it is safe to show to a developer.
9
+ */
10
+ const loadPageFromAction = (result, errorCode) => {
11
+ if (result.success) return result.page;
12
+ if (result.statusCode !== void 0) throw new __thunderid_node.ThunderIDAPIError(result.message, errorCode, "nextjs", result.statusCode);
13
+ throw new __thunderid_node.ThunderIDRuntimeError(result.message, errorCode, "nextjs");
14
+ };
15
+ var loadPageFromAction_default = loadPageFromAction;
16
+
17
+ //#endregion
18
+ exports.default = loadPageFromAction_default;
19
+ //# sourceMappingURL=loadPageFromAction.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadPageFromAction.cjs","names":["ThunderIDAPIError","ThunderIDRuntimeError"],"sources":["../../../src/client/loadPageFromAction.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\nimport {ThunderIDAPIError, ThunderIDRuntimeError} from '@thunderid/node';\nimport type {SelectPage} from '@thunderid/node';\nimport type {SelectPageActionResult} from '../server/actions/runSelectPageAction';\n\n/**\n * Turns a select page server action result into a loader page, or throws the failure it carries. The message was built\n * on the server from fixed words and the status, so it is safe to show to a developer.\n */\nconst loadPageFromAction = (result: SelectPageActionResult, errorCode: string): SelectPage => {\n if (result.success) {\n return result.page;\n }\n\n if (result.statusCode !== undefined) {\n throw new ThunderIDAPIError(result.message, errorCode, 'nextjs', result.statusCode);\n }\n\n throw new ThunderIDRuntimeError(result.message, errorCode, 'nextjs');\n};\n\nexport default loadPageFromAction;\n"],"mappings":";;;;;;;;;AAWA,MAAM,sBAAsB,QAAgC,cAAkC;AAC5F,KAAI,OAAO,QACT,QAAO,OAAO;AAGhB,KAAI,OAAO,eAAe,OACxB,OAAM,IAAIA,mCAAkB,OAAO,SAAS,WAAW,UAAU,OAAO,WAAW;AAGrF,OAAM,IAAIC,uCAAsB,OAAO,SAAS,WAAW,SAAS;;AAGtE,iCAAe"}
@@ -18,8 +18,12 @@ const require_UserProfile = require('./client/components/presentation/UserProfil
18
18
  const require_UserDropdown = require('./client/components/presentation/UserDropdown/UserDropdown.cjs');
19
19
  const require_UserAvatar = require('./client/components/presentation/UserAvatar/UserAvatar.cjs');
20
20
  const require_ChangeCredential = require('./client/components/presentation/ChangeCredential/ChangeCredential.cjs');
21
+ const require_UserSelect = require('./client/components/presentation/UserSelect/UserSelect.cjs');
22
+ const require_AuthFlowSelect = require('./client/components/presentation/AuthFlowSelect/AuthFlowSelect.cjs');
23
+ const require_UserTypeSelect = require('./client/components/presentation/UserTypeSelect/UserTypeSelect.cjs');
21
24
  require('./client/index.cjs');
22
25
 
26
+ exports.AuthFlowSelect = require_AuthFlowSelect.default;
23
27
  exports.ChangeCredential = require_ChangeCredential.default;
24
28
  exports.SignIn = require_SignIn.default;
25
29
  exports.SignInButton = require_SignInButton.default;
@@ -34,6 +38,8 @@ exports.User = require_User.default;
34
38
  exports.UserAvatar = require_UserAvatar.default;
35
39
  exports.UserDropdown = require_UserDropdown.default;
36
40
  exports.UserProfile = require_UserProfile.default;
41
+ exports.UserSelect = require_UserSelect.default;
42
+ exports.UserTypeSelect = require_UserTypeSelect.default;
37
43
  exports.backchannelLogout = require_backchannelLogout.default;
38
44
  exports.createRouteMatcher = require_createRouteMatcher.default;
39
45
  exports.removeChunkedCookieFromHeader = require_thunderIDProxy.removeChunkedCookieFromHeader;
@@ -17,7 +17,6 @@ const require_signInAction = require('./actions/signInAction.cjs');
17
17
  const require_signOutAction = require('./actions/signOutAction.cjs');
18
18
  const require_signUpAction = require('./actions/signUpAction.cjs');
19
19
  const require_updateUserProfileAction = require('./actions/updateUserProfileAction.cjs');
20
- const require_getFlowMetaAction = require('./actions/getFlowMetaAction.cjs');
21
20
  const require_ThunderIDProvider = require('../client/contexts/ThunderID/ThunderIDProvider.cjs');
22
21
  let __thunderid_node = require("@thunderid/node");
23
22
  __thunderid_node = require_rolldown_runtime.__toESM(__thunderid_node);
@@ -126,7 +125,6 @@ const ThunderIDServerProvider = async ({ children, afterSignInUrl, afterSignOutU
126
125
  applicationId: config?.applicationId,
127
126
  baseUrl: config?.baseUrl,
128
127
  initialMeta: flowMeta,
129
- fetchMeta: require_getFlowMetaAction.default,
130
128
  signIn: require_signInAction.default,
131
129
  clearSession: require_clearSession.default,
132
130
  refreshToken: require_refreshToken.default,
@@ -1 +1 @@
1
- {"version":3,"file":"ThunderIDProvider.cjs","names":["ThunderIDServerProvider: FC<PropsWithChildren<ThunderIDServerProviderProps>>","getClient","config: Partial<ThunderIDNextConfig>","ThunderIDRuntimeError","flowMeta: FlowMetadataResponse | null","FlowMetaType","sessionPayload: SessionTokenPayload | undefined","getSessionPayload","sessionId: string","getSessionId","signedIn: boolean","isSignedIn","user: User","userProfile: UserProfile","userSchema: Record<string, AttributeSchema> | null","updatedBaseUrl: string | undefined","userResponse: {\n data: {user: User | null};\n error: string | null;\n success: boolean;\n }","getUserAction","userProfileResponse: {\n data: {userProfile: UserProfile};\n error: string | null;\n success: boolean;\n }","getUserProfileAction","userSchemaResponse: {\n data: {userSchema: Record<string, AttributeSchema> | null};\n error: string | null;\n success: boolean;\n }","getUserSchemaAction","ThunderIDClientProvider","getFlowMetaAction","signInAction","clearSession","refreshToken","signOutAction","signUpAction","handleOAuthCallbackAction","updateUserProfileAction"],"sources":["../../../src/server/ThunderIDProvider.tsx"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {\n ThunderIDRuntimeError,\n AttributeSchema,\n FlowMetadataResponse,\n FlowMetaType,\n IdToken,\n User,\n UserProfile,\n getFlowMeta,\n extractUserClaimsFromIdToken,\n resolveResourceEndpoint,\n} from '@thunderid/node';\nimport {ThunderIDProviderProps} from '@thunderid/react';\nimport {FC, PropsWithChildren, ReactElement} from 'react';\nimport clearSession from './actions/clearSession';\nimport getSessionId from './actions/getSessionId';\nimport getSessionPayload from './actions/getSessionPayload';\nimport getUserAction from './actions/getUserAction';\nimport getUserProfileAction from './actions/getUserProfileAction';\nimport getUserSchemaAction from './actions/getUserSchemaAction';\nimport handleOAuthCallbackAction from './actions/handleOAuthCallbackAction';\nimport isSignedIn from './actions/isSignedIn';\nimport refreshToken from './actions/refreshToken';\nimport signInAction from './actions/signInAction';\nimport signOutAction from './actions/signOutAction';\nimport signUpAction from './actions/signUpAction';\nimport updateUserProfileAction from './actions/updateUserProfileAction';\nimport getFlowMetaAction from './actions/getFlowMetaAction';\nimport getClient from './getClient';\nimport ThunderIDClientProvider from '../client/contexts/ThunderID/ThunderIDProvider.js';\nimport {ThunderIDNextConfig} from '../models/config';\nimport logger from '../utils/logger';\nimport {SessionTokenPayload} from '../utils/SessionManager';\n\n/**\n * Props interface of {@link ThunderIDServerProvider}\n */\nexport type ThunderIDServerProviderProps = Partial<ThunderIDProviderProps> & {\n clientSecret?: string;\n /**\n * Session cookie lifetime in seconds. Determines how long the session cookie\n * remains valid in the browser after sign-in.\n *\n * Resolution order (first defined value wins):\n * 1. This prop — set here when mounting the provider.\n * 2. `THUNDERID_SESSION_COOKIE_EXPIRY_TIME` environment variable.\n * 3. Built-in default of 86400 seconds (24 hours).\n *\n * @example\n * // 8-hour session cookie\n * <ThunderIDServerProvider sessionCookieExpiryTime={28800} ... />\n */\n sessionCookieExpiryTime?: number;\n};\n\n/**\n * Server-side provider component for ThunderID authentication.\n * Wraps the client-side provider and handles server-side authentication logic.\n * Uses the singleton ThunderIDNextClient instance for consistent authentication state.\n *\n * @param props - Props injected into the component.\n *\n * @example\n * ```tsx\n * <ThunderIDServerProvider config={thunderidConfig}>\n * <YourApp />\n * </ThunderIDServerProvider>\n * ```\n *\n * @returns ThunderIDServerProvider component.\n */\nconst ThunderIDServerProvider: FC<PropsWithChildren<ThunderIDServerProviderProps>> = async ({\n children,\n afterSignInUrl,\n afterSignOutUrl,\n ..._config\n}: PropsWithChildren<ThunderIDServerProviderProps>): Promise<ReactElement> => {\n const thunderIDClient = getClient();\n let config: Partial<ThunderIDNextConfig> = {};\n\n try {\n await thunderIDClient.initialize(_config as ThunderIDNextConfig);\n\n logger.debug('[ThunderIDServerProvider] ThunderID client initialized successfully.');\n\n config = await thunderIDClient.getConfiguration();\n } catch (error) {\n logger.error('[ThunderIDServerProvider] Failed to initialize ThunderID client:', error?.toString());\n\n throw new ThunderIDRuntimeError(\n `Failed to initialize ThunderID client: ${error?.toString()}`,\n 'next-ConfigurationError-001',\n 'next',\n 'An error occurred while initializing the ThunderID client. Please check your configuration.',\n );\n }\n\n if (!thunderIDClient.isInitialized) {\n return <></>;\n }\n\n // Fetch flow metadata (design config + i18n bundle) server-side so `FlowMetaProvider` can seed\n // its state and skip a redundant client-side fetch — avoiding a flash of untranslated i18n keys\n // (e.g. raw `signin.forms.credentials.title`) while embedded flow components first render.\n let flowMeta: FlowMetadataResponse | null = null;\n try {\n flowMeta = await getFlowMeta({\n baseUrl: config?.baseUrl,\n url: resolveResourceEndpoint('flowMeta', config),\n ...(config?.applicationId ? {id: config.applicationId, type: FlowMetaType.App} : {}),\n });\n } catch (error) {\n logger.warn('[ThunderIDServerProvider] Failed to fetch flow metadata:', error?.toString());\n }\n\n // Try to get session information from JWT first, then fall back to legacy\n const sessionPayload: SessionTokenPayload | undefined = await getSessionPayload();\n const sessionId: string = sessionPayload?.sessionId || (await getSessionId()) || '';\n const signedIn: boolean = await isSignedIn(sessionId);\n\n let user: User = {};\n let userProfile: UserProfile = {\n flattenedProfile: {},\n profile: {},\n };\n let userSchema: Record<string, AttributeSchema> | null = null;\n\n const resolvedPreferences = {\n ...config?.preferences,\n ..._config.preferences,\n user: {\n ...config?.preferences?.user,\n ..._config.preferences?.user,\n },\n };\n\n if (signedIn) {\n let updatedBaseUrl: string | undefined = config?.baseUrl;\n\n if (sessionPayload?.organizationId) {\n updatedBaseUrl = `${config?.baseUrl}/o`;\n config = {...config, baseUrl: updatedBaseUrl};\n } else if (sessionId) {\n try {\n const idToken: IdToken = await thunderIDClient.getDecodedIdToken(sessionId);\n if (idToken?.['user_org']) {\n updatedBaseUrl = `${config?.baseUrl}/o`;\n config = {...config, baseUrl: updatedBaseUrl};\n }\n } catch {\n // Continue without organization info\n }\n }\n\n // Check if user profile fetching is enabled (default: true)\n const shouldFetchUserProfile: boolean = resolvedPreferences?.user?.fetchUserProfile !== false;\n\n if (shouldFetchUserProfile) {\n try {\n const userResponse: {\n data: {user: User | null};\n error: string | null;\n success: boolean;\n } = await getUserAction(sessionId);\n const userProfileResponse: {\n data: {userProfile: UserProfile};\n error: string | null;\n success: boolean;\n } = await getUserProfileAction(sessionId);\n const userSchemaResponse: {\n data: {userSchema: Record<string, AttributeSchema> | null};\n error: string | null;\n success: boolean;\n } = await getUserSchemaAction(sessionId);\n\n user = userResponse.data?.user || {};\n userProfile = userProfileResponse.data?.userProfile ?? userProfile;\n userSchema = userSchemaResponse.data?.userSchema ?? null;\n } catch (error) {\n logger.warn('[ThunderIDServerProvider] Failed to fetch user profile from /users/me:', error?.toString());\n }\n } else {\n try {\n const decodedIdToken: IdToken = await thunderIDClient.getDecodedIdToken(sessionId);\n const claims = extractUserClaimsFromIdToken(decodedIdToken);\n user = claims;\n userProfile = {\n flattenedProfile: claims,\n profile: claims,\n };\n } catch (error) {\n logger.warn('[ThunderIDServerProvider] Failed to extract user claims from ID token:', error?.toString());\n }\n }\n }\n\n return (\n <ThunderIDClientProvider\n organizationHandle={config?.organizationHandle}\n applicationId={config?.applicationId}\n baseUrl={config?.baseUrl}\n initialMeta={flowMeta}\n fetchMeta={getFlowMetaAction}\n signIn={signInAction}\n clearSession={clearSession}\n refreshToken={refreshToken}\n signOut={signOutAction}\n signUp={signUpAction}\n handleOAuthCallback={handleOAuthCallbackAction}\n signInUrl={config?.signInUrl}\n signUpUrl={config?.signUpUrl}\n preferences={resolvedPreferences}\n clientId={config?.clientId}\n user={user}\n userProfile={userProfile}\n userSchema={userSchema}\n updateProfile={updateUserProfileAction}\n isSignedIn={signedIn}\n >\n {children}\n </ThunderIDClientProvider>\n );\n};\n\nexport default ThunderIDServerProvider;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4EA,MAAMA,0BAA+E,OAAO,EAC1F,UACA,gBACA,gBACA,GAAG,cACyE;CAC5E,MAAM,kBAAkBC,2BAAW;CACnC,IAAIC,SAAuC,EAAE;AAE7C,KAAI;AACF,QAAM,gBAAgB,WAAW,QAA+B;AAEhE,yBAAO,MAAM,uEAAuE;AAEpF,WAAS,MAAM,gBAAgB,kBAAkB;UAC1C,OAAO;AACd,yBAAO,MAAM,oEAAoE,OAAO,UAAU,CAAC;AAEnG,QAAM,IAAIC,uCACR,0CAA0C,OAAO,UAAU,IAC3D,+BACA,QACA,8FACD;;AAGH,KAAI,CAAC,gBAAgB,cACnB,QAAO,0EAAK;CAMd,IAAIC,WAAwC;AAC5C,KAAI;AACF,aAAW,wCAAkB;GAC3B,SAAS,QAAQ;GACjB,mDAA6B,YAAY,OAAO;GAChD,GAAI,QAAQ,gBAAgB;IAAC,IAAI,OAAO;IAAe,MAAMC,8BAAa;IAAI,GAAG,EAAE;GACpF,CAAC;UACK,OAAO;AACd,yBAAO,KAAK,4DAA4D,OAAO,UAAU,CAAC;;CAI5F,MAAMC,iBAAkD,MAAMC,mCAAmB;CACjF,MAAMC,YAAoB,gBAAgB,aAAc,MAAMC,8BAAc,IAAK;CACjF,MAAMC,WAAoB,MAAMC,2BAAW,UAAU;CAErD,IAAIC,OAAa,EAAE;CACnB,IAAIC,cAA2B;EAC7B,kBAAkB,EAAE;EACpB,SAAS,EAAE;EACZ;CACD,IAAIC,aAAqD;CAEzD,MAAM,sBAAsB;EAC1B,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,MAAM;GACJ,GAAG,QAAQ,aAAa;GACxB,GAAG,QAAQ,aAAa;GACzB;EACF;AAED,KAAI,UAAU;EACZ,IAAIC,iBAAqC,QAAQ;AAEjD,MAAI,gBAAgB,gBAAgB;AAClC,oBAAiB,GAAG,QAAQ,QAAQ;AACpC,YAAS;IAAC,GAAG;IAAQ,SAAS;IAAe;aACpC,UACT,KAAI;AAEF,QADyB,MAAM,gBAAgB,kBAAkB,UAAU,IAC7D,aAAa;AACzB,qBAAiB,GAAG,QAAQ,QAAQ;AACpC,aAAS;KAAC,GAAG;KAAQ,SAAS;KAAe;;UAEzC;AAQV,MAFwC,qBAAqB,MAAM,qBAAqB,MAGtF,KAAI;GACF,MAAMC,eAIF,MAAMC,8BAAc,UAAU;GAClC,MAAMC,sBAIF,MAAMC,qCAAqB,UAAU;GACzC,MAAMC,qBAIF,MAAMC,oCAAoB,UAAU;AAExC,UAAO,aAAa,MAAM,QAAQ,EAAE;AACpC,iBAAc,oBAAoB,MAAM,eAAe;AACvD,gBAAa,mBAAmB,MAAM,cAAc;WAC7C,OAAO;AACd,0BAAO,KAAK,0EAA0E,OAAO,UAAU,CAAC;;MAG1G,KAAI;GAEF,MAAM,4DAD0B,MAAM,gBAAgB,kBAAkB,UAAU,CACvB;AAC3D,UAAO;AACP,iBAAc;IACZ,kBAAkB;IAClB,SAAS;IACV;WACM,OAAO;AACd,0BAAO,KAAK,0EAA0E,OAAO,UAAU,CAAC;;;AAK9G,QACE,2CAACC;EACC,oBAAoB,QAAQ;EAC5B,eAAe,QAAQ;EACvB,SAAS,QAAQ;EACjB,aAAa;EACb,WAAWC;EACX,QAAQC;EACR,cAAcC;EACd,cAAcC;EACd,SAASC;EACT,QAAQC;EACR,qBAAqBC;EACrB,WAAW,QAAQ;EACnB,WAAW,QAAQ;EACnB,aAAa;EACb,UAAU,QAAQ;EACZ;EACO;EACD;EACZ,eAAeC;EACf,YAAY;EAEX;GACuB;;AAI9B,kCAAe"}
1
+ {"version":3,"file":"ThunderIDProvider.cjs","names":["ThunderIDServerProvider: FC<PropsWithChildren<ThunderIDServerProviderProps>>","getClient","config: Partial<ThunderIDNextConfig>","ThunderIDRuntimeError","flowMeta: FlowMetadataResponse | null","FlowMetaType","sessionPayload: SessionTokenPayload | undefined","getSessionPayload","sessionId: string","getSessionId","signedIn: boolean","isSignedIn","user: User","userProfile: UserProfile","userSchema: Record<string, AttributeSchema> | null","updatedBaseUrl: string | undefined","userResponse: {\n data: {user: User | null};\n error: string | null;\n success: boolean;\n }","getUserAction","userProfileResponse: {\n data: {userProfile: UserProfile};\n error: string | null;\n success: boolean;\n }","getUserProfileAction","userSchemaResponse: {\n data: {userSchema: Record<string, AttributeSchema> | null};\n error: string | null;\n success: boolean;\n }","getUserSchemaAction","ThunderIDClientProvider","signInAction","clearSession","refreshToken","signOutAction","signUpAction","handleOAuthCallbackAction","updateUserProfileAction"],"sources":["../../../src/server/ThunderIDProvider.tsx"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {\n ThunderIDRuntimeError,\n AttributeSchema,\n FlowMetadataResponse,\n FlowMetaType,\n IdToken,\n User,\n UserProfile,\n getFlowMeta,\n extractUserClaimsFromIdToken,\n resolveResourceEndpoint,\n} from '@thunderid/node';\nimport {ThunderIDProviderProps} from '@thunderid/react';\nimport {FC, PropsWithChildren, ReactElement} from 'react';\nimport clearSession from './actions/clearSession';\nimport getSessionId from './actions/getSessionId';\nimport getSessionPayload from './actions/getSessionPayload';\nimport getUserAction from './actions/getUserAction';\nimport getUserProfileAction from './actions/getUserProfileAction';\nimport getUserSchemaAction from './actions/getUserSchemaAction';\nimport handleOAuthCallbackAction from './actions/handleOAuthCallbackAction';\nimport isSignedIn from './actions/isSignedIn';\nimport refreshToken from './actions/refreshToken';\nimport signInAction from './actions/signInAction';\nimport signOutAction from './actions/signOutAction';\nimport signUpAction from './actions/signUpAction';\nimport updateUserProfileAction from './actions/updateUserProfileAction';\nimport getClient from './getClient';\nimport ThunderIDClientProvider from '../client/contexts/ThunderID/ThunderIDProvider.js';\nimport {ThunderIDNextConfig} from '../models/config';\nimport logger from '../utils/logger';\nimport {SessionTokenPayload} from '../utils/SessionManager';\n\n/**\n * Props interface of {@link ThunderIDServerProvider}\n */\nexport type ThunderIDServerProviderProps = Partial<ThunderIDProviderProps> & {\n clientSecret?: string;\n /**\n * Session cookie lifetime in seconds. Determines how long the session cookie\n * remains valid in the browser after sign-in.\n *\n * Resolution order (first defined value wins):\n * 1. This prop — set here when mounting the provider.\n * 2. `THUNDERID_SESSION_COOKIE_EXPIRY_TIME` environment variable.\n * 3. Built-in default of 86400 seconds (24 hours).\n *\n * @example\n * // 8-hour session cookie\n * <ThunderIDServerProvider sessionCookieExpiryTime={28800} ... />\n */\n sessionCookieExpiryTime?: number;\n};\n\n/**\n * Server-side provider component for ThunderID authentication.\n * Wraps the client-side provider and handles server-side authentication logic.\n * Uses the singleton ThunderIDNextClient instance for consistent authentication state.\n *\n * @param props - Props injected into the component.\n *\n * @example\n * ```tsx\n * <ThunderIDServerProvider config={thunderidConfig}>\n * <YourApp />\n * </ThunderIDServerProvider>\n * ```\n *\n * @returns ThunderIDServerProvider component.\n */\nconst ThunderIDServerProvider: FC<PropsWithChildren<ThunderIDServerProviderProps>> = async ({\n children,\n afterSignInUrl,\n afterSignOutUrl,\n ..._config\n}: PropsWithChildren<ThunderIDServerProviderProps>): Promise<ReactElement> => {\n const thunderIDClient = getClient();\n let config: Partial<ThunderIDNextConfig> = {};\n\n try {\n await thunderIDClient.initialize(_config as ThunderIDNextConfig);\n\n logger.debug('[ThunderIDServerProvider] ThunderID client initialized successfully.');\n\n config = await thunderIDClient.getConfiguration();\n } catch (error) {\n logger.error('[ThunderIDServerProvider] Failed to initialize ThunderID client:', error?.toString());\n\n throw new ThunderIDRuntimeError(\n `Failed to initialize ThunderID client: ${error?.toString()}`,\n 'next-ConfigurationError-001',\n 'next',\n 'An error occurred while initializing the ThunderID client. Please check your configuration.',\n );\n }\n\n if (!thunderIDClient.isInitialized) {\n return <></>;\n }\n\n // Fetch flow metadata (design config + i18n bundle) server-side so `FlowMetaProvider` can seed\n // its state and skip a redundant client-side fetch — avoiding a flash of untranslated i18n keys\n // (e.g. raw `signin.forms.credentials.title`) while embedded flow components first render.\n let flowMeta: FlowMetadataResponse | null = null;\n try {\n flowMeta = await getFlowMeta({\n baseUrl: config?.baseUrl,\n url: resolveResourceEndpoint('flowMeta', config),\n ...(config?.applicationId ? {id: config.applicationId, type: FlowMetaType.App} : {}),\n });\n } catch (error) {\n logger.warn('[ThunderIDServerProvider] Failed to fetch flow metadata:', error?.toString());\n }\n\n // Try to get session information from JWT first, then fall back to legacy\n const sessionPayload: SessionTokenPayload | undefined = await getSessionPayload();\n const sessionId: string = sessionPayload?.sessionId || (await getSessionId()) || '';\n const signedIn: boolean = await isSignedIn(sessionId);\n\n let user: User = {};\n let userProfile: UserProfile = {\n flattenedProfile: {},\n profile: {},\n };\n let userSchema: Record<string, AttributeSchema> | null = null;\n\n const resolvedPreferences = {\n ...config?.preferences,\n ..._config.preferences,\n user: {\n ...config?.preferences?.user,\n ..._config.preferences?.user,\n },\n };\n\n if (signedIn) {\n let updatedBaseUrl: string | undefined = config?.baseUrl;\n\n if (sessionPayload?.organizationId) {\n updatedBaseUrl = `${config?.baseUrl}/o`;\n config = {...config, baseUrl: updatedBaseUrl};\n } else if (sessionId) {\n try {\n const idToken: IdToken = await thunderIDClient.getDecodedIdToken(sessionId);\n if (idToken?.['user_org']) {\n updatedBaseUrl = `${config?.baseUrl}/o`;\n config = {...config, baseUrl: updatedBaseUrl};\n }\n } catch {\n // Continue without organization info\n }\n }\n\n // Check if user profile fetching is enabled (default: true)\n const shouldFetchUserProfile: boolean = resolvedPreferences?.user?.fetchUserProfile !== false;\n\n if (shouldFetchUserProfile) {\n try {\n const userResponse: {\n data: {user: User | null};\n error: string | null;\n success: boolean;\n } = await getUserAction(sessionId);\n const userProfileResponse: {\n data: {userProfile: UserProfile};\n error: string | null;\n success: boolean;\n } = await getUserProfileAction(sessionId);\n const userSchemaResponse: {\n data: {userSchema: Record<string, AttributeSchema> | null};\n error: string | null;\n success: boolean;\n } = await getUserSchemaAction(sessionId);\n\n user = userResponse.data?.user || {};\n userProfile = userProfileResponse.data?.userProfile ?? userProfile;\n userSchema = userSchemaResponse.data?.userSchema ?? null;\n } catch (error) {\n logger.warn('[ThunderIDServerProvider] Failed to fetch user profile from /users/me:', error?.toString());\n }\n } else {\n try {\n const decodedIdToken: IdToken = await thunderIDClient.getDecodedIdToken(sessionId);\n const claims = extractUserClaimsFromIdToken(decodedIdToken);\n user = claims;\n userProfile = {\n flattenedProfile: claims,\n profile: claims,\n };\n } catch (error) {\n logger.warn('[ThunderIDServerProvider] Failed to extract user claims from ID token:', error?.toString());\n }\n }\n }\n\n return (\n <ThunderIDClientProvider\n organizationHandle={config?.organizationHandle}\n applicationId={config?.applicationId}\n baseUrl={config?.baseUrl}\n initialMeta={flowMeta}\n signIn={signInAction}\n clearSession={clearSession}\n refreshToken={refreshToken}\n signOut={signOutAction}\n signUp={signUpAction}\n handleOAuthCallback={handleOAuthCallbackAction}\n signInUrl={config?.signInUrl}\n signUpUrl={config?.signUpUrl}\n preferences={resolvedPreferences}\n clientId={config?.clientId}\n user={user}\n userProfile={userProfile}\n userSchema={userSchema}\n updateProfile={updateUserProfileAction}\n isSignedIn={signedIn}\n >\n {children}\n </ThunderIDClientProvider>\n );\n};\n\nexport default ThunderIDServerProvider;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2EA,MAAMA,0BAA+E,OAAO,EAC1F,UACA,gBACA,gBACA,GAAG,cACyE;CAC5E,MAAM,kBAAkBC,2BAAW;CACnC,IAAIC,SAAuC,EAAE;AAE7C,KAAI;AACF,QAAM,gBAAgB,WAAW,QAA+B;AAEhE,yBAAO,MAAM,uEAAuE;AAEpF,WAAS,MAAM,gBAAgB,kBAAkB;UAC1C,OAAO;AACd,yBAAO,MAAM,oEAAoE,OAAO,UAAU,CAAC;AAEnG,QAAM,IAAIC,uCACR,0CAA0C,OAAO,UAAU,IAC3D,+BACA,QACA,8FACD;;AAGH,KAAI,CAAC,gBAAgB,cACnB,QAAO,0EAAK;CAMd,IAAIC,WAAwC;AAC5C,KAAI;AACF,aAAW,wCAAkB;GAC3B,SAAS,QAAQ;GACjB,mDAA6B,YAAY,OAAO;GAChD,GAAI,QAAQ,gBAAgB;IAAC,IAAI,OAAO;IAAe,MAAMC,8BAAa;IAAI,GAAG,EAAE;GACpF,CAAC;UACK,OAAO;AACd,yBAAO,KAAK,4DAA4D,OAAO,UAAU,CAAC;;CAI5F,MAAMC,iBAAkD,MAAMC,mCAAmB;CACjF,MAAMC,YAAoB,gBAAgB,aAAc,MAAMC,8BAAc,IAAK;CACjF,MAAMC,WAAoB,MAAMC,2BAAW,UAAU;CAErD,IAAIC,OAAa,EAAE;CACnB,IAAIC,cAA2B;EAC7B,kBAAkB,EAAE;EACpB,SAAS,EAAE;EACZ;CACD,IAAIC,aAAqD;CAEzD,MAAM,sBAAsB;EAC1B,GAAG,QAAQ;EACX,GAAG,QAAQ;EACX,MAAM;GACJ,GAAG,QAAQ,aAAa;GACxB,GAAG,QAAQ,aAAa;GACzB;EACF;AAED,KAAI,UAAU;EACZ,IAAIC,iBAAqC,QAAQ;AAEjD,MAAI,gBAAgB,gBAAgB;AAClC,oBAAiB,GAAG,QAAQ,QAAQ;AACpC,YAAS;IAAC,GAAG;IAAQ,SAAS;IAAe;aACpC,UACT,KAAI;AAEF,QADyB,MAAM,gBAAgB,kBAAkB,UAAU,IAC7D,aAAa;AACzB,qBAAiB,GAAG,QAAQ,QAAQ;AACpC,aAAS;KAAC,GAAG;KAAQ,SAAS;KAAe;;UAEzC;AAQV,MAFwC,qBAAqB,MAAM,qBAAqB,MAGtF,KAAI;GACF,MAAMC,eAIF,MAAMC,8BAAc,UAAU;GAClC,MAAMC,sBAIF,MAAMC,qCAAqB,UAAU;GACzC,MAAMC,qBAIF,MAAMC,oCAAoB,UAAU;AAExC,UAAO,aAAa,MAAM,QAAQ,EAAE;AACpC,iBAAc,oBAAoB,MAAM,eAAe;AACvD,gBAAa,mBAAmB,MAAM,cAAc;WAC7C,OAAO;AACd,0BAAO,KAAK,0EAA0E,OAAO,UAAU,CAAC;;MAG1G,KAAI;GAEF,MAAM,4DAD0B,MAAM,gBAAgB,kBAAkB,UAAU,CACvB;AAC3D,UAAO;AACP,iBAAc;IACZ,kBAAkB;IAClB,SAAS;IACV;WACM,OAAO;AACd,0BAAO,KAAK,0EAA0E,OAAO,UAAU,CAAC;;;AAK9G,QACE,2CAACC;EACC,oBAAoB,QAAQ;EAC5B,eAAe,QAAQ;EACvB,SAAS,QAAQ;EACjB,aAAa;EACb,QAAQC;EACR,cAAcC;EACd,cAAcC;EACd,SAASC;EACT,QAAQC;EACR,qBAAqBC;EACrB,WAAW,QAAQ;EACnB,WAAW,QAAQ;EACnB,aAAa;EACb,UAAU,QAAQ;EACZ;EACO;EACD;EACZ,eAAeC;EACf,YAAY;EAEX;GACuB;;AAI9B,kCAAe"}
@@ -0,0 +1,28 @@
1
+ 'use server';
2
+
3
+
4
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
5
+ const require_runSelectPageAction = require('./runSelectPageAction.cjs');
6
+ let __thunderid_node = require("@thunderid/node");
7
+ __thunderid_node = require_rolldown_runtime.__toESM(__thunderid_node);
8
+
9
+ //#region src/server/actions/getAuthFlowsAction.ts
10
+ /**
11
+ * Loads one page of authentication flows for an `AUTH_FLOW_SELECT` picker using the signed-in user's
12
+ * server-held session.
13
+ *
14
+ * Never throws across the server action boundary; failures are mapped to a plain result.
15
+ */
16
+ const getAuthFlowsAction = async ({ limit, offset } = {}) => require_runSelectPageAction.default("auth flows", {
17
+ limit,
18
+ offset
19
+ }, async (client, sessionId, query) => (0, __thunderid_node.toAuthFlowSelectPage)(await client.getFlows({
20
+ flowType: __thunderid_node.AuthFlowSelectConstants.FLOW_TYPE,
21
+ limit: (0, __thunderid_node.capPageSize)(query.limit),
22
+ offset: query.offset
23
+ }, sessionId), query.offset ?? 0));
24
+ var getAuthFlowsAction_default = getAuthFlowsAction;
25
+
26
+ //#endregion
27
+ exports.default = getAuthFlowsAction_default;
28
+ //# sourceMappingURL=getAuthFlowsAction.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getAuthFlowsAction.cjs","names":["runSelectPageAction","AuthFlowSelectConstants"],"sources":["../../../../src/server/actions/getAuthFlowsAction.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {AuthFlowSelectConstants, capPageSize, toAuthFlowSelectPage} from '@thunderid/node';\nimport runSelectPageAction, {SelectPageActionResult} from './runSelectPageAction';\n\n/**\n * Request from the browser. Carries only paging; the session comes from the request cookie and the flow\n * type is fixed to authentication on the server.\n */\nexport interface GetAuthFlowsActionRequest {\n limit?: number;\n offset?: number;\n}\n\nexport type GetAuthFlowsActionResult = SelectPageActionResult;\n\n/**\n * Loads one page of authentication flows for an `AUTH_FLOW_SELECT` picker using the signed-in user's\n * server-held session.\n *\n * Never throws across the server action boundary; failures are mapped to a plain result.\n */\nconst getAuthFlowsAction = async ({limit, offset}: GetAuthFlowsActionRequest = {}): Promise<GetAuthFlowsActionResult> =>\n runSelectPageAction('auth flows', {limit, offset}, async (client, sessionId, query) =>\n toAuthFlowSelectPage(\n await client.getFlows(\n {flowType: AuthFlowSelectConstants.FLOW_TYPE, limit: capPageSize(query.limit), offset: query.offset},\n sessionId,\n ),\n query.offset ?? 0,\n ),\n );\n\nexport default getAuthFlowsAction;\n"],"mappings":";;;;;;;;;;;;;;;AAyBA,MAAM,qBAAqB,OAAO,EAAC,OAAO,WAAqC,EAAE,KAC/EA,oCAAoB,cAAc;CAAC;CAAO;CAAO,EAAE,OAAO,QAAQ,WAAW,qDAEzE,MAAM,OAAO,SACX;CAAC,UAAUC,yCAAwB;CAAW,yCAAmB,MAAM,MAAM;CAAE,QAAQ,MAAM;CAAO,EACpG,UACD,EACD,MAAM,UAAU,EACjB,CACF;AAEH,iCAAe"}
@@ -16,25 +16,43 @@ __thunderid_node = require_rolldown_runtime.__toESM(__thunderid_node);
16
16
  * origin. Routing it through this action instead means the browser never talks to `baseUrl`
17
17
  * directly — the request happens server-to-server, same as `signInAction`/`signUpAction`.
18
18
  *
19
+ * Never throws across the server action boundary; failures are mapped to a plain result.
20
+ *
19
21
  * @param language - Optional language override, used by `FlowMetaProvider.switchLanguage()`.
20
22
  */
21
23
  const getFlowMetaAction = async (params) => {
22
- const config = await require_getClient.default().getConfiguration();
23
- const applicationId = params?.applicationId ?? config?.applicationId;
24
24
  try {
25
- return await (0, __thunderid_node.getFlowMeta)({
26
- baseUrl: config?.baseUrl,
27
- url: (0, __thunderid_node.resolveResourceEndpoint)("flowMeta", config),
28
- ...applicationId ? {
29
- id: applicationId,
30
- type: __thunderid_node.FlowMetaType.App
31
- } : {},
32
- ...params?.language ? { language: params.language } : {}
33
- });
25
+ const config = await require_getClient.default().getConfiguration();
26
+ const url = (0, __thunderid_node.resolveResourceEndpoint)("flowMeta", config);
27
+ if (!url && !config?.baseUrl) return {
28
+ message: "Failed to load flow metadata: no base URL is configured.",
29
+ success: false
30
+ };
31
+ const applicationId = params?.applicationId ?? config?.applicationId;
32
+ return {
33
+ meta: await (0, __thunderid_node.getFlowMeta)({
34
+ baseUrl: config?.baseUrl,
35
+ url,
36
+ ...applicationId ? {
37
+ id: applicationId,
38
+ type: __thunderid_node.FlowMetaType.App
39
+ } : {},
40
+ ...params?.language ? { language: params.language } : {}
41
+ }),
42
+ success: true
43
+ };
34
44
  } catch (error) {
35
45
  const message = error instanceof Error ? error.message : String(error);
36
46
  require_logger.default.error(`[getFlowMetaAction] Error fetching flow metadata: ${message}`);
37
- throw error;
47
+ if (error instanceof __thunderid_node.ThunderIDAPIError && error.statusCode !== void 0) return {
48
+ message: `Failed to load flow metadata (HTTP ${error.statusCode}).`,
49
+ statusCode: error.statusCode,
50
+ success: false
51
+ };
52
+ return {
53
+ message: "Failed to load flow metadata.",
54
+ success: false
55
+ };
38
56
  }
39
57
  };
40
58
  var getFlowMetaAction_default = getFlowMetaAction;
@@ -1 +1 @@
1
- {"version":3,"file":"getFlowMetaAction.cjs","names":["config: ThunderIDNextConfig","getClient","applicationId: string | undefined","FlowMetaType"],"sources":["../../../../src/server/actions/getFlowMetaAction.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {FlowMetadataResponse, FlowMetaType, getFlowMeta, resolveResourceEndpoint} from '@thunderid/node';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport logger from '../../utils/logger';\nimport getClient from '../getClient';\n\n/**\n * Server Action that fetches `GET /flow/meta` server-side.\n *\n * `FlowMetaProvider` (from `@thunderid/react`) otherwise fetches this endpoint directly from the\n * browser against `baseUrl`, which requires the ThunderID server to allow CORS for the app's\n * origin. Routing it through this action instead means the browser never talks to `baseUrl`\n * directly — the request happens server-to-server, same as `signInAction`/`signUpAction`.\n *\n * @param language - Optional language override, used by `FlowMetaProvider.switchLanguage()`.\n */\nconst getFlowMetaAction = async (params?: {\n applicationId?: string;\n language?: string;\n}): Promise<FlowMetadataResponse> => {\n const client = getClient();\n const config: ThunderIDNextConfig = await client.getConfiguration();\n\n const applicationId: string | undefined = params?.applicationId ?? config?.applicationId;\n\n try {\n return await getFlowMeta({\n baseUrl: config?.baseUrl,\n url: resolveResourceEndpoint('flowMeta', config),\n ...(applicationId ? {id: applicationId, type: FlowMetaType.App} : {}),\n ...(params?.language ? {language: params.language} : {}),\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`[getFlowMetaAction] Error fetching flow metadata: ${message}`);\n throw error;\n }\n};\n\nexport default getFlowMetaAction;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBA,MAAM,oBAAoB,OAAO,WAGI;CAEnC,MAAMA,SAA8B,MADrBC,2BAAW,CACuB,kBAAkB;CAEnE,MAAMC,gBAAoC,QAAQ,iBAAiB,QAAQ;AAE3E,KAAI;AACF,SAAO,wCAAkB;GACvB,SAAS,QAAQ;GACjB,mDAA6B,YAAY,OAAO;GAChD,GAAI,gBAAgB;IAAC,IAAI;IAAe,MAAMC,8BAAa;IAAI,GAAG,EAAE;GACpE,GAAI,QAAQ,WAAW,EAAC,UAAU,OAAO,UAAS,GAAG,EAAE;GACxD,CAAC;UACK,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,yBAAO,MAAM,qDAAqD,UAAU;AAC5E,QAAM;;;AAIV,gCAAe"}
1
+ {"version":3,"file":"getFlowMetaAction.cjs","names":["config: ThunderIDNextConfig","getClient","url: string | undefined","applicationId: string | undefined","FlowMetaType","ThunderIDAPIError"],"sources":["../../../../src/server/actions/getFlowMetaAction.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {\n FlowMetadataResponse,\n FlowMetaType,\n getFlowMeta,\n resolveResourceEndpoint,\n ThunderIDAPIError,\n} from '@thunderid/node';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport logger from '../../utils/logger';\nimport getClient from '../getClient';\n\n/**\n * What {@link getFlowMetaAction} returns: the flow metadata, or a plain failure. It never throws, because a thrown\n * error reaches the browser as a generic 500 and loses its prototype chain crossing the server action boundary. A\n * failure carries a message built on the server and the status, never the text of the upstream reply.\n */\nexport type GetFlowMetaActionResult =\n | {meta: FlowMetadataResponse; success: true}\n | {message: string; statusCode?: number; success: false};\n\n/**\n * Server Action that fetches `GET /flow/meta` server-side.\n *\n * `FlowMetaProvider` (from `@thunderid/react`) otherwise fetches this endpoint directly from the\n * browser against `baseUrl`, which requires the ThunderID server to allow CORS for the app's\n * origin. Routing it through this action instead means the browser never talks to `baseUrl`\n * directly — the request happens server-to-server, same as `signInAction`/`signUpAction`.\n *\n * Never throws across the server action boundary; failures are mapped to a plain result.\n *\n * @param language - Optional language override, used by `FlowMetaProvider.switchLanguage()`.\n */\nconst getFlowMetaAction = async (params?: {\n applicationId?: string;\n language?: string;\n}): Promise<GetFlowMetaActionResult> => {\n try {\n const client = getClient();\n const config: ThunderIDNextConfig = await client.getConfiguration();\n\n const url: string | undefined = resolveResourceEndpoint('flowMeta', config);\n\n if (!url && !config?.baseUrl) {\n return {message: 'Failed to load flow metadata: no base URL is configured.', success: false};\n }\n\n const applicationId: string | undefined = params?.applicationId ?? config?.applicationId;\n\n const meta: FlowMetadataResponse = await getFlowMeta({\n baseUrl: config?.baseUrl,\n url,\n ...(applicationId ? {id: applicationId, type: FlowMetaType.App} : {}),\n ...(params?.language ? {language: params.language} : {}),\n });\n\n return {meta, success: true};\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(`[getFlowMetaAction] Error fetching flow metadata: ${message}`);\n\n if (error instanceof ThunderIDAPIError && error.statusCode !== undefined) {\n return {\n message: `Failed to load flow metadata (HTTP ${error.statusCode}).`,\n statusCode: error.statusCode,\n success: false,\n };\n }\n\n return {message: 'Failed to load flow metadata.', success: false};\n }\n};\n\nexport default getFlowMetaAction;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAM,oBAAoB,OAAO,WAGO;AACtC,KAAI;EAEF,MAAMA,SAA8B,MADrBC,2BAAW,CACuB,kBAAkB;EAEnE,MAAMC,oDAAkD,YAAY,OAAO;AAE3E,MAAI,CAAC,OAAO,CAAC,QAAQ,QACnB,QAAO;GAAC,SAAS;GAA4D,SAAS;GAAM;EAG9F,MAAMC,gBAAoC,QAAQ,iBAAiB,QAAQ;AAS3E,SAAO;GAAC,MAP2B,wCAAkB;IACnD,SAAS,QAAQ;IACjB;IACA,GAAI,gBAAgB;KAAC,IAAI;KAAe,MAAMC,8BAAa;KAAI,GAAG,EAAE;IACpE,GAAI,QAAQ,WAAW,EAAC,UAAU,OAAO,UAAS,GAAG,EAAE;IACxD,CAAC;GAEY,SAAS;GAAK;UACrB,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,yBAAO,MAAM,qDAAqD,UAAU;AAE5E,MAAI,iBAAiBC,sCAAqB,MAAM,eAAe,OAC7D,QAAO;GACL,SAAS,sCAAsC,MAAM,WAAW;GAChE,YAAY,MAAM;GAClB,SAAS;GACV;AAGH,SAAO;GAAC,SAAS;GAAiC,SAAS;GAAM;;;AAIrE,gCAAe"}
@@ -0,0 +1,27 @@
1
+ 'use server';
2
+
3
+
4
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
5
+ const require_runSelectPageAction = require('./runSelectPageAction.cjs');
6
+ let __thunderid_node = require("@thunderid/node");
7
+ __thunderid_node = require_rolldown_runtime.__toESM(__thunderid_node);
8
+
9
+ //#region src/server/actions/getUserTypesAction.ts
10
+ /**
11
+ * Loads one page of user types for a `USER_TYPE_SELECT` picker using the signed-in user's server-held
12
+ * session.
13
+ *
14
+ * Never throws across the server action boundary; failures are mapped to a plain result.
15
+ */
16
+ const getUserTypesAction = async ({ limit, offset } = {}) => require_runSelectPageAction.default("user types", {
17
+ limit,
18
+ offset
19
+ }, async (client, sessionId, query) => (0, __thunderid_node.toUserTypeSelectPage)(await client.getUserTypes({
20
+ limit: (0, __thunderid_node.capPageSize)(query.limit),
21
+ offset: query.offset
22
+ }, sessionId), query.offset ?? 0));
23
+ var getUserTypesAction_default = getUserTypesAction;
24
+
25
+ //#endregion
26
+ exports.default = getUserTypesAction_default;
27
+ //# sourceMappingURL=getUserTypesAction.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getUserTypesAction.cjs","names":["runSelectPageAction"],"sources":["../../../../src/server/actions/getUserTypesAction.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {capPageSize, toUserTypeSelectPage} from '@thunderid/node';\nimport runSelectPageAction, {SelectPageActionResult} from './runSelectPageAction';\n\n/**\n * Request from the browser. Carries only paging; the session comes from the request cookie.\n */\nexport interface GetUserTypesActionRequest {\n limit?: number;\n offset?: number;\n}\n\nexport type GetUserTypesActionResult = SelectPageActionResult;\n\n/**\n * Loads one page of user types for a `USER_TYPE_SELECT` picker using the signed-in user's server-held\n * session.\n *\n * Never throws across the server action boundary; failures are mapped to a plain result.\n */\nconst getUserTypesAction = async ({limit, offset}: GetUserTypesActionRequest = {}): Promise<GetUserTypesActionResult> =>\n runSelectPageAction('user types', {limit, offset}, async (client, sessionId, query) =>\n toUserTypeSelectPage(\n await client.getUserTypes({limit: capPageSize(query.limit), offset: query.offset}, sessionId),\n query.offset ?? 0,\n ),\n );\n\nexport default getUserTypesAction;\n"],"mappings":";;;;;;;;;;;;;;;AAwBA,MAAM,qBAAqB,OAAO,EAAC,OAAO,WAAqC,EAAE,KAC/EA,oCAAoB,cAAc;CAAC;CAAO;CAAO,EAAE,OAAO,QAAQ,WAAW,qDAEzE,MAAM,OAAO,aAAa;CAAC,yCAAmB,MAAM,MAAM;CAAE,QAAQ,MAAM;CAAO,EAAE,UAAU,EAC7F,MAAM,UAAU,EACjB,CACF;AAEH,iCAAe"}
@@ -0,0 +1,28 @@
1
+ 'use server';
2
+
3
+
4
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
5
+ const require_runSelectPageAction = require('./runSelectPageAction.cjs');
6
+ let __thunderid_node = require("@thunderid/node");
7
+ __thunderid_node = require_rolldown_runtime.__toESM(__thunderid_node);
8
+
9
+ //#region src/server/actions/getUsersAction.ts
10
+ /**
11
+ * Loads one page of users for a `USER_SELECT` picker using the signed-in user's server-held session.
12
+ *
13
+ * Never throws across the server action boundary; failures are mapped to a plain result.
14
+ */
15
+ const getUsersAction = async ({ filter, limit, offset } = {}) => require_runSelectPageAction.default("users", {
16
+ filter,
17
+ limit,
18
+ offset
19
+ }, async (client, sessionId, query) => (0, __thunderid_node.toUserSelectPage)(await client.getUsers({
20
+ filter: query.filter,
21
+ limit: query.limit,
22
+ offset: query.offset
23
+ }, sessionId), query.offset ?? 0), { allowFilter: true });
24
+ var getUsersAction_default = getUsersAction;
25
+
26
+ //#endregion
27
+ exports.default = getUsersAction_default;
28
+ //# sourceMappingURL=getUsersAction.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getUsersAction.cjs","names":["runSelectPageAction"],"sources":["../../../../src/server/actions/getUsersAction.ts"],"sourcesContent":["// Copyright 2026 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {toUserSelectPage} from '@thunderid/node';\nimport runSelectPageAction, {SelectPageActionResult} from './runSelectPageAction';\n\n/**\n * Request from the browser. Carries no session ID, token, or URL; the session comes from the request cookie.\n */\nexport interface GetUsersActionRequest {\n filter?: string;\n limit?: number;\n offset?: number;\n}\n\nexport type GetUsersActionResult = SelectPageActionResult;\n\n/**\n * Loads one page of users for a `USER_SELECT` picker using the signed-in user's server-held session.\n *\n * Never throws across the server action boundary; failures are mapped to a plain result.\n */\nconst getUsersAction = async ({filter, limit, offset}: GetUsersActionRequest = {}): Promise<GetUsersActionResult> =>\n runSelectPageAction(\n 'users',\n {filter, limit, offset},\n async (client, sessionId, query) =>\n toUserSelectPage(\n await client.getUsers({filter: query.filter, limit: query.limit, offset: query.offset}, sessionId),\n query.offset ?? 0,\n ),\n {allowFilter: true},\n );\n\nexport default getUsersAction;\n"],"mappings":";;;;;;;;;;;;;;AAwBA,MAAM,iBAAiB,OAAO,EAAC,QAAQ,OAAO,WAAiC,EAAE,KAC/EA,oCACE,SACA;CAAC;CAAQ;CAAO;CAAO,EACvB,OAAO,QAAQ,WAAW,iDAEtB,MAAM,OAAO,SAAS;CAAC,QAAQ,MAAM;CAAQ,OAAO,MAAM;CAAO,QAAQ,MAAM;CAAO,EAAE,UAAU,EAClG,MAAM,UAAU,EACjB,EACH,EAAC,aAAa,MAAK,CACpB;AAEH,6BAAe"}
@@ -26,6 +26,7 @@ const handleOAuthCallbackAction = async (code, state) => {
26
26
  success: false
27
27
  };
28
28
  const thunderIDClient = require_getClient.default();
29
+ if (!thunderIDClient.isInitialized) await thunderIDClient.initialize({});
29
30
  if (!thunderIDClient.isInitialized) return {
30
31
  error: "ThunderID client is not initialized",
31
32
  success: false
@@ -1 +1 @@
1
- {"version":3,"file":"handleOAuthCallbackAction.cjs","names":["getClient","cookieStore: RequestCookies","sessionId: string | undefined","tempSessionToken: string | undefined","SessionManager","signInResult: Record<string, unknown>","config: ThunderIDNextConfig","idToken: IdToken","accessToken: string","refreshToken: string","userIdFromToken: string","scopes: string","organizationId: string | undefined","expiresIn: number","sessionCookieExpiryTime: number","sessionToken: string"],"sources":["../../../../src/server/actions/handleOAuthCallbackAction.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {IdToken} from '@thunderid/node';\nimport {cookies} from 'next/headers';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport {setChunkedCookie} from '../../utils/chunkedCookie';\nimport logger from '../../utils/logger';\nimport SessionManager from '../../utils/SessionManager';\nimport getClient from '../getClient';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Server action to handle OAuth callback with authorization code.\n * This action processes the authorization code received from the OAuth provider\n * and exchanges it for tokens to complete the authentication flow.\n *\n * @param code - Authorization code from OAuth provider\n * @param state - State parameter from OAuth provider for CSRF protection\n * @returns Promise that resolves with success status and optional error message\n */\nconst handleOAuthCallbackAction = async (\n code: string,\n state: string,\n): Promise<{\n error?: string;\n redirectUrl?: string;\n success: boolean;\n}> => {\n try {\n if (!code || !state) {\n return {\n error: 'Missing required OAuth parameters: code and state are required',\n success: false,\n };\n }\n\n const thunderIDClient = getClient();\n\n if (!thunderIDClient.isInitialized) {\n return {\n error: 'ThunderID client is not initialized',\n success: false,\n };\n }\n\n const cookieStore: RequestCookies = await cookies();\n let sessionId: string | undefined;\n\n const tempSessionToken: string | undefined = cookieStore.get(SessionManager.getTempSessionCookieName())?.value;\n\n if (tempSessionToken) {\n try {\n const tempSession: {sessionId: string} = await SessionManager.verifyTempSession(tempSessionToken);\n sessionId = tempSession.sessionId;\n } catch {\n logger.error(\n '[handleOAuthCallbackAction] Invalid temporary session token, falling back to session ID from cookies.',\n );\n }\n }\n\n if (!sessionId) {\n logger.error('[handleOAuthCallbackAction] No session ID found in cookies or temporary session token.');\n\n return {\n error: 'No session found. Please start the authentication flow again.',\n success: false,\n };\n }\n\n // Exchange the authorization code for tokens\n const signInResult: Record<string, unknown> = await thunderIDClient.signIn(\n {\n code,\n state,\n } as any,\n {},\n sessionId,\n );\n\n const config: ThunderIDNextConfig = await thunderIDClient.getConfiguration();\n\n if (signInResult) {\n try {\n const idToken: IdToken = await thunderIDClient.getDecodedIdToken(\n sessionId,\n (signInResult['id_token'] || signInResult['idToken']) as string,\n );\n const accessToken: string = (signInResult['accessToken'] || signInResult['access_token']) as string;\n const refreshToken: string = (signInResult['refreshToken'] as string | undefined) ?? '';\n const userIdFromToken: string = (idToken.sub || signInResult['sub'] || sessionId) as string;\n const scopes: string = signInResult['scope'] as string;\n const organizationId: string | undefined = (idToken['user_org'] || idToken['organization_id']) as\n | string\n | undefined;\n const expiresIn: number = signInResult['expiresIn'] as number;\n const sessionCookieExpiryTime: number = SessionManager.resolveSessionCookieExpiry(\n config.sessionCookie?.expiryTime,\n );\n\n const sessionToken: string = await SessionManager.createSessionToken(\n accessToken,\n userIdFromToken,\n sessionId,\n scopes,\n expiresIn,\n refreshToken,\n organizationId,\n {sid: typeof idToken['sid'] === 'string' ? idToken['sid'] : undefined},\n );\n\n setChunkedCookie(\n cookieStore,\n SessionManager.getSessionCookieName(),\n sessionToken,\n SessionManager.getSessionCookieOptions(sessionCookieExpiryTime),\n );\n\n cookieStore.delete(SessionManager.getTempSessionCookieName());\n } catch (error) {\n logger.error(\n `[handleOAuthCallbackAction] Failed to create JWT session, continuing with legacy session:\n ${typeof error === 'string' ? error : JSON.stringify(error)}`,\n );\n }\n }\n\n const afterSignInUrl: string = config.afterSignInUrl || '/';\n\n return {\n redirectUrl: afterSignInUrl,\n success: true,\n };\n } catch (error) {\n let errorMessage = 'Authentication failed';\n\n if (error instanceof Error) {\n errorMessage = error.message;\n } else if (error && typeof error === 'object' && 'message' in error) {\n errorMessage = String((error as {message: unknown}).message);\n } else if (typeof error === 'string') {\n errorMessage = error;\n }\n\n return {\n error: errorMessage,\n success: false,\n };\n }\n};\n\nexport default handleOAuthCallbackAction;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,4BAA4B,OAChC,MACA,UAKI;AACJ,KAAI;AACF,MAAI,CAAC,QAAQ,CAAC,MACZ,QAAO;GACL,OAAO;GACP,SAAS;GACV;EAGH,MAAM,kBAAkBA,2BAAW;AAEnC,MAAI,CAAC,gBAAgB,cACnB,QAAO;GACL,OAAO;GACP,SAAS;GACV;EAGH,MAAMC,cAA8B,iCAAe;EACnD,IAAIC;EAEJ,MAAMC,mBAAuC,YAAY,IAAIC,+BAAe,0BAA0B,CAAC,EAAE;AAEzG,MAAI,iBACF,KAAI;AAEF,gBADyC,MAAMA,+BAAe,kBAAkB,iBAAiB,EACzE;UAClB;AACN,0BAAO,MACL,wGACD;;AAIL,MAAI,CAAC,WAAW;AACd,0BAAO,MAAM,yFAAyF;AAEtG,UAAO;IACL,OAAO;IACP,SAAS;IACV;;EAIH,MAAMC,eAAwC,MAAM,gBAAgB,OAClE;GACE;GACA;GACD,EACD,EAAE,EACF,UACD;EAED,MAAMC,SAA8B,MAAM,gBAAgB,kBAAkB;AAE5E,MAAI,aACF,KAAI;GACF,MAAMC,UAAmB,MAAM,gBAAgB,kBAC7C,WACC,aAAa,eAAe,aAAa,WAC3C;GACD,MAAMC,cAAuB,aAAa,kBAAkB,aAAa;GACzE,MAAMC,eAAwB,aAAa,mBAA0C;GACrF,MAAMC,kBAA2B,QAAQ,OAAO,aAAa,UAAU;GACvE,MAAMC,SAAiB,aAAa;GACpC,MAAMC,iBAAsC,QAAQ,eAAe,QAAQ;GAG3E,MAAMC,YAAoB,aAAa;GACvC,MAAMC,0BAAkCV,+BAAe,2BACrD,OAAO,eAAe,WACvB;GAED,MAAMW,eAAuB,MAAMX,+BAAe,mBAChD,aACA,iBACA,WACA,QACA,WACA,cACA,gBACA,EAAC,KAAK,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS,QAAU,CACvE;AAED,0CACE,aACAA,+BAAe,sBAAsB,EACrC,cACAA,+BAAe,wBAAwB,wBAAwB,CAChE;AAED,eAAY,OAAOA,+BAAe,0BAA0B,CAAC;WACtD,OAAO;AACd,0BAAO,MACL;YACE,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,MAAM,GAC5D;;AAML,SAAO;GACL,aAH6B,OAAO,kBAAkB;GAItD,SAAS;GACV;UACM,OAAO;EACd,IAAI,eAAe;AAEnB,MAAI,iBAAiB,MACnB,gBAAe,MAAM;WACZ,SAAS,OAAO,UAAU,YAAY,aAAa,MAC5D,gBAAe,OAAQ,MAA6B,QAAQ;WACnD,OAAO,UAAU,SAC1B,gBAAe;AAGjB,SAAO;GACL,OAAO;GACP,SAAS;GACV;;;AAIL,wCAAe"}
1
+ {"version":3,"file":"handleOAuthCallbackAction.cjs","names":["getClient","cookieStore: RequestCookies","sessionId: string | undefined","tempSessionToken: string | undefined","SessionManager","signInResult: Record<string, unknown>","config: ThunderIDNextConfig","idToken: IdToken","accessToken: string","refreshToken: string","userIdFromToken: string","scopes: string","organizationId: string | undefined","expiresIn: number","sessionCookieExpiryTime: number","sessionToken: string"],"sources":["../../../../src/server/actions/handleOAuthCallbackAction.ts"],"sourcesContent":["// Copyright 2025 The ThunderID Authors\n// SPDX-License-Identifier: Apache-2.0\n\n'use server';\n\nimport {IdToken} from '@thunderid/node';\nimport {cookies} from 'next/headers';\nimport {ThunderIDNextConfig} from '../../models/config';\nimport {setChunkedCookie} from '../../utils/chunkedCookie';\nimport logger from '../../utils/logger';\nimport SessionManager from '../../utils/SessionManager';\nimport getClient from '../getClient';\n\ntype RequestCookies = Awaited<ReturnType<typeof cookies>>;\n\n/**\n * Server action to handle OAuth callback with authorization code.\n * This action processes the authorization code received from the OAuth provider\n * and exchanges it for tokens to complete the authentication flow.\n *\n * @param code - Authorization code from OAuth provider\n * @param state - State parameter from OAuth provider for CSRF protection\n * @returns Promise that resolves with success status and optional error message\n */\nconst handleOAuthCallbackAction = async (\n code: string,\n state: string,\n): Promise<{\n error?: string;\n redirectUrl?: string;\n success: boolean;\n}> => {\n try {\n if (!code || !state) {\n return {\n error: 'Missing required OAuth parameters: code and state are required',\n success: false,\n };\n }\n\n const thunderIDClient = getClient();\n\n // A server action can run in a module context that no provider render has initialized, for\n // example after the dev server recompiles, so initialize from the environment first.\n if (!thunderIDClient.isInitialized) {\n await thunderIDClient.initialize({} as ThunderIDNextConfig);\n }\n\n if (!thunderIDClient.isInitialized) {\n return {\n error: 'ThunderID client is not initialized',\n success: false,\n };\n }\n\n const cookieStore: RequestCookies = await cookies();\n let sessionId: string | undefined;\n\n const tempSessionToken: string | undefined = cookieStore.get(SessionManager.getTempSessionCookieName())?.value;\n\n if (tempSessionToken) {\n try {\n const tempSession: {sessionId: string} = await SessionManager.verifyTempSession(tempSessionToken);\n sessionId = tempSession.sessionId;\n } catch {\n logger.error(\n '[handleOAuthCallbackAction] Invalid temporary session token, falling back to session ID from cookies.',\n );\n }\n }\n\n if (!sessionId) {\n logger.error('[handleOAuthCallbackAction] No session ID found in cookies or temporary session token.');\n\n return {\n error: 'No session found. Please start the authentication flow again.',\n success: false,\n };\n }\n\n // Exchange the authorization code for tokens\n const signInResult: Record<string, unknown> = await thunderIDClient.signIn(\n {\n code,\n state,\n } as any,\n {},\n sessionId,\n );\n\n const config: ThunderIDNextConfig = await thunderIDClient.getConfiguration();\n\n if (signInResult) {\n try {\n const idToken: IdToken = await thunderIDClient.getDecodedIdToken(\n sessionId,\n (signInResult['id_token'] || signInResult['idToken']) as string,\n );\n const accessToken: string = (signInResult['accessToken'] || signInResult['access_token']) as string;\n const refreshToken: string = (signInResult['refreshToken'] as string | undefined) ?? '';\n const userIdFromToken: string = (idToken.sub || signInResult['sub'] || sessionId) as string;\n const scopes: string = signInResult['scope'] as string;\n const organizationId: string | undefined = (idToken['user_org'] || idToken['organization_id']) as\n | string\n | undefined;\n const expiresIn: number = signInResult['expiresIn'] as number;\n const sessionCookieExpiryTime: number = SessionManager.resolveSessionCookieExpiry(\n config.sessionCookie?.expiryTime,\n );\n\n const sessionToken: string = await SessionManager.createSessionToken(\n accessToken,\n userIdFromToken,\n sessionId,\n scopes,\n expiresIn,\n refreshToken,\n organizationId,\n {sid: typeof idToken['sid'] === 'string' ? idToken['sid'] : undefined},\n );\n\n setChunkedCookie(\n cookieStore,\n SessionManager.getSessionCookieName(),\n sessionToken,\n SessionManager.getSessionCookieOptions(sessionCookieExpiryTime),\n );\n\n cookieStore.delete(SessionManager.getTempSessionCookieName());\n } catch (error) {\n logger.error(\n `[handleOAuthCallbackAction] Failed to create JWT session, continuing with legacy session:\n ${typeof error === 'string' ? error : JSON.stringify(error)}`,\n );\n }\n }\n\n const afterSignInUrl: string = config.afterSignInUrl || '/';\n\n return {\n redirectUrl: afterSignInUrl,\n success: true,\n };\n } catch (error) {\n let errorMessage = 'Authentication failed';\n\n if (error instanceof Error) {\n errorMessage = error.message;\n } else if (error && typeof error === 'object' && 'message' in error) {\n errorMessage = String((error as {message: unknown}).message);\n } else if (typeof error === 'string') {\n errorMessage = error;\n }\n\n return {\n error: errorMessage,\n success: false,\n };\n }\n};\n\nexport default handleOAuthCallbackAction;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAwBA,MAAM,4BAA4B,OAChC,MACA,UAKI;AACJ,KAAI;AACF,MAAI,CAAC,QAAQ,CAAC,MACZ,QAAO;GACL,OAAO;GACP,SAAS;GACV;EAGH,MAAM,kBAAkBA,2BAAW;AAInC,MAAI,CAAC,gBAAgB,cACnB,OAAM,gBAAgB,WAAW,EAAE,CAAwB;AAG7D,MAAI,CAAC,gBAAgB,cACnB,QAAO;GACL,OAAO;GACP,SAAS;GACV;EAGH,MAAMC,cAA8B,iCAAe;EACnD,IAAIC;EAEJ,MAAMC,mBAAuC,YAAY,IAAIC,+BAAe,0BAA0B,CAAC,EAAE;AAEzG,MAAI,iBACF,KAAI;AAEF,gBADyC,MAAMA,+BAAe,kBAAkB,iBAAiB,EACzE;UAClB;AACN,0BAAO,MACL,wGACD;;AAIL,MAAI,CAAC,WAAW;AACd,0BAAO,MAAM,yFAAyF;AAEtG,UAAO;IACL,OAAO;IACP,SAAS;IACV;;EAIH,MAAMC,eAAwC,MAAM,gBAAgB,OAClE;GACE;GACA;GACD,EACD,EAAE,EACF,UACD;EAED,MAAMC,SAA8B,MAAM,gBAAgB,kBAAkB;AAE5E,MAAI,aACF,KAAI;GACF,MAAMC,UAAmB,MAAM,gBAAgB,kBAC7C,WACC,aAAa,eAAe,aAAa,WAC3C;GACD,MAAMC,cAAuB,aAAa,kBAAkB,aAAa;GACzE,MAAMC,eAAwB,aAAa,mBAA0C;GACrF,MAAMC,kBAA2B,QAAQ,OAAO,aAAa,UAAU;GACvE,MAAMC,SAAiB,aAAa;GACpC,MAAMC,iBAAsC,QAAQ,eAAe,QAAQ;GAG3E,MAAMC,YAAoB,aAAa;GACvC,MAAMC,0BAAkCV,+BAAe,2BACrD,OAAO,eAAe,WACvB;GAED,MAAMW,eAAuB,MAAMX,+BAAe,mBAChD,aACA,iBACA,WACA,QACA,WACA,cACA,gBACA,EAAC,KAAK,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS,QAAU,CACvE;AAED,0CACE,aACAA,+BAAe,sBAAsB,EACrC,cACAA,+BAAe,wBAAwB,wBAAwB,CAChE;AAED,eAAY,OAAOA,+BAAe,0BAA0B,CAAC;WACtD,OAAO;AACd,0BAAO,MACL;YACE,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,MAAM,GAC5D;;AAML,SAAO;GACL,aAH6B,OAAO,kBAAkB;GAItD,SAAS;GACV;UACM,OAAO;EACd,IAAI,eAAe;AAEnB,MAAI,iBAAiB,MACnB,gBAAe,MAAM;WACZ,SAAS,OAAO,UAAU,YAAY,aAAa,MAC5D,gBAAe,OAAQ,MAA6B,QAAQ;WACnD,OAAO,UAAU,SAC1B,gBAAe;AAGjB,SAAO;GACL,OAAO;GACP,SAAS;GACV;;;AAIL,wCAAe"}