@thunderid/react 0.11.2 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ThunderIDReactClient.d.ts.map +1 -1
- package/dist/ThunderIDReactClient.js +13 -7
- package/dist/ThunderIDReactClient.js.map +1 -1
- package/dist/cjs/ThunderIDReactClient.cjs +12 -6
- package/dist/cjs/ThunderIDReactClient.cjs.map +1 -1
- package/dist/cjs/components/presentation/auth/InviteUser/InviteUser.cjs +4 -3
- package/dist/cjs/components/presentation/auth/InviteUser/InviteUser.cjs.map +1 -1
- package/dist/cjs/contexts/FlowMeta/FlowMetaProvider.cjs +5 -1
- package/dist/cjs/contexts/FlowMeta/FlowMetaProvider.cjs.map +1 -1
- package/dist/cjs/contexts/ThunderID/ThunderIDContext.cjs.map +1 -1
- package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs +33 -17
- package/dist/cjs/contexts/ThunderID/ThunderIDProvider.cjs.map +1 -1
- package/dist/components/presentation/auth/InviteUser/InviteUser.d.ts.map +1 -1
- package/dist/components/presentation/auth/InviteUser/InviteUser.js +5 -4
- package/dist/components/presentation/auth/InviteUser/InviteUser.js.map +1 -1
- package/dist/contexts/FlowMeta/FlowMetaProvider.d.ts.map +1 -1
- package/dist/contexts/FlowMeta/FlowMetaProvider.js +6 -2
- package/dist/contexts/FlowMeta/FlowMetaProvider.js.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDContext.d.ts +5 -0
- package/dist/contexts/ThunderID/ThunderIDContext.d.ts.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDContext.js.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDProvider.d.ts.map +1 -1
- package/dist/contexts/ThunderID/ThunderIDProvider.js +34 -18
- package/dist/contexts/ThunderID/ThunderIDProvider.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThunderIDReactClient.d.ts","sourceRoot":"","sources":["../src/ThunderIDReactClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,sBAAsB,EACtB,WAAW,EACX,aAAa,EACb,IAAI,EACJ,aAAa,EAGb,OAAO,EAEP,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,0BAA0B,EAE1B,0BAA0B,
|
|
1
|
+
{"version":3,"file":"ThunderIDReactClient.d.ts","sourceRoot":"","sources":["../src/ThunderIDReactClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACL,sBAAsB,EACtB,WAAW,EACX,aAAa,EACb,IAAI,EACJ,aAAa,EAGb,OAAO,EAEP,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,0BAA0B,EAE1B,0BAA0B,EAM3B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,oBAAoB,EAAC,MAAM,iBAAiB,CAAC;AAErD,cAAM,oBAAoB,CAAC,CAAC,SAAS,oBAAoB,GAAG,oBAAoB,CAAE,SAAQ,sBAAsB,CAAC,CAAC,CAAC;IACjH,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,iBAAiB,CAAmC;gBAEhD,UAAU,SAAI;IAI1B,OAAO,CAAC,UAAU;YAIJ,WAAW;IAUhB,UAAU,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC;IAY1D,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAoB/D,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIlC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAIxB,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvD,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAI7B,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAW5C,SAAS,IAAI,OAAO;IAId,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAI9B,aAAa,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,aAAa,GAAG,QAAQ,CAAC;IAIpF,MAAM,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,GAAG,0BAA0B,CAAC;IAmFlE,cAAc,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC;IAIhE,MAAM,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9C,MAAM,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAoDlC,OAAO,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAUnC,iBAAiB,IAAI,GAAG;IAIlC,OAAO,CAAC,aAAa,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAItE,UAAU,CAAC,cAAc,CAAC,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;CAGrF;AAED,eAAe,oBAAoB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EmbeddedSignInFlowStatus, EmbeddedSignUpFlowStatus, ThunderIDBrowserClient, ThunderIDRuntimeError, executeEmbeddedRecoveryFlow, executeEmbeddedSignInFlow, executeEmbeddedSignUpFlow, extractUserClaimsFromIdToken, isEmpty } from "@thunderid/browser";
|
|
1
|
+
import { EmbeddedSignInFlowStatus, EmbeddedSignUpFlowStatus, ThunderIDBrowserClient, ThunderIDRuntimeError, executeEmbeddedRecoveryFlow, executeEmbeddedSignInFlow, executeEmbeddedSignUpFlow, extractUserClaimsFromIdToken, isEmpty, resolveResourceEndpoint } from "@thunderid/browser";
|
|
2
2
|
|
|
3
3
|
//#region src/ThunderIDReactClient.ts
|
|
4
4
|
var ThunderIDReactClient = class extends ThunderIDBrowserClient {
|
|
@@ -74,8 +74,11 @@ var ThunderIDReactClient = class extends ThunderIDBrowserClient {
|
|
|
74
74
|
return this.withLoading(async () => {
|
|
75
75
|
const arg1 = args[0];
|
|
76
76
|
const arg2 = args[1];
|
|
77
|
-
|
|
78
|
-
if (!config || Object.keys(config).length === 0)
|
|
77
|
+
let config = await this.getStorageManager().getConfigData();
|
|
78
|
+
if (!config || Object.keys(config).length === 0) {
|
|
79
|
+
await this.initialize(this._initializeConfig);
|
|
80
|
+
config = await this.getStorageManager().getConfigData();
|
|
81
|
+
}
|
|
79
82
|
if (typeof arg1 === "object" && arg1 !== null && arg1.callOnlyOnRedirect === true) return;
|
|
80
83
|
if (typeof arg1 === "object" && arg1 !== null && !isEmpty(arg1) && ("executionId" in arg1 || "applicationId" in arg1)) {
|
|
81
84
|
const authIdFromUrl = new URL(window.location.href).searchParams.get("authId") ?? "";
|
|
@@ -84,7 +87,7 @@ var ThunderIDReactClient = class extends ThunderIDBrowserClient {
|
|
|
84
87
|
authId: authIdFromUrl || authIdFromStorage,
|
|
85
88
|
baseUrl: config?.baseUrl ?? "",
|
|
86
89
|
payload: arg1,
|
|
87
|
-
url: arg2?.url
|
|
90
|
+
url: resolveResourceEndpoint("flowExecute", config, arg2?.url)
|
|
88
91
|
});
|
|
89
92
|
if (response && typeof response === "object" && response.flowStatus === EmbeddedSignInFlowStatus.Complete && response.assertion) {
|
|
90
93
|
const decodedAssertion = await this.decodeJwtToken(response.assertion);
|
|
@@ -118,7 +121,8 @@ var ThunderIDReactClient = class extends ThunderIDBrowserClient {
|
|
|
118
121
|
payload: typeof firstArg === "object" && "flowType" in firstArg ? {
|
|
119
122
|
...firstArg,
|
|
120
123
|
verbose: true
|
|
121
|
-
} : firstArg
|
|
124
|
+
} : firstArg,
|
|
125
|
+
url: resolveResourceEndpoint("flowExecute", config)
|
|
122
126
|
});
|
|
123
127
|
if (response && typeof response === "object" && response.flowStatus === EmbeddedSignUpFlowStatus.Complete && response.assertion) {
|
|
124
128
|
const decodedAssertion = await this.decodeJwtToken(response.assertion);
|
|
@@ -137,12 +141,14 @@ var ThunderIDReactClient = class extends ThunderIDBrowserClient {
|
|
|
137
141
|
return response;
|
|
138
142
|
}
|
|
139
143
|
async recover(payload) {
|
|
144
|
+
const config = await this.getStorageManager().getConfigData();
|
|
140
145
|
return executeEmbeddedRecoveryFlow({
|
|
141
|
-
baseUrl:
|
|
146
|
+
baseUrl: config?.baseUrl,
|
|
142
147
|
payload: {
|
|
143
148
|
...payload,
|
|
144
149
|
verbose: true
|
|
145
|
-
}
|
|
150
|
+
},
|
|
151
|
+
url: resolveResourceEndpoint("flowExecute", config)
|
|
146
152
|
});
|
|
147
153
|
}
|
|
148
154
|
getStorageManager() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThunderIDReactClient.js","names":["isInitialized: boolean","claims: User","arg1: any","arg2: any","config: ThunderIDReactConfig | undefined","authIdFromUrl: string","authIdFromStorage: string","response: EmbeddedSignInFlowResponse","decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }","createdAt: number","expiresIn: number","config: ThunderIDReactConfig","firstArg: any","baseUrl: string","response: any","decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }"],"sources":["../src/ThunderIDReactClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2025-2026, 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 ThunderIDBrowserClient,\n UserProfile,\n SignInOptions,\n User,\n SignUpOptions,\n ThunderIDRuntimeError,\n executeEmbeddedSignInFlow,\n IdToken,\n extractUserClaimsFromIdToken,\n TokenResponse,\n HttpRequestConfig,\n HttpResponse,\n TokenExchangeRequestConfig,\n isEmpty,\n EmbeddedSignInFlowResponse,\n executeEmbeddedSignUpFlow,\n executeEmbeddedRecoveryFlow,\n EmbeddedSignInFlowStatus,\n EmbeddedSignUpFlowStatus,\n} from '@thunderid/browser';\nimport {ThunderIDReactConfig} from './models/config';\n\nclass ThunderIDReactClient<T extends ThunderIDReactConfig = ThunderIDReactConfig> extends ThunderIDBrowserClient<T> {\n private loadingState = false;\n\n private _initializeConfig: ThunderIDReactConfig | undefined;\n\n constructor(instanceId = 0) {\n super(instanceId);\n }\n\n private setLoading(loading: boolean): void {\n this.loadingState = loading;\n }\n\n private async withLoading<TResult>(operation: () => Promise<TResult>): Promise<TResult> {\n this.setLoading(true);\n try {\n const result: TResult = await operation();\n return result;\n } finally {\n this.setLoading(false);\n }\n }\n\n override initialize(config: ThunderIDReactConfig): Promise<boolean> {\n return this.withLoading(async () => {\n this._initializeConfig = {\n ...config,\n periodicTokenRefresh:\n config?.tokenLifecycle?.refreshToken?.autoRefresh ?? (config as any)?.periodicTokenRefresh,\n } as any;\n\n return super.initialize(this._initializeConfig as unknown as T);\n });\n }\n\n override reInitialize(config: Partial<ThunderIDReactConfig>): Promise<boolean> {\n return this.withLoading(async () => {\n let isInitialized: boolean;\n\n try {\n await super.reInitialize(config as Partial<T>);\n isInitialized = true;\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to check if the client is initialized: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDReactClient-reInitialize-RuntimeError-001',\n 'react',\n 'An error occurred while checking the initialization status of the client.',\n );\n }\n\n return isInitialized;\n });\n }\n\n override async updateUserProfile(): Promise<User> {\n throw new Error('Not implemented');\n }\n\n override async getUser(): Promise<User> {\n return extractUserClaimsFromIdToken(await this.getDecodedIdToken());\n }\n\n override async getDecodedIdToken(sessionId?: string): Promise<IdToken> {\n return super.getDecodedIdToken(sessionId);\n }\n\n override async getIdToken(): Promise<string> {\n return this.withLoading(async () => super.getIdToken());\n }\n\n override async getUserProfile(): Promise<UserProfile> {\n return this.withLoading(async () => {\n const claims: User = extractUserClaimsFromIdToken(await this.getDecodedIdToken());\n return {\n flattenedProfile: claims,\n profile: claims,\n schemas: [],\n };\n });\n }\n\n override isLoading(): boolean {\n return this.loadingState;\n }\n\n override async isSignedIn(): Promise<boolean> {\n return super.isSignedIn();\n }\n\n override async exchangeToken(config: TokenExchangeRequestConfig): Promise<TokenResponse | Response> {\n return this.withLoading(async () => super.exchangeToken(config) as unknown as TokenResponse | Response);\n }\n\n override async signIn(...args: any[]): Promise<User | EmbeddedSignInFlowResponse> {\n return this.withLoading(async () => {\n const arg1: any = args[0];\n const arg2: any = args[1];\n\n const config: ThunderIDReactConfig | undefined = (await this.getStorageManager().getConfigData()) as\n | ThunderIDReactConfig\n | undefined;\n\n // NOTE: With React 19 strict mode, the initialization logic runs twice, and there's an intermittent\n // issue where the config object is not getting stored in the storage layer with Vite scaffolding.\n // Hence, we need to check if the client is initialized but the config object is empty, and reinitialize.\n if (!config || Object.keys(config).length === 0) {\n await this.initialize(this._initializeConfig!);\n }\n\n if (typeof arg1 === 'object' && arg1 !== null && arg1.callOnlyOnRedirect === true) {\n return undefined as any;\n }\n\n if (\n typeof arg1 === 'object' &&\n arg1 !== null &&\n !isEmpty(arg1) &&\n ('executionId' in arg1 || 'applicationId' in arg1)\n ) {\n const authIdFromUrl: string = new URL(window.location.href).searchParams.get('authId') ?? '';\n const authIdFromStorage: string =\n ((await this.getStorageManager().getHybridDataParameter('authId')) as string) ?? '';\n const authId: string = authIdFromUrl || authIdFromStorage;\n const baseUrl: string = config?.baseUrl ?? '';\n\n const response: EmbeddedSignInFlowResponse = await executeEmbeddedSignInFlow({\n authId,\n baseUrl,\n payload: arg1,\n url: arg2?.url,\n });\n\n if (\n response &&\n typeof response === 'object' &&\n response.flowStatus === EmbeddedSignInFlowStatus.Complete &&\n response.assertion\n ) {\n const decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n } = await this.decodeJwtToken<{\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }>(response.assertion);\n\n const createdAt: number = decodedAssertion.iat ? decodedAssertion.iat * 1000 : Date.now();\n const expiresIn: number =\n decodedAssertion.exp && decodedAssertion.iat ? decodedAssertion.exp - decodedAssertion.iat : 3600;\n\n await this.setSession({\n access_token: response.assertion,\n created_at: createdAt,\n expires_in: expiresIn,\n id_token: response.assertion,\n scope: decodedAssertion.scope,\n token_type: 'Bearer',\n });\n\n this.notifySignIn(extractUserClaimsFromIdToken(decodedAssertion as IdToken) as User);\n }\n\n return response;\n }\n\n return (await super.signIn(...args)) as unknown as User;\n });\n }\n\n override async signInSilently(options?: SignInOptions): Promise<User | boolean> {\n return super.signInSilently(options as Record<string, string | boolean>) as Promise<User | boolean>;\n }\n\n override async signUp(options?: SignUpOptions): Promise<void>;\n override async signUp(payload: any): Promise<any>;\n override async signUp(...args: any[]): Promise<void | any> {\n const config: ThunderIDReactConfig = (await this.getStorageManager().getConfigData()) as ThunderIDReactConfig;\n const firstArg: any = args[0];\n const baseUrl: string = config?.baseUrl ?? '';\n\n const authId: string = new URL(window.location.href).searchParams.get('authId') ?? '';\n\n const response: any = await executeEmbeddedSignUpFlow({\n authId,\n baseUrl,\n payload: typeof firstArg === 'object' && 'flowType' in firstArg ? {...firstArg, verbose: true} : firstArg,\n });\n\n if (\n response &&\n typeof response === 'object' &&\n response.flowStatus === EmbeddedSignUpFlowStatus.Complete &&\n response.assertion\n ) {\n const decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n } = await this.decodeJwtToken<{\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }>(response.assertion);\n\n const createdAt: number = decodedAssertion.iat ? decodedAssertion.iat * 1000 : Date.now();\n const expiresIn: number =\n decodedAssertion.exp && decodedAssertion.iat ? decodedAssertion.exp - decodedAssertion.iat : 3600;\n\n await this.setSession({\n access_token: response.assertion,\n created_at: createdAt,\n expires_in: expiresIn,\n id_token: response.assertion,\n scope: decodedAssertion.scope,\n token_type: 'Bearer',\n });\n\n this.notifySignIn(extractUserClaimsFromIdToken(decodedAssertion as IdToken) as User);\n }\n\n return response;\n }\n\n override async recover(payload?: any): Promise<any> {\n const config: ThunderIDReactConfig = (await this.getStorageManager().getConfigData()) as ThunderIDReactConfig;\n\n return executeEmbeddedRecoveryFlow({\n baseUrl: config?.baseUrl,\n payload: {...payload, verbose: true},\n }) as any;\n }\n\n public override getStorageManager(): any {\n return super.getStorageManager();\n }\n\n async request(requestConfig?: HttpRequestConfig): Promise<HttpResponse<any>> {\n return super.httpRequest(requestConfig!) as Promise<HttpResponse<any>>;\n }\n\n async requestAll(requestConfigs?: HttpRequestConfig[]): Promise<HttpResponse<any>[]> {\n return super.httpRequestAll(requestConfigs!) as Promise<HttpResponse<any>[]>;\n }\n}\n\nexport default ThunderIDReactClient;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ThunderIDReactClient.js","names":["isInitialized: boolean","claims: User","arg1: any","arg2: any","config: ThunderIDReactConfig | undefined","authIdFromUrl: string","authIdFromStorage: string","response: EmbeddedSignInFlowResponse","decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }","createdAt: number","expiresIn: number","config: ThunderIDReactConfig","firstArg: any","baseUrl: string","response: any","decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }"],"sources":["../src/ThunderIDReactClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2025-2026, 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 ThunderIDBrowserClient,\n UserProfile,\n SignInOptions,\n User,\n SignUpOptions,\n ThunderIDRuntimeError,\n executeEmbeddedSignInFlow,\n IdToken,\n extractUserClaimsFromIdToken,\n TokenResponse,\n HttpRequestConfig,\n HttpResponse,\n TokenExchangeRequestConfig,\n isEmpty,\n EmbeddedSignInFlowResponse,\n executeEmbeddedSignUpFlow,\n executeEmbeddedRecoveryFlow,\n EmbeddedSignInFlowStatus,\n EmbeddedSignUpFlowStatus,\n resolveResourceEndpoint,\n} from '@thunderid/browser';\nimport {ThunderIDReactConfig} from './models/config';\n\nclass ThunderIDReactClient<T extends ThunderIDReactConfig = ThunderIDReactConfig> extends ThunderIDBrowserClient<T> {\n private loadingState = false;\n\n private _initializeConfig: ThunderIDReactConfig | undefined;\n\n constructor(instanceId = 0) {\n super(instanceId);\n }\n\n private setLoading(loading: boolean): void {\n this.loadingState = loading;\n }\n\n private async withLoading<TResult>(operation: () => Promise<TResult>): Promise<TResult> {\n this.setLoading(true);\n try {\n const result: TResult = await operation();\n return result;\n } finally {\n this.setLoading(false);\n }\n }\n\n override initialize(config: ThunderIDReactConfig): Promise<boolean> {\n return this.withLoading(async () => {\n this._initializeConfig = {\n ...config,\n periodicTokenRefresh:\n config?.tokenLifecycle?.refreshToken?.autoRefresh ?? (config as any)?.periodicTokenRefresh,\n } as any;\n\n return super.initialize(this._initializeConfig as unknown as T);\n });\n }\n\n override reInitialize(config: Partial<ThunderIDReactConfig>): Promise<boolean> {\n return this.withLoading(async () => {\n let isInitialized: boolean;\n\n try {\n await super.reInitialize(config as Partial<T>);\n isInitialized = true;\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to check if the client is initialized: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDReactClient-reInitialize-RuntimeError-001',\n 'react',\n 'An error occurred while checking the initialization status of the client.',\n );\n }\n\n return isInitialized;\n });\n }\n\n override async updateUserProfile(): Promise<User> {\n throw new Error('Not implemented');\n }\n\n override async getUser(): Promise<User> {\n return extractUserClaimsFromIdToken(await this.getDecodedIdToken());\n }\n\n override async getDecodedIdToken(sessionId?: string): Promise<IdToken> {\n return super.getDecodedIdToken(sessionId);\n }\n\n override async getIdToken(): Promise<string> {\n return this.withLoading(async () => super.getIdToken());\n }\n\n override async getUserProfile(): Promise<UserProfile> {\n return this.withLoading(async () => {\n const claims: User = extractUserClaimsFromIdToken(await this.getDecodedIdToken());\n return {\n flattenedProfile: claims,\n profile: claims,\n schemas: [],\n };\n });\n }\n\n override isLoading(): boolean {\n return this.loadingState;\n }\n\n override async isSignedIn(): Promise<boolean> {\n return super.isSignedIn();\n }\n\n override async exchangeToken(config: TokenExchangeRequestConfig): Promise<TokenResponse | Response> {\n return this.withLoading(async () => super.exchangeToken(config) as unknown as TokenResponse | Response);\n }\n\n override async signIn(...args: any[]): Promise<User | EmbeddedSignInFlowResponse> {\n return this.withLoading(async () => {\n const arg1: any = args[0];\n const arg2: any = args[1];\n\n let config: ThunderIDReactConfig | undefined = (await this.getStorageManager().getConfigData()) as\n | ThunderIDReactConfig\n | undefined;\n\n // NOTE: With React 19 strict mode, the initialization logic runs twice, and there's an intermittent\n // issue where the config object is not getting stored in the storage layer with Vite scaffolding.\n // Hence, we need to check if the client is initialized but the config object is empty, and reinitialize.\n if (!config || Object.keys(config).length === 0) {\n await this.initialize(this._initializeConfig!);\n // Reload the config persisted by initialization so downstream endpoint resolution\n // (baseUrl and the flowExecute override) uses the recovered values, not the stale empty config.\n config = (await this.getStorageManager().getConfigData()) as ThunderIDReactConfig | undefined;\n }\n\n if (typeof arg1 === 'object' && arg1 !== null && arg1.callOnlyOnRedirect === true) {\n return undefined as any;\n }\n\n if (\n typeof arg1 === 'object' &&\n arg1 !== null &&\n !isEmpty(arg1) &&\n ('executionId' in arg1 || 'applicationId' in arg1)\n ) {\n const authIdFromUrl: string = new URL(window.location.href).searchParams.get('authId') ?? '';\n const authIdFromStorage: string =\n ((await this.getStorageManager().getHybridDataParameter('authId')) as string) ?? '';\n const authId: string = authIdFromUrl || authIdFromStorage;\n const baseUrl: string = config?.baseUrl ?? '';\n\n const response: EmbeddedSignInFlowResponse = await executeEmbeddedSignInFlow({\n authId,\n baseUrl,\n payload: arg1,\n url: resolveResourceEndpoint('flowExecute', config, arg2?.url),\n });\n\n if (\n response &&\n typeof response === 'object' &&\n response.flowStatus === EmbeddedSignInFlowStatus.Complete &&\n response.assertion\n ) {\n const decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n } = await this.decodeJwtToken<{\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }>(response.assertion);\n\n const createdAt: number = decodedAssertion.iat ? decodedAssertion.iat * 1000 : Date.now();\n const expiresIn: number =\n decodedAssertion.exp && decodedAssertion.iat ? decodedAssertion.exp - decodedAssertion.iat : 3600;\n\n await this.setSession({\n access_token: response.assertion,\n created_at: createdAt,\n expires_in: expiresIn,\n id_token: response.assertion,\n scope: decodedAssertion.scope,\n token_type: 'Bearer',\n });\n\n this.notifySignIn(extractUserClaimsFromIdToken(decodedAssertion as IdToken) as User);\n }\n\n return response;\n }\n\n return (await super.signIn(...args)) as unknown as User;\n });\n }\n\n override async signInSilently(options?: SignInOptions): Promise<User | boolean> {\n return super.signInSilently(options as Record<string, string | boolean>) as Promise<User | boolean>;\n }\n\n override async signUp(options?: SignUpOptions): Promise<void>;\n override async signUp(payload: any): Promise<any>;\n override async signUp(...args: any[]): Promise<void | any> {\n const config: ThunderIDReactConfig = (await this.getStorageManager().getConfigData()) as ThunderIDReactConfig;\n const firstArg: any = args[0];\n const baseUrl: string = config?.baseUrl ?? '';\n\n const authId: string = new URL(window.location.href).searchParams.get('authId') ?? '';\n\n const response: any = await executeEmbeddedSignUpFlow({\n authId,\n baseUrl,\n payload: typeof firstArg === 'object' && 'flowType' in firstArg ? {...firstArg, verbose: true} : firstArg,\n url: resolveResourceEndpoint('flowExecute', config),\n });\n\n if (\n response &&\n typeof response === 'object' &&\n response.flowStatus === EmbeddedSignUpFlowStatus.Complete &&\n response.assertion\n ) {\n const decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n } = await this.decodeJwtToken<{\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }>(response.assertion);\n\n const createdAt: number = decodedAssertion.iat ? decodedAssertion.iat * 1000 : Date.now();\n const expiresIn: number =\n decodedAssertion.exp && decodedAssertion.iat ? decodedAssertion.exp - decodedAssertion.iat : 3600;\n\n await this.setSession({\n access_token: response.assertion,\n created_at: createdAt,\n expires_in: expiresIn,\n id_token: response.assertion,\n scope: decodedAssertion.scope,\n token_type: 'Bearer',\n });\n\n this.notifySignIn(extractUserClaimsFromIdToken(decodedAssertion as IdToken) as User);\n }\n\n return response;\n }\n\n override async recover(payload?: any): Promise<any> {\n const config: ThunderIDReactConfig = (await this.getStorageManager().getConfigData()) as ThunderIDReactConfig;\n\n return executeEmbeddedRecoveryFlow({\n baseUrl: config?.baseUrl,\n payload: {...payload, verbose: true},\n url: resolveResourceEndpoint('flowExecute', config),\n }) as any;\n }\n\n public override getStorageManager(): any {\n return super.getStorageManager();\n }\n\n async request(requestConfig?: HttpRequestConfig): Promise<HttpResponse<any>> {\n return super.httpRequest(requestConfig!) as Promise<HttpResponse<any>>;\n }\n\n async requestAll(requestConfigs?: HttpRequestConfig[]): Promise<HttpResponse<any>[]> {\n return super.httpRequestAll(requestConfigs!) as Promise<HttpResponse<any>[]>;\n }\n}\n\nexport default ThunderIDReactClient;\n"],"mappings":"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"}
|
|
@@ -76,8 +76,11 @@ var ThunderIDReactClient = class extends __thunderid_browser.ThunderIDBrowserCli
|
|
|
76
76
|
return this.withLoading(async () => {
|
|
77
77
|
const arg1 = args[0];
|
|
78
78
|
const arg2 = args[1];
|
|
79
|
-
|
|
80
|
-
if (!config || Object.keys(config).length === 0)
|
|
79
|
+
let config = await this.getStorageManager().getConfigData();
|
|
80
|
+
if (!config || Object.keys(config).length === 0) {
|
|
81
|
+
await this.initialize(this._initializeConfig);
|
|
82
|
+
config = await this.getStorageManager().getConfigData();
|
|
83
|
+
}
|
|
81
84
|
if (typeof arg1 === "object" && arg1 !== null && arg1.callOnlyOnRedirect === true) return;
|
|
82
85
|
if (typeof arg1 === "object" && arg1 !== null && !(0, __thunderid_browser.isEmpty)(arg1) && ("executionId" in arg1 || "applicationId" in arg1)) {
|
|
83
86
|
const authIdFromUrl = new URL(window.location.href).searchParams.get("authId") ?? "";
|
|
@@ -86,7 +89,7 @@ var ThunderIDReactClient = class extends __thunderid_browser.ThunderIDBrowserCli
|
|
|
86
89
|
authId: authIdFromUrl || authIdFromStorage,
|
|
87
90
|
baseUrl: config?.baseUrl ?? "",
|
|
88
91
|
payload: arg1,
|
|
89
|
-
url: arg2?.url
|
|
92
|
+
url: (0, __thunderid_browser.resolveResourceEndpoint)("flowExecute", config, arg2?.url)
|
|
90
93
|
});
|
|
91
94
|
if (response && typeof response === "object" && response.flowStatus === __thunderid_browser.EmbeddedSignInFlowStatus.Complete && response.assertion) {
|
|
92
95
|
const decodedAssertion = await this.decodeJwtToken(response.assertion);
|
|
@@ -120,7 +123,8 @@ var ThunderIDReactClient = class extends __thunderid_browser.ThunderIDBrowserCli
|
|
|
120
123
|
payload: typeof firstArg === "object" && "flowType" in firstArg ? {
|
|
121
124
|
...firstArg,
|
|
122
125
|
verbose: true
|
|
123
|
-
} : firstArg
|
|
126
|
+
} : firstArg,
|
|
127
|
+
url: (0, __thunderid_browser.resolveResourceEndpoint)("flowExecute", config)
|
|
124
128
|
});
|
|
125
129
|
if (response && typeof response === "object" && response.flowStatus === __thunderid_browser.EmbeddedSignUpFlowStatus.Complete && response.assertion) {
|
|
126
130
|
const decodedAssertion = await this.decodeJwtToken(response.assertion);
|
|
@@ -139,12 +143,14 @@ var ThunderIDReactClient = class extends __thunderid_browser.ThunderIDBrowserCli
|
|
|
139
143
|
return response;
|
|
140
144
|
}
|
|
141
145
|
async recover(payload) {
|
|
146
|
+
const config = await this.getStorageManager().getConfigData();
|
|
142
147
|
return (0, __thunderid_browser.executeEmbeddedRecoveryFlow)({
|
|
143
|
-
baseUrl:
|
|
148
|
+
baseUrl: config?.baseUrl,
|
|
144
149
|
payload: {
|
|
145
150
|
...payload,
|
|
146
151
|
verbose: true
|
|
147
|
-
}
|
|
152
|
+
},
|
|
153
|
+
url: (0, __thunderid_browser.resolveResourceEndpoint)("flowExecute", config)
|
|
148
154
|
});
|
|
149
155
|
}
|
|
150
156
|
getStorageManager() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThunderIDReactClient.cjs","names":["ThunderIDBrowserClient","isInitialized: boolean","ThunderIDRuntimeError","claims: User","arg1: any","arg2: any","config: ThunderIDReactConfig | undefined","authIdFromUrl: string","authIdFromStorage: string","response: EmbeddedSignInFlowResponse","EmbeddedSignInFlowStatus","decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }","createdAt: number","expiresIn: number","config: ThunderIDReactConfig","firstArg: any","baseUrl: string","response: any","EmbeddedSignUpFlowStatus","decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }"],"sources":["../../src/ThunderIDReactClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2025-2026, 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 ThunderIDBrowserClient,\n UserProfile,\n SignInOptions,\n User,\n SignUpOptions,\n ThunderIDRuntimeError,\n executeEmbeddedSignInFlow,\n IdToken,\n extractUserClaimsFromIdToken,\n TokenResponse,\n HttpRequestConfig,\n HttpResponse,\n TokenExchangeRequestConfig,\n isEmpty,\n EmbeddedSignInFlowResponse,\n executeEmbeddedSignUpFlow,\n executeEmbeddedRecoveryFlow,\n EmbeddedSignInFlowStatus,\n EmbeddedSignUpFlowStatus,\n} from '@thunderid/browser';\nimport {ThunderIDReactConfig} from './models/config';\n\nclass ThunderIDReactClient<T extends ThunderIDReactConfig = ThunderIDReactConfig> extends ThunderIDBrowserClient<T> {\n private loadingState = false;\n\n private _initializeConfig: ThunderIDReactConfig | undefined;\n\n constructor(instanceId = 0) {\n super(instanceId);\n }\n\n private setLoading(loading: boolean): void {\n this.loadingState = loading;\n }\n\n private async withLoading<TResult>(operation: () => Promise<TResult>): Promise<TResult> {\n this.setLoading(true);\n try {\n const result: TResult = await operation();\n return result;\n } finally {\n this.setLoading(false);\n }\n }\n\n override initialize(config: ThunderIDReactConfig): Promise<boolean> {\n return this.withLoading(async () => {\n this._initializeConfig = {\n ...config,\n periodicTokenRefresh:\n config?.tokenLifecycle?.refreshToken?.autoRefresh ?? (config as any)?.periodicTokenRefresh,\n } as any;\n\n return super.initialize(this._initializeConfig as unknown as T);\n });\n }\n\n override reInitialize(config: Partial<ThunderIDReactConfig>): Promise<boolean> {\n return this.withLoading(async () => {\n let isInitialized: boolean;\n\n try {\n await super.reInitialize(config as Partial<T>);\n isInitialized = true;\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to check if the client is initialized: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDReactClient-reInitialize-RuntimeError-001',\n 'react',\n 'An error occurred while checking the initialization status of the client.',\n );\n }\n\n return isInitialized;\n });\n }\n\n override async updateUserProfile(): Promise<User> {\n throw new Error('Not implemented');\n }\n\n override async getUser(): Promise<User> {\n return extractUserClaimsFromIdToken(await this.getDecodedIdToken());\n }\n\n override async getDecodedIdToken(sessionId?: string): Promise<IdToken> {\n return super.getDecodedIdToken(sessionId);\n }\n\n override async getIdToken(): Promise<string> {\n return this.withLoading(async () => super.getIdToken());\n }\n\n override async getUserProfile(): Promise<UserProfile> {\n return this.withLoading(async () => {\n const claims: User = extractUserClaimsFromIdToken(await this.getDecodedIdToken());\n return {\n flattenedProfile: claims,\n profile: claims,\n schemas: [],\n };\n });\n }\n\n override isLoading(): boolean {\n return this.loadingState;\n }\n\n override async isSignedIn(): Promise<boolean> {\n return super.isSignedIn();\n }\n\n override async exchangeToken(config: TokenExchangeRequestConfig): Promise<TokenResponse | Response> {\n return this.withLoading(async () => super.exchangeToken(config) as unknown as TokenResponse | Response);\n }\n\n override async signIn(...args: any[]): Promise<User | EmbeddedSignInFlowResponse> {\n return this.withLoading(async () => {\n const arg1: any = args[0];\n const arg2: any = args[1];\n\n const config: ThunderIDReactConfig | undefined = (await this.getStorageManager().getConfigData()) as\n | ThunderIDReactConfig\n | undefined;\n\n // NOTE: With React 19 strict mode, the initialization logic runs twice, and there's an intermittent\n // issue where the config object is not getting stored in the storage layer with Vite scaffolding.\n // Hence, we need to check if the client is initialized but the config object is empty, and reinitialize.\n if (!config || Object.keys(config).length === 0) {\n await this.initialize(this._initializeConfig!);\n }\n\n if (typeof arg1 === 'object' && arg1 !== null && arg1.callOnlyOnRedirect === true) {\n return undefined as any;\n }\n\n if (\n typeof arg1 === 'object' &&\n arg1 !== null &&\n !isEmpty(arg1) &&\n ('executionId' in arg1 || 'applicationId' in arg1)\n ) {\n const authIdFromUrl: string = new URL(window.location.href).searchParams.get('authId') ?? '';\n const authIdFromStorage: string =\n ((await this.getStorageManager().getHybridDataParameter('authId')) as string) ?? '';\n const authId: string = authIdFromUrl || authIdFromStorage;\n const baseUrl: string = config?.baseUrl ?? '';\n\n const response: EmbeddedSignInFlowResponse = await executeEmbeddedSignInFlow({\n authId,\n baseUrl,\n payload: arg1,\n url: arg2?.url,\n });\n\n if (\n response &&\n typeof response === 'object' &&\n response.flowStatus === EmbeddedSignInFlowStatus.Complete &&\n response.assertion\n ) {\n const decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n } = await this.decodeJwtToken<{\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }>(response.assertion);\n\n const createdAt: number = decodedAssertion.iat ? decodedAssertion.iat * 1000 : Date.now();\n const expiresIn: number =\n decodedAssertion.exp && decodedAssertion.iat ? decodedAssertion.exp - decodedAssertion.iat : 3600;\n\n await this.setSession({\n access_token: response.assertion,\n created_at: createdAt,\n expires_in: expiresIn,\n id_token: response.assertion,\n scope: decodedAssertion.scope,\n token_type: 'Bearer',\n });\n\n this.notifySignIn(extractUserClaimsFromIdToken(decodedAssertion as IdToken) as User);\n }\n\n return response;\n }\n\n return (await super.signIn(...args)) as unknown as User;\n });\n }\n\n override async signInSilently(options?: SignInOptions): Promise<User | boolean> {\n return super.signInSilently(options as Record<string, string | boolean>) as Promise<User | boolean>;\n }\n\n override async signUp(options?: SignUpOptions): Promise<void>;\n override async signUp(payload: any): Promise<any>;\n override async signUp(...args: any[]): Promise<void | any> {\n const config: ThunderIDReactConfig = (await this.getStorageManager().getConfigData()) as ThunderIDReactConfig;\n const firstArg: any = args[0];\n const baseUrl: string = config?.baseUrl ?? '';\n\n const authId: string = new URL(window.location.href).searchParams.get('authId') ?? '';\n\n const response: any = await executeEmbeddedSignUpFlow({\n authId,\n baseUrl,\n payload: typeof firstArg === 'object' && 'flowType' in firstArg ? {...firstArg, verbose: true} : firstArg,\n });\n\n if (\n response &&\n typeof response === 'object' &&\n response.flowStatus === EmbeddedSignUpFlowStatus.Complete &&\n response.assertion\n ) {\n const decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n } = await this.decodeJwtToken<{\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }>(response.assertion);\n\n const createdAt: number = decodedAssertion.iat ? decodedAssertion.iat * 1000 : Date.now();\n const expiresIn: number =\n decodedAssertion.exp && decodedAssertion.iat ? decodedAssertion.exp - decodedAssertion.iat : 3600;\n\n await this.setSession({\n access_token: response.assertion,\n created_at: createdAt,\n expires_in: expiresIn,\n id_token: response.assertion,\n scope: decodedAssertion.scope,\n token_type: 'Bearer',\n });\n\n this.notifySignIn(extractUserClaimsFromIdToken(decodedAssertion as IdToken) as User);\n }\n\n return response;\n }\n\n override async recover(payload?: any): Promise<any> {\n const config: ThunderIDReactConfig = (await this.getStorageManager().getConfigData()) as ThunderIDReactConfig;\n\n return executeEmbeddedRecoveryFlow({\n baseUrl: config?.baseUrl,\n payload: {...payload, verbose: true},\n }) as any;\n }\n\n public override getStorageManager(): any {\n return super.getStorageManager();\n }\n\n async request(requestConfig?: HttpRequestConfig): Promise<HttpResponse<any>> {\n return super.httpRequest(requestConfig!) as Promise<HttpResponse<any>>;\n }\n\n async requestAll(requestConfigs?: HttpRequestConfig[]): Promise<HttpResponse<any>[]> {\n return super.httpRequestAll(requestConfigs!) as Promise<HttpResponse<any>[]>;\n }\n}\n\nexport default ThunderIDReactClient;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ThunderIDReactClient.cjs","names":["ThunderIDBrowserClient","isInitialized: boolean","ThunderIDRuntimeError","claims: User","arg1: any","arg2: any","config: ThunderIDReactConfig | undefined","authIdFromUrl: string","authIdFromStorage: string","response: EmbeddedSignInFlowResponse","EmbeddedSignInFlowStatus","decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }","createdAt: number","expiresIn: number","config: ThunderIDReactConfig","firstArg: any","baseUrl: string","response: any","EmbeddedSignUpFlowStatus","decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }"],"sources":["../../src/ThunderIDReactClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2025-2026, 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 ThunderIDBrowserClient,\n UserProfile,\n SignInOptions,\n User,\n SignUpOptions,\n ThunderIDRuntimeError,\n executeEmbeddedSignInFlow,\n IdToken,\n extractUserClaimsFromIdToken,\n TokenResponse,\n HttpRequestConfig,\n HttpResponse,\n TokenExchangeRequestConfig,\n isEmpty,\n EmbeddedSignInFlowResponse,\n executeEmbeddedSignUpFlow,\n executeEmbeddedRecoveryFlow,\n EmbeddedSignInFlowStatus,\n EmbeddedSignUpFlowStatus,\n resolveResourceEndpoint,\n} from '@thunderid/browser';\nimport {ThunderIDReactConfig} from './models/config';\n\nclass ThunderIDReactClient<T extends ThunderIDReactConfig = ThunderIDReactConfig> extends ThunderIDBrowserClient<T> {\n private loadingState = false;\n\n private _initializeConfig: ThunderIDReactConfig | undefined;\n\n constructor(instanceId = 0) {\n super(instanceId);\n }\n\n private setLoading(loading: boolean): void {\n this.loadingState = loading;\n }\n\n private async withLoading<TResult>(operation: () => Promise<TResult>): Promise<TResult> {\n this.setLoading(true);\n try {\n const result: TResult = await operation();\n return result;\n } finally {\n this.setLoading(false);\n }\n }\n\n override initialize(config: ThunderIDReactConfig): Promise<boolean> {\n return this.withLoading(async () => {\n this._initializeConfig = {\n ...config,\n periodicTokenRefresh:\n config?.tokenLifecycle?.refreshToken?.autoRefresh ?? (config as any)?.periodicTokenRefresh,\n } as any;\n\n return super.initialize(this._initializeConfig as unknown as T);\n });\n }\n\n override reInitialize(config: Partial<ThunderIDReactConfig>): Promise<boolean> {\n return this.withLoading(async () => {\n let isInitialized: boolean;\n\n try {\n await super.reInitialize(config as Partial<T>);\n isInitialized = true;\n } catch (error) {\n throw new ThunderIDRuntimeError(\n `Failed to check if the client is initialized: ${error instanceof Error ? error.message : String(error)}`,\n 'ThunderIDReactClient-reInitialize-RuntimeError-001',\n 'react',\n 'An error occurred while checking the initialization status of the client.',\n );\n }\n\n return isInitialized;\n });\n }\n\n override async updateUserProfile(): Promise<User> {\n throw new Error('Not implemented');\n }\n\n override async getUser(): Promise<User> {\n return extractUserClaimsFromIdToken(await this.getDecodedIdToken());\n }\n\n override async getDecodedIdToken(sessionId?: string): Promise<IdToken> {\n return super.getDecodedIdToken(sessionId);\n }\n\n override async getIdToken(): Promise<string> {\n return this.withLoading(async () => super.getIdToken());\n }\n\n override async getUserProfile(): Promise<UserProfile> {\n return this.withLoading(async () => {\n const claims: User = extractUserClaimsFromIdToken(await this.getDecodedIdToken());\n return {\n flattenedProfile: claims,\n profile: claims,\n schemas: [],\n };\n });\n }\n\n override isLoading(): boolean {\n return this.loadingState;\n }\n\n override async isSignedIn(): Promise<boolean> {\n return super.isSignedIn();\n }\n\n override async exchangeToken(config: TokenExchangeRequestConfig): Promise<TokenResponse | Response> {\n return this.withLoading(async () => super.exchangeToken(config) as unknown as TokenResponse | Response);\n }\n\n override async signIn(...args: any[]): Promise<User | EmbeddedSignInFlowResponse> {\n return this.withLoading(async () => {\n const arg1: any = args[0];\n const arg2: any = args[1];\n\n let config: ThunderIDReactConfig | undefined = (await this.getStorageManager().getConfigData()) as\n | ThunderIDReactConfig\n | undefined;\n\n // NOTE: With React 19 strict mode, the initialization logic runs twice, and there's an intermittent\n // issue where the config object is not getting stored in the storage layer with Vite scaffolding.\n // Hence, we need to check if the client is initialized but the config object is empty, and reinitialize.\n if (!config || Object.keys(config).length === 0) {\n await this.initialize(this._initializeConfig!);\n // Reload the config persisted by initialization so downstream endpoint resolution\n // (baseUrl and the flowExecute override) uses the recovered values, not the stale empty config.\n config = (await this.getStorageManager().getConfigData()) as ThunderIDReactConfig | undefined;\n }\n\n if (typeof arg1 === 'object' && arg1 !== null && arg1.callOnlyOnRedirect === true) {\n return undefined as any;\n }\n\n if (\n typeof arg1 === 'object' &&\n arg1 !== null &&\n !isEmpty(arg1) &&\n ('executionId' in arg1 || 'applicationId' in arg1)\n ) {\n const authIdFromUrl: string = new URL(window.location.href).searchParams.get('authId') ?? '';\n const authIdFromStorage: string =\n ((await this.getStorageManager().getHybridDataParameter('authId')) as string) ?? '';\n const authId: string = authIdFromUrl || authIdFromStorage;\n const baseUrl: string = config?.baseUrl ?? '';\n\n const response: EmbeddedSignInFlowResponse = await executeEmbeddedSignInFlow({\n authId,\n baseUrl,\n payload: arg1,\n url: resolveResourceEndpoint('flowExecute', config, arg2?.url),\n });\n\n if (\n response &&\n typeof response === 'object' &&\n response.flowStatus === EmbeddedSignInFlowStatus.Complete &&\n response.assertion\n ) {\n const decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n } = await this.decodeJwtToken<{\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }>(response.assertion);\n\n const createdAt: number = decodedAssertion.iat ? decodedAssertion.iat * 1000 : Date.now();\n const expiresIn: number =\n decodedAssertion.exp && decodedAssertion.iat ? decodedAssertion.exp - decodedAssertion.iat : 3600;\n\n await this.setSession({\n access_token: response.assertion,\n created_at: createdAt,\n expires_in: expiresIn,\n id_token: response.assertion,\n scope: decodedAssertion.scope,\n token_type: 'Bearer',\n });\n\n this.notifySignIn(extractUserClaimsFromIdToken(decodedAssertion as IdToken) as User);\n }\n\n return response;\n }\n\n return (await super.signIn(...args)) as unknown as User;\n });\n }\n\n override async signInSilently(options?: SignInOptions): Promise<User | boolean> {\n return super.signInSilently(options as Record<string, string | boolean>) as Promise<User | boolean>;\n }\n\n override async signUp(options?: SignUpOptions): Promise<void>;\n override async signUp(payload: any): Promise<any>;\n override async signUp(...args: any[]): Promise<void | any> {\n const config: ThunderIDReactConfig = (await this.getStorageManager().getConfigData()) as ThunderIDReactConfig;\n const firstArg: any = args[0];\n const baseUrl: string = config?.baseUrl ?? '';\n\n const authId: string = new URL(window.location.href).searchParams.get('authId') ?? '';\n\n const response: any = await executeEmbeddedSignUpFlow({\n authId,\n baseUrl,\n payload: typeof firstArg === 'object' && 'flowType' in firstArg ? {...firstArg, verbose: true} : firstArg,\n url: resolveResourceEndpoint('flowExecute', config),\n });\n\n if (\n response &&\n typeof response === 'object' &&\n response.flowStatus === EmbeddedSignUpFlowStatus.Complete &&\n response.assertion\n ) {\n const decodedAssertion: {\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n } = await this.decodeJwtToken<{\n [key: string]: unknown;\n exp?: number;\n iat?: number;\n scope?: string;\n }>(response.assertion);\n\n const createdAt: number = decodedAssertion.iat ? decodedAssertion.iat * 1000 : Date.now();\n const expiresIn: number =\n decodedAssertion.exp && decodedAssertion.iat ? decodedAssertion.exp - decodedAssertion.iat : 3600;\n\n await this.setSession({\n access_token: response.assertion,\n created_at: createdAt,\n expires_in: expiresIn,\n id_token: response.assertion,\n scope: decodedAssertion.scope,\n token_type: 'Bearer',\n });\n\n this.notifySignIn(extractUserClaimsFromIdToken(decodedAssertion as IdToken) as User);\n }\n\n return response;\n }\n\n override async recover(payload?: any): Promise<any> {\n const config: ThunderIDReactConfig = (await this.getStorageManager().getConfigData()) as ThunderIDReactConfig;\n\n return executeEmbeddedRecoveryFlow({\n baseUrl: config?.baseUrl,\n payload: {...payload, verbose: true},\n url: resolveResourceEndpoint('flowExecute', config),\n }) as any;\n }\n\n public override getStorageManager(): any {\n return super.getStorageManager();\n }\n\n async request(requestConfig?: HttpRequestConfig): Promise<HttpResponse<any>> {\n return super.httpRequest(requestConfig!) as Promise<HttpResponse<any>>;\n }\n\n async requestAll(requestConfigs?: HttpRequestConfig[]): Promise<HttpResponse<any>[]> {\n return super.httpRequestAll(requestConfigs!) as Promise<HttpResponse<any>[]>;\n }\n}\n\nexport default ThunderIDReactClient;\n"],"mappings":"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"}
|
|
@@ -50,7 +50,8 @@ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
|
|
|
50
50
|
* ```
|
|
51
51
|
*/
|
|
52
52
|
const InviteUser = ({ onError, onFlowChange, className, children, size = "medium", variant = "outlined", showTitle = true, showSubtitle = true }) => {
|
|
53
|
-
const { http, baseUrl, getAccessToken, isInitialized } = require_useThunderID.default();
|
|
53
|
+
const { http, baseUrl, endpoints, getAccessToken, isInitialized } = require_useThunderID.default();
|
|
54
|
+
const flowExecuteUrl = (0, __thunderid_browser.resolveResourceEndpoint)("flowExecute", { endpoints }) ?? `${baseUrl}/flow/execute`;
|
|
54
55
|
/**
|
|
55
56
|
* Initialize the invite user flow.
|
|
56
57
|
* Makes an authenticated request to /flow/execute with flowType: USER_ONBOARDING.
|
|
@@ -67,7 +68,7 @@ const InviteUser = ({ onError, onFlowChange, className, children, size = "medium
|
|
|
67
68
|
"Content-Type": "application/json"
|
|
68
69
|
},
|
|
69
70
|
method: "POST",
|
|
70
|
-
url:
|
|
71
|
+
url: flowExecuteUrl
|
|
71
72
|
})).data;
|
|
72
73
|
};
|
|
73
74
|
/**
|
|
@@ -85,7 +86,7 @@ const InviteUser = ({ onError, onFlowChange, className, children, size = "medium
|
|
|
85
86
|
"Content-Type": "application/json"
|
|
86
87
|
},
|
|
87
88
|
method: "POST",
|
|
88
|
-
url:
|
|
89
|
+
url: flowExecuteUrl
|
|
89
90
|
})).data;
|
|
90
91
|
};
|
|
91
92
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_BaseInviteUser.default, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InviteUser.cjs","names":["InviteUser: FC<InviteUserProps>","useThunderID","EmbeddedFlowType","BaseInviteUser"],"sources":["../../../../../../src/components/presentation/auth/InviteUser/InviteUser.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\nimport {EmbeddedFlowType
|
|
1
|
+
{"version":3,"file":"InviteUser.cjs","names":["InviteUser: FC<InviteUserProps>","useThunderID","flowExecuteUrl: string","EmbeddedFlowType","BaseInviteUser"],"sources":["../../../../../../src/components/presentation/auth/InviteUser/InviteUser.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\nimport {\n EmbeddedFlowType,\n getOrganizationUnitChildren,\n OrganizationUnitListResponse,\n resolveResourceEndpoint,\n} from '@thunderid/browser';\nimport {FC, ReactElement, ReactNode, useCallback} from 'react';\n// eslint-disable-next-line import/no-named-as-default\nimport BaseInviteUser, {BaseInviteUserRenderProps, InviteUserFlowResponse} from './BaseInviteUser';\nimport useThunderID from '../../../../contexts/ThunderID/useThunderID';\n\n/**\n * Render props for InviteUser (re-exported for convenience).\n */\nexport type InviteUserRenderProps = BaseInviteUserRenderProps;\n\n/**\n * Props for the InviteUser component.\n */\nexport interface InviteUserProps {\n /**\n * Render props function for custom UI.\n * If not provided, default UI will be rendered by the SDK.\n */\n children?: (props: InviteUserRenderProps) => ReactNode;\n\n /**\n * Custom CSS class name.\n */\n className?: string;\n\n /**\n * Callback when an error occurs.\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback when the flow state changes.\n */\n onFlowChange?: (response: InviteUserFlowResponse) => void;\n\n /**\n * Whether to show the subtitle.\n */\n showSubtitle?: boolean;\n\n /**\n * Whether to show the title.\n */\n showTitle?: boolean;\n\n /**\n * Size variant for the component.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * Theme variant for the component card.\n */\n variant?: 'outlined' | 'elevated';\n}\n\n/**\n * InviteUser component for initiating invite user flow.\n *\n * This component is designed for admin users in the thunder-develop app to:\n * 1. Select a user type (if multiple available)\n * 2. Enter user details (username, email)\n * 3. Generate an invite link for the end user\n *\n * The component uses the authenticated ThunderID SDK context to make API calls\n * with the admin's access token (requires 'system' scope).\n *\n * @example\n * ```tsx\n * import { InviteUser } from '@thunderid/react';\n *\n * const InviteUserPage = () => {\n * const [inviteLink, setInviteLink] = useState<string>();\n *\n * return (\n * <InviteUser\n * onInviteLinkGenerated={(link, executionId) => setInviteLink(link)}\n * onError={(error) => console.error(error)}\n * >\n * {({ values, components, isLoading, handleInputChange, handleSubmit, inviteLink, isInviteGenerated }) => (\n * <div>\n * {isInviteGenerated ? (\n * <div>\n * <h2>Invite Link Generated!</h2>\n * <p>{inviteLink}</p>\n * </div>\n * ) : (\n * // Render form based on components\n * )}\n * </div>\n * )}\n * </InviteUser>\n * );\n * };\n * ```\n */\nconst InviteUser: FC<InviteUserProps> = ({\n onError,\n onFlowChange,\n className,\n children,\n size = 'medium',\n variant = 'outlined',\n showTitle = true,\n showSubtitle = true,\n}: InviteUserProps): ReactElement => {\n const {http, baseUrl, endpoints, getAccessToken, isInitialized} = useThunderID();\n\n // The user-onboarding flow runs on the resource server, which may differ from `baseUrl` (the\n // authorization server) in a trusted-issuer setup. Honor the `flowExecute` endpoint override.\n const flowExecuteUrl: string = resolveResourceEndpoint('flowExecute', {endpoints}) ?? `${baseUrl}/flow/execute`;\n\n /**\n * Initialize the invite user flow.\n * Makes an authenticated request to /flow/execute with flowType: USER_ONBOARDING.\n */\n const handleInitialize = async (payload: Record<string, any>): Promise<InviteUserFlowResponse> => {\n const response: any = await http.request({\n data: {\n ...payload,\n flowType: EmbeddedFlowType.UserOnboarding,\n verbose: true,\n },\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n url: flowExecuteUrl,\n } as any);\n\n return response.data as InviteUserFlowResponse;\n };\n\n /**\n * Submit flow step data.\n * Makes an authenticated request to /flow/execute with the step data.\n */\n const handleSubmit = async (payload: Record<string, any>): Promise<InviteUserFlowResponse> => {\n const response: any = await http.request({\n data: {\n ...payload,\n verbose: true,\n },\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n method: 'POST',\n url: flowExecuteUrl,\n } as any);\n\n return response.data as InviteUserFlowResponse;\n };\n\n const fetchOrganizationUnitChildren: (\n parentId: string,\n limit: number,\n offset: number,\n ) => Promise<OrganizationUnitListResponse> = useCallback(\n async (parentId: string, limit: number, offset: number): Promise<OrganizationUnitListResponse> => {\n const accessToken: string = await getAccessToken();\n\n return getOrganizationUnitChildren({\n baseUrl,\n headers: {Authorization: `Bearer ${accessToken}`},\n limit,\n offset,\n organizationUnitId: parentId,\n });\n },\n [baseUrl, getAccessToken],\n );\n\n return (\n <BaseInviteUser\n onInitialize={handleInitialize}\n onSubmit={handleSubmit}\n onError={onError}\n onFlowChange={onFlowChange}\n className={className}\n fetchOrganizationUnitChildren={fetchOrganizationUnitChildren}\n isInitialized={isInitialized}\n size={size}\n variant={variant}\n showTitle={showTitle}\n showSubtitle={showSubtitle}\n >\n {children}\n </BaseInviteUser>\n );\n};\n\nexport default InviteUser;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwHA,MAAMA,cAAmC,EACvC,SACA,cACA,WACA,UACA,OAAO,UACP,UAAU,YACV,YAAY,MACZ,eAAe,WACoB;CACnC,MAAM,EAAC,MAAM,SAAS,WAAW,gBAAgB,kBAAiBC,8BAAc;CAIhF,MAAMC,kEAAiD,eAAe,EAAC,WAAU,CAAC,IAAI,GAAG,QAAQ;;;;;CAMjG,MAAM,mBAAmB,OAAO,YAAkE;AAehG,UAdsB,MAAM,KAAK,QAAQ;GACvC,MAAM;IACJ,GAAG;IACH,UAAUC,qCAAiB;IAC3B,SAAS;IACV;GACD,SAAS;IACP,QAAQ;IACR,gBAAgB;IACjB;GACD,QAAQ;GACR,KAAK;GACN,CAAQ,EAEO;;;;;;CAOlB,MAAM,eAAe,OAAO,YAAkE;AAc5F,UAbsB,MAAM,KAAK,QAAQ;GACvC,MAAM;IACJ,GAAG;IACH,SAAS;IACV;GACD,SAAS;IACP,QAAQ;IACR,gBAAgB;IACjB;GACD,QAAQ;GACR,KAAK;GACN,CAAQ,EAEO;;AAsBlB,QACE,2CAACC;EACC,cAAc;EACd,UAAU;EACD;EACK;EACH;EACX,sDArBF,OAAO,UAAkB,OAAe,WAA0D;AAGhG,+DAAmC;IACjC;IACA,SAAS,EAAC,eAAe,UAJC,MAAM,gBAAgB,IAIC;IACjD;IACA;IACA,oBAAoB;IACrB,CAAC;KAEJ,CAAC,SAAS,eAAe,CAC1B;EAUkB;EACT;EACG;EACE;EACG;EAEb;GACc;;AAIrB,yBAAe"}
|
|
@@ -34,7 +34,7 @@ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
|
|
|
34
34
|
* ```
|
|
35
35
|
*/
|
|
36
36
|
const FlowMetaProvider = ({ children, enabled = true, initialMeta = null }) => {
|
|
37
|
-
const { baseUrl, applicationId, isInitialized } = require_useThunderID.default();
|
|
37
|
+
const { baseUrl, endpoints, applicationId, isInitialized } = require_useThunderID.default();
|
|
38
38
|
const i18nContext = require_useI18n.default();
|
|
39
39
|
const [meta, setMeta] = (0, react.useState)(initialMeta);
|
|
40
40
|
const [isLoading, setIsLoading] = (0, react.useState)(!initialMeta);
|
|
@@ -54,6 +54,7 @@ const FlowMetaProvider = ({ children, enabled = true, initialMeta = null }) => {
|
|
|
54
54
|
try {
|
|
55
55
|
setMeta(await (0, __thunderid_browser.getFlowMeta)({
|
|
56
56
|
baseUrl,
|
|
57
|
+
url: (0, __thunderid_browser.resolveResourceEndpoint)("flowMeta", { endpoints }),
|
|
57
58
|
...applicationId ? {
|
|
58
59
|
id: applicationId,
|
|
59
60
|
type: __thunderid_browser.FlowMetaType.App
|
|
@@ -68,6 +69,7 @@ const FlowMetaProvider = ({ children, enabled = true, initialMeta = null }) => {
|
|
|
68
69
|
}, [
|
|
69
70
|
enabled,
|
|
70
71
|
baseUrl,
|
|
72
|
+
endpoints,
|
|
71
73
|
applicationId,
|
|
72
74
|
isInitialized,
|
|
73
75
|
i18nContext?.currentLanguage
|
|
@@ -79,6 +81,7 @@ const FlowMetaProvider = ({ children, enabled = true, initialMeta = null }) => {
|
|
|
79
81
|
try {
|
|
80
82
|
const result = await (0, __thunderid_browser.getFlowMeta)({
|
|
81
83
|
baseUrl,
|
|
84
|
+
url: (0, __thunderid_browser.resolveResourceEndpoint)("flowMeta", { endpoints }),
|
|
82
85
|
...applicationId ? {
|
|
83
86
|
id: applicationId,
|
|
84
87
|
type: __thunderid_browser.FlowMetaType.App
|
|
@@ -105,6 +108,7 @@ const FlowMetaProvider = ({ children, enabled = true, initialMeta = null }) => {
|
|
|
105
108
|
}, [
|
|
106
109
|
enabled,
|
|
107
110
|
baseUrl,
|
|
111
|
+
endpoints,
|
|
108
112
|
applicationId,
|
|
109
113
|
i18nContext
|
|
110
114
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FlowMetaProvider.cjs","names":["FlowMetaProvider: FC<PropsWithChildren<FlowMetaProviderProps>>","useThunderID","i18nContext: I18nContextValue","useI18n","lastFetchedRef: RefObject<(() => Promise<void>) | null>","initialMetaConsumedRef: RefObject<boolean>","fetchFlowMeta: () => Promise<void>","FlowMetaType","err: unknown","switchLanguage: (language: string) => Promise<void>","result: FlowMetadataResponse","flatTranslations: Record<string, string>","value","bundle: I18nBundle","metaLanguage: string","TranslationBundleConstants","bundlesToInject: Record<string, I18nBundle>","value: any","FlowMetaContext"],"sources":["../../../../src/contexts/FlowMeta/FlowMetaProvider.tsx"],"sourcesContent":["/**\n * Copyright (c) 2026, 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 FlowMetadataResponse,\n FlowMetaType,\n getFlowMeta,\n I18nBundle,\n TranslationBundleConstants,\n} from '@thunderid/browser';\nimport {FC, PropsWithChildren, ReactElement, RefObject, useCallback, useEffect, useRef, useState} from 'react';\nimport FlowMetaContext from './FlowMetaContext';\nimport {I18nContextValue} from '../I18n/I18nContext';\nimport useI18n from '../I18n/useI18n';\nimport useThunderID from '../ThunderID/useThunderID';\n\nexport interface FlowMetaProviderProps {\n /**\n * When false the provider skips fetching and provides null meta.\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Flow metadata resolved ahead of time (e.g. fetched server-side during SSR) and used to seed\n * the provider's state. When present, the provider skips its own initial client-side fetch —\n * avoiding a redundant request and the flash of untranslated i18n keys while that fetch is in\n * flight — but still fetches normally on subsequent changes (e.g. an explicit language switch).\n */\n initialMeta?: FlowMetadataResponse | null;\n}\n\n/**\n * FlowMetaProvider fetches flow metadata from the `GET /flow/meta` endpoint\n * (v2 API) and makes it available to child components through `FlowMetaContext`.\n *\n * It is designed to be used in v2 embedded-flow scenarios and integrates with\n * `ThemeProvider` so that theme settings (colors, direction, typography, …)\n * from the server-side design configuration are applied automatically.\n *\n * @example\n * ```tsx\n * <FlowMetaProvider\n * config={{\n * baseUrl: 'https://localhost:8090',\n * type: FlowMetaType.App,\n * id: 'your-app-id',\n * }}\n * >\n * <ThemeProvider>\n * <App />\n * </ThemeProvider>\n * </FlowMetaProvider>\n * ```\n */\nconst FlowMetaProvider: FC<PropsWithChildren<FlowMetaProviderProps>> = ({\n children,\n enabled = true,\n initialMeta = null,\n}: PropsWithChildren<FlowMetaProviderProps>): ReactElement => {\n const {baseUrl, applicationId, isInitialized} = useThunderID();\n const i18nContext: I18nContextValue = useI18n();\n\n const [meta, setMeta] = useState<FlowMetadataResponse | null>(initialMeta);\n const [isLoading, setIsLoading] = useState<boolean>(!initialMeta);\n const [error, setError] = useState<Error | null>(null);\n const [pendingLanguage, setPendingLanguage] = useState<string | null>(null);\n\n // Track the last fetchFlowMeta reference that was actually dispatched.\n // This prevents two classes of double-fetch:\n // 1. React StrictMode simulates unmount+remount — the re-mount fires the\n // effect again with the same fetchFlowMeta reference; without this guard\n // the else-branch would issue a redundant second network request.\n // 2. Rapid dependency changes (e.g. baseUrl stabilising) that produce two\n // effect firings before the first fetch completes.\n const lastFetchedRef: RefObject<(() => Promise<void>) | null> = useRef<(() => Promise<void>) | null>(null);\n const initialMetaConsumedRef: RefObject<boolean> = useRef(false);\n const fetchFlowMeta: () => Promise<void> = useCallback(async (): Promise<void> => {\n if (!enabled) {\n setMeta(null);\n setIsLoading(false);\n return;\n }\n\n // Defer until ThunderID finishes initializing (e.g. loading applicationId\n // from storage on refresh). Once initialized, proceed even if applicationId\n // is absent — some flows (e.g. AcceptInvite) have no applicationId by design.\n if (!isInitialized && !applicationId) {\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result: FlowMetadataResponse = await getFlowMeta({\n baseUrl,\n ...(applicationId ? {id: applicationId, type: FlowMetaType.App} : {}),\n language: i18nContext?.currentLanguage,\n });\n setMeta(result);\n } catch (err: unknown) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [enabled, baseUrl, applicationId, isInitialized, i18nContext?.currentLanguage]);\n\n const switchLanguage: (language: string) => Promise<void> = useCallback(\n async (language: string): Promise<void> => {\n if (!enabled) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result: FlowMetadataResponse = await getFlowMeta({\n baseUrl,\n ...(applicationId ? {id: applicationId, type: FlowMetaType.App} : {}),\n language,\n });\n\n // Inject translations for the new language before switching\n if (result.i18n?.translations && i18nContext?.injectBundles) {\n const flatTranslations: Record<string, string> = {};\n Object.entries(result.i18n.translations).forEach(([namespace, keys]: [string, Record<string, string>]) => {\n Object.entries(keys).forEach(([key, value]: [string, string]) => {\n flatTranslations[`${namespace}.${key}`] = value;\n });\n });\n const bundle: I18nBundle = {translations: flatTranslations} as unknown as I18nBundle;\n i18nContext.injectBundles({[language]: bundle});\n }\n\n // Defer setLanguage to the next effect cycle so injectBundles state\n // is committed before I18nProvider's setLanguage checks mergedBundles.\n setPendingLanguage(language);\n setMeta(result);\n } catch (err: unknown) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n },\n [enabled, baseUrl, applicationId, i18nContext],\n );\n\n // After injectBundles + setPendingLanguage are batched and committed, this\n // effect fires with the updated i18nContext (mergedBundles now includes the\n // new language), so setLanguage succeeds on the first switch.\n useEffect(() => {\n if (pendingLanguage && i18nContext?.setLanguage) {\n i18nContext.setLanguage(pendingLanguage);\n setPendingLanguage(null);\n }\n }, [pendingLanguage, i18nContext?.setLanguage]);\n\n useEffect(() => {\n if (!initialMetaConsumedRef.current) {\n initialMetaConsumedRef.current = true;\n\n if (initialMeta) {\n // Seeded from SSR (or another caller) — skip the redundant first client-side fetch.\n // Later dependency changes (e.g. an explicit language switch) still fetch normally.\n lastFetchedRef.current = fetchFlowMeta;\n return;\n }\n }\n\n if (lastFetchedRef.current === fetchFlowMeta) {\n // Same reference as the last dispatch — this is a StrictMode re-mount\n // or an effect re-fire with unchanged deps. Skip to avoid a duplicate fetch.\n return;\n }\n\n lastFetchedRef.current = fetchFlowMeta;\n fetchFlowMeta();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fetchFlowMeta]);\n\n // When meta loads with i18n translations, inject them into the i18n system.\n // Meta translations act as the base layer — prop-provided bundles still take precedence.\n useEffect(() => {\n if (!meta?.i18n?.translations || !i18nContext?.injectBundles) {\n return;\n }\n\n const metaLanguage: string = meta.i18n.language || TranslationBundleConstants.FALLBACK_LOCALE;\n\n // Flatten namespace-keyed translations to dot-path keys:\n // { \"signin\": { \"heading\": \"Sign In\" } } → { \"signin.heading\": \"Sign In\" }\n const flatTranslations: Record<string, string> = {};\n Object.entries(meta.i18n.translations).forEach(([namespace, keys]: [string, Record<string, string>]) => {\n Object.entries(keys).forEach(([key, value]: [string, string]) => {\n flatTranslations[`${namespace}.${key}`] = value;\n });\n });\n\n const bundle: I18nBundle = {translations: flatTranslations} as unknown as I18nBundle;\n\n // Inject under the meta language code and the i18n current language so\n // lookups succeed regardless of whether the system uses \"en\" or \"en-US\".\n const bundlesToInject: Record<string, I18nBundle> = {[metaLanguage]: bundle};\n if (i18nContext.currentLanguage && i18nContext.currentLanguage !== metaLanguage) {\n bundlesToInject[i18nContext.currentLanguage] = bundle;\n }\n if (i18nContext.fallbackLanguage && i18nContext.fallbackLanguage !== metaLanguage) {\n bundlesToInject[i18nContext.fallbackLanguage] = bundle;\n }\n\n i18nContext.injectBundles(bundlesToInject);\n }, [meta?.i18n?.translations, i18nContext?.injectBundles]);\n\n const value: any = {\n error,\n fetchFlowMeta,\n isLoading,\n meta,\n switchLanguage,\n };\n\n return <FlowMetaContext.Provider value={value}>{children}</FlowMetaContext.Provider>;\n};\n\nexport default FlowMetaProvider;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FlowMetaProvider.cjs","names":["FlowMetaProvider: FC<PropsWithChildren<FlowMetaProviderProps>>","useThunderID","i18nContext: I18nContextValue","useI18n","lastFetchedRef: RefObject<(() => Promise<void>) | null>","initialMetaConsumedRef: RefObject<boolean>","fetchFlowMeta: () => Promise<void>","FlowMetaType","err: unknown","switchLanguage: (language: string) => Promise<void>","result: FlowMetadataResponse","flatTranslations: Record<string, string>","value","bundle: I18nBundle","metaLanguage: string","TranslationBundleConstants","bundlesToInject: Record<string, I18nBundle>","value: any","FlowMetaContext"],"sources":["../../../../src/contexts/FlowMeta/FlowMetaProvider.tsx"],"sourcesContent":["/**\n * Copyright (c) 2026, 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 FlowMetadataResponse,\n FlowMetaType,\n getFlowMeta,\n I18nBundle,\n resolveResourceEndpoint,\n TranslationBundleConstants,\n} from '@thunderid/browser';\nimport {FC, PropsWithChildren, ReactElement, RefObject, useCallback, useEffect, useRef, useState} from 'react';\nimport FlowMetaContext from './FlowMetaContext';\nimport {I18nContextValue} from '../I18n/I18nContext';\nimport useI18n from '../I18n/useI18n';\nimport useThunderID from '../ThunderID/useThunderID';\n\nexport interface FlowMetaProviderProps {\n /**\n * When false the provider skips fetching and provides null meta.\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Flow metadata resolved ahead of time (e.g. fetched server-side during SSR) and used to seed\n * the provider's state. When present, the provider skips its own initial client-side fetch —\n * avoiding a redundant request and the flash of untranslated i18n keys while that fetch is in\n * flight — but still fetches normally on subsequent changes (e.g. an explicit language switch).\n */\n initialMeta?: FlowMetadataResponse | null;\n}\n\n/**\n * FlowMetaProvider fetches flow metadata from the `GET /flow/meta` endpoint\n * (v2 API) and makes it available to child components through `FlowMetaContext`.\n *\n * It is designed to be used in v2 embedded-flow scenarios and integrates with\n * `ThemeProvider` so that theme settings (colors, direction, typography, …)\n * from the server-side design configuration are applied automatically.\n *\n * @example\n * ```tsx\n * <FlowMetaProvider\n * config={{\n * baseUrl: 'https://localhost:8090',\n * type: FlowMetaType.App,\n * id: 'your-app-id',\n * }}\n * >\n * <ThemeProvider>\n * <App />\n * </ThemeProvider>\n * </FlowMetaProvider>\n * ```\n */\nconst FlowMetaProvider: FC<PropsWithChildren<FlowMetaProviderProps>> = ({\n children,\n enabled = true,\n initialMeta = null,\n}: PropsWithChildren<FlowMetaProviderProps>): ReactElement => {\n const {baseUrl, endpoints, applicationId, isInitialized} = useThunderID();\n const i18nContext: I18nContextValue = useI18n();\n\n const [meta, setMeta] = useState<FlowMetadataResponse | null>(initialMeta);\n const [isLoading, setIsLoading] = useState<boolean>(!initialMeta);\n const [error, setError] = useState<Error | null>(null);\n const [pendingLanguage, setPendingLanguage] = useState<string | null>(null);\n\n // Track the last fetchFlowMeta reference that was actually dispatched.\n // This prevents two classes of double-fetch:\n // 1. React StrictMode simulates unmount+remount — the re-mount fires the\n // effect again with the same fetchFlowMeta reference; without this guard\n // the else-branch would issue a redundant second network request.\n // 2. Rapid dependency changes (e.g. baseUrl stabilising) that produce two\n // effect firings before the first fetch completes.\n const lastFetchedRef: RefObject<(() => Promise<void>) | null> = useRef<(() => Promise<void>) | null>(null);\n const initialMetaConsumedRef: RefObject<boolean> = useRef(false);\n const fetchFlowMeta: () => Promise<void> = useCallback(async (): Promise<void> => {\n if (!enabled) {\n setMeta(null);\n setIsLoading(false);\n return;\n }\n\n // Defer until ThunderID finishes initializing (e.g. loading applicationId\n // from storage on refresh). Once initialized, proceed even if applicationId\n // is absent — some flows (e.g. AcceptInvite) have no applicationId by design.\n if (!isInitialized && !applicationId) {\n return;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result: FlowMetadataResponse = await getFlowMeta({\n baseUrl,\n url: resolveResourceEndpoint('flowMeta', {endpoints}),\n ...(applicationId ? {id: applicationId, type: FlowMetaType.App} : {}),\n language: i18nContext?.currentLanguage,\n });\n setMeta(result);\n } catch (err: unknown) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n }, [enabled, baseUrl, endpoints, applicationId, isInitialized, i18nContext?.currentLanguage]);\n\n const switchLanguage: (language: string) => Promise<void> = useCallback(\n async (language: string): Promise<void> => {\n if (!enabled) return;\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result: FlowMetadataResponse = await getFlowMeta({\n baseUrl,\n url: resolveResourceEndpoint('flowMeta', {endpoints}),\n ...(applicationId ? {id: applicationId, type: FlowMetaType.App} : {}),\n language,\n });\n\n // Inject translations for the new language before switching\n if (result.i18n?.translations && i18nContext?.injectBundles) {\n const flatTranslations: Record<string, string> = {};\n Object.entries(result.i18n.translations).forEach(([namespace, keys]: [string, Record<string, string>]) => {\n Object.entries(keys).forEach(([key, value]: [string, string]) => {\n flatTranslations[`${namespace}.${key}`] = value;\n });\n });\n const bundle: I18nBundle = {translations: flatTranslations} as unknown as I18nBundle;\n i18nContext.injectBundles({[language]: bundle});\n }\n\n // Defer setLanguage to the next effect cycle so injectBundles state\n // is committed before I18nProvider's setLanguage checks mergedBundles.\n setPendingLanguage(language);\n setMeta(result);\n } catch (err: unknown) {\n setError(err instanceof Error ? err : new Error(String(err)));\n } finally {\n setIsLoading(false);\n }\n },\n [enabled, baseUrl, endpoints, applicationId, i18nContext],\n );\n\n // After injectBundles + setPendingLanguage are batched and committed, this\n // effect fires with the updated i18nContext (mergedBundles now includes the\n // new language), so setLanguage succeeds on the first switch.\n useEffect(() => {\n if (pendingLanguage && i18nContext?.setLanguage) {\n i18nContext.setLanguage(pendingLanguage);\n setPendingLanguage(null);\n }\n }, [pendingLanguage, i18nContext?.setLanguage]);\n\n useEffect(() => {\n if (!initialMetaConsumedRef.current) {\n initialMetaConsumedRef.current = true;\n\n if (initialMeta) {\n // Seeded from SSR (or another caller) — skip the redundant first client-side fetch.\n // Later dependency changes (e.g. an explicit language switch) still fetch normally.\n lastFetchedRef.current = fetchFlowMeta;\n return;\n }\n }\n\n if (lastFetchedRef.current === fetchFlowMeta) {\n // Same reference as the last dispatch — this is a StrictMode re-mount\n // or an effect re-fire with unchanged deps. Skip to avoid a duplicate fetch.\n return;\n }\n\n lastFetchedRef.current = fetchFlowMeta;\n fetchFlowMeta();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fetchFlowMeta]);\n\n // When meta loads with i18n translations, inject them into the i18n system.\n // Meta translations act as the base layer — prop-provided bundles still take precedence.\n useEffect(() => {\n if (!meta?.i18n?.translations || !i18nContext?.injectBundles) {\n return;\n }\n\n const metaLanguage: string = meta.i18n.language || TranslationBundleConstants.FALLBACK_LOCALE;\n\n // Flatten namespace-keyed translations to dot-path keys:\n // { \"signin\": { \"heading\": \"Sign In\" } } → { \"signin.heading\": \"Sign In\" }\n const flatTranslations: Record<string, string> = {};\n Object.entries(meta.i18n.translations).forEach(([namespace, keys]: [string, Record<string, string>]) => {\n Object.entries(keys).forEach(([key, value]: [string, string]) => {\n flatTranslations[`${namespace}.${key}`] = value;\n });\n });\n\n const bundle: I18nBundle = {translations: flatTranslations} as unknown as I18nBundle;\n\n // Inject under the meta language code and the i18n current language so\n // lookups succeed regardless of whether the system uses \"en\" or \"en-US\".\n const bundlesToInject: Record<string, I18nBundle> = {[metaLanguage]: bundle};\n if (i18nContext.currentLanguage && i18nContext.currentLanguage !== metaLanguage) {\n bundlesToInject[i18nContext.currentLanguage] = bundle;\n }\n if (i18nContext.fallbackLanguage && i18nContext.fallbackLanguage !== metaLanguage) {\n bundlesToInject[i18nContext.fallbackLanguage] = bundle;\n }\n\n i18nContext.injectBundles(bundlesToInject);\n }, [meta?.i18n?.translations, i18nContext?.injectBundles]);\n\n const value: any = {\n error,\n fetchFlowMeta,\n isLoading,\n meta,\n switchLanguage,\n };\n\n return <FlowMetaContext.Provider value={value}>{children}</FlowMetaContext.Provider>;\n};\n\nexport default FlowMetaProvider;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThunderIDContext.cjs","names":["ThunderIDContext: Context<ThunderIDContextProps | null>","VendorConstants"],"sources":["../../../../src/contexts/ThunderID/ThunderIDContext.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 FlowMetadataResponse,\n HttpRequestConfig,\n HttpResponse,\n IdToken,\n OIDCDiscoveryApiResponse,\n SignInOptions,\n TokenExchangeRequestConfig,\n TokenResponse,\n VendorConstants,\n} from '@thunderid/browser';\nimport {Context, createContext} from 'react';\nimport {ThunderIDReactConfig} from '../../models/config';\nimport ThunderIDReactClient from '../../ThunderIDReactClient';\n\n/**\n * Props interface of {@link ThunderIDContext}\n */\nexport type ThunderIDContextProps = {\n afterSignInUrl: string | undefined;\n applicationId: string | undefined;\n baseUrl: string | undefined;\n clientId: string | undefined;\n preferences?: ThunderIDReactConfig['preferences'];\n scopes: string | string[] | undefined;\n /**\n * OIDC discovery data.\n */\n discovery: {\n /**\n * The response from the `.well-known/openid-configuration` endpoint.\n * Contains server capabilities, supported endpoints, and metadata.\n * `null` while loading or when discovery has not been fetched.\n */\n wellKnown: OIDCDiscoveryApiResponse | null;\n };\n /**\n * Swaps the current access token with a new one based on the provided configuration (with a grant type).\n * @param config - Configuration for the token exchange request.\n * @returns A promise that resolves to the token response or the raw response.\n */\n exchangeToken: (config: TokenExchangeRequestConfig) => Promise<TokenResponse | Response>;\n /**\n * Retrieves the access token stored in the storage.\n * This function retrieves the access token and returns it.\n * @remarks This does not work in the `webWorker` or any other worker environment.\n * @returns A promise that resolves to the access token.\n */\n getAccessToken: () => Promise<string>;\n /**\n * Function to retrieve the decoded ID token.\n * This function decodes the ID token and returns its payload.\n * It can be used to access user claims and other information contained in the ID token.\n *\n * @returns A promise that resolves to the decoded ID token payload.\n */\n getDecodedIdToken: () => Promise<IdToken>;\n /**\n * Function to retrieve the ID token.\n * This function retrieves the ID token and returns it.\n *\n * @returns A promise that resolves to the ID token.\n */\n getIdToken: () => Promise<string>;\n /**\n * Returns the underlying StorageManager instance for reading and writing SDK-managed storage.\n */\n getStorageManager: () => Promise<any>;\n /**\n * HTTP request function to make API calls.\n * @param requestConfig - Configuration for the HTTP request.\n * @returns A promise that resolves to the HTTP response.\n */\n http: {\n /**\n * Makes an HTTP request using the provided configuration.\n * @param requestConfig - Configuration for the HTTP request.\n * @returns A promise that resolves to the HTTP response.\n */\n request: (requestConfig?: HttpRequestConfig) => Promise<HttpResponse<any>>;\n /**\n * Makes multiple HTTP requests based on the provided configuration.\n * @param requestConfigs - Set of configurations for the HTTP requests.\n * @returns A promise that resolves to an array of HTTP responses.\n */\n requestAll: (requestConfigs?: HttpRequestConfig[]) => Promise<HttpResponse<any>[]>;\n };\n /**\n * Instance ID for multi-instance support.\n */\n instanceId: number;\n isInitialized: boolean;\n /**\n * Flag indicating whether the SDK is working in the background.\n */\n isLoading: boolean;\n /**\n * Flag indicating whether flow metadata is currently being fetched.\n */\n isMetaLoading: boolean;\n /**\n * Flag indicating whether the user is signed in or not.\n */\n isSignedIn: boolean;\n\n /**\n * Flow metadata returned by `GET /flow/meta` (v2 platform only).\n * `null` while loading or when `resolveFromMeta` is disabled.\n */\n meta: FlowMetadataResponse | null;\n\n organizationHandle: string | undefined;\n\n /**\n * Re-initializes the client with a new configuration.\n *\n * @remarks\n * This can be partial configuration to update only specific fields.\n *\n * @param config - New configuration to re-initialize the client with.\n * @returns Promise resolving to boolean indicating success.\n */\n reInitialize: (config: Partial<ThunderIDReactConfig>) => Promise<boolean>;\n\n /**\n * Recovery function to initiate the account/password recovery flow.\n */\n recover: (...args: any[]) => Promise<any>;\n\n /**\n * Resolves `{{ t(key) }}` and `{{ meta(path) }}` template expressions in a string,\n * using the current i18n translation function and flow metadata from context.\n *\n * Useful in render-props patterns where consumers need to expand template strings\n * that come from the server (e.g. component labels, placeholders, headings).\n *\n * @example\n * const {resolveFlowTemplateLiterals} = useThunderID();\n * resolveFlowTemplateLiterals('{{ t(signin.heading.label) }}') // → 'Sign In'\n * resolveFlowTemplateLiterals('Login to {{ meta(application.name) }}') // → 'Login to My App'\n */\n resolveFlowTemplateLiterals: (text: string | undefined) => string;\n\n /**\n * Sign-in function to initiate the authentication process.\n * @remark This is the programmatic version of the `SignInButton` component.\n * TODO: Fix the types.\n */\n signIn: (...args: any) => Promise<any>;\n\n /**\n * Optional additional parameters to be sent in the sign-in request.\n * This can include custom parameters that your authorization server supports.\n * These parameters will be included in the authorization request sent to the server.\n * If not provided, no additional parameters will be sent.\n *\n * @example\n * signInOptions: { prompt: \"login\", fidp: \"OrganizationSSO\" }\n */\n signInOptions?: SignInOptions;\n\n /**\n * Optional token request configuration. params are appended to the token endpoint POST body.\n *\n * @example\n * tokenRequest: { params: { resource: \"https://api.example.com\" } }\n */\n tokenRequest?: {\n params?: Record<string, unknown>;\n };\n\n /**\n * Silent sign-in function to re-authenticate the user without user interaction.\n * @remark This is the programmatic version of the `SilentSignIn` component.\n */\n signInSilently: ThunderIDReactClient['signInSilently'];\n\n signInUrl: string | undefined;\n /**\n * Sign-out function to terminate the authentication session.\n * @remark This is the programmatic version of the `SignOutButton` component.\n * FIXME: Fix the types.\n */\n signOut: any;\n\n /**\n * Sign-up function to initiate the registration process.\n * @remark This is the programmatic version of the `SignUpButton` component.\n */\n signUp: (...args: any[]) => Promise<any>;\n\n signUpUrl: string | undefined;\n\n user: any;\n\n /**\n * Vendor/brand namespace used to prefix storage keys, cookie names, and CSS class names.\n * Resolved from the `vendor` config option, defaulting to `'thunderid'`.\n */\n vendor: string;\n} & Pick<ThunderIDReactClient, 'clearSession'>;\n\n/**\n * Context object for managing the Authentication flow builder core context.\n */\nconst ThunderIDContext: Context<ThunderIDContextProps | null> = createContext<null | ThunderIDContextProps>({\n afterSignInUrl: undefined,\n applicationId: undefined,\n baseUrl: undefined,\n clearSession: () => {},\n clientId: undefined,\n preferences: undefined,\n scopes: undefined,\n discovery: {\n wellKnown: null,\n },\n exchangeToken: null as unknown as ThunderIDContextProps['exchangeToken'],\n getAccessToken: null as unknown as ThunderIDContextProps['getAccessToken'],\n getDecodedIdToken: null as unknown as ThunderIDContextProps['getDecodedIdToken'],\n getIdToken: null as unknown as ThunderIDContextProps['getIdToken'],\n getStorageManager: () => Promise.resolve(null),\n http: {\n request: () => null as unknown as Promise<HttpResponse<any>>,\n requestAll: () => null as unknown as Promise<HttpResponse<any>[]>,\n },\n instanceId: 0,\n isInitialized: false,\n isLoading: true,\n isMetaLoading: false,\n isSignedIn: false,\n meta: null,\n organizationHandle: undefined,\n reInitialize: null as unknown as ThunderIDContextProps['reInitialize'],\n recover: () => Promise.resolve({} as any),\n resolveFlowTemplateLiterals: (text: string | undefined) => text ?? '',\n signIn: () => Promise.resolve({} as any),\n signInSilently: () => Promise.resolve({} as any),\n signInUrl: undefined,\n signOut: () => Promise.resolve({} as any),\n signUp: () => Promise.resolve({} as any),\n signUpUrl: undefined,\n user: null,\n vendor: VendorConstants.VENDOR_PREFIX,\n});\n\nThunderIDContext.displayName = 'ThunderIDContext';\n\nexport default ThunderIDContext;\n"],"mappings":";;;;;;;;;;AA+NA,MAAMA,4CAAsG;CAC1G,gBAAgB;CAChB,eAAe;CACf,SAAS;CACT,oBAAoB;CACpB,UAAU;CACV,aAAa;CACb,QAAQ;CACR,WAAW,EACT,WAAW,MACZ;CACD,eAAe;CACf,gBAAgB;CAChB,mBAAmB;CACnB,YAAY;CACZ,yBAAyB,QAAQ,QAAQ,KAAK;CAC9C,MAAM;EACJ,eAAe;EACf,kBAAkB;EACnB;CACD,YAAY;CACZ,eAAe;CACf,WAAW;CACX,eAAe;CACf,YAAY;CACZ,MAAM;CACN,oBAAoB;CACpB,cAAc;CACd,eAAe,QAAQ,QAAQ,EAAE,CAAQ;CACzC,8BAA8B,SAA6B,QAAQ;CACnE,cAAc,QAAQ,QAAQ,EAAE,CAAQ;CACxC,sBAAsB,QAAQ,QAAQ,EAAE,CAAQ;CAChD,WAAW;CACX,eAAe,QAAQ,QAAQ,EAAE,CAAQ;CACzC,cAAc,QAAQ,QAAQ,EAAE,CAAQ;CACxC,WAAW;CACX,MAAM;CACN,QAAQC,oCAAgB;CACzB,CAAC;AAEF,iBAAiB,cAAc;AAE/B,+BAAe"}
|
|
1
|
+
{"version":3,"file":"ThunderIDContext.cjs","names":["ThunderIDContext: Context<ThunderIDContextProps | null>","VendorConstants"],"sources":["../../../../src/contexts/ThunderID/ThunderIDContext.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 FlowMetadataResponse,\n HttpRequestConfig,\n HttpResponse,\n IdToken,\n OIDCDiscoveryApiResponse,\n SignInOptions,\n TokenExchangeRequestConfig,\n TokenResponse,\n VendorConstants,\n} from '@thunderid/browser';\nimport {Context, createContext} from 'react';\nimport {ThunderIDReactConfig} from '../../models/config';\nimport ThunderIDReactClient from '../../ThunderIDReactClient';\n\n/**\n * Props interface of {@link ThunderIDContext}\n */\nexport type ThunderIDContextProps = {\n afterSignInUrl: string | undefined;\n applicationId: string | undefined;\n baseUrl: string | undefined;\n clientId: string | undefined;\n /**\n * Optional endpoint URL overrides from the client config. Used to resolve resource-server\n * endpoints (e.g. flow/user-management) independently of `baseUrl` — see `resolveResourceEndpoint`.\n */\n endpoints?: ThunderIDReactConfig['endpoints'];\n preferences?: ThunderIDReactConfig['preferences'];\n scopes: string | string[] | undefined;\n /**\n * OIDC discovery data.\n */\n discovery: {\n /**\n * The response from the `.well-known/openid-configuration` endpoint.\n * Contains server capabilities, supported endpoints, and metadata.\n * `null` while loading or when discovery has not been fetched.\n */\n wellKnown: OIDCDiscoveryApiResponse | null;\n };\n /**\n * Swaps the current access token with a new one based on the provided configuration (with a grant type).\n * @param config - Configuration for the token exchange request.\n * @returns A promise that resolves to the token response or the raw response.\n */\n exchangeToken: (config: TokenExchangeRequestConfig) => Promise<TokenResponse | Response>;\n /**\n * Retrieves the access token stored in the storage.\n * This function retrieves the access token and returns it.\n * @remarks This does not work in the `webWorker` or any other worker environment.\n * @returns A promise that resolves to the access token.\n */\n getAccessToken: () => Promise<string>;\n /**\n * Function to retrieve the decoded ID token.\n * This function decodes the ID token and returns its payload.\n * It can be used to access user claims and other information contained in the ID token.\n *\n * @returns A promise that resolves to the decoded ID token payload.\n */\n getDecodedIdToken: () => Promise<IdToken>;\n /**\n * Function to retrieve the ID token.\n * This function retrieves the ID token and returns it.\n *\n * @returns A promise that resolves to the ID token.\n */\n getIdToken: () => Promise<string>;\n /**\n * Returns the underlying StorageManager instance for reading and writing SDK-managed storage.\n */\n getStorageManager: () => Promise<any>;\n /**\n * HTTP request function to make API calls.\n * @param requestConfig - Configuration for the HTTP request.\n * @returns A promise that resolves to the HTTP response.\n */\n http: {\n /**\n * Makes an HTTP request using the provided configuration.\n * @param requestConfig - Configuration for the HTTP request.\n * @returns A promise that resolves to the HTTP response.\n */\n request: (requestConfig?: HttpRequestConfig) => Promise<HttpResponse<any>>;\n /**\n * Makes multiple HTTP requests based on the provided configuration.\n * @param requestConfigs - Set of configurations for the HTTP requests.\n * @returns A promise that resolves to an array of HTTP responses.\n */\n requestAll: (requestConfigs?: HttpRequestConfig[]) => Promise<HttpResponse<any>[]>;\n };\n /**\n * Instance ID for multi-instance support.\n */\n instanceId: number;\n isInitialized: boolean;\n /**\n * Flag indicating whether the SDK is working in the background.\n */\n isLoading: boolean;\n /**\n * Flag indicating whether flow metadata is currently being fetched.\n */\n isMetaLoading: boolean;\n /**\n * Flag indicating whether the user is signed in or not.\n */\n isSignedIn: boolean;\n\n /**\n * Flow metadata returned by `GET /flow/meta` (v2 platform only).\n * `null` while loading or when `resolveFromMeta` is disabled.\n */\n meta: FlowMetadataResponse | null;\n\n organizationHandle: string | undefined;\n\n /**\n * Re-initializes the client with a new configuration.\n *\n * @remarks\n * This can be partial configuration to update only specific fields.\n *\n * @param config - New configuration to re-initialize the client with.\n * @returns Promise resolving to boolean indicating success.\n */\n reInitialize: (config: Partial<ThunderIDReactConfig>) => Promise<boolean>;\n\n /**\n * Recovery function to initiate the account/password recovery flow.\n */\n recover: (...args: any[]) => Promise<any>;\n\n /**\n * Resolves `{{ t(key) }}` and `{{ meta(path) }}` template expressions in a string,\n * using the current i18n translation function and flow metadata from context.\n *\n * Useful in render-props patterns where consumers need to expand template strings\n * that come from the server (e.g. component labels, placeholders, headings).\n *\n * @example\n * const {resolveFlowTemplateLiterals} = useThunderID();\n * resolveFlowTemplateLiterals('{{ t(signin.heading.label) }}') // → 'Sign In'\n * resolveFlowTemplateLiterals('Login to {{ meta(application.name) }}') // → 'Login to My App'\n */\n resolveFlowTemplateLiterals: (text: string | undefined) => string;\n\n /**\n * Sign-in function to initiate the authentication process.\n * @remark This is the programmatic version of the `SignInButton` component.\n * TODO: Fix the types.\n */\n signIn: (...args: any) => Promise<any>;\n\n /**\n * Optional additional parameters to be sent in the sign-in request.\n * This can include custom parameters that your authorization server supports.\n * These parameters will be included in the authorization request sent to the server.\n * If not provided, no additional parameters will be sent.\n *\n * @example\n * signInOptions: { prompt: \"login\", fidp: \"OrganizationSSO\" }\n */\n signInOptions?: SignInOptions;\n\n /**\n * Optional token request configuration. params are appended to the token endpoint POST body.\n *\n * @example\n * tokenRequest: { params: { resource: \"https://api.example.com\" } }\n */\n tokenRequest?: {\n params?: Record<string, unknown>;\n };\n\n /**\n * Silent sign-in function to re-authenticate the user without user interaction.\n * @remark This is the programmatic version of the `SilentSignIn` component.\n */\n signInSilently: ThunderIDReactClient['signInSilently'];\n\n signInUrl: string | undefined;\n /**\n * Sign-out function to terminate the authentication session.\n * @remark This is the programmatic version of the `SignOutButton` component.\n * FIXME: Fix the types.\n */\n signOut: any;\n\n /**\n * Sign-up function to initiate the registration process.\n * @remark This is the programmatic version of the `SignUpButton` component.\n */\n signUp: (...args: any[]) => Promise<any>;\n\n signUpUrl: string | undefined;\n\n user: any;\n\n /**\n * Vendor/brand namespace used to prefix storage keys, cookie names, and CSS class names.\n * Resolved from the `vendor` config option, defaulting to `'thunderid'`.\n */\n vendor: string;\n} & Pick<ThunderIDReactClient, 'clearSession'>;\n\n/**\n * Context object for managing the Authentication flow builder core context.\n */\nconst ThunderIDContext: Context<ThunderIDContextProps | null> = createContext<null | ThunderIDContextProps>({\n afterSignInUrl: undefined,\n applicationId: undefined,\n baseUrl: undefined,\n clearSession: () => {},\n clientId: undefined,\n preferences: undefined,\n scopes: undefined,\n discovery: {\n wellKnown: null,\n },\n exchangeToken: null as unknown as ThunderIDContextProps['exchangeToken'],\n getAccessToken: null as unknown as ThunderIDContextProps['getAccessToken'],\n getDecodedIdToken: null as unknown as ThunderIDContextProps['getDecodedIdToken'],\n getIdToken: null as unknown as ThunderIDContextProps['getIdToken'],\n getStorageManager: () => Promise.resolve(null),\n http: {\n request: () => null as unknown as Promise<HttpResponse<any>>,\n requestAll: () => null as unknown as Promise<HttpResponse<any>[]>,\n },\n instanceId: 0,\n isInitialized: false,\n isLoading: true,\n isMetaLoading: false,\n isSignedIn: false,\n meta: null,\n organizationHandle: undefined,\n reInitialize: null as unknown as ThunderIDContextProps['reInitialize'],\n recover: () => Promise.resolve({} as any),\n resolveFlowTemplateLiterals: (text: string | undefined) => text ?? '',\n signIn: () => Promise.resolve({} as any),\n signInSilently: () => Promise.resolve({} as any),\n signInUrl: undefined,\n signOut: () => Promise.resolve({} as any),\n signUp: () => Promise.resolve({} as any),\n signUpUrl: undefined,\n user: null,\n vendor: VendorConstants.VENDOR_PREFIX,\n});\n\nThunderIDContext.displayName = 'ThunderIDContext';\n\nexport default ThunderIDContext;\n"],"mappings":";;;;;;;;;;AAoOA,MAAMA,4CAAsG;CAC1G,gBAAgB;CAChB,eAAe;CACf,SAAS;CACT,oBAAoB;CACpB,UAAU;CACV,aAAa;CACb,QAAQ;CACR,WAAW,EACT,WAAW,MACZ;CACD,eAAe;CACf,gBAAgB;CAChB,mBAAmB;CACnB,YAAY;CACZ,yBAAyB,QAAQ,QAAQ,KAAK;CAC9C,MAAM;EACJ,eAAe;EACf,kBAAkB;EACnB;CACD,YAAY;CACZ,eAAe;CACf,WAAW;CACX,eAAe;CACf,YAAY;CACZ,MAAM;CACN,oBAAoB;CACpB,cAAc;CACd,eAAe,QAAQ,QAAQ,EAAE,CAAQ;CACzC,8BAA8B,SAA6B,QAAQ;CACnE,cAAc,QAAQ,QAAQ,EAAE,CAAQ;CACxC,sBAAsB,QAAQ,QAAQ,EAAE,CAAQ;CAChD,WAAW;CACX,eAAe,QAAQ,QAAQ,EAAE,CAAQ;CACzC,cAAc,QAAQ,QAAQ,EAAE,CAAQ;CACxC,WAAW;CACX,MAAM;CACN,QAAQC,oCAAgB;CACzB,CAAC;AAEF,iBAAiB,cAAc;AAE/B,+BAAe"}
|
|
@@ -47,6 +47,7 @@ const ThunderIDProvider = ({ afterSignInUrl, afterSignOutUrl, baseUrl: initialBa
|
|
|
47
47
|
});
|
|
48
48
|
const [isUpdatingSession, setIsUpdatingSession] = (0, react.useState)(false);
|
|
49
49
|
const [wellKnown, setWellKnown] = (0, react.useState)(null);
|
|
50
|
+
const pendingSessionUpdateRef = (0, react.useRef)(null);
|
|
50
51
|
(0, react.useEffect)(() => {
|
|
51
52
|
setBaseUrl(initialBaseUrl ?? "");
|
|
52
53
|
}, [initialBaseUrl]);
|
|
@@ -57,7 +58,7 @@ const ThunderIDProvider = ({ afterSignInUrl, afterSignOutUrl, baseUrl: initialBa
|
|
|
57
58
|
setWellKnown(await client.getDiscoveryResponse());
|
|
58
59
|
})();
|
|
59
60
|
}, []);
|
|
60
|
-
async function
|
|
61
|
+
async function performSessionUpdate() {
|
|
61
62
|
try {
|
|
62
63
|
setIsUpdatingSession(true);
|
|
63
64
|
setIsLoadingSync(true);
|
|
@@ -74,6 +75,7 @@ const ThunderIDProvider = ({ afterSignInUrl, afterSignOutUrl, baseUrl: initialBa
|
|
|
74
75
|
if (currentSignInStatus && shouldFetchProfile) try {
|
|
75
76
|
const fetchedProfile = await require_getUsersMe.default({
|
|
76
77
|
baseUrl: resolvedBaseUrl,
|
|
78
|
+
url: (0, __thunderid_browser.resolveResourceEndpoint)("usersMe", config),
|
|
77
79
|
instanceId
|
|
78
80
|
});
|
|
79
81
|
profileData = {
|
|
@@ -94,6 +96,20 @@ const ThunderIDProvider = ({ afterSignInUrl, afterSignOutUrl, baseUrl: initialBa
|
|
|
94
96
|
setIsLoadingSync(client.isLoading());
|
|
95
97
|
}
|
|
96
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Single-flight wrapper around {@link performSessionUpdate}.
|
|
101
|
+
*
|
|
102
|
+
* Concurrent callers share the in-flight request instead of each issuing their own `/users/me`.
|
|
103
|
+
* This is not a cache: once the request settles the ref is cleared, so a later caller (e.g.
|
|
104
|
+
* revalidation after a profile update) fetches again.
|
|
105
|
+
*/
|
|
106
|
+
async function updateSession() {
|
|
107
|
+
if (pendingSessionUpdateRef.current) return pendingSessionUpdateRef.current;
|
|
108
|
+
pendingSessionUpdateRef.current = performSessionUpdate().finally(() => {
|
|
109
|
+
pendingSessionUpdateRef.current = null;
|
|
110
|
+
});
|
|
111
|
+
return pendingSessionUpdateRef.current;
|
|
112
|
+
}
|
|
97
113
|
async function signIn(...args) {
|
|
98
114
|
const arg1 = args[0];
|
|
99
115
|
const isV2FlowRequest = typeof arg1 === "object" && arg1 !== null && ("executionId" in arg1 || "applicationId" in arg1);
|
|
@@ -122,22 +138,13 @@ const ThunderIDProvider = ({ afterSignInUrl, afterSignOutUrl, baseUrl: initialBa
|
|
|
122
138
|
await client.on("sign-in", async () => {
|
|
123
139
|
await updateSession();
|
|
124
140
|
});
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
logger.warn("Failed to schedule automatic token refresh.", error);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
const resumeSession = async () => {
|
|
134
|
-
await updateSession();
|
|
135
|
-
await scheduleAutoRefresh();
|
|
136
|
-
};
|
|
137
|
-
if (isAlreadySignedIn) await resumeSession();
|
|
138
|
-
await scheduleAutoRefresh();
|
|
141
|
+
try {
|
|
142
|
+
await client.startAutoRefreshToken();
|
|
143
|
+
} catch (error) {
|
|
144
|
+
logger.warn("Failed to schedule automatic token refresh.", error);
|
|
145
|
+
}
|
|
139
146
|
if (await client.isSignedIn()) {
|
|
140
|
-
await
|
|
147
|
+
await updateSession();
|
|
141
148
|
return;
|
|
142
149
|
}
|
|
143
150
|
const currentUrl = new URL(window.location.href);
|
|
@@ -241,11 +248,19 @@ const ThunderIDProvider = ({ afterSignInUrl, afterSignOutUrl, baseUrl: initialBa
|
|
|
241
248
|
const recover = (0, react.useCallback)(async (payload) => client.recover(payload), [client]);
|
|
242
249
|
const signUp = (0, react.useCallback)(async (...args) => client.signUp(...args), [client]);
|
|
243
250
|
const clearSession = (0, react.useCallback)(async (...args) => client.clearSession(...args), [client]);
|
|
244
|
-
const reInitialize = (0, react.useCallback)(async (reInitConfig) =>
|
|
251
|
+
const reInitialize = (0, react.useCallback)(async (reInitConfig) => {
|
|
252
|
+
const result = await client.reInitialize(reInitConfig);
|
|
253
|
+
const reinitializedConfig = await client.getConfiguration();
|
|
254
|
+
setConfig(reinitializedConfig);
|
|
255
|
+
setBaseUrl(reinitializedConfig.baseUrl ?? "");
|
|
256
|
+
setWellKnown(await client.getDiscoveryResponse());
|
|
257
|
+
return result;
|
|
258
|
+
}, [client]);
|
|
245
259
|
const value = (0, react.useMemo)(() => ({
|
|
246
260
|
afterSignInUrl: config.afterSignInUrl,
|
|
247
261
|
applicationId: config.applicationId,
|
|
248
262
|
baseUrl,
|
|
263
|
+
endpoints: config.endpoints,
|
|
249
264
|
scopes: config.scopes,
|
|
250
265
|
clearSession,
|
|
251
266
|
clientId,
|
|
@@ -284,6 +299,7 @@ const ThunderIDProvider = ({ afterSignInUrl, afterSignOutUrl, baseUrl: initialBa
|
|
|
284
299
|
config?.organizationHandle,
|
|
285
300
|
config.vendor,
|
|
286
301
|
config.afterSignInUrl,
|
|
302
|
+
config.endpoints,
|
|
287
303
|
config.scopes,
|
|
288
304
|
signInUrl,
|
|
289
305
|
signUpUrl,
|