@thunderid/nextjs 0.4.0 → 0.5.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 (27) hide show
  1. package/dist/ThunderIDNextClient.d.ts.map +1 -1
  2. package/dist/ThunderIDNextClient.js +10 -18
  3. package/dist/ThunderIDNextClient.js.map +1 -1
  4. package/dist/cjs/ThunderIDNextClient.cjs +9 -17
  5. package/dist/cjs/ThunderIDNextClient.cjs.map +1 -1
  6. package/dist/cjs/client/components/presentation/UserProfile/UserProfile.cjs +31 -5
  7. package/dist/cjs/client/components/presentation/UserProfile/UserProfile.cjs.map +1 -1
  8. package/dist/cjs/client/contexts/ThunderID/ThunderIDProvider.cjs +4 -2
  9. package/dist/cjs/client/contexts/ThunderID/ThunderIDProvider.cjs.map +1 -1
  10. package/dist/cjs/server/ThunderIDProvider.cjs +22 -5
  11. package/dist/cjs/server/ThunderIDProvider.cjs.map +1 -1
  12. package/dist/cjs/server/actions/getUserProfileAction.cjs +1 -2
  13. package/dist/cjs/server/actions/getUserProfileAction.cjs.map +1 -1
  14. package/dist/client/components/presentation/UserProfile/UserProfile.d.ts +1 -1
  15. package/dist/client/components/presentation/UserProfile/UserProfile.d.ts.map +1 -1
  16. package/dist/client/components/presentation/UserProfile/UserProfile.js +30 -6
  17. package/dist/client/components/presentation/UserProfile/UserProfile.js.map +1 -1
  18. package/dist/client/contexts/ThunderID/ThunderIDProvider.d.ts.map +1 -1
  19. package/dist/client/contexts/ThunderID/ThunderIDProvider.js +4 -2
  20. package/dist/client/contexts/ThunderID/ThunderIDProvider.js.map +1 -1
  21. package/dist/server/ThunderIDProvider.d.ts.map +1 -1
  22. package/dist/server/ThunderIDProvider.js +23 -6
  23. package/dist/server/ThunderIDProvider.js.map +1 -1
  24. package/dist/server/actions/getUserProfileAction.d.ts.map +1 -1
  25. package/dist/server/actions/getUserProfileAction.js +1 -2
  26. package/dist/server/actions/getUserProfileAction.js.map +1 -1
  27. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"ThunderIDNextClient.d.ts","sourceRoot":"","sources":["../src/ThunderIDNextClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,mBAAmB,EAInB,iCAAiC,EAEjC,OAAO,EAEP,aAAa,EACb,aAAa,EACb,OAAO,EACP,0BAA0B,EAC1B,aAAa,EACb,IAAI,EACJ,WAAW,EASZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAC,mBAAmB,EAAC,MAAM,iBAAiB,CAAC;AAKpD,cAAM,mBAAmB,CAAC,CAAC,SAAS,mBAAmB,GAAG,mBAAmB,CAAE,SAAQ,mBAAmB,CAAC,CAAC,CAAC;IACpG,aAAa,UAAS;;YAMf,iBAAiB;IAehB,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAwC1D,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAclD,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BvC,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAqCrD,iBAAiB,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBrE,SAAS,IAAI,OAAO;IAIpB,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhD,aAAa,CAAC,MAAM,EAAE,0BAA0B,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,QAAQ,CAAC;IAKlG,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBpD,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKzE,MAAM,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IA6BpC,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAuBxC,MAAM,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrD,cAAc,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC;IAS7D,sBAAsB,CACjC,YAAY,EAAE,iCAAiC,EAC/C,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;IAKF,iBAAiB,IAAI,GAAG;IAIlB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IASpC,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzF,cAAc,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAGhF;AAED,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"ThunderIDNextClient.d.ts","sourceRoot":"","sources":["../src/ThunderIDNextClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,mBAAmB,EAInB,iCAAiC,EACjC,OAAO,EACP,aAAa,EACb,aAAa,EACb,OAAO,EACP,0BAA0B,EAC1B,aAAa,EACb,IAAI,EACJ,WAAW,EAMZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAC,mBAAmB,EAAC,MAAM,iBAAiB,CAAC;AAKpD,cAAM,mBAAmB,CAAC,CAAC,SAAS,mBAAmB,GAAG,mBAAmB,CAAE,SAAQ,mBAAmB,CAAC,CAAC,CAAC;IACpG,aAAa,UAAS;;YAMf,iBAAiB;IAehB,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAwC1D,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAclD,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqBvC,cAAc,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA0BrD,iBAAiB,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBrE,SAAS,IAAI,OAAO;IAIpB,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIhD,aAAa,CAAC,MAAM,EAAE,0BAA0B,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,QAAQ,CAAC;IAKlG,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBpD,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKzE,MAAM,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IA6BpC,OAAO,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IA4BxC,MAAM,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrD,cAAc,CAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC;IAS7D,sBAAsB,CACjC,YAAY,EAAE,iCAAiC,EAC/C,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;IAKF,iBAAiB,IAAI,GAAG;IAIlB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IASpC,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzF,cAAc,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAGhF;AAED,eAAe,mBAAmB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import getClientOrigin_default from "./server/actions/getClientOrigin.js";
2
2
  import getSessionId_default from "./server/actions/getSessionId.js";
3
3
  import decorateConfigWithNextEnv_default from "./utils/decorateConfigWithNextEnv.js";
4
- import { ThunderIDNodeClient, ThunderIDRuntimeError, executeEmbeddedSignInFlow, extractUserClaimsFromIdToken, flattenUserSchema, generateFlattenedUserProfile, generateUserProfile, getSchemas, getScim2Me, updateMeProfile } from "@thunderid/node";
4
+ import { ThunderIDNodeClient, ThunderIDRuntimeError, executeEmbeddedSignInFlow, extractUserClaimsFromIdToken, generateFlattenedUserProfile, getUsersMe, updateMeProfile } from "@thunderid/node";
5
5
 
6
6
  //#region src/ThunderIDNextClient.ts
7
7
  var ThunderIDNextClient = class extends ThunderIDNodeClient {
@@ -45,13 +45,10 @@ var ThunderIDNextClient = class extends ThunderIDNodeClient {
45
45
  const resolvedSessionId = userId || await getSessionId_default();
46
46
  try {
47
47
  const baseUrl = (await this.getStorageManager().getConfigData())?.baseUrl;
48
- return generateUserProfile(await getScim2Me({
48
+ return await getUsersMe({
49
49
  baseUrl,
50
50
  headers: { Authorization: `Bearer ${await this.getAccessToken(userId)}` }
51
- }), flattenUserSchema(await getSchemas({
52
- baseUrl,
53
- headers: { Authorization: `Bearer ${await this.getAccessToken(userId)}` }
54
- })));
51
+ });
55
52
  } catch (error) {
56
53
  return await super.getUser(resolvedSessionId);
57
54
  }
@@ -60,24 +57,18 @@ var ThunderIDNextClient = class extends ThunderIDNodeClient {
60
57
  await this.ensureInitialized();
61
58
  try {
62
59
  const baseUrl = (await this.getStorageManager().getConfigData())?.baseUrl;
63
- const profile = await getScim2Me({
60
+ const profile = await getUsersMe({
64
61
  baseUrl,
65
62
  headers: { Authorization: `Bearer ${await this.getAccessToken(userId)}` }
66
63
  });
67
- const processedSchemas = flattenUserSchema(await getSchemas({
68
- baseUrl,
69
- headers: { Authorization: `Bearer ${await this.getAccessToken(userId)}` }
70
- }));
71
64
  return {
72
- flattenedProfile: generateFlattenedUserProfile(profile, processedSchemas),
73
- profile,
74
- schemas: processedSchemas
65
+ flattenedProfile: generateFlattenedUserProfile(profile),
66
+ profile
75
67
  };
76
68
  } catch (error) {
77
69
  return {
78
70
  flattenedProfile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)),
79
- profile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)),
80
- schemas: []
71
+ profile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId))
81
72
  };
82
73
  }
83
74
  }
@@ -88,7 +79,7 @@ var ThunderIDNextClient = class extends ThunderIDNodeClient {
88
79
  return updateMeProfile({
89
80
  baseUrl,
90
81
  headers: { Authorization: `Bearer ${await this.getAccessToken(userId)}` },
91
- payload
82
+ payload: payload?.payload ?? payload
92
83
  });
93
84
  } catch (error) {
94
85
  throw new ThunderIDRuntimeError(`Failed to update user profile: ${error instanceof Error ? error.message : String(error)}`, "ThunderIDNextClient-UpdateProfileError-001", "react", "An error occurred while updating the user profile. Please check your configuration and network connection.");
@@ -136,7 +127,8 @@ var ThunderIDNextClient = class extends ThunderIDNodeClient {
136
127
  try {
137
128
  await super.signOut(resolvedSessionId);
138
129
  } catch (error) {
139
- if (!(error instanceof Error ? error.message : String(error)).includes("end_session_endpoint")) throw error;
130
+ const message = error instanceof Error ? error.message : String(error);
131
+ if (!message.includes("end_session_endpoint") && !message.includes("sign-out endpoint") && !message.includes("Sign-out endpoint") && !message.includes("Sign-out redirect URL")) throw error;
140
132
  }
141
133
  return afterSignOutUrl;
142
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ThunderIDNextClient.js","names":["decorateConfigWithNextEnv","origin: string","getClientOrigin","initialized: boolean","resolvedSessionId: string","getSessionId","baseUrl: string | undefined","profile: User","processedSchemas: FlattenedSchema[]","token: string | undefined","arg1: any","arg2: any","arg3: any","arg4: any","afterSignOutUrl: string"],"sources":["../src/ThunderIDNextClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {\n ThunderIDNodeClient,\n ThunderIDRuntimeError,\n AuthClientConfig,\n EmbeddedSignInFlowResponse,\n ExtendedAuthorizeRequestUrlParams,\n FlattenedSchema,\n IdToken,\n Schema,\n SignInOptions,\n SignUpOptions,\n Storage,\n TokenExchangeRequestConfig,\n TokenResponse,\n User,\n UserProfile,\n executeEmbeddedSignInFlow,\n extractUserClaimsFromIdToken,\n flattenUserSchema,\n generateFlattenedUserProfile,\n generateUserProfile,\n getScim2Me,\n getSchemas,\n updateMeProfile,\n} from '@thunderid/node';\nimport {ThunderIDNextConfig} from './models/config';\nimport getClientOrigin from './server/actions/getClientOrigin';\nimport getSessionId from './server/actions/getSessionId';\nimport decorateConfigWithNextEnv from './utils/decorateConfigWithNextEnv';\n\nclass ThunderIDNextClient<T extends ThunderIDNextConfig = ThunderIDNextConfig> extends ThunderIDNodeClient<T> {\n public isInitialized = false;\n\n public constructor() {\n super();\n }\n\n private async ensureInitialized(): Promise<void> {\n if (!this.isInitialized) {\n // Server actions may run in a module context that hasn't been through\n // ThunderIDServerProvider (e.g. a different worker). Try to initialize\n // from environment variables before giving up.\n await this.initialize({} as T);\n }\n\n if (!this.isInitialized) {\n throw new Error(\n '[ThunderIDNextClient] Client is not initialized. Make sure you have wrapped your app with ThunderIDProvider and provided the required configuration (baseUrl, clientId, etc.).',\n );\n }\n }\n\n override async initialize(config: T, storage?: Storage): Promise<boolean> {\n if (this.isInitialized) {\n return Promise.resolve(true);\n }\n\n const {\n baseUrl,\n organizationHandle,\n clientId,\n clientSecret,\n signInUrl,\n afterSignInUrl,\n afterSignOutUrl,\n signUpUrl,\n ...rest\n } = decorateConfigWithNextEnv(config);\n\n const origin: string = await getClientOrigin();\n\n const initialized: boolean = await super.initialize(\n {\n ...rest,\n afterSignInUrl: afterSignInUrl ?? origin,\n afterSignOutUrl: afterSignOutUrl ?? origin,\n baseUrl,\n clientId,\n clientSecret,\n enablePKCE: (rest as any).enablePKCE ?? true,\n organizationHandle,\n signInUrl,\n signUpUrl,\n } as any,\n storage,\n );\n\n this.isInitialized = initialized;\n\n return initialized;\n }\n\n override async reInitialize(config: Partial<T>): Promise<boolean> {\n try {\n await super.reInitialize(config);\n return true;\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to re-initialize the client: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDNextClient-reInitialize-RuntimeError-001',\n 'nextjs',\n 'An error occurred while re-initializing the client. Please check your configuration and network connection.',\n );\n }\n }\n\n override async getUser(userId?: string): Promise<User> {\n await this.ensureInitialized();\n const resolvedSessionId: string = userId || (await getSessionId())!;\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n const profile: User = await getScim2Me({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n const schemas: Schema[] = await getSchemas({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n return generateUserProfile(profile, flattenUserSchema(schemas));\n } catch (error) {\n return await super.getUser(resolvedSessionId);\n }\n }\n\n override async getUserProfile(userId?: string): Promise<UserProfile> {\n await this.ensureInitialized();\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n const profile: User = await getScim2Me({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n const schemas: Schema[] = await getSchemas({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n const processedSchemas: FlattenedSchema[] = flattenUserSchema(schemas);\n\n return {\n flattenedProfile: generateFlattenedUserProfile(profile, processedSchemas),\n profile,\n schemas: processedSchemas,\n };\n } catch (error) {\n return {\n flattenedProfile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)),\n profile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)),\n schemas: [],\n };\n }\n }\n\n override async updateUserProfile(payload: any, userId?: string): Promise<User> {\n await this.ensureInitialized();\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n return updateMeProfile({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n payload,\n });\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to update user profile: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDNextClient-UpdateProfileError-001',\n 'react',\n 'An error occurred while updating the user profile. Please check your configuration and network connection.',\n );\n }\n }\n\n override isLoading(): boolean {\n return false;\n }\n\n override isSignedIn(sessionId?: string): Promise<boolean> {\n return super.isSignedIn(sessionId);\n }\n\n override exchangeToken(config: TokenExchangeRequestConfig, sessionId?: string): Promise<TokenResponse | Response> {\n return super.exchangeToken(config, sessionId) as unknown as Promise<TokenResponse | Response>;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n override async getAccessToken(_sessionId?: string): Promise<string> {\n const {default: getAccessToken} = await import('./server/actions/getAccessToken');\n const token: string | undefined = await getAccessToken();\n\n if (typeof token !== 'string' || !token) {\n throw new ThunderIDRuntimeError(\n 'Failed to get access token.',\n 'ThunderIDNextClient-getAccessToken-RuntimeError-003',\n 'nextjs',\n 'An error occurred while obtaining the access token. Please check your configuration and network connection.',\n );\n }\n\n return token;\n }\n\n override async getDecodedIdToken(sessionId?: string, idToken?: string): Promise<IdToken> {\n await this.ensureInitialized();\n return await super.getDecodedIdToken(sessionId, idToken);\n }\n\n override async signIn(...args: any[]): Promise<any> {\n const arg1: any = args[0];\n const arg2: any = args[1];\n const arg3: any = args[2];\n const arg4: any = args[3];\n\n // An embedded sign-in flow payload initiates or continues a `POST /flow/execute` step\n // (identified by `applicationId` for a new flow or `executionId` to continue one). This is\n // distinct from the OAuth authorization_code exchange handled by `super.signIn` below, which\n // is used once the embedded flow completes and returns an authorization code.\n const isEmbeddedFlowPayload: boolean =\n typeof arg1 === 'object' && arg1 !== null && ('executionId' in arg1 || 'applicationId' in arg1);\n\n if (isEmbeddedFlowPayload) {\n await this.ensureInitialized();\n\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n\n return executeEmbeddedSignInFlow({\n baseUrl: configData?.baseUrl,\n flowSecret: arg2?.flowSecret,\n payload: arg1,\n url: arg2?.url,\n }) as unknown as Promise<EmbeddedSignInFlowResponse>;\n }\n\n return super.signIn(arg4, arg3, arg1?.code, arg1?.session_state, arg1?.state, arg1) as unknown as Promise<User>;\n }\n\n override async signOut(...args: any[]): Promise<string> {\n if (args[1] && typeof args[1] !== 'string') {\n throw new Error('The second argument must be a string.');\n }\n\n const config: T = this.getConfiguration();\n const afterSignOutUrl: string = config?.afterSignOutUrl || '/';\n\n const resolvedSessionId: string = args[1] || (await getSessionId())!;\n\n try {\n await (super.signOut as (...a: any[]) => Promise<string>)(resolvedSessionId);\n } catch (error) {\n const message: string = error instanceof Error ? error.message : String(error);\n\n if (!message.includes('end_session_endpoint')) {\n throw error;\n }\n }\n\n return afterSignOutUrl;\n }\n\n override async signUp(_options?: SignUpOptions): Promise<void> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-ValidationError-002',\n 'nextjs',\n 'The signUp method is not implemented in the Next.js client.',\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n override signInSilently(_options?: SignInOptions): Promise<User | boolean> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-signInSilently-NotImplementedError-001',\n 'nextjs',\n 'The signInSilently method is not implemented in the Next.js client.',\n );\n }\n\n public async getAuthorizeRequestUrl(\n customParams: ExtendedAuthorizeRequestUrlParams,\n userId?: string,\n ): Promise<string> {\n await this.ensureInitialized();\n return this.getSignInUrl(customParams, userId);\n }\n\n public override getStorageManager(): any {\n return super.getStorageManager();\n }\n\n public override async clearSession(): Promise<void> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-clearSession-NotImplementedError-001',\n 'nextjs',\n 'The clearSession method is not implemented in the Next.js client.',\n );\n }\n\n override async setSession(sessionData: Record<string, unknown>, sessionId?: string): Promise<void> {\n return this.getStorageManager().setSessionData(sessionData, sessionId);\n }\n\n override decodeJwtToken<R = Record<string, unknown>>(token: string): Promise<R> {\n return super.decodeJwtToken<R>(token);\n }\n}\n\nexport default ThunderIDNextClient;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ThunderIDNextClient.js","names":["decorateConfigWithNextEnv","origin: string","getClientOrigin","initialized: boolean","resolvedSessionId: string","getSessionId","baseUrl: string | undefined","profile: User","token: string | undefined","arg1: any","arg2: any","arg3: any","arg4: any","afterSignOutUrl: string","message: string"],"sources":["../src/ThunderIDNextClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {\n ThunderIDNodeClient,\n ThunderIDRuntimeError,\n AuthClientConfig,\n EmbeddedSignInFlowResponse,\n ExtendedAuthorizeRequestUrlParams,\n IdToken,\n SignInOptions,\n SignUpOptions,\n Storage,\n TokenExchangeRequestConfig,\n TokenResponse,\n User,\n UserProfile,\n executeEmbeddedSignInFlow,\n extractUserClaimsFromIdToken,\n generateFlattenedUserProfile,\n getUsersMe,\n updateMeProfile,\n} from '@thunderid/node';\nimport {ThunderIDNextConfig} from './models/config';\nimport getClientOrigin from './server/actions/getClientOrigin';\nimport getSessionId from './server/actions/getSessionId';\nimport decorateConfigWithNextEnv from './utils/decorateConfigWithNextEnv';\n\nclass ThunderIDNextClient<T extends ThunderIDNextConfig = ThunderIDNextConfig> extends ThunderIDNodeClient<T> {\n public isInitialized = false;\n\n public constructor() {\n super();\n }\n\n private async ensureInitialized(): Promise<void> {\n if (!this.isInitialized) {\n // Server actions may run in a module context that hasn't been through\n // ThunderIDServerProvider (e.g. a different worker). Try to initialize\n // from environment variables before giving up.\n await this.initialize({} as T);\n }\n\n if (!this.isInitialized) {\n throw new Error(\n '[ThunderIDNextClient] Client is not initialized. Make sure you have wrapped your app with ThunderIDProvider and provided the required configuration (baseUrl, clientId, etc.).',\n );\n }\n }\n\n override async initialize(config: T, storage?: Storage): Promise<boolean> {\n if (this.isInitialized) {\n return Promise.resolve(true);\n }\n\n const {\n baseUrl,\n organizationHandle,\n clientId,\n clientSecret,\n signInUrl,\n afterSignInUrl,\n afterSignOutUrl,\n signUpUrl,\n ...rest\n } = decorateConfigWithNextEnv(config);\n\n const origin: string = await getClientOrigin();\n\n const initialized: boolean = await super.initialize(\n {\n ...rest,\n afterSignInUrl: afterSignInUrl ?? origin,\n afterSignOutUrl: afterSignOutUrl ?? origin,\n baseUrl,\n clientId,\n clientSecret,\n enablePKCE: (rest as any).enablePKCE ?? true,\n organizationHandle,\n signInUrl,\n signUpUrl,\n } as any,\n storage,\n );\n\n this.isInitialized = initialized;\n\n return initialized;\n }\n\n override async reInitialize(config: Partial<T>): Promise<boolean> {\n try {\n await super.reInitialize(config);\n return true;\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to re-initialize the client: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDNextClient-reInitialize-RuntimeError-001',\n 'nextjs',\n 'An error occurred while re-initializing the client. Please check your configuration and network connection.',\n );\n }\n }\n\n override async getUser(userId?: string): Promise<User> {\n await this.ensureInitialized();\n const resolvedSessionId: string = userId || (await getSessionId())!;\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n const profile: User = await getUsersMe({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n return profile;\n } catch (error) {\n return await super.getUser(resolvedSessionId);\n }\n }\n\n override async getUserProfile(userId?: string): Promise<UserProfile> {\n await this.ensureInitialized();\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n const profile: User = await getUsersMe({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n return {\n flattenedProfile: generateFlattenedUserProfile(profile),\n profile,\n };\n } catch (error) {\n return {\n flattenedProfile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)),\n profile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)),\n };\n }\n }\n\n override async updateUserProfile(payload: any, userId?: string): Promise<User> {\n await this.ensureInitialized();\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n return updateMeProfile({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n payload: payload?.payload ?? payload,\n });\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to update user profile: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDNextClient-UpdateProfileError-001',\n 'react',\n 'An error occurred while updating the user profile. Please check your configuration and network connection.',\n );\n }\n }\n\n override isLoading(): boolean {\n return false;\n }\n\n override isSignedIn(sessionId?: string): Promise<boolean> {\n return super.isSignedIn(sessionId);\n }\n\n override exchangeToken(config: TokenExchangeRequestConfig, sessionId?: string): Promise<TokenResponse | Response> {\n return super.exchangeToken(config, sessionId) as unknown as Promise<TokenResponse | Response>;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n override async getAccessToken(_sessionId?: string): Promise<string> {\n const {default: getAccessToken} = await import('./server/actions/getAccessToken');\n const token: string | undefined = await getAccessToken();\n\n if (typeof token !== 'string' || !token) {\n throw new ThunderIDRuntimeError(\n 'Failed to get access token.',\n 'ThunderIDNextClient-getAccessToken-RuntimeError-003',\n 'nextjs',\n 'An error occurred while obtaining the access token. Please check your configuration and network connection.',\n );\n }\n\n return token;\n }\n\n override async getDecodedIdToken(sessionId?: string, idToken?: string): Promise<IdToken> {\n await this.ensureInitialized();\n return await super.getDecodedIdToken(sessionId, idToken);\n }\n\n override async signIn(...args: any[]): Promise<any> {\n const arg1: any = args[0];\n const arg2: any = args[1];\n const arg3: any = args[2];\n const arg4: any = args[3];\n\n // An embedded sign-in flow payload initiates or continues a `POST /flow/execute` step\n // (identified by `applicationId` for a new flow or `executionId` to continue one). This is\n // distinct from the OAuth authorization_code exchange handled by `super.signIn` below, which\n // is used once the embedded flow completes and returns an authorization code.\n const isEmbeddedFlowPayload: boolean =\n typeof arg1 === 'object' && arg1 !== null && ('executionId' in arg1 || 'applicationId' in arg1);\n\n if (isEmbeddedFlowPayload) {\n await this.ensureInitialized();\n\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n\n return executeEmbeddedSignInFlow({\n baseUrl: configData?.baseUrl,\n flowSecret: arg2?.flowSecret,\n payload: arg1,\n url: arg2?.url,\n }) as unknown as Promise<EmbeddedSignInFlowResponse>;\n }\n\n return super.signIn(arg4, arg3, arg1?.code, arg1?.session_state, arg1?.state, arg1) as unknown as Promise<User>;\n }\n\n override async signOut(...args: any[]): Promise<string> {\n if (args[1] && typeof args[1] !== 'string') {\n throw new Error('The second argument must be a string.');\n }\n\n const config: T = this.getConfiguration();\n const afterSignOutUrl: string = config?.afterSignOutUrl || '/';\n\n const resolvedSessionId: string = args[1] || (await getSessionId())!;\n\n try {\n await (super.signOut as (...a: any[]) => Promise<string>)(resolvedSessionId);\n } catch (error) {\n const message: string = error instanceof Error ? error.message : String(error);\n\n if (\n !message.includes('end_session_endpoint') &&\n !message.includes('sign-out endpoint') &&\n !message.includes('Sign-out endpoint') &&\n !message.includes('Sign-out redirect URL')\n ) {\n throw error;\n }\n }\n\n return afterSignOutUrl;\n }\n\n override async signUp(_options?: SignUpOptions): Promise<void> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-ValidationError-002',\n 'nextjs',\n 'The signUp method is not implemented in the Next.js client.',\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n override signInSilently(_options?: SignInOptions): Promise<User | boolean> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-signInSilently-NotImplementedError-001',\n 'nextjs',\n 'The signInSilently method is not implemented in the Next.js client.',\n );\n }\n\n public async getAuthorizeRequestUrl(\n customParams: ExtendedAuthorizeRequestUrlParams,\n userId?: string,\n ): Promise<string> {\n await this.ensureInitialized();\n return this.getSignInUrl(customParams, userId);\n }\n\n public override getStorageManager(): any {\n return super.getStorageManager();\n }\n\n public override async clearSession(): Promise<void> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-clearSession-NotImplementedError-001',\n 'nextjs',\n 'The clearSession method is not implemented in the Next.js client.',\n );\n }\n\n override async setSession(sessionData: Record<string, unknown>, sessionId?: string): Promise<void> {\n return this.getStorageManager().setSessionData(sessionData, sessionId);\n }\n\n override decodeJwtToken<R = Record<string, unknown>>(token: string): Promise<R> {\n return super.decodeJwtToken<R>(token);\n }\n}\n\nexport default ThunderIDNextClient;\n"],"mappings":"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"}
@@ -47,13 +47,10 @@ var ThunderIDNextClient = class extends __thunderid_node.ThunderIDNodeClient {
47
47
  const resolvedSessionId = userId || await require_getSessionId.default();
48
48
  try {
49
49
  const baseUrl = (await this.getStorageManager().getConfigData())?.baseUrl;
50
- return (0, __thunderid_node.generateUserProfile)(await (0, __thunderid_node.getScim2Me)({
50
+ return await (0, __thunderid_node.getUsersMe)({
51
51
  baseUrl,
52
52
  headers: { Authorization: `Bearer ${await this.getAccessToken(userId)}` }
53
- }), (0, __thunderid_node.flattenUserSchema)(await (0, __thunderid_node.getSchemas)({
54
- baseUrl,
55
- headers: { Authorization: `Bearer ${await this.getAccessToken(userId)}` }
56
- })));
53
+ });
57
54
  } catch (error) {
58
55
  return await super.getUser(resolvedSessionId);
59
56
  }
@@ -62,24 +59,18 @@ var ThunderIDNextClient = class extends __thunderid_node.ThunderIDNodeClient {
62
59
  await this.ensureInitialized();
63
60
  try {
64
61
  const baseUrl = (await this.getStorageManager().getConfigData())?.baseUrl;
65
- const profile = await (0, __thunderid_node.getScim2Me)({
62
+ const profile = await (0, __thunderid_node.getUsersMe)({
66
63
  baseUrl,
67
64
  headers: { Authorization: `Bearer ${await this.getAccessToken(userId)}` }
68
65
  });
69
- const processedSchemas = (0, __thunderid_node.flattenUserSchema)(await (0, __thunderid_node.getSchemas)({
70
- baseUrl,
71
- headers: { Authorization: `Bearer ${await this.getAccessToken(userId)}` }
72
- }));
73
66
  return {
74
- flattenedProfile: (0, __thunderid_node.generateFlattenedUserProfile)(profile, processedSchemas),
75
- profile,
76
- schemas: processedSchemas
67
+ flattenedProfile: (0, __thunderid_node.generateFlattenedUserProfile)(profile),
68
+ profile
77
69
  };
78
70
  } catch (error) {
79
71
  return {
80
72
  flattenedProfile: (0, __thunderid_node.extractUserClaimsFromIdToken)(await super.getDecodedIdToken(userId)),
81
- profile: (0, __thunderid_node.extractUserClaimsFromIdToken)(await super.getDecodedIdToken(userId)),
82
- schemas: []
73
+ profile: (0, __thunderid_node.extractUserClaimsFromIdToken)(await super.getDecodedIdToken(userId))
83
74
  };
84
75
  }
85
76
  }
@@ -90,7 +81,7 @@ var ThunderIDNextClient = class extends __thunderid_node.ThunderIDNodeClient {
90
81
  return (0, __thunderid_node.updateMeProfile)({
91
82
  baseUrl,
92
83
  headers: { Authorization: `Bearer ${await this.getAccessToken(userId)}` },
93
- payload
84
+ payload: payload?.payload ?? payload
94
85
  });
95
86
  } catch (error) {
96
87
  throw new __thunderid_node.ThunderIDRuntimeError(`Failed to update user profile: ${error instanceof Error ? error.message : String(error)}`, "ThunderIDNextClient-UpdateProfileError-001", "react", "An error occurred while updating the user profile. Please check your configuration and network connection.");
@@ -138,7 +129,8 @@ var ThunderIDNextClient = class extends __thunderid_node.ThunderIDNodeClient {
138
129
  try {
139
130
  await super.signOut(resolvedSessionId);
140
131
  } catch (error) {
141
- if (!(error instanceof Error ? error.message : String(error)).includes("end_session_endpoint")) throw error;
132
+ const message = error instanceof Error ? error.message : String(error);
133
+ if (!message.includes("end_session_endpoint") && !message.includes("sign-out endpoint") && !message.includes("Sign-out endpoint") && !message.includes("Sign-out redirect URL")) throw error;
142
134
  }
143
135
  return afterSignOutUrl;
144
136
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ThunderIDNextClient.cjs","names":["ThunderIDNodeClient","decorateConfigWithNextEnv","origin: string","getClientOrigin","initialized: boolean","ThunderIDRuntimeError","resolvedSessionId: string","getSessionId","baseUrl: string | undefined","profile: User","processedSchemas: FlattenedSchema[]","token: string | undefined","arg1: any","arg2: any","arg3: any","arg4: any","afterSignOutUrl: string"],"sources":["../../src/ThunderIDNextClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {\n ThunderIDNodeClient,\n ThunderIDRuntimeError,\n AuthClientConfig,\n EmbeddedSignInFlowResponse,\n ExtendedAuthorizeRequestUrlParams,\n FlattenedSchema,\n IdToken,\n Schema,\n SignInOptions,\n SignUpOptions,\n Storage,\n TokenExchangeRequestConfig,\n TokenResponse,\n User,\n UserProfile,\n executeEmbeddedSignInFlow,\n extractUserClaimsFromIdToken,\n flattenUserSchema,\n generateFlattenedUserProfile,\n generateUserProfile,\n getScim2Me,\n getSchemas,\n updateMeProfile,\n} from '@thunderid/node';\nimport {ThunderIDNextConfig} from './models/config';\nimport getClientOrigin from './server/actions/getClientOrigin';\nimport getSessionId from './server/actions/getSessionId';\nimport decorateConfigWithNextEnv from './utils/decorateConfigWithNextEnv';\n\nclass ThunderIDNextClient<T extends ThunderIDNextConfig = ThunderIDNextConfig> extends ThunderIDNodeClient<T> {\n public isInitialized = false;\n\n public constructor() {\n super();\n }\n\n private async ensureInitialized(): Promise<void> {\n if (!this.isInitialized) {\n // Server actions may run in a module context that hasn't been through\n // ThunderIDServerProvider (e.g. a different worker). Try to initialize\n // from environment variables before giving up.\n await this.initialize({} as T);\n }\n\n if (!this.isInitialized) {\n throw new Error(\n '[ThunderIDNextClient] Client is not initialized. Make sure you have wrapped your app with ThunderIDProvider and provided the required configuration (baseUrl, clientId, etc.).',\n );\n }\n }\n\n override async initialize(config: T, storage?: Storage): Promise<boolean> {\n if (this.isInitialized) {\n return Promise.resolve(true);\n }\n\n const {\n baseUrl,\n organizationHandle,\n clientId,\n clientSecret,\n signInUrl,\n afterSignInUrl,\n afterSignOutUrl,\n signUpUrl,\n ...rest\n } = decorateConfigWithNextEnv(config);\n\n const origin: string = await getClientOrigin();\n\n const initialized: boolean = await super.initialize(\n {\n ...rest,\n afterSignInUrl: afterSignInUrl ?? origin,\n afterSignOutUrl: afterSignOutUrl ?? origin,\n baseUrl,\n clientId,\n clientSecret,\n enablePKCE: (rest as any).enablePKCE ?? true,\n organizationHandle,\n signInUrl,\n signUpUrl,\n } as any,\n storage,\n );\n\n this.isInitialized = initialized;\n\n return initialized;\n }\n\n override async reInitialize(config: Partial<T>): Promise<boolean> {\n try {\n await super.reInitialize(config);\n return true;\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to re-initialize the client: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDNextClient-reInitialize-RuntimeError-001',\n 'nextjs',\n 'An error occurred while re-initializing the client. Please check your configuration and network connection.',\n );\n }\n }\n\n override async getUser(userId?: string): Promise<User> {\n await this.ensureInitialized();\n const resolvedSessionId: string = userId || (await getSessionId())!;\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n const profile: User = await getScim2Me({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n const schemas: Schema[] = await getSchemas({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n return generateUserProfile(profile, flattenUserSchema(schemas));\n } catch (error) {\n return await super.getUser(resolvedSessionId);\n }\n }\n\n override async getUserProfile(userId?: string): Promise<UserProfile> {\n await this.ensureInitialized();\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n const profile: User = await getScim2Me({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n const schemas: Schema[] = await getSchemas({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n const processedSchemas: FlattenedSchema[] = flattenUserSchema(schemas);\n\n return {\n flattenedProfile: generateFlattenedUserProfile(profile, processedSchemas),\n profile,\n schemas: processedSchemas,\n };\n } catch (error) {\n return {\n flattenedProfile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)),\n profile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)),\n schemas: [],\n };\n }\n }\n\n override async updateUserProfile(payload: any, userId?: string): Promise<User> {\n await this.ensureInitialized();\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n return updateMeProfile({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n payload,\n });\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to update user profile: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDNextClient-UpdateProfileError-001',\n 'react',\n 'An error occurred while updating the user profile. Please check your configuration and network connection.',\n );\n }\n }\n\n override isLoading(): boolean {\n return false;\n }\n\n override isSignedIn(sessionId?: string): Promise<boolean> {\n return super.isSignedIn(sessionId);\n }\n\n override exchangeToken(config: TokenExchangeRequestConfig, sessionId?: string): Promise<TokenResponse | Response> {\n return super.exchangeToken(config, sessionId) as unknown as Promise<TokenResponse | Response>;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n override async getAccessToken(_sessionId?: string): Promise<string> {\n const {default: getAccessToken} = await import('./server/actions/getAccessToken');\n const token: string | undefined = await getAccessToken();\n\n if (typeof token !== 'string' || !token) {\n throw new ThunderIDRuntimeError(\n 'Failed to get access token.',\n 'ThunderIDNextClient-getAccessToken-RuntimeError-003',\n 'nextjs',\n 'An error occurred while obtaining the access token. Please check your configuration and network connection.',\n );\n }\n\n return token;\n }\n\n override async getDecodedIdToken(sessionId?: string, idToken?: string): Promise<IdToken> {\n await this.ensureInitialized();\n return await super.getDecodedIdToken(sessionId, idToken);\n }\n\n override async signIn(...args: any[]): Promise<any> {\n const arg1: any = args[0];\n const arg2: any = args[1];\n const arg3: any = args[2];\n const arg4: any = args[3];\n\n // An embedded sign-in flow payload initiates or continues a `POST /flow/execute` step\n // (identified by `applicationId` for a new flow or `executionId` to continue one). This is\n // distinct from the OAuth authorization_code exchange handled by `super.signIn` below, which\n // is used once the embedded flow completes and returns an authorization code.\n const isEmbeddedFlowPayload: boolean =\n typeof arg1 === 'object' && arg1 !== null && ('executionId' in arg1 || 'applicationId' in arg1);\n\n if (isEmbeddedFlowPayload) {\n await this.ensureInitialized();\n\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n\n return executeEmbeddedSignInFlow({\n baseUrl: configData?.baseUrl,\n flowSecret: arg2?.flowSecret,\n payload: arg1,\n url: arg2?.url,\n }) as unknown as Promise<EmbeddedSignInFlowResponse>;\n }\n\n return super.signIn(arg4, arg3, arg1?.code, arg1?.session_state, arg1?.state, arg1) as unknown as Promise<User>;\n }\n\n override async signOut(...args: any[]): Promise<string> {\n if (args[1] && typeof args[1] !== 'string') {\n throw new Error('The second argument must be a string.');\n }\n\n const config: T = this.getConfiguration();\n const afterSignOutUrl: string = config?.afterSignOutUrl || '/';\n\n const resolvedSessionId: string = args[1] || (await getSessionId())!;\n\n try {\n await (super.signOut as (...a: any[]) => Promise<string>)(resolvedSessionId);\n } catch (error) {\n const message: string = error instanceof Error ? error.message : String(error);\n\n if (!message.includes('end_session_endpoint')) {\n throw error;\n }\n }\n\n return afterSignOutUrl;\n }\n\n override async signUp(_options?: SignUpOptions): Promise<void> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-ValidationError-002',\n 'nextjs',\n 'The signUp method is not implemented in the Next.js client.',\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n override signInSilently(_options?: SignInOptions): Promise<User | boolean> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-signInSilently-NotImplementedError-001',\n 'nextjs',\n 'The signInSilently method is not implemented in the Next.js client.',\n );\n }\n\n public async getAuthorizeRequestUrl(\n customParams: ExtendedAuthorizeRequestUrlParams,\n userId?: string,\n ): Promise<string> {\n await this.ensureInitialized();\n return this.getSignInUrl(customParams, userId);\n }\n\n public override getStorageManager(): any {\n return super.getStorageManager();\n }\n\n public override async clearSession(): Promise<void> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-clearSession-NotImplementedError-001',\n 'nextjs',\n 'The clearSession method is not implemented in the Next.js client.',\n );\n }\n\n override async setSession(sessionData: Record<string, unknown>, sessionId?: string): Promise<void> {\n return this.getStorageManager().setSessionData(sessionData, sessionId);\n }\n\n override decodeJwtToken<R = Record<string, unknown>>(token: string): Promise<R> {\n return super.decodeJwtToken<R>(token);\n }\n}\n\nexport default ThunderIDNextClient;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ThunderIDNextClient.cjs","names":["ThunderIDNodeClient","decorateConfigWithNextEnv","origin: string","getClientOrigin","initialized: boolean","ThunderIDRuntimeError","resolvedSessionId: string","getSessionId","baseUrl: string | undefined","profile: User","token: string | undefined","arg1: any","arg2: any","arg3: any","arg4: any","afterSignOutUrl: string","message: string"],"sources":["../../src/ThunderIDNextClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\nimport {\n ThunderIDNodeClient,\n ThunderIDRuntimeError,\n AuthClientConfig,\n EmbeddedSignInFlowResponse,\n ExtendedAuthorizeRequestUrlParams,\n IdToken,\n SignInOptions,\n SignUpOptions,\n Storage,\n TokenExchangeRequestConfig,\n TokenResponse,\n User,\n UserProfile,\n executeEmbeddedSignInFlow,\n extractUserClaimsFromIdToken,\n generateFlattenedUserProfile,\n getUsersMe,\n updateMeProfile,\n} from '@thunderid/node';\nimport {ThunderIDNextConfig} from './models/config';\nimport getClientOrigin from './server/actions/getClientOrigin';\nimport getSessionId from './server/actions/getSessionId';\nimport decorateConfigWithNextEnv from './utils/decorateConfigWithNextEnv';\n\nclass ThunderIDNextClient<T extends ThunderIDNextConfig = ThunderIDNextConfig> extends ThunderIDNodeClient<T> {\n public isInitialized = false;\n\n public constructor() {\n super();\n }\n\n private async ensureInitialized(): Promise<void> {\n if (!this.isInitialized) {\n // Server actions may run in a module context that hasn't been through\n // ThunderIDServerProvider (e.g. a different worker). Try to initialize\n // from environment variables before giving up.\n await this.initialize({} as T);\n }\n\n if (!this.isInitialized) {\n throw new Error(\n '[ThunderIDNextClient] Client is not initialized. Make sure you have wrapped your app with ThunderIDProvider and provided the required configuration (baseUrl, clientId, etc.).',\n );\n }\n }\n\n override async initialize(config: T, storage?: Storage): Promise<boolean> {\n if (this.isInitialized) {\n return Promise.resolve(true);\n }\n\n const {\n baseUrl,\n organizationHandle,\n clientId,\n clientSecret,\n signInUrl,\n afterSignInUrl,\n afterSignOutUrl,\n signUpUrl,\n ...rest\n } = decorateConfigWithNextEnv(config);\n\n const origin: string = await getClientOrigin();\n\n const initialized: boolean = await super.initialize(\n {\n ...rest,\n afterSignInUrl: afterSignInUrl ?? origin,\n afterSignOutUrl: afterSignOutUrl ?? origin,\n baseUrl,\n clientId,\n clientSecret,\n enablePKCE: (rest as any).enablePKCE ?? true,\n organizationHandle,\n signInUrl,\n signUpUrl,\n } as any,\n storage,\n );\n\n this.isInitialized = initialized;\n\n return initialized;\n }\n\n override async reInitialize(config: Partial<T>): Promise<boolean> {\n try {\n await super.reInitialize(config);\n return true;\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to re-initialize the client: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDNextClient-reInitialize-RuntimeError-001',\n 'nextjs',\n 'An error occurred while re-initializing the client. Please check your configuration and network connection.',\n );\n }\n }\n\n override async getUser(userId?: string): Promise<User> {\n await this.ensureInitialized();\n const resolvedSessionId: string = userId || (await getSessionId())!;\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n const profile: User = await getUsersMe({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n return profile;\n } catch (error) {\n return await super.getUser(resolvedSessionId);\n }\n }\n\n override async getUserProfile(userId?: string): Promise<UserProfile> {\n await this.ensureInitialized();\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n const profile: User = await getUsersMe({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n });\n\n return {\n flattenedProfile: generateFlattenedUserProfile(profile),\n profile,\n };\n } catch (error) {\n return {\n flattenedProfile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)),\n profile: extractUserClaimsFromIdToken(await super.getDecodedIdToken(userId)),\n };\n }\n }\n\n override async updateUserProfile(payload: any, userId?: string): Promise<User> {\n await this.ensureInitialized();\n\n try {\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n const baseUrl: string | undefined = configData?.baseUrl;\n\n return updateMeProfile({\n baseUrl,\n headers: {\n Authorization: `Bearer ${await this.getAccessToken(userId)}`,\n },\n payload: payload?.payload ?? payload,\n });\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to update user profile: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDNextClient-UpdateProfileError-001',\n 'react',\n 'An error occurred while updating the user profile. Please check your configuration and network connection.',\n );\n }\n }\n\n override isLoading(): boolean {\n return false;\n }\n\n override isSignedIn(sessionId?: string): Promise<boolean> {\n return super.isSignedIn(sessionId);\n }\n\n override exchangeToken(config: TokenExchangeRequestConfig, sessionId?: string): Promise<TokenResponse | Response> {\n return super.exchangeToken(config, sessionId) as unknown as Promise<TokenResponse | Response>;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n override async getAccessToken(_sessionId?: string): Promise<string> {\n const {default: getAccessToken} = await import('./server/actions/getAccessToken');\n const token: string | undefined = await getAccessToken();\n\n if (typeof token !== 'string' || !token) {\n throw new ThunderIDRuntimeError(\n 'Failed to get access token.',\n 'ThunderIDNextClient-getAccessToken-RuntimeError-003',\n 'nextjs',\n 'An error occurred while obtaining the access token. Please check your configuration and network connection.',\n );\n }\n\n return token;\n }\n\n override async getDecodedIdToken(sessionId?: string, idToken?: string): Promise<IdToken> {\n await this.ensureInitialized();\n return await super.getDecodedIdToken(sessionId, idToken);\n }\n\n override async signIn(...args: any[]): Promise<any> {\n const arg1: any = args[0];\n const arg2: any = args[1];\n const arg3: any = args[2];\n const arg4: any = args[3];\n\n // An embedded sign-in flow payload initiates or continues a `POST /flow/execute` step\n // (identified by `applicationId` for a new flow or `executionId` to continue one). This is\n // distinct from the OAuth authorization_code exchange handled by `super.signIn` below, which\n // is used once the embedded flow completes and returns an authorization code.\n const isEmbeddedFlowPayload: boolean =\n typeof arg1 === 'object' && arg1 !== null && ('executionId' in arg1 || 'applicationId' in arg1);\n\n if (isEmbeddedFlowPayload) {\n await this.ensureInitialized();\n\n const configData: AuthClientConfig<T> = await this.getStorageManager().getConfigData();\n\n return executeEmbeddedSignInFlow({\n baseUrl: configData?.baseUrl,\n flowSecret: arg2?.flowSecret,\n payload: arg1,\n url: arg2?.url,\n }) as unknown as Promise<EmbeddedSignInFlowResponse>;\n }\n\n return super.signIn(arg4, arg3, arg1?.code, arg1?.session_state, arg1?.state, arg1) as unknown as Promise<User>;\n }\n\n override async signOut(...args: any[]): Promise<string> {\n if (args[1] && typeof args[1] !== 'string') {\n throw new Error('The second argument must be a string.');\n }\n\n const config: T = this.getConfiguration();\n const afterSignOutUrl: string = config?.afterSignOutUrl || '/';\n\n const resolvedSessionId: string = args[1] || (await getSessionId())!;\n\n try {\n await (super.signOut as (...a: any[]) => Promise<string>)(resolvedSessionId);\n } catch (error) {\n const message: string = error instanceof Error ? error.message : String(error);\n\n if (\n !message.includes('end_session_endpoint') &&\n !message.includes('sign-out endpoint') &&\n !message.includes('Sign-out endpoint') &&\n !message.includes('Sign-out redirect URL')\n ) {\n throw error;\n }\n }\n\n return afterSignOutUrl;\n }\n\n override async signUp(_options?: SignUpOptions): Promise<void> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-ValidationError-002',\n 'nextjs',\n 'The signUp method is not implemented in the Next.js client.',\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n override signInSilently(_options?: SignInOptions): Promise<User | boolean> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-signInSilently-NotImplementedError-001',\n 'nextjs',\n 'The signInSilently method is not implemented in the Next.js client.',\n );\n }\n\n public async getAuthorizeRequestUrl(\n customParams: ExtendedAuthorizeRequestUrlParams,\n userId?: string,\n ): Promise<string> {\n await this.ensureInitialized();\n return this.getSignInUrl(customParams, userId);\n }\n\n public override getStorageManager(): any {\n return super.getStorageManager();\n }\n\n public override async clearSession(): Promise<void> {\n throw new ThunderIDRuntimeError(\n 'Not implemented',\n 'ThunderIDNextClient-clearSession-NotImplementedError-001',\n 'nextjs',\n 'The clearSession method is not implemented in the Next.js client.',\n );\n }\n\n override async setSession(sessionData: Record<string, unknown>, sessionId?: string): Promise<void> {\n return this.getStorageManager().setSessionData(sessionData, sessionId);\n }\n\n override decodeJwtToken<R = Record<string, unknown>>(token: string): Promise<R> {\n return super.decodeJwtToken<R>(token);\n }\n}\n\nexport default ThunderIDNextClient;\n"],"mappings":"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"}
@@ -3,8 +3,13 @@
3
3
 
4
4
  const require_rolldown_runtime = require('../../../../_virtual/rolldown_runtime.cjs');
5
5
  const require_getSessionId = require('../../../../server/actions/getSessionId.cjs');
6
+ const require_useThunderID = require('../../../contexts/ThunderID/useThunderID.cjs');
7
+ let __thunderid_node = require("@thunderid/node");
8
+ __thunderid_node = require_rolldown_runtime.__toESM(__thunderid_node);
6
9
  let __thunderid_react = require("@thunderid/react");
7
10
  __thunderid_react = require_rolldown_runtime.__toESM(__thunderid_react);
11
+ let react = require("react");
12
+ react = require_rolldown_runtime.__toESM(react);
8
13
  let react_jsx_runtime = require("react/jsx-runtime");
9
14
  react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
10
15
 
@@ -32,16 +37,37 @@ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
32
37
  * />
33
38
  * ```
34
39
  */
35
- const UserProfile = ({ ...rest }) => {
36
- const { profile, flattenedProfile, schemas, onUpdateProfile, updateProfile } = (0, __thunderid_react.useUser)();
40
+ const UserProfile = ({ preferences, editable = true,...rest }) => {
41
+ const { preferences: contextPreferences } = require_useThunderID.default();
42
+ const { profile, flattenedProfile, onUpdateProfile, updateProfile } = (0, __thunderid_react.useUser)();
43
+ const resolvedPreferences = {
44
+ ...contextPreferences,
45
+ ...preferences,
46
+ user: {
47
+ ...contextPreferences?.user,
48
+ ...preferences?.user
49
+ }
50
+ };
51
+ const { t } = (0, __thunderid_react.useTranslation)(resolvedPreferences?.i18n);
52
+ const isEditableProfile = resolvedPreferences?.user?.fetchUserProfile === false ? false : editable;
53
+ const [error, setError] = (0, react.useState)(null);
37
54
  const handleProfileUpdate = async (payload) => {
38
- onUpdateProfile((await updateProfile(payload, await require_getSessionId.default()))?.data?.user);
55
+ setError(null);
56
+ const updatedAttributes = (0, __thunderid_node.deepMerge)(profile?.["attributes"] ?? {}, payload);
57
+ Object.keys(updatedAttributes).forEach((key) => {
58
+ if (updatedAttributes[key] === void 0 || updatedAttributes[key] === null) delete updatedAttributes[key];
59
+ });
60
+ const result = await updateProfile({ payload: updatedAttributes }, await require_getSessionId.default());
61
+ if (result.success) onUpdateProfile(result.data.user);
62
+ else setError(result.error || t("user.profile.update.generic.error"));
39
63
  };
40
64
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__thunderid_react.BaseUserProfile, {
41
65
  profile,
42
66
  flattenedProfile,
43
- schemas,
44
- onUpdate: handleProfileUpdate,
67
+ editable: isEditableProfile,
68
+ onUpdate: isEditableProfile ? handleProfileUpdate : void 0,
69
+ error,
70
+ preferences: resolvedPreferences,
45
71
  ...rest
46
72
  });
47
73
  };
@@ -1 +1 @@
1
- {"version":3,"file":"UserProfile.cjs","names":["UserProfile: FC<UserProfileProps>","getSessionId","BaseUserProfile"],"sources":["../../../../../../src/client/components/presentation/UserProfile/UserProfile.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use client';\n\nimport {Schema, User} from '@thunderid/node';\nimport {BaseUserProfile, BaseUserProfileProps, useUser} from '@thunderid/react';\nimport {FC, ReactElement} from 'react';\nimport getSessionId from '../../../../server/actions/getSessionId';\n\n/**\n * Props for the UserProfile component.\n * Extends BaseUserProfileProps but makes the user prop optional since it will be obtained from useThunderID\n */\nexport type UserProfileProps = Omit<BaseUserProfileProps, 'user' | 'profile' | 'flattenedProfile' | 'schemas'>;\n\n/**\n * UserProfile component displays the authenticated user's profile information in a\n * structured and styled format. It shows user details such as display name, email,\n * username, and other available profile information from ThunderID.\n *\n * This component is the React-specific implementation that uses the BaseUserProfile\n * and automatically retrieves the user data from ThunderID context if not provided.\n *\n * @example\n * ```tsx\n * // Basic usage - will use user from ThunderID context\n * <UserProfile />\n *\n * // With explicit user data\n * <UserProfile user={specificUser} />\n *\n * // With card layout and custom fallback\n * <UserProfile\n * cardLayout={true}\n * fallback={<div>Please sign in to view your profile</div>}\n * />\n * ```\n */\nconst UserProfile: FC<UserProfileProps> = ({...rest}: UserProfileProps): ReactElement => {\n const {profile, flattenedProfile, schemas, onUpdateProfile, updateProfile} = useUser();\n\n const handleProfileUpdate = async (payload: any): Promise<void> => {\n const result: {data: {user: User}; error: string; success: boolean} = await updateProfile(\n payload,\n await getSessionId(),\n );\n onUpdateProfile(result?.data?.user);\n };\n\n return (\n <BaseUserProfile\n profile={profile!}\n flattenedProfile={flattenedProfile!}\n schemas={schemas!}\n onUpdate={handleProfileUpdate}\n {...rest}\n />\n );\n};\n\nexport default UserProfile;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,MAAMA,eAAqC,EAAC,GAAG,WAA0C;CACvF,MAAM,EAAC,SAAS,kBAAkB,SAAS,iBAAiB,kDAA0B;CAEtF,MAAM,sBAAsB,OAAO,YAAgC;AAKjE,mBAJsE,MAAM,cAC1E,SACA,MAAMC,8BAAc,CACrB,GACuB,MAAM,KAAK;;AAGrC,QACE,2CAACC;EACU;EACS;EACT;EACT,UAAU;EACV,GAAI;GACJ;;AAIN,0BAAe"}
1
+ {"version":3,"file":"UserProfile.cjs","names":["UserProfile: FC<UserProfileProps>","useThunderID","isEditableProfile: boolean","result: {data: {user: User}; error: string; success: boolean}","getSessionId","BaseUserProfile"],"sources":["../../../../../../src/client/components/presentation/UserProfile/UserProfile.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use client';\n\nimport {deepMerge, User} from '@thunderid/node';\nimport {BaseUserProfile, BaseUserProfileProps, useUser, useTranslation} from '@thunderid/react';\nimport {FC, ReactElement, useState} from 'react';\nimport useThunderID from '../../../contexts/ThunderID/useThunderID';\nimport getSessionId from '../../../../server/actions/getSessionId';\n\n/**\n * Props for the UserProfile component.\n * Extends BaseUserProfileProps but makes the user prop optional since it will be obtained from useThunderID\n */\nexport type UserProfileProps = Omit<BaseUserProfileProps, 'user' | 'profile' | 'flattenedProfile'>;\n\n/**\n * UserProfile component displays the authenticated user's profile information in a\n * structured and styled format. It shows user details such as display name, email,\n * username, and other available profile information from ThunderID.\n *\n * This component is the React-specific implementation that uses the BaseUserProfile\n * and automatically retrieves the user data from ThunderID context if not provided.\n *\n * @example\n * ```tsx\n * // Basic usage - will use user from ThunderID context\n * <UserProfile />\n *\n * // With explicit user data\n * <UserProfile user={specificUser} />\n *\n * // With card layout and custom fallback\n * <UserProfile\n * cardLayout={true}\n * fallback={<div>Please sign in to view your profile</div>}\n * />\n * ```\n */\nconst UserProfile: FC<UserProfileProps> = ({preferences, editable = true, ...rest}: UserProfileProps): ReactElement => {\n const {preferences: contextPreferences} = useThunderID();\n const {profile, flattenedProfile, onUpdateProfile, updateProfile} = useUser();\n const resolvedPreferences = {\n ...contextPreferences,\n ...preferences,\n user: {\n ...contextPreferences?.user,\n ...preferences?.user,\n },\n };\n const {t} = useTranslation(resolvedPreferences?.i18n);\n const isEditableProfile: boolean = resolvedPreferences?.user?.fetchUserProfile === false ? false : editable;\n\n const [error, setError] = useState<string | null>(null);\n\n const handleProfileUpdate = async (payload: any): Promise<void> => {\n setError(null);\n\n const updatedAttributes = deepMerge((profile?.['attributes'] as Record<string, unknown>) ?? {}, payload);\n\n Object.keys(updatedAttributes).forEach((key) => {\n if (updatedAttributes[key] === undefined || updatedAttributes[key] === null) {\n delete updatedAttributes[key];\n }\n });\n\n const result: {data: {user: User}; error: string; success: boolean} = await updateProfile(\n {payload: updatedAttributes},\n await getSessionId(),\n );\n\n if (result.success) {\n onUpdateProfile(result.data.user);\n } else {\n setError(result.error || t('user.profile.update.generic.error'));\n }\n };\n\n return (\n <BaseUserProfile\n profile={profile!}\n flattenedProfile={flattenedProfile!}\n editable={isEditableProfile}\n onUpdate={isEditableProfile ? handleProfileUpdate : undefined}\n error={error}\n preferences={resolvedPreferences}\n {...rest}\n />\n );\n};\n\nexport default UserProfile;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuDA,MAAMA,eAAqC,EAAC,aAAa,WAAW,KAAM,GAAG,WAA0C;CACrH,MAAM,EAAC,aAAa,uBAAsBC,8BAAc;CACxD,MAAM,EAAC,SAAS,kBAAkB,iBAAiB,kDAA0B;CAC7E,MAAM,sBAAsB;EAC1B,GAAG;EACH,GAAG;EACH,MAAM;GACJ,GAAG,oBAAoB;GACvB,GAAG,aAAa;GACjB;EACF;CACD,MAAM,EAAC,4CAAoB,qBAAqB,KAAK;CACrD,MAAMC,oBAA6B,qBAAqB,MAAM,qBAAqB,QAAQ,QAAQ;CAEnG,MAAM,CAAC,OAAO,gCAAoC,KAAK;CAEvD,MAAM,sBAAsB,OAAO,YAAgC;AACjE,WAAS,KAAK;EAEd,MAAM,oDAA+B,UAAU,iBAA6C,EAAE,EAAE,QAAQ;AAExG,SAAO,KAAK,kBAAkB,CAAC,SAAS,QAAQ;AAC9C,OAAI,kBAAkB,SAAS,UAAa,kBAAkB,SAAS,KACrE,QAAO,kBAAkB;IAE3B;EAEF,MAAMC,SAAgE,MAAM,cAC1E,EAAC,SAAS,mBAAkB,EAC5B,MAAMC,8BAAc,CACrB;AAED,MAAI,OAAO,QACT,iBAAgB,OAAO,KAAK,KAAK;MAEjC,UAAS,OAAO,SAAS,EAAE,oCAAoC,CAAC;;AAIpE,QACE,2CAACC;EACU;EACS;EAClB,UAAU;EACV,UAAU,oBAAoB,sBAAsB;EAC7C;EACP,aAAa;EACb,GAAI;GACJ;;AAIN,0BAAe"}
@@ -111,6 +111,7 @@ const ThunderIDClientProvider = ({ baseUrl, children, signIn, clearSession, refr
111
111
  isLoading,
112
112
  isSignedIn,
113
113
  organizationHandle,
114
+ preferences,
114
115
  refreshToken,
115
116
  scopes,
116
117
  signIn: handleSignIn,
@@ -128,13 +129,14 @@ const ThunderIDClientProvider = ({ baseUrl, children, signIn, clearSession, refr
128
129
  signUpUrl,
129
130
  applicationId,
130
131
  organizationHandle,
131
- scopes
132
+ scopes,
133
+ preferences
132
134
  ]);
133
135
  const handleProfileUpdate = (payload) => {
134
136
  setUser(payload);
135
137
  setUserProfile((prev) => ({
136
138
  ...prev,
137
- flattenedProfile: (0, __thunderid_node.generateFlattenedUserProfile)(payload, prev?.schemas),
139
+ flattenedProfile: (0, __thunderid_node.generateFlattenedUserProfile)(payload),
138
140
  profile: payload
139
141
  }));
140
142
  };
@@ -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","sessionState: 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":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use client';\n\nimport {\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 getActiveTheme,\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 handleOAuthCallback: (\n code: string,\n state: string,\n sessionState?: 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 };\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 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\n useEffect(() => {\n setUserProfile(_userProfile);\n }, [_userProfile]);\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 sessionState: string | null = searchParams.get('session_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 sessionState || undefined,\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 refreshToken,\n scopes,\n signIn: handleSignIn,\n signInUrl,\n signOut: handleSignOut,\n signUp: handleSignUp,\n signUpUrl,\n user,\n }),\n [baseUrl, user, isSignedIn, isLoading, signInUrl, signUpUrl, applicationId, organizationHandle, scopes],\n );\n\n const handleProfileUpdate = (payload: User): void => {\n setUser(payload);\n setUserProfile((prev: UserProfile) => ({\n ...prev,\n flattenedProfile: generateFlattenedUserProfile(payload, prev?.schemas),\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 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 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 enabled={preferences?.resolveFromMeta !== false} initialMeta={initialMeta}>\n <ThemeProvider theme={preferences?.theme?.overrides} mode={getActiveTheme(preferences?.theme?.mode as any)}>\n <FlowProvider>\n <UserProvider profile={userProfile} onUpdateProfile={handleProfileUpdate} updateProfile={updateProfile}>\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","sessionState: 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":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use client';\n\nimport {\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 getActiveTheme,\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 handleOAuthCallback: (\n code: string,\n state: string,\n sessionState?: 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 };\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 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\n useEffect(() => {\n setUserProfile(_userProfile);\n }, [_userProfile]);\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 sessionState: string | null = searchParams.get('session_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 sessionState || undefined,\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 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 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 enabled={preferences?.resolveFromMeta !== false} initialMeta={initialMeta}>\n <ThemeProvider theme={preferences?.theme?.overrides} mode={getActiveTheme(preferences?.theme?.mode as any)}>\n <FlowProvider>\n <UserProvider profile={userProfile} onUpdateProfile={handleProfileUpdate} updateProfile={updateProfile}>\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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"}
@@ -69,8 +69,15 @@ const ThunderIDServerProvider = async ({ children, afterSignInUrl, afterSignOutU
69
69
  let user = {};
70
70
  let userProfile = {
71
71
  flattenedProfile: {},
72
- profile: {},
73
- schemas: []
72
+ profile: {}
73
+ };
74
+ const resolvedPreferences = {
75
+ ...config?.preferences,
76
+ ..._config.preferences,
77
+ user: {
78
+ ...config?.preferences?.user,
79
+ ..._config.preferences?.user
80
+ }
74
81
  };
75
82
  if (signedIn) {
76
83
  let updatedBaseUrl = config?.baseUrl;
@@ -89,13 +96,23 @@ const ThunderIDServerProvider = async ({ children, afterSignInUrl, afterSignOutU
89
96
  };
90
97
  }
91
98
  } catch {}
92
- if (config?.preferences?.user?.fetchUserProfile !== false) try {
99
+ if (resolvedPreferences?.user?.fetchUserProfile !== false) try {
93
100
  const userResponse = await require_getUserAction.default(sessionId);
94
101
  const userProfileResponse = await require_getUserProfileAction.default(sessionId);
95
102
  user = userResponse.data?.user || {};
96
103
  userProfile = userProfileResponse.data?.userProfile ?? userProfile;
97
104
  } catch (error) {
98
- require_logger.default.warn("[ThunderIDServerProvider] Failed to fetch user profile from SCIM2:", error?.toString());
105
+ require_logger.default.warn("[ThunderIDServerProvider] Failed to fetch user profile from /users/me:", error?.toString());
106
+ }
107
+ else try {
108
+ const claims = (0, __thunderid_node.extractUserClaimsFromIdToken)(await thunderIDClient.getDecodedIdToken(sessionId));
109
+ user = claims;
110
+ userProfile = {
111
+ flattenedProfile: claims,
112
+ profile: claims
113
+ };
114
+ } catch (error) {
115
+ require_logger.default.warn("[ThunderIDServerProvider] Failed to extract user claims from ID token:", error?.toString());
99
116
  }
100
117
  }
101
118
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ThunderIDProvider.default, {
@@ -111,7 +128,7 @@ const ThunderIDServerProvider = async ({ children, afterSignInUrl, afterSignOutU
111
128
  handleOAuthCallback: require_handleOAuthCallbackAction.default,
112
129
  signInUrl: config?.signInUrl,
113
130
  signUpUrl: config?.signUpUrl,
114
- preferences: config?.preferences,
131
+ preferences: resolvedPreferences,
115
132
  clientId: config?.clientId,
116
133
  user,
117
134
  userProfile,
@@ -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","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","ThunderIDClientProvider","signInAction","clearSession","refreshToken","signOutAction","signUpAction","handleOAuthCallbackAction","updateUserProfileAction"],"sources":["../../../src/server/ThunderIDProvider.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use server';\n\nimport {\n ThunderIDRuntimeError,\n FlowMetadataResponse,\n FlowMetaType,\n IdToken,\n User,\n UserProfile,\n getFlowMeta,\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 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 ...(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 schemas: [],\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 = config?.preferences?.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\n user = userResponse.data?.user || {};\n userProfile = userProfileResponse.data?.userProfile ?? userProfile;\n } catch (error) {\n logger.warn('[ThunderIDServerProvider] Failed to fetch user profile from SCIM2:', 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={config?.preferences}\n clientId={config?.clientId}\n user={user}\n userProfile={userProfile}\n updateProfile={updateUserProfileAction}\n isSignedIn={signedIn}\n >\n {children}\n </ThunderIDClientProvider>\n );\n};\n\nexport default ThunderIDServerProvider;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsFA,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,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;EACX,SAAS,EAAE;EACZ;AACD,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,QAAQ,aAAa,MAAM,qBAAqB,MAGtF,KAAI;GACF,MAAMC,eAIF,MAAMC,8BAAc,UAAU;GAClC,MAAMC,sBAIF,MAAMC,qCAAqB,UAAU;AAEzC,UAAO,aAAa,MAAM,QAAQ,EAAE;AACpC,iBAAc,oBAAoB,MAAM,eAAe;WAChD,OAAO;AACd,0BAAO,KAAK,sEAAsE,OAAO,UAAU,CAAC;;;AAK1G,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,QAAQ;EACrB,UAAU,QAAQ;EACZ;EACO;EACb,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","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","ThunderIDClientProvider","signInAction","clearSession","refreshToken","signOutAction","signUpAction","handleOAuthCallbackAction","updateUserProfileAction"],"sources":["../../../src/server/ThunderIDProvider.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use server';\n\nimport {\n ThunderIDRuntimeError,\n FlowMetadataResponse,\n FlowMetaType,\n IdToken,\n User,\n UserProfile,\n getFlowMeta,\n extractUserClaimsFromIdToken,\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 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 ...(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\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\n user = userResponse.data?.user || {};\n userProfile = userProfileResponse.data?.userProfile ?? userProfile;\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 updateProfile={updateUserProfileAction}\n isSignedIn={signedIn}\n >\n {children}\n </ThunderIDClientProvider>\n );\n};\n\nexport default ThunderIDServerProvider;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFA,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,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;CAED,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;AAEzC,UAAO,aAAa,MAAM,QAAQ,EAAE;AACpC,iBAAc,oBAAoB,MAAM,eAAe;WAChD,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;EACb,eAAeC;EACf,YAAY;EAEX;GACuB;;AAI9B,kCAAe"}
@@ -19,8 +19,7 @@ const getUserProfileAction = async (sessionId) => {
19
19
  return {
20
20
  data: { userProfile: {
21
21
  flattenedProfile: {},
22
- profile: {},
23
- schemas: []
22
+ profile: {}
24
23
  } },
25
24
  error: "Failed to get user profile",
26
25
  success: false
@@ -1 +1 @@
1
- {"version":3,"file":"getUserProfileAction.cjs","names":["getClient"],"sources":["../../../../src/server/actions/getUserProfileAction.ts"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use server';\n\nimport {UserProfile} from '@thunderid/node';\nimport getClient from '../getClient';\n\n/**\n * Server action to get the current user.\n * Returns the user profile if signed in.\n */\nconst getUserProfileAction = async (\n sessionId: string,\n): Promise<{data: {userProfile: UserProfile}; error: string | null; success: boolean}> => {\n try {\n const client = getClient();\n const updatedProfile: UserProfile = await client.getUserProfile(sessionId);\n return {data: {userProfile: updatedProfile}, error: null, success: true};\n } catch (error) {\n return {\n data: {\n userProfile: {\n flattenedProfile: {},\n profile: {},\n schemas: [],\n },\n },\n error: 'Failed to get user profile',\n success: false,\n };\n }\n};\n\nexport default getUserProfileAction;\n"],"mappings":";;;;;;;;;;AA2BA,MAAM,uBAAuB,OAC3B,cACwF;AACxF,KAAI;AAGF,SAAO;GAAC,MAAM,EAAC,aADqB,MADrBA,2BAAW,CACuB,eAAe,UAAU,EAC/B;GAAE,OAAO;GAAM,SAAS;GAAK;UACjE,OAAO;AACd,SAAO;GACL,MAAM,EACJ,aAAa;IACX,kBAAkB,EAAE;IACpB,SAAS,EAAE;IACX,SAAS,EAAE;IACZ,EACF;GACD,OAAO;GACP,SAAS;GACV;;;AAIL,mCAAe"}
1
+ {"version":3,"file":"getUserProfileAction.cjs","names":["getClient"],"sources":["../../../../src/server/actions/getUserProfileAction.ts"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use server';\n\nimport {UserProfile} from '@thunderid/node';\nimport getClient from '../getClient';\n\n/**\n * Server action to get the current user.\n * Returns the user profile if signed in.\n */\nconst getUserProfileAction = async (\n sessionId: string,\n): Promise<{data: {userProfile: UserProfile}; error: string | null; success: boolean}> => {\n try {\n const client = getClient();\n const updatedProfile: UserProfile = await client.getUserProfile(sessionId);\n return {data: {userProfile: updatedProfile}, error: null, success: true};\n } catch (error) {\n return {\n data: {\n userProfile: {\n flattenedProfile: {},\n profile: {},\n },\n },\n error: 'Failed to get user profile',\n success: false,\n };\n }\n};\n\nexport default getUserProfileAction;\n"],"mappings":";;;;;;;;;;AA2BA,MAAM,uBAAuB,OAC3B,cACwF;AACxF,KAAI;AAGF,SAAO;GAAC,MAAM,EAAC,aADqB,MADrBA,2BAAW,CACuB,eAAe,UAAU,EAC/B;GAAE,OAAO;GAAM,SAAS;GAAK;UACjE,OAAO;AACd,SAAO;GACL,MAAM,EACJ,aAAa;IACX,kBAAkB,EAAE;IACpB,SAAS,EAAE;IACZ,EACF;GACD,OAAO;GACP,SAAS;GACV;;;AAIL,mCAAe"}
@@ -21,7 +21,7 @@ import { FC } from 'react';
21
21
  * Props for the UserProfile component.
22
22
  * Extends BaseUserProfileProps but makes the user prop optional since it will be obtained from useThunderID
23
23
  */
24
- export type UserProfileProps = Omit<BaseUserProfileProps, 'user' | 'profile' | 'flattenedProfile' | 'schemas'>;
24
+ export type UserProfileProps = Omit<BaseUserProfileProps, 'user' | 'profile' | 'flattenedProfile'>;
25
25
  /**
26
26
  * UserProfile component displays the authenticated user's profile information in a
27
27
  * structured and styled format. It shows user details such as display name, email,
@@ -1 +1 @@
1
- {"version":3,"file":"UserProfile.d.ts","sourceRoot":"","sources":["../../../../../src/client/components/presentation/UserProfile/UserProfile.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,EAAkB,oBAAoB,EAAU,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAC,EAAE,EAAe,MAAM,OAAO,CAAC;AAGvC;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAAC,CAAC;AAE/G;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,QAAA,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAoBrC,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"UserProfile.d.ts","sourceRoot":"","sources":["../../../../../src/client/components/presentation/UserProfile/UserProfile.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,OAAO,EAAkB,oBAAoB,EAA0B,MAAM,kBAAkB,CAAC;AAChG,OAAO,EAAC,EAAE,EAAyB,MAAM,OAAO,CAAC;AAIjD;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,CAAC,CAAC;AAEnG;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,QAAA,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAkDrC,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -2,7 +2,10 @@
2
2
 
3
3
 
4
4
  import getSessionId_default from "../../../../server/actions/getSessionId.js";
5
- import { BaseUserProfile, useUser } from "@thunderid/react";
5
+ import useThunderID_default from "../../../contexts/ThunderID/useThunderID.js";
6
+ import { deepMerge } from "@thunderid/node";
7
+ import { BaseUserProfile, useTranslation, useUser } from "@thunderid/react";
8
+ import { useState } from "react";
6
9
  import { jsx } from "react/jsx-runtime";
7
10
 
8
11
  //#region src/client/components/presentation/UserProfile/UserProfile.tsx
@@ -29,16 +32,37 @@ import { jsx } from "react/jsx-runtime";
29
32
  * />
30
33
  * ```
31
34
  */
32
- const UserProfile = ({ ...rest }) => {
33
- const { profile, flattenedProfile, schemas, onUpdateProfile, updateProfile } = useUser();
35
+ const UserProfile = ({ preferences, editable = true,...rest }) => {
36
+ const { preferences: contextPreferences } = useThunderID_default();
37
+ const { profile, flattenedProfile, onUpdateProfile, updateProfile } = useUser();
38
+ const resolvedPreferences = {
39
+ ...contextPreferences,
40
+ ...preferences,
41
+ user: {
42
+ ...contextPreferences?.user,
43
+ ...preferences?.user
44
+ }
45
+ };
46
+ const { t } = useTranslation(resolvedPreferences?.i18n);
47
+ const isEditableProfile = resolvedPreferences?.user?.fetchUserProfile === false ? false : editable;
48
+ const [error, setError] = useState(null);
34
49
  const handleProfileUpdate = async (payload) => {
35
- onUpdateProfile((await updateProfile(payload, await getSessionId_default()))?.data?.user);
50
+ setError(null);
51
+ const updatedAttributes = deepMerge(profile?.["attributes"] ?? {}, payload);
52
+ Object.keys(updatedAttributes).forEach((key) => {
53
+ if (updatedAttributes[key] === void 0 || updatedAttributes[key] === null) delete updatedAttributes[key];
54
+ });
55
+ const result = await updateProfile({ payload: updatedAttributes }, await getSessionId_default());
56
+ if (result.success) onUpdateProfile(result.data.user);
57
+ else setError(result.error || t("user.profile.update.generic.error"));
36
58
  };
37
59
  return /* @__PURE__ */ jsx(BaseUserProfile, {
38
60
  profile,
39
61
  flattenedProfile,
40
- schemas,
41
- onUpdate: handleProfileUpdate,
62
+ editable: isEditableProfile,
63
+ onUpdate: isEditableProfile ? handleProfileUpdate : void 0,
64
+ error,
65
+ preferences: resolvedPreferences,
42
66
  ...rest
43
67
  });
44
68
  };
@@ -1 +1 @@
1
- {"version":3,"file":"UserProfile.js","names":["UserProfile: FC<UserProfileProps>","getSessionId"],"sources":["../../../../../src/client/components/presentation/UserProfile/UserProfile.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use client';\n\nimport {Schema, User} from '@thunderid/node';\nimport {BaseUserProfile, BaseUserProfileProps, useUser} from '@thunderid/react';\nimport {FC, ReactElement} from 'react';\nimport getSessionId from '../../../../server/actions/getSessionId';\n\n/**\n * Props for the UserProfile component.\n * Extends BaseUserProfileProps but makes the user prop optional since it will be obtained from useThunderID\n */\nexport type UserProfileProps = Omit<BaseUserProfileProps, 'user' | 'profile' | 'flattenedProfile' | 'schemas'>;\n\n/**\n * UserProfile component displays the authenticated user's profile information in a\n * structured and styled format. It shows user details such as display name, email,\n * username, and other available profile information from ThunderID.\n *\n * This component is the React-specific implementation that uses the BaseUserProfile\n * and automatically retrieves the user data from ThunderID context if not provided.\n *\n * @example\n * ```tsx\n * // Basic usage - will use user from ThunderID context\n * <UserProfile />\n *\n * // With explicit user data\n * <UserProfile user={specificUser} />\n *\n * // With card layout and custom fallback\n * <UserProfile\n * cardLayout={true}\n * fallback={<div>Please sign in to view your profile</div>}\n * />\n * ```\n */\nconst UserProfile: FC<UserProfileProps> = ({...rest}: UserProfileProps): ReactElement => {\n const {profile, flattenedProfile, schemas, onUpdateProfile, updateProfile} = useUser();\n\n const handleProfileUpdate = async (payload: any): Promise<void> => {\n const result: {data: {user: User}; error: string; success: boolean} = await updateProfile(\n payload,\n await getSessionId(),\n );\n onUpdateProfile(result?.data?.user);\n };\n\n return (\n <BaseUserProfile\n profile={profile!}\n flattenedProfile={flattenedProfile!}\n schemas={schemas!}\n onUpdate={handleProfileUpdate}\n {...rest}\n />\n );\n};\n\nexport default UserProfile;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsDA,MAAMA,eAAqC,EAAC,GAAG,WAA0C;CACvF,MAAM,EAAC,SAAS,kBAAkB,SAAS,iBAAiB,kBAAiB,SAAS;CAEtF,MAAM,sBAAsB,OAAO,YAAgC;AAKjE,mBAJsE,MAAM,cAC1E,SACA,MAAMC,sBAAc,CACrB,GACuB,MAAM,KAAK;;AAGrC,QACE,oBAAC;EACU;EACS;EACT;EACT,UAAU;EACV,GAAI;GACJ;;AAIN,0BAAe"}
1
+ {"version":3,"file":"UserProfile.js","names":["UserProfile: FC<UserProfileProps>","useThunderID","isEditableProfile: boolean","result: {data: {user: User}; error: string; success: boolean}","getSessionId"],"sources":["../../../../../src/client/components/presentation/UserProfile/UserProfile.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use client';\n\nimport {deepMerge, User} from '@thunderid/node';\nimport {BaseUserProfile, BaseUserProfileProps, useUser, useTranslation} from '@thunderid/react';\nimport {FC, ReactElement, useState} from 'react';\nimport useThunderID from '../../../contexts/ThunderID/useThunderID';\nimport getSessionId from '../../../../server/actions/getSessionId';\n\n/**\n * Props for the UserProfile component.\n * Extends BaseUserProfileProps but makes the user prop optional since it will be obtained from useThunderID\n */\nexport type UserProfileProps = Omit<BaseUserProfileProps, 'user' | 'profile' | 'flattenedProfile'>;\n\n/**\n * UserProfile component displays the authenticated user's profile information in a\n * structured and styled format. It shows user details such as display name, email,\n * username, and other available profile information from ThunderID.\n *\n * This component is the React-specific implementation that uses the BaseUserProfile\n * and automatically retrieves the user data from ThunderID context if not provided.\n *\n * @example\n * ```tsx\n * // Basic usage - will use user from ThunderID context\n * <UserProfile />\n *\n * // With explicit user data\n * <UserProfile user={specificUser} />\n *\n * // With card layout and custom fallback\n * <UserProfile\n * cardLayout={true}\n * fallback={<div>Please sign in to view your profile</div>}\n * />\n * ```\n */\nconst UserProfile: FC<UserProfileProps> = ({preferences, editable = true, ...rest}: UserProfileProps): ReactElement => {\n const {preferences: contextPreferences} = useThunderID();\n const {profile, flattenedProfile, onUpdateProfile, updateProfile} = useUser();\n const resolvedPreferences = {\n ...contextPreferences,\n ...preferences,\n user: {\n ...contextPreferences?.user,\n ...preferences?.user,\n },\n };\n const {t} = useTranslation(resolvedPreferences?.i18n);\n const isEditableProfile: boolean = resolvedPreferences?.user?.fetchUserProfile === false ? false : editable;\n\n const [error, setError] = useState<string | null>(null);\n\n const handleProfileUpdate = async (payload: any): Promise<void> => {\n setError(null);\n\n const updatedAttributes = deepMerge((profile?.['attributes'] as Record<string, unknown>) ?? {}, payload);\n\n Object.keys(updatedAttributes).forEach((key) => {\n if (updatedAttributes[key] === undefined || updatedAttributes[key] === null) {\n delete updatedAttributes[key];\n }\n });\n\n const result: {data: {user: User}; error: string; success: boolean} = await updateProfile(\n {payload: updatedAttributes},\n await getSessionId(),\n );\n\n if (result.success) {\n onUpdateProfile(result.data.user);\n } else {\n setError(result.error || t('user.profile.update.generic.error'));\n }\n };\n\n return (\n <BaseUserProfile\n profile={profile!}\n flattenedProfile={flattenedProfile!}\n editable={isEditableProfile}\n onUpdate={isEditableProfile ? handleProfileUpdate : undefined}\n error={error}\n preferences={resolvedPreferences}\n {...rest}\n />\n );\n};\n\nexport default UserProfile;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuDA,MAAMA,eAAqC,EAAC,aAAa,WAAW,KAAM,GAAG,WAA0C;CACrH,MAAM,EAAC,aAAa,uBAAsBC,sBAAc;CACxD,MAAM,EAAC,SAAS,kBAAkB,iBAAiB,kBAAiB,SAAS;CAC7E,MAAM,sBAAsB;EAC1B,GAAG;EACH,GAAG;EACH,MAAM;GACJ,GAAG,oBAAoB;GACvB,GAAG,aAAa;GACjB;EACF;CACD,MAAM,EAAC,MAAK,eAAe,qBAAqB,KAAK;CACrD,MAAMC,oBAA6B,qBAAqB,MAAM,qBAAqB,QAAQ,QAAQ;CAEnG,MAAM,CAAC,OAAO,YAAY,SAAwB,KAAK;CAEvD,MAAM,sBAAsB,OAAO,YAAgC;AACjE,WAAS,KAAK;EAEd,MAAM,oBAAoB,UAAW,UAAU,iBAA6C,EAAE,EAAE,QAAQ;AAExG,SAAO,KAAK,kBAAkB,CAAC,SAAS,QAAQ;AAC9C,OAAI,kBAAkB,SAAS,UAAa,kBAAkB,SAAS,KACrE,QAAO,kBAAkB;IAE3B;EAEF,MAAMC,SAAgE,MAAM,cAC1E,EAAC,SAAS,mBAAkB,EAC5B,MAAMC,sBAAc,CACrB;AAED,MAAI,OAAO,QACT,iBAAgB,OAAO,KAAK,KAAK;MAEjC,UAAS,OAAO,SAAS,EAAE,oCAAoC,CAAC;;AAIpE,QACE,oBAAC;EACU;EACS;EAClB,UAAU;EACV,UAAU,oBAAoB,sBAAsB;EAC7C;EACP,aAAa;EACb,GAAI;GACJ;;AAIN,0BAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"ThunderIDProvider.d.ts","sourceRoot":"","sources":["../../../../src/client/contexts/ThunderID/ThunderIDProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,EAEL,oBAAoB,EAEpB,qBAAqB,EACrB,IAAI,EACJ,WAAW,EAGZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAQL,sBAAsB,EAEvB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAC,EAAE,EAAE,iBAAiB,EAAkD,MAAM,OAAO,CAAC;AAC7F,OAAyB,EAAC,qBAAqB,EAAC,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAC,aAAa,EAAC,MAAM,sCAAsC,CAAC;AAGnE;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,SAAS,GAAG,UAAU,CAAC,CAAC,GACtG,IAAI,CAAC,sBAAsB,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG;IACrD,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC;IACtD,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,mBAAmB,EAAE,CACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,KAClB,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAC,CAAC,CAAC;IACvE;;;OAGG;IACH,WAAW,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,UAAU,EAAE,OAAO,CAAC;IACpB,kBAAkB,EAAE,qBAAqB,CAAC,oBAAoB,CAAC,CAAC;IAChE,YAAY,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3C,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACxC,OAAO,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACxC,aAAa,EAAE,CACb,aAAa,EAAE,qBAAqB,EACpC,SAAS,CAAC,EAAE,MAAM,KACf,OAAO,CAAC;QAAC,IAAI,EAAE;YAAC,IAAI,EAAE,IAAI,CAAA;SAAC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAC,CAAC,CAAC;IACpE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AAEJ,QAAA,MAAM,uBAAuB,EAAE,EAAE,CAAC,iBAAiB,CAAC,4BAA4B,CAAC,CA+ThF,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ThunderIDProvider.d.ts","sourceRoot":"","sources":["../../../../src/client/contexts/ThunderID/ThunderIDProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,EAEL,oBAAoB,EAEpB,qBAAqB,EACrB,IAAI,EACJ,WAAW,EAGZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAQL,sBAAsB,EAEvB,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAAC,EAAE,EAAE,iBAAiB,EAAkD,MAAM,OAAO,CAAC;AAC7F,OAAyB,EAAC,qBAAqB,EAAC,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAC,aAAa,EAAC,MAAM,sCAAsC,CAAC;AAGnE;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,SAAS,GAAG,UAAU,CAAC,CAAC,GACtG,IAAI,CAAC,sBAAsB,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG;IACrD,aAAa,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC;IACtD,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,mBAAmB,EAAE,CACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,MAAM,KAClB,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAC,CAAC,CAAC;IACvE;;;OAGG;IACH,WAAW,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,UAAU,EAAE,OAAO,CAAC;IACpB,kBAAkB,EAAE,qBAAqB,CAAC,oBAAoB,CAAC,CAAC;IAChE,YAAY,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,CAAC;IAC3C,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACxC,OAAO,EAAE,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACxC,aAAa,EAAE,CACb,aAAa,EAAE,qBAAqB,EACpC,SAAS,CAAC,EAAE,MAAM,KACf,OAAO,CAAC;QAAC,IAAI,EAAE;YAAC,IAAI,EAAE,IAAI,CAAA;SAAC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAC,CAAC,CAAC;IACpE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;CAC1B,CAAC;AAEJ,QAAA,MAAM,uBAAuB,EAAE,EAAE,CAAC,iBAAiB,CAAC,4BAA4B,CAAC,CA2UhF,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -105,6 +105,7 @@ const ThunderIDClientProvider = ({ baseUrl, children, signIn, clearSession, refr
105
105
  isLoading,
106
106
  isSignedIn,
107
107
  organizationHandle,
108
+ preferences,
108
109
  refreshToken,
109
110
  scopes,
110
111
  signIn: handleSignIn,
@@ -122,13 +123,14 @@ const ThunderIDClientProvider = ({ baseUrl, children, signIn, clearSession, refr
122
123
  signUpUrl,
123
124
  applicationId,
124
125
  organizationHandle,
125
- scopes
126
+ scopes,
127
+ preferences
126
128
  ]);
127
129
  const handleProfileUpdate = (payload) => {
128
130
  setUser(payload);
129
131
  setUserProfile((prev) => ({
130
132
  ...prev,
131
- flattenedProfile: generateFlattenedUserProfile(payload, prev?.schemas),
133
+ flattenedProfile: generateFlattenedUserProfile(payload),
132
134
  profile: payload
133
135
  }));
134
136
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ThunderIDProvider.js","names":["ThunderIDClientProvider: FC<PropsWithChildren<ThunderIDClientProviderProps>>","reRenderCheckRef: RefObject<boolean>","router: AppRouterInstance","searchParams: ReadonlyURLSearchParams","code: string | null","state: string | null","sessionState: string | null","result: {error?: string; redirectUrl?: string; success: boolean}","result: any","contextValue: ThunderIDContextProps","reactContextValue: ReactThunderIDContextProps","ThunderIDContext","ReactThunderIDContext"],"sources":["../../../../src/client/contexts/ThunderID/ThunderIDProvider.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use client';\n\nimport {\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 getActiveTheme,\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 handleOAuthCallback: (\n code: string,\n state: string,\n sessionState?: 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 };\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 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\n useEffect(() => {\n setUserProfile(_userProfile);\n }, [_userProfile]);\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 sessionState: string | null = searchParams.get('session_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 sessionState || undefined,\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 refreshToken,\n scopes,\n signIn: handleSignIn,\n signInUrl,\n signOut: handleSignOut,\n signUp: handleSignUp,\n signUpUrl,\n user,\n }),\n [baseUrl, user, isSignedIn, isLoading, signInUrl, signUpUrl, applicationId, organizationHandle, scopes],\n );\n\n const handleProfileUpdate = (payload: User): void => {\n setUser(payload);\n setUserProfile((prev: UserProfile) => ({\n ...prev,\n flattenedProfile: generateFlattenedUserProfile(payload, prev?.schemas),\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 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 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 enabled={preferences?.resolveFromMeta !== false} initialMeta={initialMeta}>\n <ThemeProvider theme={preferences?.theme?.overrides} mode={getActiveTheme(preferences?.theme?.mode as any)}>\n <FlowProvider>\n <UserProvider profile={userProfile} onUpdateProfile={handleProfileUpdate} updateProfile={updateProfile}>\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.js","names":["ThunderIDClientProvider: FC<PropsWithChildren<ThunderIDClientProviderProps>>","reRenderCheckRef: RefObject<boolean>","router: AppRouterInstance","searchParams: ReadonlyURLSearchParams","code: string | null","state: string | null","sessionState: string | null","result: {error?: string; redirectUrl?: string; success: boolean}","result: any","contextValue: ThunderIDContextProps","reactContextValue: ReactThunderIDContextProps","ThunderIDContext","ReactThunderIDContext"],"sources":["../../../../src/client/contexts/ThunderID/ThunderIDProvider.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use client';\n\nimport {\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 getActiveTheme,\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 handleOAuthCallback: (\n code: string,\n state: string,\n sessionState?: 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 };\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 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\n useEffect(() => {\n setUserProfile(_userProfile);\n }, [_userProfile]);\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 sessionState: string | null = searchParams.get('session_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 sessionState || undefined,\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 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 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 enabled={preferences?.resolveFromMeta !== false} initialMeta={initialMeta}>\n <ThemeProvider theme={preferences?.theme?.overrides} mode={getActiveTheme(preferences?.theme?.mode as any)}>\n <FlowProvider>\n <UserProvider profile={userProfile} onUpdateProfile={handleProfileUpdate} updateProfile={updateProfile}>\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 +1 @@
1
- {"version":3,"file":"ThunderIDProvider.d.ts","sourceRoot":"","sources":["../../src/server/ThunderIDProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAaH,OAAO,EAAC,sBAAsB,EAAC,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAC,EAAE,EAAE,iBAAiB,EAAe,MAAM,OAAO,CAAC;AAmB1D;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,OAAO,CAAC,sBAAsB,CAAC,GAAG;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;OAYG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,uBAAuB,EAAE,EAAE,CAAC,iBAAiB,CAAC,4BAA4B,CAAC,CAwHhF,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
1
+ {"version":3,"file":"ThunderIDProvider.d.ts","sourceRoot":"","sources":["../../src/server/ThunderIDProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAcH,OAAO,EAAC,sBAAsB,EAAC,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAC,EAAE,EAAE,iBAAiB,EAAe,MAAM,OAAO,CAAC;AAmB1D;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,OAAO,CAAC,sBAAsB,CAAC,GAAG;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;;;;OAYG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,QAAA,MAAM,uBAAuB,EAAE,EAAE,CAAC,iBAAiB,CAAC,4BAA4B,CAAC,CA6IhF,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
@@ -16,7 +16,7 @@ import signOutAction_default from "./actions/signOutAction.js";
16
16
  import signUpAction_default from "./actions/signUpAction.js";
17
17
  import updateUserProfileAction_default from "./actions/updateUserProfileAction.js";
18
18
  import ThunderIDProvider_default from "../client/contexts/ThunderID/ThunderIDProvider.js";
19
- import { FlowMetaType, ThunderIDRuntimeError, getFlowMeta } from "@thunderid/node";
19
+ import { FlowMetaType, ThunderIDRuntimeError, extractUserClaimsFromIdToken, getFlowMeta } from "@thunderid/node";
20
20
  import { Fragment, jsx } from "react/jsx-runtime";
21
21
 
22
22
  //#region src/server/ThunderIDProvider.tsx
@@ -66,8 +66,15 @@ const ThunderIDServerProvider = async ({ children, afterSignInUrl, afterSignOutU
66
66
  let user = {};
67
67
  let userProfile = {
68
68
  flattenedProfile: {},
69
- profile: {},
70
- schemas: []
69
+ profile: {}
70
+ };
71
+ const resolvedPreferences = {
72
+ ...config?.preferences,
73
+ ..._config.preferences,
74
+ user: {
75
+ ...config?.preferences?.user,
76
+ ..._config.preferences?.user
77
+ }
71
78
  };
72
79
  if (signedIn) {
73
80
  let updatedBaseUrl = config?.baseUrl;
@@ -86,13 +93,23 @@ const ThunderIDServerProvider = async ({ children, afterSignInUrl, afterSignOutU
86
93
  };
87
94
  }
88
95
  } catch {}
89
- if (config?.preferences?.user?.fetchUserProfile !== false) try {
96
+ if (resolvedPreferences?.user?.fetchUserProfile !== false) try {
90
97
  const userResponse = await getUserAction_default(sessionId);
91
98
  const userProfileResponse = await getUserProfileAction_default(sessionId);
92
99
  user = userResponse.data?.user || {};
93
100
  userProfile = userProfileResponse.data?.userProfile ?? userProfile;
94
101
  } catch (error) {
95
- logger_default.warn("[ThunderIDServerProvider] Failed to fetch user profile from SCIM2:", error?.toString());
102
+ logger_default.warn("[ThunderIDServerProvider] Failed to fetch user profile from /users/me:", error?.toString());
103
+ }
104
+ else try {
105
+ const claims = extractUserClaimsFromIdToken(await thunderIDClient.getDecodedIdToken(sessionId));
106
+ user = claims;
107
+ userProfile = {
108
+ flattenedProfile: claims,
109
+ profile: claims
110
+ };
111
+ } catch (error) {
112
+ logger_default.warn("[ThunderIDServerProvider] Failed to extract user claims from ID token:", error?.toString());
96
113
  }
97
114
  }
98
115
  return /* @__PURE__ */ jsx(ThunderIDProvider_default, {
@@ -108,7 +125,7 @@ const ThunderIDServerProvider = async ({ children, afterSignInUrl, afterSignOutU
108
125
  handleOAuthCallback: handleOAuthCallbackAction_default,
109
126
  signInUrl: config?.signInUrl,
110
127
  signUpUrl: config?.signUpUrl,
111
- preferences: config?.preferences,
128
+ preferences: resolvedPreferences,
112
129
  clientId: config?.clientId,
113
130
  user,
114
131
  userProfile,
@@ -1 +1 @@
1
- {"version":3,"file":"ThunderIDProvider.js","names":["ThunderIDServerProvider: FC<PropsWithChildren<ThunderIDServerProviderProps>>","getClient","config: Partial<ThunderIDNextConfig>","flowMeta: FlowMetadataResponse | null","sessionPayload: SessionTokenPayload | undefined","getSessionPayload","sessionId: string","getSessionId","signedIn: boolean","isSignedIn","user: User","userProfile: UserProfile","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","ThunderIDClientProvider","signInAction","clearSession","refreshToken","signOutAction","signUpAction","handleOAuthCallbackAction","updateUserProfileAction"],"sources":["../../src/server/ThunderIDProvider.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use server';\n\nimport {\n ThunderIDRuntimeError,\n FlowMetadataResponse,\n FlowMetaType,\n IdToken,\n User,\n UserProfile,\n getFlowMeta,\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 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 ...(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 schemas: [],\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 = config?.preferences?.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\n user = userResponse.data?.user || {};\n userProfile = userProfileResponse.data?.userProfile ?? userProfile;\n } catch (error) {\n logger.warn('[ThunderIDServerProvider] Failed to fetch user profile from SCIM2:', 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={config?.preferences}\n clientId={config?.clientId}\n user={user}\n userProfile={userProfile}\n updateProfile={updateUserProfileAction}\n isSignedIn={signedIn}\n >\n {children}\n </ThunderIDClientProvider>\n );\n};\n\nexport default ThunderIDServerProvider;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsFA,MAAMA,0BAA+E,OAAO,EAC1F,UACA,gBACA,gBACA,GAAG,cACyE;CAC5E,MAAM,kBAAkBC,mBAAW;CACnC,IAAIC,SAAuC,EAAE;AAE7C,KAAI;AACF,QAAM,gBAAgB,WAAW,QAA+B;AAEhE,iBAAO,MAAM,uEAAuE;AAEpF,WAAS,MAAM,gBAAgB,kBAAkB;UAC1C,OAAO;AACd,iBAAO,MAAM,oEAAoE,OAAO,UAAU,CAAC;AAEnG,QAAM,IAAI,sBACR,0CAA0C,OAAO,UAAU,IAC3D,+BACA,QACA,8FACD;;AAGH,KAAI,CAAC,gBAAgB,cACnB,QAAO,iCAAK;CAMd,IAAIC,WAAwC;AAC5C,KAAI;AACF,aAAW,MAAM,YAAY;GAC3B,SAAS,QAAQ;GACjB,GAAI,QAAQ,gBAAgB;IAAC,IAAI,OAAO;IAAe,MAAM,aAAa;IAAI,GAAG,EAAE;GACpF,CAAC;UACK,OAAO;AACd,iBAAO,KAAK,4DAA4D,OAAO,UAAU,CAAC;;CAI5F,MAAMC,iBAAkD,MAAMC,2BAAmB;CACjF,MAAMC,YAAoB,gBAAgB,aAAc,MAAMC,sBAAc,IAAK;CACjF,MAAMC,WAAoB,MAAMC,mBAAW,UAAU;CAErD,IAAIC,OAAa,EAAE;CACnB,IAAIC,cAA2B;EAC7B,kBAAkB,EAAE;EACpB,SAAS,EAAE;EACX,SAAS,EAAE;EACZ;AACD,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,QAAQ,aAAa,MAAM,qBAAqB,MAGtF,KAAI;GACF,MAAMC,eAIF,MAAMC,sBAAc,UAAU;GAClC,MAAMC,sBAIF,MAAMC,6BAAqB,UAAU;AAEzC,UAAO,aAAa,MAAM,QAAQ,EAAE;AACpC,iBAAc,oBAAoB,MAAM,eAAe;WAChD,OAAO;AACd,kBAAO,KAAK,sEAAsE,OAAO,UAAU,CAAC;;;AAK1G,QACE,oBAACC;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,QAAQ;EACrB,UAAU,QAAQ;EACZ;EACO;EACb,eAAeC;EACf,YAAY;EAEX;GACuB;;AAI9B,kCAAe"}
1
+ {"version":3,"file":"ThunderIDProvider.js","names":["ThunderIDServerProvider: FC<PropsWithChildren<ThunderIDServerProviderProps>>","getClient","config: Partial<ThunderIDNextConfig>","flowMeta: FlowMetadataResponse | null","sessionPayload: SessionTokenPayload | undefined","getSessionPayload","sessionId: string","getSessionId","signedIn: boolean","isSignedIn","user: User","userProfile: UserProfile","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","ThunderIDClientProvider","signInAction","clearSession","refreshToken","signOutAction","signUpAction","handleOAuthCallbackAction","updateUserProfileAction"],"sources":["../../src/server/ThunderIDProvider.tsx"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use server';\n\nimport {\n ThunderIDRuntimeError,\n FlowMetadataResponse,\n FlowMetaType,\n IdToken,\n User,\n UserProfile,\n getFlowMeta,\n extractUserClaimsFromIdToken,\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 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 ...(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\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\n user = userResponse.data?.user || {};\n userProfile = userProfileResponse.data?.userProfile ?? userProfile;\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 updateProfile={updateUserProfileAction}\n isSignedIn={signedIn}\n >\n {children}\n </ThunderIDClientProvider>\n );\n};\n\nexport default ThunderIDServerProvider;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFA,MAAMA,0BAA+E,OAAO,EAC1F,UACA,gBACA,gBACA,GAAG,cACyE;CAC5E,MAAM,kBAAkBC,mBAAW;CACnC,IAAIC,SAAuC,EAAE;AAE7C,KAAI;AACF,QAAM,gBAAgB,WAAW,QAA+B;AAEhE,iBAAO,MAAM,uEAAuE;AAEpF,WAAS,MAAM,gBAAgB,kBAAkB;UAC1C,OAAO;AACd,iBAAO,MAAM,oEAAoE,OAAO,UAAU,CAAC;AAEnG,QAAM,IAAI,sBACR,0CAA0C,OAAO,UAAU,IAC3D,+BACA,QACA,8FACD;;AAGH,KAAI,CAAC,gBAAgB,cACnB,QAAO,iCAAK;CAMd,IAAIC,WAAwC;AAC5C,KAAI;AACF,aAAW,MAAM,YAAY;GAC3B,SAAS,QAAQ;GACjB,GAAI,QAAQ,gBAAgB;IAAC,IAAI,OAAO;IAAe,MAAM,aAAa;IAAI,GAAG,EAAE;GACpF,CAAC;UACK,OAAO;AACd,iBAAO,KAAK,4DAA4D,OAAO,UAAU,CAAC;;CAI5F,MAAMC,iBAAkD,MAAMC,2BAAmB;CACjF,MAAMC,YAAoB,gBAAgB,aAAc,MAAMC,sBAAc,IAAK;CACjF,MAAMC,WAAoB,MAAMC,mBAAW,UAAU;CAErD,IAAIC,OAAa,EAAE;CACnB,IAAIC,cAA2B;EAC7B,kBAAkB,EAAE;EACpB,SAAS,EAAE;EACZ;CAED,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,sBAAc,UAAU;GAClC,MAAMC,sBAIF,MAAMC,6BAAqB,UAAU;AAEzC,UAAO,aAAa,MAAM,QAAQ,EAAE;AACpC,iBAAc,oBAAoB,MAAM,eAAe;WAChD,OAAO;AACd,kBAAO,KAAK,0EAA0E,OAAO,UAAU,CAAC;;MAG1G,KAAI;GAEF,MAAM,SAAS,6BADiB,MAAM,gBAAgB,kBAAkB,UAAU,CACvB;AAC3D,UAAO;AACP,iBAAc;IACZ,kBAAkB;IAClB,SAAS;IACV;WACM,OAAO;AACd,kBAAO,KAAK,0EAA0E,OAAO,UAAU,CAAC;;;AAK9G,QACE,oBAACC;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;EACb,eAAeC;EACf,YAAY;EAEX;GACuB;;AAI9B,kCAAe"}
@@ -1 +1 @@
1
- {"version":3,"file":"getUserProfileAction.d.ts","sourceRoot":"","sources":["../../../src/server/actions/getUserProfileAction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAC;AAG5C;;;GAGG;AACH,QAAA,MAAM,oBAAoB,GACxB,WAAW,MAAM,KAChB,OAAO,CAAC;IAAC,IAAI,EAAE;QAAC,WAAW,EAAE,WAAW,CAAA;KAAC,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CAkBpF,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"getUserProfileAction.d.ts","sourceRoot":"","sources":["../../../src/server/actions/getUserProfileAction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAC;AAG5C;;;GAGG;AACH,QAAA,MAAM,oBAAoB,GACxB,WAAW,MAAM,KAChB,OAAO,CAAC;IAAC,IAAI,EAAE;QAAC,WAAW,EAAE,WAAW,CAAA;KAAC,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAC,CAiBpF,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -19,8 +19,7 @@ const getUserProfileAction = async (sessionId) => {
19
19
  return {
20
20
  data: { userProfile: {
21
21
  flattenedProfile: {},
22
- profile: {},
23
- schemas: []
22
+ profile: {}
24
23
  } },
25
24
  error: "Failed to get user profile",
26
25
  success: false
@@ -1 +1 @@
1
- {"version":3,"file":"getUserProfileAction.js","names":["getClient"],"sources":["../../../src/server/actions/getUserProfileAction.ts"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use server';\n\nimport {UserProfile} from '@thunderid/node';\nimport getClient from '../getClient';\n\n/**\n * Server action to get the current user.\n * Returns the user profile if signed in.\n */\nconst getUserProfileAction = async (\n sessionId: string,\n): Promise<{data: {userProfile: UserProfile}; error: string | null; success: boolean}> => {\n try {\n const client = getClient();\n const updatedProfile: UserProfile = await client.getUserProfile(sessionId);\n return {data: {userProfile: updatedProfile}, error: null, success: true};\n } catch (error) {\n return {\n data: {\n userProfile: {\n flattenedProfile: {},\n profile: {},\n schemas: [],\n },\n },\n error: 'Failed to get user profile',\n success: false,\n };\n }\n};\n\nexport default getUserProfileAction;\n"],"mappings":";;;;;;;;;;AA2BA,MAAM,uBAAuB,OAC3B,cACwF;AACxF,KAAI;AAGF,SAAO;GAAC,MAAM,EAAC,aADqB,MADrBA,mBAAW,CACuB,eAAe,UAAU,EAC/B;GAAE,OAAO;GAAM,SAAS;GAAK;UACjE,OAAO;AACd,SAAO;GACL,MAAM,EACJ,aAAa;IACX,kBAAkB,EAAE;IACpB,SAAS,EAAE;IACX,SAAS,EAAE;IACZ,EACF;GACD,OAAO;GACP,SAAS;GACV;;;AAIL,mCAAe"}
1
+ {"version":3,"file":"getUserProfileAction.js","names":["getClient"],"sources":["../../../src/server/actions/getUserProfileAction.ts"],"sourcesContent":["/**\n * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).\n *\n * WSO2 LLC. licenses this file to you under the Apache License,\n * Version 2.0 (the \"License\"); you may not use this file except\n * in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing,\n * software distributed under the License is distributed on an\n * \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n * KIND, either express or implied. See the License for the\n * specific language governing permissions and limitations\n * under the License.\n */\n\n'use server';\n\nimport {UserProfile} from '@thunderid/node';\nimport getClient from '../getClient';\n\n/**\n * Server action to get the current user.\n * Returns the user profile if signed in.\n */\nconst getUserProfileAction = async (\n sessionId: string,\n): Promise<{data: {userProfile: UserProfile}; error: string | null; success: boolean}> => {\n try {\n const client = getClient();\n const updatedProfile: UserProfile = await client.getUserProfile(sessionId);\n return {data: {userProfile: updatedProfile}, error: null, success: true};\n } catch (error) {\n return {\n data: {\n userProfile: {\n flattenedProfile: {},\n profile: {},\n },\n },\n error: 'Failed to get user profile',\n success: false,\n };\n }\n};\n\nexport default getUserProfileAction;\n"],"mappings":";;;;;;;;;;AA2BA,MAAM,uBAAuB,OAC3B,cACwF;AACxF,KAAI;AAGF,SAAO;GAAC,MAAM,EAAC,aADqB,MADrBA,mBAAW,CACuB,eAAe,UAAU,EAC/B;GAAE,OAAO;GAAM,SAAS;GAAK;UACjE,OAAO;AACd,SAAO;GACL,MAAM,EACJ,aAAa;IACX,kBAAkB,EAAE;IACpB,SAAS,EAAE;IACZ,EACF;GACD,OAAO;GACP,SAAS;GACV;;;AAIL,mCAAe"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thunderid/nextjs",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Next.js SDK for ThunderID",
5
5
  "keywords": [
6
6
  "thunderid",
@@ -40,8 +40,8 @@
40
40
  "@types/react": "19.2.14",
41
41
  "jose": "5.2.0",
42
42
  "tslib": "2.8.1",
43
- "@thunderid/node": "^0.5.0",
44
- "@thunderid/react": "^0.5.0"
43
+ "@thunderid/node": "^0.6.1",
44
+ "@thunderid/react": "^0.6.1"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@thunderid/eslint-plugin": "0.0.2",