@thunderid/javascript 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +2 -1
  2. package/dist/HttpClient.d.ts.map +1 -1
  3. package/dist/StorageManager.d.ts +10 -4
  4. package/dist/StorageManager.d.ts.map +1 -1
  5. package/dist/ThunderIDJavaScriptClient.d.ts.map +1 -1
  6. package/dist/api/createOrganization.d.ts +2 -2
  7. package/dist/api/executeEmbeddedSignUpFlow.d.ts +1 -1
  8. package/dist/api/getAllOrganizations.d.ts +2 -2
  9. package/dist/api/getBrandingPreference.d.ts +2 -2
  10. package/dist/api/getMeOrganizations.d.ts +2 -2
  11. package/dist/api/getOrganization.d.ts +2 -2
  12. package/dist/api/getSchemas.d.ts +2 -2
  13. package/dist/api/getScim2Me.d.ts +2 -2
  14. package/dist/api/getUserInfo.d.ts +1 -1
  15. package/dist/api/initializeEmbeddedSignInFlow.d.ts +1 -1
  16. package/dist/api/updateMeProfile.d.ts +2 -2
  17. package/dist/api/updateOrganization.d.ts +3 -3
  18. package/dist/api/v2/executeEmbeddedRecoveryFlowV2.d.ts +2 -2
  19. package/dist/api/v2/executeEmbeddedRecoveryFlowV2.d.ts.map +1 -1
  20. package/dist/api/v2/executeEmbeddedSignInFlowV2.d.ts +1 -1
  21. package/dist/api/v2/executeEmbeddedSignInFlowV2.d.ts.map +1 -1
  22. package/dist/api/v2/executeEmbeddedSignUpFlowV2.d.ts +1 -1
  23. package/dist/api/v2/executeEmbeddedSignUpFlowV2.d.ts.map +1 -1
  24. package/dist/api/v2/executeEmbeddedUserOnboardingFlowV2.d.ts +4 -4
  25. package/dist/api/v2/executeEmbeddedUserOnboardingFlowV2.d.ts.map +1 -1
  26. package/dist/cjs/index.cjs +269 -149
  27. package/dist/edge/index.js +269 -149
  28. package/dist/errors/ThunderIDAPIError.d.ts +3 -3
  29. package/dist/errors/ThunderIDAPIError.d.ts.map +1 -1
  30. package/dist/errors/ThunderIDRuntimeError.d.ts +2 -2
  31. package/dist/errors/ThunderIDRuntimeError.d.ts.map +1 -1
  32. package/dist/index.d.ts +1 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +269 -149
  35. package/dist/models/config.d.ts +10 -3
  36. package/dist/models/config.d.ts.map +1 -1
  37. package/dist/models/embedded-flow.d.ts +1 -6
  38. package/dist/models/embedded-flow.d.ts.map +1 -1
  39. package/dist/models/store.d.ts +9 -1
  40. package/dist/models/store.d.ts.map +1 -1
  41. package/dist/models/v2/embedded-flow-v2.d.ts +22 -3
  42. package/dist/models/v2/embedded-flow-v2.d.ts.map +1 -1
  43. package/dist/models/v2/embedded-recovery-flow-v2.d.ts +4 -15
  44. package/dist/models/v2/embedded-recovery-flow-v2.d.ts.map +1 -1
  45. package/dist/models/v2/embedded-signin-flow-v2.d.ts +12 -7
  46. package/dist/models/v2/embedded-signin-flow-v2.d.ts.map +1 -1
  47. package/dist/models/v2/embedded-signup-flow-v2.d.ts +21 -54
  48. package/dist/models/v2/embedded-signup-flow-v2.d.ts.map +1 -1
  49. package/dist/theme/createTheme.d.ts.map +1 -1
  50. package/dist/utils/AuthenticationHelper.d.ts.map +1 -1
  51. package/dist/utils/deriveOrganizationHandleFromBaseUrl.d.ts +3 -11
  52. package/dist/utils/deriveOrganizationHandleFromBaseUrl.d.ts.map +1 -1
  53. package/dist/utils/identifyPlatform.d.ts.map +1 -1
  54. package/dist/utils/isRecognizedBaseUrlPattern.d.ts +1 -1
  55. package/dist/utils/parseApiErrorMessage.d.ts +1 -1
  56. package/dist/utils/v2/injectRequestedPermissions.d.ts +26 -0
  57. package/dist/utils/v2/injectRequestedPermissions.d.ts.map +1 -0
  58. package/package.json +5 -4
@@ -256,7 +256,7 @@ var ThunderIDError = class ThunderIDError extends Error {
256
256
  * The backend returns errors in the following form:
257
257
  * {"code":"...","message":{"key":"...","defaultValue":"..."},"description":{"key":"...","defaultValue":"..."}}
258
258
  *
259
- * Returns `description.defaultValue` if present, then `message.defaultValue`, and falls back
259
+ * Returns `message.defaultValue` if present, then `description.defaultValue`, and falls back
260
260
  * to the raw `errorText` when the response is not a recognised structured error.
261
261
  */
262
262
  const parseApiErrorMessage = (errorText) => {
@@ -264,8 +264,10 @@ const parseApiErrorMessage = (errorText) => {
264
264
  const parsed = JSON.parse(errorText);
265
265
  const description = parsed["description"];
266
266
  const message = parsed["message"];
267
- if (description?.defaultValue) return description.defaultValue;
268
- if (message?.defaultValue) return message.defaultValue;
267
+ const descFallback = description?.defaultValue;
268
+ const msgFallback = message?.defaultValue;
269
+ if (msgFallback) return msgFallback;
270
+ if (descFallback) return descFallback;
269
271
  } catch {}
270
272
  return errorText;
271
273
  };
@@ -339,7 +341,7 @@ var ThunderIDAPIError = class extends ThunderIDError {
339
341
  * ```typescript
340
342
  * try {
341
343
  * const authResponse = await initializeEmbeddedSignInFlow({
342
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/oauth2/authorize",
344
+ * url: "https://localhost:8090/oauth2/authorize",
343
345
  * payload: {
344
346
  * response_type: "code",
345
347
  * client_id: "your-client-id",
@@ -480,7 +482,7 @@ let EmbeddedFlowComponentType = /* @__PURE__ */ function(EmbeddedFlowComponentTy
480
482
  * ```typescript
481
483
  * try {
482
484
  * const embeddedSignUpResponse = await executeEmbeddedSignUpFlow({
483
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/api/server/v1/flow/execute",
485
+ * url: "https://localhost:8090/api/server/v1/flow/execute",
484
486
  * payload: {
485
487
  * flowType: "REGISTRATION"
486
488
  * }
@@ -532,7 +534,7 @@ var executeEmbeddedSignUpFlow_default = executeEmbeddedSignUpFlow;
532
534
  * @returns A promise that resolves with the user information.
533
535
  * @throw
534
536
  * const userInfo = await getUserInfo({
535
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/oauth2/userinfo",
537
+ * url: "https://localhost:8090/oauth2/userinfo",
536
538
  * });
537
539
  * console.log(userInfo);
538
540
  * } catch (error) {
@@ -667,7 +669,7 @@ var processUsername_default = processUsername;
667
669
  * // Using default fetch
668
670
  * try {
669
671
  * const userProfile = await getScim2Me({
670
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/scim2/Me",
672
+ * url: "https://localhost:8090/scim2/Me",
671
673
  * });
672
674
  * console.log(userProfile);
673
675
  * } catch (error) {
@@ -682,7 +684,7 @@ var processUsername_default = processUsername;
682
684
  * // Using custom fetcher (e.g., axios-based httpClient)
683
685
  * try {
684
686
  * const userProfile = await getScim2Me({
685
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/scim2/Me",
687
+ * url: "https://localhost:8090/scim2/Me",
686
688
  * fetcher: async (url, config) => {
687
689
  * const response = await httpClient({
688
690
  * url,
@@ -748,7 +750,7 @@ var getScim2Me_default = getScim2Me;
748
750
  * // Using default fetch
749
751
  * try {
750
752
  * const schemas = await getSchemas({
751
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/scim2/Schemas",
753
+ * url: "https://localhost:8090/scim2/Schemas",
752
754
  * });
753
755
  * console.log(schemas);
754
756
  * } catch (error) {
@@ -763,7 +765,7 @@ var getScim2Me_default = getScim2Me;
763
765
  * // Using custom fetcher (e.g., axios-based httpClient)
764
766
  * try {
765
767
  * const schemas = await getSchemas({
766
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/scim2/Schemas",
768
+ * url: "https://localhost:8090/scim2/Schemas",
767
769
  * fetcher: async (url, config) => {
768
770
  * const response = await httpClient({
769
771
  * url,
@@ -829,7 +831,7 @@ var getSchemas_default = getSchemas;
829
831
  * // Using default fetch
830
832
  * try {
831
833
  * const response = await getAllOrganizations({
832
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
834
+ * baseUrl: "https://localhost:8090",
833
835
  * filter: "",
834
836
  * limit: 10,
835
837
  * recursive: false
@@ -847,7 +849,7 @@ var getSchemas_default = getSchemas;
847
849
  * // Using custom fetcher (e.g., axios-based httpClient)
848
850
  * try {
849
851
  * const response = await getAllOrganizations({
850
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
852
+ * baseUrl: "https://localhost:8090",
851
853
  * filter: "",
852
854
  * limit: 10,
853
855
  * recursive: false,
@@ -927,7 +929,7 @@ var getAllOrganizations_default = getAllOrganizations;
927
929
  * // Using default fetch
928
930
  * try {
929
931
  * const organization = await createOrganization({
930
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
932
+ * baseUrl: "https://localhost:8090",
931
933
  * payload: {
932
934
  * description: "Share your screens",
933
935
  * name: "Team Viewer",
@@ -949,7 +951,7 @@ var getAllOrganizations_default = getAllOrganizations;
949
951
  * // Using custom fetcher (e.g., axios-based httpClient)
950
952
  * try {
951
953
  * const organization = await createOrganization({
952
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
954
+ * baseUrl: "https://localhost:8090",
953
955
  * payload: {
954
956
  * description: "Share your screens",
955
957
  * name: "Team Viewer",
@@ -1029,7 +1031,7 @@ var createOrganization_default = createOrganization;
1029
1031
  * // Using default fetch
1030
1032
  * try {
1031
1033
  * const organizations = await getMeOrganizations({
1032
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
1034
+ * baseUrl: "https://localhost:8090",
1033
1035
  * after: "",
1034
1036
  * before: "",
1035
1037
  * filter: "",
@@ -1049,7 +1051,7 @@ var createOrganization_default = createOrganization;
1049
1051
  * // Using custom fetcher (e.g., axios-based httpClient)
1050
1052
  * try {
1051
1053
  * const organizations = await getMeOrganizations({
1052
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
1054
+ * baseUrl: "https://localhost:8090",
1053
1055
  * after: "",
1054
1056
  * before: "",
1055
1057
  * filter: "",
@@ -1128,7 +1130,7 @@ var getMeOrganizations_default = getMeOrganizations;
1128
1130
  * // Using default fetch
1129
1131
  * try {
1130
1132
  * const organization = await getOrganization({
1131
- * baseUrl: "https://api.asgardeo.io/t/dxlab",
1133
+ * baseUrl: "https://localhost:8090",
1132
1134
  * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1"
1133
1135
  * });
1134
1136
  * console.log(organization);
@@ -1144,7 +1146,7 @@ var getMeOrganizations_default = getMeOrganizations;
1144
1146
  * // Using custom fetcher (e.g., axios-based httpClient)
1145
1147
  * try {
1146
1148
  * const organization = await getOrganization({
1147
- * baseUrl: "https://api.asgardeo.io/t/dxlab",
1149
+ * baseUrl: "https://localhost:8090",
1148
1150
  * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1",
1149
1151
  * fetcher: async (url, config) => {
1150
1152
  * const response = await httpClient({
@@ -1274,14 +1276,14 @@ var isEmpty_default = isEmpty;
1274
1276
  * });
1275
1277
  *
1276
1278
  * await updateOrganization({
1277
- * baseUrl: "https://api.asgardeo.io/t/<ORG>",
1279
+ * baseUrl: "https://localhost:8090",
1278
1280
  * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1",
1279
1281
  * operations
1280
1282
  * });
1281
1283
  *
1282
1284
  * // Or manually specify operations
1283
1285
  * await updateOrganization({
1284
- * baseUrl: "https://api.asgardeo.io/t/<ORG>",
1286
+ * baseUrl: "https://localhost:8090",
1285
1287
  * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1",
1286
1288
  * operations: [
1287
1289
  * { operation: "REPLACE", path: "/name", value: "Updated Organization Name" },
@@ -1294,7 +1296,7 @@ var isEmpty_default = isEmpty;
1294
1296
  * ```typescript
1295
1297
  * // Using custom fetcher (e.g., axios-based httpClient)
1296
1298
  * await updateOrganization({
1297
- * baseUrl: "https://api.asgardeo.io/t/<ORG>",
1299
+ * baseUrl: "https://localhost:8090",
1298
1300
  * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1",
1299
1301
  * operations: [
1300
1302
  * { operation: "REPLACE", path: "/name", value: "Updated Organization Name" }
@@ -1379,7 +1381,7 @@ var updateOrganization_default = updateOrganization;
1379
1381
  * ```typescript
1380
1382
  * // Using default fetch
1381
1383
  * await updateMeProfile({
1382
- * url: "https://api.asgardeo.io/t/<ORG>/scim2/Me",
1384
+ * url: "https://localhost:8090/scim2/Me",
1383
1385
  * payload: { "urn:scim:wso2:schema": { mobileNumbers: ["0777933830"] } }
1384
1386
  * });
1385
1387
  * ```
@@ -1388,7 +1390,7 @@ var updateOrganization_default = updateOrganization;
1388
1390
  * ```typescript
1389
1391
  * // Using custom fetcher (e.g., axios-based httpClient)
1390
1392
  * await updateMeProfile({
1391
- * url: "https://api.asgardeo.io/t/<ORG>/scim2/Me",
1393
+ * url: "https://localhost:8090/scim2/Me",
1392
1394
  * payload: { "urn:scim:wso2:schema": { mobileNumbers: ["0777933830"] } },
1393
1395
  * fetcher: async (url, config) => {
1394
1396
  * const response = await httpClient({
@@ -1845,7 +1847,7 @@ var ThunderIDRuntimeError = class extends ThunderIDError {
1845
1847
  * @returns boolean - true if sensible fallbacks can be used, false otherwise
1846
1848
  *
1847
1849
  * @example
1848
- * isRecognizedBaseUrlPattern('https://dev.asgardeo.io/t/dxlab'); // true
1850
+ * isRecognizedBaseUrlPattern('https://localhost:8090/t/dxlab'); // true
1849
1851
  * isRecognizedBaseUrlPattern('https://custom.example.com/auth'); // false
1850
1852
  */
1851
1853
  const isRecognizedBaseUrlPattern = (baseUrl) => {
@@ -1908,7 +1910,7 @@ var identifyPlatform_default = identifyPlatform;
1908
1910
  * // Using default fetch
1909
1911
  * try {
1910
1912
  * const response = await getBrandingPreference({
1911
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
1913
+ * baseUrl: "https://localhost:8090",
1912
1914
  * locale: "en-US",
1913
1915
  * name: "my-branding",
1914
1916
  * type: "org"
@@ -1926,7 +1928,7 @@ var identifyPlatform_default = identifyPlatform;
1926
1928
  * // Using custom fetcher (e.g., axios-based httpClient)
1927
1929
  * try {
1928
1930
  * const response = await getBrandingPreference({
1929
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
1931
+ * baseUrl: "https://localhost:8090",
1930
1932
  * locale: "en-US",
1931
1933
  * name: "my-branding",
1932
1934
  * type: "org",
@@ -2086,18 +2088,59 @@ let EmbeddedSignInFlowType$1 = /* @__PURE__ */ function(EmbeddedSignInFlowType$2
2086
2088
  return EmbeddedSignInFlowType$2;
2087
2089
  }({});
2088
2090
 
2091
+ //#endregion
2092
+ //#region src/utils/v2/injectRequestedPermissions.ts
2093
+ /**
2094
+ * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com).
2095
+ *
2096
+ * WSO2 LLC. licenses this file to you under the Apache License,
2097
+ * Version 2.0 (the "License"); you may not use this file except
2098
+ * in compliance with the License.
2099
+ * You may obtain a copy of the License at
2100
+ *
2101
+ * http://www.apache.org/licenses/LICENSE-2.0
2102
+ *
2103
+ * Unless required by applicable law or agreed to in writing,
2104
+ * software distributed under the License is distributed on an
2105
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
2106
+ * KIND, either express or implied. See the License for the
2107
+ * specific language governing permissions and limitations
2108
+ * under the License.
2109
+ */
2110
+ /**
2111
+ * Strips the top-level `scopes` field from a payload and injects it as
2112
+ * `inputs.requested_permissions` (space-separated string).
2113
+ *
2114
+ * The backend reads requested_permissions from UserInputs (the `inputs` map), not a top-level field.
2115
+ */
2116
+ const injectRequestedPermissions = (payload) => {
2117
+ const { scopes,...rest } = payload;
2118
+ const normalizedScopes = Array.isArray(scopes) ? scopes.map((s) => String(s).trim()).filter(Boolean).join(" ") : typeof scopes === "string" ? scopes.trim() : "";
2119
+ if (!normalizedScopes) return rest;
2120
+ const existingInputs = rest["inputs"] != null && typeof rest["inputs"] === "object" && !Array.isArray(rest["inputs"]) ? rest["inputs"] : {};
2121
+ return {
2122
+ ...rest,
2123
+ inputs: {
2124
+ ...existingInputs,
2125
+ requested_permissions: normalizedScopes
2126
+ }
2127
+ };
2128
+ };
2129
+ var injectRequestedPermissions_default = injectRequestedPermissions;
2130
+
2089
2131
  //#endregion
2090
2132
  //#region src/api/v2/executeEmbeddedSignInFlowV2.ts
2091
2133
  const executeEmbeddedSignInFlowV2 = async ({ url, baseUrl, payload, authId,...requestConfig }) => {
2092
2134
  if (!payload) throw new ThunderIDAPIError("Authorization payload is required", "executeEmbeddedSignInFlow-ValidationError-002", "javascript", 400, "If an authorization payload is not provided, the request cannot be constructed correctly.");
2093
2135
  const endpoint = url ?? `${baseUrl}/flow/execute`;
2094
2136
  const cleanPayload = typeof payload === "object" && payload !== null ? Object.fromEntries(Object.entries(payload).filter(([key]) => key !== "verbose")) : payload;
2095
- const hasOnlyAppIdAndFlowType = typeof cleanPayload === "object" && cleanPayload !== null && "applicationId" in cleanPayload && "flowType" in cleanPayload && Object.keys(cleanPayload).length === 2;
2137
+ const isNewFlowStart = typeof cleanPayload === "object" && cleanPayload !== null && "applicationId" in cleanPayload && "flowType" in cleanPayload;
2096
2138
  const hasOnlyFlowId = typeof cleanPayload === "object" && cleanPayload !== null && "executionId" in cleanPayload && Object.keys(cleanPayload).length === 1;
2097
- const requestPayload = hasOnlyAppIdAndFlowType || hasOnlyFlowId ? {
2098
- ...cleanPayload,
2139
+ const basePayload = isNewFlowStart ? injectRequestedPermissions_default(cleanPayload) : cleanPayload;
2140
+ const requestPayload = isNewFlowStart || hasOnlyFlowId ? {
2141
+ ...basePayload,
2099
2142
  verbose: true
2100
- } : cleanPayload;
2143
+ } : basePayload;
2101
2144
  const response = await fetch(endpoint, {
2102
2145
  ...requestConfig,
2103
2146
  body: JSON.stringify(requestPayload),
@@ -2124,14 +2167,15 @@ const executeEmbeddedSignInFlowV2 = async ({ url, baseUrl, payload, authId,...re
2124
2167
  },
2125
2168
  method: "POST"
2126
2169
  });
2127
- if (!oauth2Response.ok) throw new ThunderIDAPIError(`OAuth2 authorization failed: ${await oauth2Response.text()}`, "executeEmbeddedSignInFlow-OAuth2Error-002", "javascript", oauth2Response.status, oauth2Response.statusText);
2170
+ if (!oauth2Response.ok) throw new ThunderIDAPIError(await oauth2Response.text(), "executeEmbeddedSignInFlow-OAuth2Error-002", "javascript", oauth2Response.status, oauth2Response.statusText, "OAuth2 authorization failed");
2128
2171
  const oauth2Result = await oauth2Response.json();
2129
2172
  return {
2130
2173
  flowStatus: flowResponse.flowStatus,
2131
2174
  redirectUrl: oauth2Result["redirect_uri"]
2132
2175
  };
2133
2176
  } catch (authError) {
2134
- throw new ThunderIDAPIError(`OAuth2 authorization failed: ${authError instanceof Error ? authError.message : "Unknown error"}`, "executeEmbeddedSignInFlow-OAuth2Error-001", "javascript", 500, "Failed to complete OAuth2 authorization after successful embedded sign-in flow.");
2177
+ if (authError instanceof ThunderIDAPIError) throw authError;
2178
+ throw new ThunderIDAPIError(authError instanceof Error ? authError.message : "Unknown error", "executeEmbeddedSignInFlow-OAuth2Error-001", "javascript", 500, "Failed to complete OAuth2 authorization after successful embedded sign-in flow.", "OAuth2 authorization failed");
2135
2179
  }
2136
2180
  return flowResponse;
2137
2181
  };
@@ -2156,9 +2200,9 @@ var executeEmbeddedSignInFlowV2_default = executeEmbeddedSignInFlowV2;
2156
2200
  * // Registration successful - handle completion
2157
2201
  * break;
2158
2202
  * case EmbeddedSignUpFlowStatus.Error:
2159
- * // Registration failed - show detailed error message
2203
+ * // Registration failed - show error details
2160
2204
  * const errorResponse = response as EmbeddedSignUpFlowErrorResponse;
2161
- * showError(errorResponse.failureReason);
2205
+ * showError(errorResponse.error.description.defaultValue);
2162
2206
  * break;
2163
2207
  * }
2164
2208
  * ```
@@ -2230,12 +2274,13 @@ const executeEmbeddedSignUpFlowV2 = async ({ url, baseUrl, payload, authId,...re
2230
2274
  if (!payload) throw new ThunderIDAPIError("Registration payload is required", "executeEmbeddedSignUpFlow-ValidationError-002", "javascript", 400, "If a registration payload is not provided, the request cannot be constructed correctly.");
2231
2275
  const endpoint = url ?? `${baseUrl}/flow/execute`;
2232
2276
  const cleanPayload = typeof payload === "object" && payload !== null ? Object.fromEntries(Object.entries(payload).filter(([key]) => key !== "verbose")) : payload;
2233
- const hasOnlyAppIdAndFlowType = typeof cleanPayload === "object" && cleanPayload !== null && "applicationId" in cleanPayload && "flowType" in cleanPayload && Object.keys(cleanPayload).length === 2;
2277
+ const isNewFlowStart = typeof cleanPayload === "object" && cleanPayload !== null && "applicationId" in cleanPayload && "flowType" in cleanPayload;
2234
2278
  const hasOnlyFlowId = typeof cleanPayload === "object" && cleanPayload !== null && "executionId" in cleanPayload && Object.keys(cleanPayload).length === 1;
2235
- const requestPayload = hasOnlyAppIdAndFlowType || hasOnlyFlowId ? {
2236
- ...cleanPayload,
2279
+ const basePayload = isNewFlowStart ? injectRequestedPermissions_default(cleanPayload) : cleanPayload;
2280
+ const requestPayload = isNewFlowStart || hasOnlyFlowId ? {
2281
+ ...basePayload,
2237
2282
  verbose: true
2238
- } : cleanPayload;
2283
+ } : basePayload;
2239
2284
  const response = await fetch(endpoint, {
2240
2285
  ...requestConfig,
2241
2286
  body: JSON.stringify(requestPayload),
@@ -2262,14 +2307,15 @@ const executeEmbeddedSignUpFlowV2 = async ({ url, baseUrl, payload, authId,...re
2262
2307
  },
2263
2308
  method: "POST"
2264
2309
  });
2265
- if (!oauth2Response.ok) throw new ThunderIDAPIError(`OAuth2 authorization failed: ${await oauth2Response.text()}`, "executeEmbeddedSignUpFlow-OAuth2Error-002", "javascript", oauth2Response.status, oauth2Response.statusText);
2310
+ if (!oauth2Response.ok) throw new ThunderIDAPIError(await oauth2Response.text(), "executeEmbeddedSignUpFlow-OAuth2Error-002", "javascript", oauth2Response.status, oauth2Response.statusText, "OAuth2 authorization failed");
2266
2311
  const oauth2Result = await oauth2Response.json();
2267
2312
  return {
2268
2313
  flowStatus: flowResponse.flowStatus,
2269
2314
  redirectUrl: oauth2Result["redirect_uri"]
2270
2315
  };
2271
2316
  } catch (authError) {
2272
- throw new ThunderIDAPIError(`OAuth2 authorization failed: ${authError instanceof Error ? authError.message : "Unknown error"}`, "executeEmbeddedSignUpFlow-OAuth2Error-001", "javascript", 500, "Failed to complete OAuth2 authorization after successful embedded sign-up flow.");
2317
+ if (authError instanceof ThunderIDAPIError) throw authError;
2318
+ throw new ThunderIDAPIError(authError instanceof Error ? authError.message : "Unknown error", "executeEmbeddedSignUpFlow-OAuth2Error-001", "javascript", 500, "Failed to complete OAuth2 authorization after successful embedded sign-up flow.", "OAuth2 authorization failed");
2273
2319
  }
2274
2320
  return flowResponse;
2275
2321
  };
@@ -2293,7 +2339,7 @@ var executeEmbeddedSignUpFlowV2_default = executeEmbeddedSignUpFlowV2;
2293
2339
  * ```typescript
2294
2340
  * // Initiate recovery flow
2295
2341
  * const response = await executeEmbeddedRecoveryFlowV2({
2296
- * baseUrl: 'https://api.asgardeo.io/t/myorg',
2342
+ * baseUrl: 'https://localhost:8090',
2297
2343
  * payload: {
2298
2344
  * flowType: 'RECOVERY',
2299
2345
  * applicationId: 'my-app-id',
@@ -2302,7 +2348,7 @@ var executeEmbeddedSignUpFlowV2_default = executeEmbeddedSignUpFlowV2;
2302
2348
  *
2303
2349
  * // Continue recovery flow with user input
2304
2350
  * const nextResponse = await executeEmbeddedRecoveryFlowV2({
2305
- * baseUrl: 'https://api.asgardeo.io/t/myorg',
2351
+ * baseUrl: 'https://localhost:8090',
2306
2352
  * payload: {
2307
2353
  * executionId: response.executionId,
2308
2354
  * action: 'submit',
@@ -2332,7 +2378,7 @@ const executeEmbeddedRecoveryFlowV2 = async ({ url, baseUrl, payload,...requestC
2332
2378
  },
2333
2379
  method: requestConfig.method || "POST"
2334
2380
  });
2335
- if (!response.ok) throw new ThunderIDAPIError(`Recovery request failed: ${await response.text()}`, "executeEmbeddedRecoveryFlow-ResponseError-001", "javascript", response.status, response.statusText);
2381
+ if (!response.ok) throw new ThunderIDAPIError(await response.text(), "executeEmbeddedRecoveryFlow-ResponseError-001", "javascript", response.status, response.statusText, "Recovery request failed");
2336
2382
  return await response.json();
2337
2383
  };
2338
2384
  var executeEmbeddedRecoveryFlowV2_default = executeEmbeddedRecoveryFlowV2;
@@ -2747,6 +2793,8 @@ let EmbeddedFlowComponentType$1 = /* @__PURE__ */ function(EmbeddedFlowComponent
2747
2793
  EmbeddedFlowComponentType$2["TextInput"] = "TEXT_INPUT";
2748
2794
  /** Timer component for displaying a countdown */
2749
2795
  EmbeddedFlowComponentType$2["Timer"] = "TIMER";
2796
+ /** QR code display component for wallet-based flows (e.g. OpenID4VP) */
2797
+ EmbeddedFlowComponentType$2["QrCode"] = "QR_CODE";
2750
2798
  return EmbeddedFlowComponentType$2;
2751
2799
  }({});
2752
2800
  /**
@@ -3231,6 +3279,10 @@ let Stores = /* @__PURE__ */ function(Stores$1) {
3231
3279
  * Store for temporary data that needs to persist only for a short duration.
3232
3280
  */
3233
3281
  Stores$1["TemporaryData"] = "temporary_data";
3282
+ /**
3283
+ * Store for data that leverages local storage if available, falling back to the configured storage.
3284
+ */
3285
+ Stores$1["HybridData"] = "hybrid_data";
3234
3286
  return Stores$1;
3235
3287
  }({});
3236
3288
 
@@ -3292,7 +3344,18 @@ var StorageManager = class StorageManager {
3292
3344
  this.setDataInBulk(this.resolveKey(Stores.OIDCProviderMetaData), oidcProviderMetaData);
3293
3345
  }
3294
3346
  async setTemporaryData(temporaryData, userId) {
3295
- this.setDataInBulk(this.resolveKey(Stores.TemporaryData, userId), temporaryData);
3347
+ await this.setDataInBulk(this.resolveKey(Stores.TemporaryData, userId), temporaryData);
3348
+ }
3349
+ async setHybridData(hybridData, userId) {
3350
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3351
+ if (StorageManager.isLocalStorageAvailable()) {
3352
+ const existingDataJSON = localStorage.getItem(resolvedKey);
3353
+ const dataToBeSaved = {
3354
+ ...existingDataJSON ? JSON.parse(existingDataJSON) : {},
3355
+ ...hybridData
3356
+ };
3357
+ localStorage.setItem(resolvedKey, JSON.stringify(dataToBeSaved));
3358
+ } else await this.setDataInBulk(resolvedKey, hybridData);
3296
3359
  }
3297
3360
  async setSessionData(sessionData, userId) {
3298
3361
  this.setDataInBulk(this.resolveKey(Stores.SessionData, userId), sessionData);
@@ -3307,7 +3370,35 @@ var StorageManager = class StorageManager {
3307
3370
  return JSON.parse(await this.store.getData(this.resolveKey(Stores.OIDCProviderMetaData)) ?? null);
3308
3371
  }
3309
3372
  async getTemporaryData(userId) {
3310
- return JSON.parse(await this.store.getData(this.resolveKey(Stores.TemporaryData, userId)) ?? null);
3373
+ const data = await this.store.getData(this.resolveKey(Stores.TemporaryData, userId));
3374
+ if (data) try {
3375
+ return JSON.parse(data);
3376
+ } catch (error$1) {
3377
+ logger_default.error(`StorageManager: Failed to parse temporary data for key ${this.resolveKey(Stores.TemporaryData, userId)}`, error$1);
3378
+ return {};
3379
+ }
3380
+ return {};
3381
+ }
3382
+ async getHybridData(userId) {
3383
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3384
+ if (StorageManager.isLocalStorageAvailable()) {
3385
+ const storeDataJSON$1 = localStorage.getItem(resolvedKey);
3386
+ if (storeDataJSON$1) try {
3387
+ return JSON.parse(storeDataJSON$1);
3388
+ } catch (error$1) {
3389
+ logger_default.error(`StorageManager: Failed to parse hybrid data from local storage for key ${resolvedKey}`, error$1);
3390
+ return {};
3391
+ }
3392
+ return {};
3393
+ }
3394
+ const storeDataJSON = await this.store.getData(resolvedKey) ?? null;
3395
+ if (storeDataJSON) try {
3396
+ return JSON.parse(storeDataJSON);
3397
+ } catch (error$1) {
3398
+ logger_default.error(`StorageManager: Failed to parse hybrid data from store for key ${resolvedKey}`, error$1);
3399
+ return {};
3400
+ }
3401
+ return {};
3311
3402
  }
3312
3403
  async getPersistedData(userId) {
3313
3404
  return JSON.parse(await this.store.getData(this.resolveKey(Stores.PersistedData, userId)) ?? null);
@@ -3339,6 +3430,11 @@ var StorageManager = class StorageManager {
3339
3430
  async removeTemporaryData(userId) {
3340
3431
  await this.store.removeData(this.resolveKey(Stores.TemporaryData, userId));
3341
3432
  }
3433
+ async removeHybridData(userId) {
3434
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3435
+ if (StorageManager.isLocalStorageAvailable()) localStorage.removeItem(resolvedKey);
3436
+ else await this.store.removeData(resolvedKey);
3437
+ }
3342
3438
  async removeSessionData(userId) {
3343
3439
  await this.store.removeData(this.resolveKey(Stores.SessionData, userId));
3344
3440
  }
@@ -3354,6 +3450,15 @@ var StorageManager = class StorageManager {
3354
3450
  const data = await this.store.getData(this.resolveKey(Stores.TemporaryData, userId));
3355
3451
  return data && JSON.parse(data)[key];
3356
3452
  }
3453
+ async getHybridDataParameter(key, userId) {
3454
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3455
+ if (StorageManager.isLocalStorageAvailable()) {
3456
+ const existingDataJSON = localStorage.getItem(resolvedKey);
3457
+ return (existingDataJSON ? JSON.parse(existingDataJSON) : {})[key];
3458
+ }
3459
+ const data = await this.store.getData(resolvedKey);
3460
+ return data && JSON.parse(data)[key];
3461
+ }
3357
3462
  async getSessionDataParameter(key, userId) {
3358
3463
  const data = await this.store.getData(this.resolveKey(Stores.SessionData, userId));
3359
3464
  return data && JSON.parse(data)[key];
@@ -3367,6 +3472,17 @@ var StorageManager = class StorageManager {
3367
3472
  async setTemporaryDataParameter(key, value, userId) {
3368
3473
  await this.setValue(this.resolveKey(Stores.TemporaryData, userId), key, value);
3369
3474
  }
3475
+ async setHybridDataParameter(key, value, userId) {
3476
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3477
+ if (StorageManager.isLocalStorageAvailable()) {
3478
+ const existingDataJSON = localStorage.getItem(resolvedKey);
3479
+ const dataToBeSaved = {
3480
+ ...existingDataJSON ? JSON.parse(existingDataJSON) : {},
3481
+ [key]: value
3482
+ };
3483
+ localStorage.setItem(resolvedKey, JSON.stringify(dataToBeSaved));
3484
+ } else await this.setValue(resolvedKey, key, value);
3485
+ }
3370
3486
  async setSessionDataParameter(key, value, userId) {
3371
3487
  await this.setValue(this.resolveKey(Stores.SessionData, userId), key, value);
3372
3488
  }
@@ -3379,56 +3495,21 @@ var StorageManager = class StorageManager {
3379
3495
  async removeTemporaryDataParameter(key, userId) {
3380
3496
  await this.removeValue(this.resolveKey(Stores.TemporaryData, userId), key);
3381
3497
  }
3498
+ async removeHybridDataParameter(key, userId) {
3499
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3500
+ if (StorageManager.isLocalStorageAvailable()) {
3501
+ const existingDataJSON = localStorage.getItem(resolvedKey);
3502
+ const existingData = existingDataJSON ? JSON.parse(existingDataJSON) : {};
3503
+ delete existingData[key];
3504
+ localStorage.setItem(resolvedKey, JSON.stringify(existingData));
3505
+ } else await this.removeValue(resolvedKey, key);
3506
+ }
3382
3507
  async removeSessionDataParameter(key, userId) {
3383
3508
  await this.removeValue(this.resolveKey(Stores.SessionData, userId), key);
3384
3509
  }
3385
3510
  };
3386
3511
  var StorageManager_default = StorageManager;
3387
3512
 
3388
- //#endregion
3389
- //#region src/constants/TokenExchangeConstants.ts
3390
- /**
3391
- * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3392
- *
3393
- * WSO2 LLC. licenses this file to you under the Apache License,
3394
- * Version 2.0 (the "License"); you may not use this file except
3395
- * in compliance with the License.
3396
- * You may obtain a copy of the License at
3397
- *
3398
- * http://www.apache.org/licenses/LICENSE-2.0
3399
- *
3400
- * Unless required by applicable law or agreed to in writing,
3401
- * software distributed under the License is distributed on an
3402
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
3403
- * KIND, either express or implied. See the License for the
3404
- * specific language governing permissions and limitations
3405
- * under the License.
3406
- */
3407
- /**
3408
- * Constants for OAuth 2.0 Token Exchange operations.
3409
- * This object contains placeholders used in token exchange requests
3410
- * and responses for dynamic value substitution.
3411
- *
3412
- * @remarks
3413
- * These placeholders are used in token exchange templates and are replaced
3414
- * with actual values during request processing. They help in creating
3415
- * flexible and reusable token exchange configurations.
3416
- *
3417
- * @example
3418
- * ```typescript
3419
- * // Using placeholders in a token exchange template
3420
- * const template = `grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=${TokenExchangeConstants.Placeholders.TOKEN}`;
3421
- * ```
3422
- */
3423
- const TokenExchangeConstants = { Placeholders: {
3424
- ACCESS_TOKEN: "{{accessToken}}",
3425
- CLIENT_ID: "{{clientId}}",
3426
- CLIENT_SECRET: "{{clientSecret}}",
3427
- SCOPES: "{{scopes}}",
3428
- USERNAME: "{{username}}"
3429
- } };
3430
- var TokenExchangeConstants_default = TokenExchangeConstants;
3431
-
3432
3513
  //#endregion
3433
3514
  //#region src/utils/extractUserClaimsFromIdToken.ts
3434
3515
  /**
@@ -3524,6 +3605,50 @@ const processOpenIDScopes = (scopes) => {
3524
3605
  };
3525
3606
  var processOpenIDScopes_default = processOpenIDScopes;
3526
3607
 
3608
+ //#endregion
3609
+ //#region src/constants/TokenExchangeConstants.ts
3610
+ /**
3611
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3612
+ *
3613
+ * WSO2 LLC. licenses this file to you under the Apache License,
3614
+ * Version 2.0 (the "License"); you may not use this file except
3615
+ * in compliance with the License.
3616
+ * You may obtain a copy of the License at
3617
+ *
3618
+ * http://www.apache.org/licenses/LICENSE-2.0
3619
+ *
3620
+ * Unless required by applicable law or agreed to in writing,
3621
+ * software distributed under the License is distributed on an
3622
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
3623
+ * KIND, either express or implied. See the License for the
3624
+ * specific language governing permissions and limitations
3625
+ * under the License.
3626
+ */
3627
+ /**
3628
+ * Constants for OAuth 2.0 Token Exchange operations.
3629
+ * This object contains placeholders used in token exchange requests
3630
+ * and responses for dynamic value substitution.
3631
+ *
3632
+ * @remarks
3633
+ * These placeholders are used in token exchange templates and are replaced
3634
+ * with actual values during request processing. They help in creating
3635
+ * flexible and reusable token exchange configurations.
3636
+ *
3637
+ * @example
3638
+ * ```typescript
3639
+ * // Using placeholders in a token exchange template
3640
+ * const template = `grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=${TokenExchangeConstants.Placeholders.TOKEN}`;
3641
+ * ```
3642
+ */
3643
+ const TokenExchangeConstants = { Placeholders: {
3644
+ ACCESS_TOKEN: "{{accessToken}}",
3645
+ CLIENT_ID: "{{clientId}}",
3646
+ CLIENT_SECRET: "{{clientSecret}}",
3647
+ SCOPES: "{{scopes}}",
3648
+ USERNAME: "{{username}}"
3649
+ } };
3650
+ var TokenExchangeConstants_default = TokenExchangeConstants;
3651
+
3527
3652
  //#endregion
3528
3653
  //#region src/utils/AuthenticationHelper.ts
3529
3654
  /**
@@ -3649,7 +3774,7 @@ var AuthenticationHelper = class {
3649
3774
  const { issuer } = await this.oidcProviderMetaData();
3650
3775
  const { keys } = await response.json();
3651
3776
  const jwk = await this.cryptoHelper.getJWKForTheIdToken(idToken.split(".")[0], keys);
3652
- return this.cryptoHelper.isValidIdToken(idToken, jwk, (await this.config()).clientId, issuer ?? "", this.cryptoHelper.decodeJwtToken(idToken).sub, (await this.config()).tokenValidation?.idToken?.clockTolerance, (await this.config()).tokenValidation?.idToken?.validateIssuer ?? true);
3777
+ return this.cryptoHelper.isValidIdToken(idToken, jwk, (await this.config()).clientId ?? "", issuer ?? "", this.cryptoHelper.decodeJwtToken(idToken).sub, (await this.config()).tokenValidation?.idToken?.clockTolerance, (await this.config()).tokenValidation?.idToken?.validateIssuer ?? true);
3653
3778
  }
3654
3779
  /**
3655
3780
  * Extracts user information from a decoded ID token payload.
@@ -3691,7 +3816,7 @@ var AuthenticationHelper = class {
3691
3816
  } else sessionData = await this.storageManager.getSessionData(userId);
3692
3817
  const scope = processOpenIDScopes_default(configData.scopes);
3693
3818
  if (typeof text !== "string") return text;
3694
- return text.replace(TokenExchangeConstants_default.Placeholders.ACCESS_TOKEN, sessionData.access_token).replace(TokenExchangeConstants_default.Placeholders.USERNAME, this.getAuthenticatedUserInfo(sessionData.id_token).username).replace(TokenExchangeConstants_default.Placeholders.SCOPES, scope).replace(TokenExchangeConstants_default.Placeholders.CLIENT_ID, configData.clientId).replace(TokenExchangeConstants_default.Placeholders.CLIENT_SECRET, configData.clientSecret ?? "");
3819
+ return text.replace(TokenExchangeConstants_default.Placeholders.ACCESS_TOKEN, sessionData.access_token).replace(TokenExchangeConstants_default.Placeholders.USERNAME, this.getAuthenticatedUserInfo(sessionData.id_token).username ?? "").replace(TokenExchangeConstants_default.Placeholders.SCOPES, scope).replace(TokenExchangeConstants_default.Placeholders.CLIENT_ID, configData.clientId ?? "").replace(TokenExchangeConstants_default.Placeholders.CLIENT_SECRET, configData.clientSecret ?? "");
3695
3820
  }
3696
3821
  /**
3697
3822
  * Clears all temporary and session data for the given user.
@@ -3940,7 +4065,7 @@ const getAuthorizeRequestUrlParams = (options, pkceOptions, customParams) => {
3940
4065
  const authorizeRequestParams = /* @__PURE__ */ new Map();
3941
4066
  authorizeRequestParams.set("response_type", "code");
3942
4067
  authorizeRequestParams.set("client_id", clientId);
3943
- authorizeRequestParams.set("scope", scopes);
4068
+ authorizeRequestParams.set("scope", scopes ?? "");
3944
4069
  authorizeRequestParams.set("redirect_uri", redirectUri);
3945
4070
  if (responseMode) authorizeRequestParams.set("response_mode", responseMode);
3946
4071
  const pkceKey = pkceOptions?.key;
@@ -4007,13 +4132,11 @@ var ThunderIDJavaScriptClient = class {
4007
4132
  if (persistedData?.["applicationId"]) resolvedApplicationId = persistedData["applicationId"];
4008
4133
  }
4009
4134
  const resolvedEndpoints = endpoints ? { ...endpoints } : {};
4010
- await this.storageManager.setConfigData({
4011
- ...DEFAULT_CONFIG,
4012
- ...fullConfig,
4135
+ await this.storageManager.setConfigData(deepMerge_default({}, DEFAULT_CONFIG, fullConfig, {
4013
4136
  applicationId: resolvedApplicationId,
4014
4137
  endpoints: resolvedEndpoints,
4015
4138
  scope: processOpenIDScopes_default(fullConfig.scopes)
4016
- });
4139
+ }));
4017
4140
  this.baseURL = fullConfig.baseUrl ?? "";
4018
4141
  return true;
4019
4142
  }
@@ -4161,19 +4284,19 @@ var ThunderIDJavaScriptClient = class {
4161
4284
  if (configData.enablePKCE) {
4162
4285
  codeVerifier = this.cryptoHelper?.getCodeVerifier();
4163
4286
  codeChallenge = await this.cryptoHelper?.getCodeChallenge(codeVerifier);
4164
- await this.storageManager.setTemporaryDataParameter(pkceKey, codeVerifier, userId);
4287
+ await this.storageManager.setHybridDataParameter(pkceKey, codeVerifier, userId);
4165
4288
  }
4166
- if (authRequestConfig["client_secret"]) authRequestConfig["client_secret"] = configData.clientSecret;
4167
- const authorizeRequestParams = getAuthorizeRequestUrlParams_default({
4168
- clientId: configData.clientId,
4289
+ if (authRequestConfig["client_secret"]) authRequestConfig["client_secret"] = configData.clientSecret ?? "";
4290
+ const authorizeRequestParams = getAuthorizeRequestUrlParams_default(Object.fromEntries(Object.entries({
4291
+ clientId: configData.clientId ?? "",
4169
4292
  codeChallenge,
4170
4293
  codeChallengeMethod: PKCEConstants_default.DEFAULT_CODE_CHALLENGE_METHOD,
4171
4294
  instanceId: this.getInstanceId().toString(),
4172
4295
  prompt: configData.prompt,
4173
- redirectUri: configData.afterSignInUrl,
4296
+ redirectUri: configData.afterSignInUrl ?? "",
4174
4297
  responseMode: configData.responseMode,
4175
4298
  scopes: processOpenIDScopes_default(configData.scopes)
4176
- }, { key: pkceKey }, authRequestConfig);
4299
+ }).filter(([, v]) => v !== void 0)), { key: pkceKey }, authRequestConfig);
4177
4300
  Array.from(authorizeRequestParams.entries()).forEach(([paramKey, paramValue]) => {
4178
4301
  authorizeRequest.searchParams.append(paramKey, paramValue);
4179
4302
  });
@@ -4189,19 +4312,19 @@ var ThunderIDJavaScriptClient = class {
4189
4312
  if (!tokenEndpoint || tokenEndpoint.trim().length === 0) throw new ThunderIDAuthException("JS-AUTH_CORE-RAT1-NF01", "Token endpoint not found.", "No token endpoint was found in the OIDC provider meta data returned by the well-known endpoint or the token endpoint passed to the SDK is empty.");
4190
4313
  if (sessionState) await this.storageManager.setSessionDataParameter(OIDCRequestConstants_default.Params.SESSION_STATE, sessionState, userId);
4191
4314
  const body = new URLSearchParams();
4192
- body.set("client_id", configData.clientId);
4315
+ body.set("client_id", configData.clientId ?? "");
4193
4316
  const hasSecret = Boolean(configData.clientSecret && configData.clientSecret.trim().length > 0);
4194
4317
  const tokenEndpointAuthMethod = configData.tokenRequest?.authMethod ?? "client_secret_basic";
4195
4318
  if (hasSecret && tokenEndpointAuthMethod === "client_secret_post") body.set("client_secret", configData.clientSecret);
4196
4319
  body.set("code", authorizationCode);
4197
4320
  body.set("grant_type", "authorization_code");
4198
- body.set("redirect_uri", configData.afterSignInUrl);
4321
+ body.set("redirect_uri", configData.afterSignInUrl ?? "");
4199
4322
  if (tokenRequestConfig?.params) Object.entries(tokenRequestConfig.params).forEach(([key, value]) => {
4200
4323
  body.append(key, value);
4201
4324
  });
4202
4325
  if (configData.enablePKCE) {
4203
- body.set("code_verifier", `${await this.storageManager.getTemporaryDataParameter(extractPkceStorageKeyFromState_default(state), userId)}`);
4204
- await this.storageManager.removeTemporaryDataParameter(extractPkceStorageKeyFromState_default(state), userId);
4326
+ body.set("code_verifier", `${await this.storageManager.getHybridDataParameter(extractPkceStorageKeyFromState_default(state), userId)}`);
4327
+ await this.storageManager.removeHybridDataParameter(extractPkceStorageKeyFromState_default(state), userId);
4205
4328
  }
4206
4329
  const tokenRequestHeaders = {
4207
4330
  Accept: "application/json",
@@ -4234,7 +4357,7 @@ var ThunderIDJavaScriptClient = class {
4234
4357
  const idToken = (await this.storageManager.getSessionData(userId))?.id_token;
4235
4358
  if (!idToken || idToken.trim().length === 0) throw new ThunderIDAuthException("JS-AUTH_CORE-GSOU-NF02", "ID token not found.", "No ID token could be found. Either the session information is lost or you have not signed in.");
4236
4359
  queryParams.set("id_token_hint", idToken);
4237
- } else queryParams.set("client_id", configData.clientId);
4360
+ } else queryParams.set("client_id", configData.clientId ?? "");
4238
4361
  queryParams.set("state", OIDCRequestConstants_default.Params.SIGN_OUT_SUCCESS);
4239
4362
  return `${logoutEndpoint}?${queryParams.toString()}`;
4240
4363
  }
@@ -4329,10 +4452,10 @@ var ThunderIDJavaScriptClient = class {
4329
4452
  return response;
4330
4453
  }
4331
4454
  async getPKCECode(state, userId) {
4332
- return await this.storageManager.getTemporaryDataParameter(extractPkceStorageKeyFromState_default(state), userId);
4455
+ return await this.storageManager.getHybridDataParameter(extractPkceStorageKeyFromState_default(state), userId);
4333
4456
  }
4334
4457
  async setPKCECode(pkce, state, userId) {
4335
- return this.storageManager.setTemporaryDataParameter(extractPkceStorageKeyFromState_default(state), pkce, userId);
4458
+ return this.storageManager.setHybridDataParameter(extractPkceStorageKeyFromState_default(state), pkce, userId);
4336
4459
  }
4337
4460
  getInstanceId() {
4338
4461
  return this.instanceIdValue;
@@ -4663,12 +4786,15 @@ const toCssVariables = (theme) => {
4663
4786
  if (theme.typography?.lineHeights?.tight !== void 0) cssVars[`--${prefix}-typography-lineHeight-tight`] = theme.typography.lineHeights.tight.toString();
4664
4787
  if (theme.typography?.lineHeights?.normal !== void 0) cssVars[`--${prefix}-typography-lineHeight-normal`] = theme.typography.lineHeights.normal.toString();
4665
4788
  if (theme.typography?.lineHeights?.relaxed !== void 0) cssVars[`--${prefix}-typography-lineHeight-relaxed`] = theme.typography.lineHeights.relaxed.toString();
4666
- if (theme.images) Object.keys(theme.images).forEach((imageKey) => {
4667
- const imageConfig = theme.images[imageKey];
4668
- if (imageConfig?.url) cssVars[`--${prefix}-image-${imageKey}-url`] = imageConfig.url;
4669
- if (imageConfig?.title) cssVars[`--${prefix}-image-${imageKey}-title`] = imageConfig.title;
4670
- if (imageConfig?.alt) cssVars[`--${prefix}-image-${imageKey}-alt`] = imageConfig.alt;
4671
- });
4789
+ if (theme.images) {
4790
+ const themeImages = theme.images;
4791
+ Object.keys(themeImages).forEach((imageKey) => {
4792
+ const imageConfig = themeImages[imageKey];
4793
+ if (imageConfig?.url) cssVars[`--${prefix}-image-${imageKey}-url`] = imageConfig.url;
4794
+ if (imageConfig?.title) cssVars[`--${prefix}-image-${imageKey}-title`] = imageConfig.title;
4795
+ if (imageConfig?.alt) cssVars[`--${prefix}-image-${imageKey}-alt`] = imageConfig.alt;
4796
+ });
4797
+ }
4672
4798
  if (theme.components?.Button?.styleOverrides?.root?.borderRadius) cssVars[`--${prefix}-component-button-root-borderRadius`] = theme.components.Button.styleOverrides.root.borderRadius;
4673
4799
  if (theme.components?.Field?.styleOverrides?.root?.borderRadius) cssVars[`--${prefix}-component-field-root-borderRadius`] = theme.components.Field.styleOverrides.root.borderRadius;
4674
4800
  return cssVars;
@@ -4765,9 +4891,11 @@ const toThemeVars = (theme) => {
4765
4891
  };
4766
4892
  if (theme.images) {
4767
4893
  themeVars.images = {};
4768
- Object.keys(theme.images).forEach((imageKey) => {
4769
- const imageConfig = theme.images[imageKey];
4770
- themeVars.images[imageKey] = {
4894
+ const themeImages = theme.images;
4895
+ const imageVars = themeVars.images;
4896
+ Object.keys(themeImages).forEach((imageKey) => {
4897
+ const imageConfig = themeImages[imageKey];
4898
+ imageVars[imageKey] = {
4771
4899
  alt: imageConfig?.alt ? `var(--${prefix}-image-${imageKey}-alt)` : void 0,
4772
4900
  title: imageConfig?.title ? `var(--${prefix}-image-${imageKey}-title)` : void 0,
4773
4901
  url: imageConfig?.url ? `var(--${prefix}-image-${imageKey}-url)` : void 0
@@ -5061,13 +5189,9 @@ var formatDate_default = formatDate;
5061
5189
  //#endregion
5062
5190
  //#region src/utils/deriveOrganizationHandleFromBaseUrl.ts
5063
5191
  /**
5064
- * Extracts the organization handle from an ThunderID base URL.
5192
+ * Extracts the organization handle from a ThunderID base URL.
5065
5193
  *
5066
- * This function parses ThunderID URLs with the standard pattern:
5067
- * - https://dev.asgardeo.io/t/{orgHandle}
5068
- * - https://stage.asgardeo.io/t/{orgHandle}
5069
- * - https://prod.asgardeo.io/t/{orgHandle}
5070
- * - https://{subdomain}.asgardeo.io/t/{orgHandle}
5194
+ * Parses URLs following the `/t/{orgHandle}` pattern.
5071
5195
  *
5072
5196
  * @param baseUrl - The base URL of the ThunderID identity server
5073
5197
  * @returns The extracted organization handle
@@ -5076,13 +5200,9 @@ var formatDate_default = formatDate;
5076
5200
  *
5077
5201
  * @example
5078
5202
  * ```typescript
5079
- * // Standard ThunderID URLs
5080
- * const handle1 = deriveOrganizationHandleFromBaseUrl('https://dev.asgardeo.io/t/dxlab');
5203
+ * const handle = deriveOrganizationHandleFromBaseUrl('https://localhost:8090/t/dxlab');
5081
5204
  * // Returns: 'dxlab'
5082
5205
  *
5083
- * const handle2 = deriveOrganizationHandleFromBaseUrl('https://stage.asgardeo.io/t/myorg');
5084
- * // Returns: 'myorg'
5085
- *
5086
5206
  * // Custom domain - returns empty string with a warning
5087
5207
  * const handle2 = deriveOrganizationHandleFromBaseUrl('https://custom.example.com/auth');
5088
5208
  * // Returns: '' and logs a warning
@@ -5907,7 +6027,7 @@ var withVendorCSSClassPrefix_default = withVendorCSSClassPrefix;
5907
6027
  //#endregion
5908
6028
  //#region src/utils/transformBrandingPreferenceToTheme.ts
5909
6029
  const extractColorValue = (colorVariant, preferDark = false) => {
5910
- if (preferDark && colorVariant?.dark && colorVariant.dark.trim()) return colorVariant.dark;
6030
+ if (preferDark && colorVariant?.dark?.trim()) return colorVariant.dark;
5911
6031
  return colorVariant?.main;
5912
6032
  };
5913
6033
  /**
@@ -5940,47 +6060,47 @@ const transformThemeVariant = (themeVariant, isDark = false) => {
5940
6060
  background: {
5941
6061
  body: {
5942
6062
  dark: (colors?.background?.body)?.dark || (colors?.background?.body)?.main,
5943
- main: extractColorValue(colors?.background?.body, isDark)
6063
+ main: extractColorValue(colors?.background?.body, isDark) ?? ""
5944
6064
  },
5945
6065
  dark: (colors?.background?.surface)?.dark || (colors?.background?.surface)?.main,
5946
- disabled: extractColorValue(colors?.background?.surface, isDark),
5947
- surface: extractColorValue(colors?.background?.surface, isDark)
6066
+ disabled: extractColorValue(colors?.background?.surface, isDark) ?? "",
6067
+ surface: extractColorValue(colors?.background?.surface, isDark) ?? ""
5948
6068
  },
5949
- border: colors?.outlined?.default,
6069
+ border: colors?.outlined?.default ?? "",
5950
6070
  error: {
5951
- contrastText: extractContrastText(colors?.alerts?.error),
6071
+ contrastText: extractContrastText(colors?.alerts?.error) ?? "",
5952
6072
  dark: (colors?.alerts?.error)?.dark || (colors?.alerts?.error)?.main,
5953
- main: extractColorValue(colors?.alerts?.error, isDark)
6073
+ main: extractColorValue(colors?.alerts?.error, isDark) ?? ""
5954
6074
  },
5955
6075
  info: {
5956
- contrastText: extractContrastText(colors?.alerts?.info),
6076
+ contrastText: extractContrastText(colors?.alerts?.info) ?? "",
5957
6077
  dark: (colors?.alerts?.info)?.dark || (colors?.alerts?.info)?.main,
5958
- main: extractColorValue(colors?.alerts?.info, isDark)
6078
+ main: extractColorValue(colors?.alerts?.info, isDark) ?? ""
5959
6079
  },
5960
6080
  primary: {
5961
- contrastText: extractContrastText(colors?.primary),
6081
+ contrastText: extractContrastText(colors?.primary) ?? "",
5962
6082
  dark: colors?.primary?.dark || (colors?.primary)?.main,
5963
- main: extractColorValue(colors?.primary, isDark)
6083
+ main: extractColorValue(colors?.primary, isDark) ?? ""
5964
6084
  },
5965
6085
  secondary: {
5966
- contrastText: extractContrastText(colors?.secondary),
6086
+ contrastText: extractContrastText(colors?.secondary) ?? "",
5967
6087
  dark: colors?.secondary?.dark || (colors?.secondary)?.main,
5968
- main: extractColorValue(colors?.secondary, isDark)
6088
+ main: extractColorValue(colors?.secondary, isDark) ?? ""
5969
6089
  },
5970
6090
  success: {
5971
- contrastText: extractContrastText(colors?.alerts?.neutral),
6091
+ contrastText: extractContrastText(colors?.alerts?.neutral) ?? "",
5972
6092
  dark: (colors?.alerts?.neutral)?.dark || (colors?.alerts?.neutral)?.main,
5973
- main: extractColorValue(colors?.alerts?.neutral, isDark)
6093
+ main: extractColorValue(colors?.alerts?.neutral, isDark) ?? ""
5974
6094
  },
5975
6095
  text: {
5976
6096
  dark: (colors?.text)?.dark || (colors?.text)?.primary,
5977
- primary: (colors?.text)?.primary,
5978
- secondary: (colors?.text)?.secondary
6097
+ primary: (colors?.text)?.primary ?? "",
6098
+ secondary: (colors?.text)?.secondary ?? ""
5979
6099
  },
5980
6100
  warning: {
5981
- contrastText: extractContrastText(colors?.alerts?.warning),
6101
+ contrastText: extractContrastText(colors?.alerts?.warning) ?? "",
5982
6102
  dark: (colors?.alerts?.warning)?.dark || (colors?.alerts?.warning)?.main,
5983
- main: extractColorValue(colors?.alerts?.warning, isDark)
6103
+ main: extractColorValue(colors?.alerts?.warning, isDark) ?? ""
5984
6104
  }
5985
6105
  },
5986
6106
  images: {
@@ -6118,7 +6238,7 @@ var HttpClient = class HttpClient {
6118
6238
  return (array) => callback(...array);
6119
6239
  }
6120
6240
  async requestHandler(config) {
6121
- await this.attachToken(config);
6241
+ if (config.attachToken !== false) await this.attachToken(config);
6122
6242
  if (config.shouldEncodeToFormData && config.data) {
6123
6243
  const formData = new FormData();
6124
6244
  Object.keys(config.data).forEach((key) => formData.append(key, config.data[key]));