@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
@@ -276,7 +276,7 @@ var ThunderIDError = class ThunderIDError extends Error {
276
276
  * The backend returns errors in the following form:
277
277
  * {"code":"...","message":{"key":"...","defaultValue":"..."},"description":{"key":"...","defaultValue":"..."}}
278
278
  *
279
- * Returns `description.defaultValue` if present, then `message.defaultValue`, and falls back
279
+ * Returns `message.defaultValue` if present, then `description.defaultValue`, and falls back
280
280
  * to the raw `errorText` when the response is not a recognised structured error.
281
281
  */
282
282
  const parseApiErrorMessage = (errorText) => {
@@ -284,8 +284,10 @@ const parseApiErrorMessage = (errorText) => {
284
284
  const parsed = JSON.parse(errorText);
285
285
  const description = parsed["description"];
286
286
  const message = parsed["message"];
287
- if (description?.defaultValue) return description.defaultValue;
288
- if (message?.defaultValue) return message.defaultValue;
287
+ const descFallback = description?.defaultValue;
288
+ const msgFallback = message?.defaultValue;
289
+ if (msgFallback) return msgFallback;
290
+ if (descFallback) return descFallback;
289
291
  } catch {}
290
292
  return errorText;
291
293
  };
@@ -359,7 +361,7 @@ var ThunderIDAPIError = class extends ThunderIDError {
359
361
  * ```typescript
360
362
  * try {
361
363
  * const authResponse = await initializeEmbeddedSignInFlow({
362
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/oauth2/authorize",
364
+ * url: "https://localhost:8090/oauth2/authorize",
363
365
  * payload: {
364
366
  * response_type: "code",
365
367
  * client_id: "your-client-id",
@@ -500,7 +502,7 @@ let EmbeddedFlowComponentType = /* @__PURE__ */ function(EmbeddedFlowComponentTy
500
502
  * ```typescript
501
503
  * try {
502
504
  * const embeddedSignUpResponse = await executeEmbeddedSignUpFlow({
503
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/api/server/v1/flow/execute",
505
+ * url: "https://localhost:8090/api/server/v1/flow/execute",
504
506
  * payload: {
505
507
  * flowType: "REGISTRATION"
506
508
  * }
@@ -552,7 +554,7 @@ var executeEmbeddedSignUpFlow_default = executeEmbeddedSignUpFlow;
552
554
  * @returns A promise that resolves with the user information.
553
555
  * @throw
554
556
  * const userInfo = await getUserInfo({
555
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/oauth2/userinfo",
557
+ * url: "https://localhost:8090/oauth2/userinfo",
556
558
  * });
557
559
  * console.log(userInfo);
558
560
  * } catch (error) {
@@ -687,7 +689,7 @@ var processUsername_default = processUsername;
687
689
  * // Using default fetch
688
690
  * try {
689
691
  * const userProfile = await getScim2Me({
690
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/scim2/Me",
692
+ * url: "https://localhost:8090/scim2/Me",
691
693
  * });
692
694
  * console.log(userProfile);
693
695
  * } catch (error) {
@@ -702,7 +704,7 @@ var processUsername_default = processUsername;
702
704
  * // Using custom fetcher (e.g., axios-based httpClient)
703
705
  * try {
704
706
  * const userProfile = await getScim2Me({
705
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/scim2/Me",
707
+ * url: "https://localhost:8090/scim2/Me",
706
708
  * fetcher: async (url, config) => {
707
709
  * const response = await httpClient({
708
710
  * url,
@@ -768,7 +770,7 @@ var getScim2Me_default = getScim2Me;
768
770
  * // Using default fetch
769
771
  * try {
770
772
  * const schemas = await getSchemas({
771
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/scim2/Schemas",
773
+ * url: "https://localhost:8090/scim2/Schemas",
772
774
  * });
773
775
  * console.log(schemas);
774
776
  * } catch (error) {
@@ -783,7 +785,7 @@ var getScim2Me_default = getScim2Me;
783
785
  * // Using custom fetcher (e.g., axios-based httpClient)
784
786
  * try {
785
787
  * const schemas = await getSchemas({
786
- * url: "https://api.asgardeo.io/t/<ORGANIZATION>/scim2/Schemas",
788
+ * url: "https://localhost:8090/scim2/Schemas",
787
789
  * fetcher: async (url, config) => {
788
790
  * const response = await httpClient({
789
791
  * url,
@@ -849,7 +851,7 @@ var getSchemas_default = getSchemas;
849
851
  * // Using default fetch
850
852
  * try {
851
853
  * const response = await getAllOrganizations({
852
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
854
+ * baseUrl: "https://localhost:8090",
853
855
  * filter: "",
854
856
  * limit: 10,
855
857
  * recursive: false
@@ -867,7 +869,7 @@ var getSchemas_default = getSchemas;
867
869
  * // Using custom fetcher (e.g., axios-based httpClient)
868
870
  * try {
869
871
  * const response = await getAllOrganizations({
870
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
872
+ * baseUrl: "https://localhost:8090",
871
873
  * filter: "",
872
874
  * limit: 10,
873
875
  * recursive: false,
@@ -947,7 +949,7 @@ var getAllOrganizations_default = getAllOrganizations;
947
949
  * // Using default fetch
948
950
  * try {
949
951
  * const organization = await createOrganization({
950
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
952
+ * baseUrl: "https://localhost:8090",
951
953
  * payload: {
952
954
  * description: "Share your screens",
953
955
  * name: "Team Viewer",
@@ -969,7 +971,7 @@ var getAllOrganizations_default = getAllOrganizations;
969
971
  * // Using custom fetcher (e.g., axios-based httpClient)
970
972
  * try {
971
973
  * const organization = await createOrganization({
972
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
974
+ * baseUrl: "https://localhost:8090",
973
975
  * payload: {
974
976
  * description: "Share your screens",
975
977
  * name: "Team Viewer",
@@ -1049,7 +1051,7 @@ var createOrganization_default = createOrganization;
1049
1051
  * // Using default fetch
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: "",
@@ -1069,7 +1071,7 @@ var createOrganization_default = createOrganization;
1069
1071
  * // Using custom fetcher (e.g., axios-based httpClient)
1070
1072
  * try {
1071
1073
  * const organizations = await getMeOrganizations({
1072
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
1074
+ * baseUrl: "https://localhost:8090",
1073
1075
  * after: "",
1074
1076
  * before: "",
1075
1077
  * filter: "",
@@ -1148,7 +1150,7 @@ var getMeOrganizations_default = getMeOrganizations;
1148
1150
  * // Using default fetch
1149
1151
  * try {
1150
1152
  * const organization = await getOrganization({
1151
- * baseUrl: "https://api.asgardeo.io/t/dxlab",
1153
+ * baseUrl: "https://localhost:8090",
1152
1154
  * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1"
1153
1155
  * });
1154
1156
  * console.log(organization);
@@ -1164,7 +1166,7 @@ var getMeOrganizations_default = getMeOrganizations;
1164
1166
  * // Using custom fetcher (e.g., axios-based httpClient)
1165
1167
  * try {
1166
1168
  * const organization = await getOrganization({
1167
- * baseUrl: "https://api.asgardeo.io/t/dxlab",
1169
+ * baseUrl: "https://localhost:8090",
1168
1170
  * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1",
1169
1171
  * fetcher: async (url, config) => {
1170
1172
  * const response = await httpClient({
@@ -1294,14 +1296,14 @@ var isEmpty_default = isEmpty;
1294
1296
  * });
1295
1297
  *
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
  * });
1301
1303
  *
1302
1304
  * // Or manually specify operations
1303
1305
  * await updateOrganization({
1304
- * baseUrl: "https://api.asgardeo.io/t/<ORG>",
1306
+ * baseUrl: "https://localhost:8090",
1305
1307
  * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1",
1306
1308
  * operations: [
1307
1309
  * { operation: "REPLACE", path: "/name", value: "Updated Organization Name" },
@@ -1314,7 +1316,7 @@ var isEmpty_default = isEmpty;
1314
1316
  * ```typescript
1315
1317
  * // Using custom fetcher (e.g., axios-based httpClient)
1316
1318
  * await updateOrganization({
1317
- * baseUrl: "https://api.asgardeo.io/t/<ORG>",
1319
+ * baseUrl: "https://localhost:8090",
1318
1320
  * organizationId: "0d5e071b-d3d3-475d-b3c6-1a20ee2fa9b1",
1319
1321
  * operations: [
1320
1322
  * { operation: "REPLACE", path: "/name", value: "Updated Organization Name" }
@@ -1399,7 +1401,7 @@ var updateOrganization_default = updateOrganization;
1399
1401
  * ```typescript
1400
1402
  * // Using default fetch
1401
1403
  * await updateMeProfile({
1402
- * url: "https://api.asgardeo.io/t/<ORG>/scim2/Me",
1404
+ * url: "https://localhost:8090/scim2/Me",
1403
1405
  * payload: { "urn:scim:wso2:schema": { mobileNumbers: ["0777933830"] } }
1404
1406
  * });
1405
1407
  * ```
@@ -1408,7 +1410,7 @@ var updateOrganization_default = updateOrganization;
1408
1410
  * ```typescript
1409
1411
  * // Using custom fetcher (e.g., axios-based httpClient)
1410
1412
  * await updateMeProfile({
1411
- * url: "https://api.asgardeo.io/t/<ORG>/scim2/Me",
1413
+ * url: "https://localhost:8090/scim2/Me",
1412
1414
  * payload: { "urn:scim:wso2:schema": { mobileNumbers: ["0777933830"] } },
1413
1415
  * fetcher: async (url, config) => {
1414
1416
  * const response = await httpClient({
@@ -1865,7 +1867,7 @@ var ThunderIDRuntimeError = class extends ThunderIDError {
1865
1867
  * @returns boolean - true if sensible fallbacks can be used, false otherwise
1866
1868
  *
1867
1869
  * @example
1868
- * isRecognizedBaseUrlPattern('https://dev.asgardeo.io/t/dxlab'); // true
1870
+ * isRecognizedBaseUrlPattern('https://localhost:8090/t/dxlab'); // true
1869
1871
  * isRecognizedBaseUrlPattern('https://custom.example.com/auth'); // false
1870
1872
  */
1871
1873
  const isRecognizedBaseUrlPattern = (baseUrl) => {
@@ -1928,7 +1930,7 @@ var identifyPlatform_default = identifyPlatform;
1928
1930
  * // Using default fetch
1929
1931
  * try {
1930
1932
  * const response = await getBrandingPreference({
1931
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
1933
+ * baseUrl: "https://localhost:8090",
1932
1934
  * locale: "en-US",
1933
1935
  * name: "my-branding",
1934
1936
  * type: "org"
@@ -1946,7 +1948,7 @@ var identifyPlatform_default = identifyPlatform;
1946
1948
  * // Using custom fetcher (e.g., axios-based httpClient)
1947
1949
  * try {
1948
1950
  * const response = await getBrandingPreference({
1949
- * baseUrl: "https://api.asgardeo.io/t/<ORGANIZATION>",
1951
+ * baseUrl: "https://localhost:8090",
1950
1952
  * locale: "en-US",
1951
1953
  * name: "my-branding",
1952
1954
  * type: "org",
@@ -2106,18 +2108,59 @@ let EmbeddedSignInFlowType$1 = /* @__PURE__ */ function(EmbeddedSignInFlowType$2
2106
2108
  return EmbeddedSignInFlowType$2;
2107
2109
  }({});
2108
2110
 
2111
+ //#endregion
2112
+ //#region src/utils/v2/injectRequestedPermissions.ts
2113
+ /**
2114
+ * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com).
2115
+ *
2116
+ * WSO2 LLC. licenses this file to you under the Apache License,
2117
+ * Version 2.0 (the "License"); you may not use this file except
2118
+ * in compliance with the License.
2119
+ * You may obtain a copy of the License at
2120
+ *
2121
+ * http://www.apache.org/licenses/LICENSE-2.0
2122
+ *
2123
+ * Unless required by applicable law or agreed to in writing,
2124
+ * software distributed under the License is distributed on an
2125
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
2126
+ * KIND, either express or implied. See the License for the
2127
+ * specific language governing permissions and limitations
2128
+ * under the License.
2129
+ */
2130
+ /**
2131
+ * Strips the top-level `scopes` field from a payload and injects it as
2132
+ * `inputs.requested_permissions` (space-separated string).
2133
+ *
2134
+ * The backend reads requested_permissions from UserInputs (the `inputs` map), not a top-level field.
2135
+ */
2136
+ const injectRequestedPermissions = (payload) => {
2137
+ const { scopes,...rest } = payload;
2138
+ const normalizedScopes = Array.isArray(scopes) ? scopes.map((s) => String(s).trim()).filter(Boolean).join(" ") : typeof scopes === "string" ? scopes.trim() : "";
2139
+ if (!normalizedScopes) return rest;
2140
+ const existingInputs = rest["inputs"] != null && typeof rest["inputs"] === "object" && !Array.isArray(rest["inputs"]) ? rest["inputs"] : {};
2141
+ return {
2142
+ ...rest,
2143
+ inputs: {
2144
+ ...existingInputs,
2145
+ requested_permissions: normalizedScopes
2146
+ }
2147
+ };
2148
+ };
2149
+ var injectRequestedPermissions_default = injectRequestedPermissions;
2150
+
2109
2151
  //#endregion
2110
2152
  //#region src/api/v2/executeEmbeddedSignInFlowV2.ts
2111
2153
  const executeEmbeddedSignInFlowV2 = async ({ url, baseUrl, payload, authId,...requestConfig }) => {
2112
2154
  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.");
2113
2155
  const endpoint = url ?? `${baseUrl}/flow/execute`;
2114
2156
  const cleanPayload = typeof payload === "object" && payload !== null ? Object.fromEntries(Object.entries(payload).filter(([key]) => key !== "verbose")) : payload;
2115
- const hasOnlyAppIdAndFlowType = typeof cleanPayload === "object" && cleanPayload !== null && "applicationId" in cleanPayload && "flowType" in cleanPayload && Object.keys(cleanPayload).length === 2;
2157
+ const isNewFlowStart = typeof cleanPayload === "object" && cleanPayload !== null && "applicationId" in cleanPayload && "flowType" in cleanPayload;
2116
2158
  const hasOnlyFlowId = typeof cleanPayload === "object" && cleanPayload !== null && "executionId" in cleanPayload && Object.keys(cleanPayload).length === 1;
2117
- const requestPayload = hasOnlyAppIdAndFlowType || hasOnlyFlowId ? {
2118
- ...cleanPayload,
2159
+ const basePayload = isNewFlowStart ? injectRequestedPermissions_default(cleanPayload) : cleanPayload;
2160
+ const requestPayload = isNewFlowStart || hasOnlyFlowId ? {
2161
+ ...basePayload,
2119
2162
  verbose: true
2120
- } : cleanPayload;
2163
+ } : basePayload;
2121
2164
  const response = await fetch(endpoint, {
2122
2165
  ...requestConfig,
2123
2166
  body: JSON.stringify(requestPayload),
@@ -2144,14 +2187,15 @@ const executeEmbeddedSignInFlowV2 = async ({ url, baseUrl, payload, authId,...re
2144
2187
  },
2145
2188
  method: "POST"
2146
2189
  });
2147
- if (!oauth2Response.ok) throw new ThunderIDAPIError(`OAuth2 authorization failed: ${await oauth2Response.text()}`, "executeEmbeddedSignInFlow-OAuth2Error-002", "javascript", oauth2Response.status, oauth2Response.statusText);
2190
+ if (!oauth2Response.ok) throw new ThunderIDAPIError(await oauth2Response.text(), "executeEmbeddedSignInFlow-OAuth2Error-002", "javascript", oauth2Response.status, oauth2Response.statusText, "OAuth2 authorization failed");
2148
2191
  const oauth2Result = await oauth2Response.json();
2149
2192
  return {
2150
2193
  flowStatus: flowResponse.flowStatus,
2151
2194
  redirectUrl: oauth2Result["redirect_uri"]
2152
2195
  };
2153
2196
  } catch (authError) {
2154
- 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.");
2197
+ if (authError instanceof ThunderIDAPIError) throw authError;
2198
+ 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");
2155
2199
  }
2156
2200
  return flowResponse;
2157
2201
  };
@@ -2176,9 +2220,9 @@ var executeEmbeddedSignInFlowV2_default = executeEmbeddedSignInFlowV2;
2176
2220
  * // Registration successful - handle completion
2177
2221
  * break;
2178
2222
  * case EmbeddedSignUpFlowStatus.Error:
2179
- * // Registration failed - show detailed error message
2223
+ * // Registration failed - show error details
2180
2224
  * const errorResponse = response as EmbeddedSignUpFlowErrorResponse;
2181
- * showError(errorResponse.failureReason);
2225
+ * showError(errorResponse.error.description.defaultValue);
2182
2226
  * break;
2183
2227
  * }
2184
2228
  * ```
@@ -2250,12 +2294,13 @@ const executeEmbeddedSignUpFlowV2 = async ({ url, baseUrl, payload, authId,...re
2250
2294
  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.");
2251
2295
  const endpoint = url ?? `${baseUrl}/flow/execute`;
2252
2296
  const cleanPayload = typeof payload === "object" && payload !== null ? Object.fromEntries(Object.entries(payload).filter(([key]) => key !== "verbose")) : payload;
2253
- const hasOnlyAppIdAndFlowType = typeof cleanPayload === "object" && cleanPayload !== null && "applicationId" in cleanPayload && "flowType" in cleanPayload && Object.keys(cleanPayload).length === 2;
2297
+ const isNewFlowStart = typeof cleanPayload === "object" && cleanPayload !== null && "applicationId" in cleanPayload && "flowType" in cleanPayload;
2254
2298
  const hasOnlyFlowId = typeof cleanPayload === "object" && cleanPayload !== null && "executionId" in cleanPayload && Object.keys(cleanPayload).length === 1;
2255
- const requestPayload = hasOnlyAppIdAndFlowType || hasOnlyFlowId ? {
2256
- ...cleanPayload,
2299
+ const basePayload = isNewFlowStart ? injectRequestedPermissions_default(cleanPayload) : cleanPayload;
2300
+ const requestPayload = isNewFlowStart || hasOnlyFlowId ? {
2301
+ ...basePayload,
2257
2302
  verbose: true
2258
- } : cleanPayload;
2303
+ } : basePayload;
2259
2304
  const response = await fetch(endpoint, {
2260
2305
  ...requestConfig,
2261
2306
  body: JSON.stringify(requestPayload),
@@ -2282,14 +2327,15 @@ const executeEmbeddedSignUpFlowV2 = async ({ url, baseUrl, payload, authId,...re
2282
2327
  },
2283
2328
  method: "POST"
2284
2329
  });
2285
- if (!oauth2Response.ok) throw new ThunderIDAPIError(`OAuth2 authorization failed: ${await oauth2Response.text()}`, "executeEmbeddedSignUpFlow-OAuth2Error-002", "javascript", oauth2Response.status, oauth2Response.statusText);
2330
+ if (!oauth2Response.ok) throw new ThunderIDAPIError(await oauth2Response.text(), "executeEmbeddedSignUpFlow-OAuth2Error-002", "javascript", oauth2Response.status, oauth2Response.statusText, "OAuth2 authorization failed");
2286
2331
  const oauth2Result = await oauth2Response.json();
2287
2332
  return {
2288
2333
  flowStatus: flowResponse.flowStatus,
2289
2334
  redirectUrl: oauth2Result["redirect_uri"]
2290
2335
  };
2291
2336
  } catch (authError) {
2292
- 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.");
2337
+ if (authError instanceof ThunderIDAPIError) throw authError;
2338
+ 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");
2293
2339
  }
2294
2340
  return flowResponse;
2295
2341
  };
@@ -2313,7 +2359,7 @@ var executeEmbeddedSignUpFlowV2_default = executeEmbeddedSignUpFlowV2;
2313
2359
  * ```typescript
2314
2360
  * // Initiate recovery flow
2315
2361
  * const response = await executeEmbeddedRecoveryFlowV2({
2316
- * baseUrl: 'https://api.asgardeo.io/t/myorg',
2362
+ * baseUrl: 'https://localhost:8090',
2317
2363
  * payload: {
2318
2364
  * flowType: 'RECOVERY',
2319
2365
  * applicationId: 'my-app-id',
@@ -2322,7 +2368,7 @@ var executeEmbeddedSignUpFlowV2_default = executeEmbeddedSignUpFlowV2;
2322
2368
  *
2323
2369
  * // Continue recovery flow with user input
2324
2370
  * const nextResponse = await executeEmbeddedRecoveryFlowV2({
2325
- * baseUrl: 'https://api.asgardeo.io/t/myorg',
2371
+ * baseUrl: 'https://localhost:8090',
2326
2372
  * payload: {
2327
2373
  * executionId: response.executionId,
2328
2374
  * action: 'submit',
@@ -2352,7 +2398,7 @@ const executeEmbeddedRecoveryFlowV2 = async ({ url, baseUrl, payload,...requestC
2352
2398
  },
2353
2399
  method: requestConfig.method || "POST"
2354
2400
  });
2355
- if (!response.ok) throw new ThunderIDAPIError(`Recovery request failed: ${await response.text()}`, "executeEmbeddedRecoveryFlow-ResponseError-001", "javascript", response.status, response.statusText);
2401
+ if (!response.ok) throw new ThunderIDAPIError(await response.text(), "executeEmbeddedRecoveryFlow-ResponseError-001", "javascript", response.status, response.statusText, "Recovery request failed");
2356
2402
  return await response.json();
2357
2403
  };
2358
2404
  var executeEmbeddedRecoveryFlowV2_default = executeEmbeddedRecoveryFlowV2;
@@ -2767,6 +2813,8 @@ let EmbeddedFlowComponentType$1 = /* @__PURE__ */ function(EmbeddedFlowComponent
2767
2813
  EmbeddedFlowComponentType$2["TextInput"] = "TEXT_INPUT";
2768
2814
  /** Timer component for displaying a countdown */
2769
2815
  EmbeddedFlowComponentType$2["Timer"] = "TIMER";
2816
+ /** QR code display component for wallet-based flows (e.g. OpenID4VP) */
2817
+ EmbeddedFlowComponentType$2["QrCode"] = "QR_CODE";
2770
2818
  return EmbeddedFlowComponentType$2;
2771
2819
  }({});
2772
2820
  /**
@@ -3251,6 +3299,10 @@ let Stores = /* @__PURE__ */ function(Stores$1) {
3251
3299
  * Store for temporary data that needs to persist only for a short duration.
3252
3300
  */
3253
3301
  Stores$1["TemporaryData"] = "temporary_data";
3302
+ /**
3303
+ * Store for data that leverages local storage if available, falling back to the configured storage.
3304
+ */
3305
+ Stores$1["HybridData"] = "hybrid_data";
3254
3306
  return Stores$1;
3255
3307
  }({});
3256
3308
 
@@ -3312,7 +3364,18 @@ var StorageManager = class StorageManager {
3312
3364
  this.setDataInBulk(this.resolveKey(Stores.OIDCProviderMetaData), oidcProviderMetaData);
3313
3365
  }
3314
3366
  async setTemporaryData(temporaryData, userId) {
3315
- this.setDataInBulk(this.resolveKey(Stores.TemporaryData, userId), temporaryData);
3367
+ await this.setDataInBulk(this.resolveKey(Stores.TemporaryData, userId), temporaryData);
3368
+ }
3369
+ async setHybridData(hybridData, userId) {
3370
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3371
+ if (StorageManager.isLocalStorageAvailable()) {
3372
+ const existingDataJSON = localStorage.getItem(resolvedKey);
3373
+ const dataToBeSaved = {
3374
+ ...existingDataJSON ? JSON.parse(existingDataJSON) : {},
3375
+ ...hybridData
3376
+ };
3377
+ localStorage.setItem(resolvedKey, JSON.stringify(dataToBeSaved));
3378
+ } else await this.setDataInBulk(resolvedKey, hybridData);
3316
3379
  }
3317
3380
  async setSessionData(sessionData, userId) {
3318
3381
  this.setDataInBulk(this.resolveKey(Stores.SessionData, userId), sessionData);
@@ -3327,7 +3390,35 @@ var StorageManager = class StorageManager {
3327
3390
  return JSON.parse(await this.store.getData(this.resolveKey(Stores.OIDCProviderMetaData)) ?? null);
3328
3391
  }
3329
3392
  async getTemporaryData(userId) {
3330
- return JSON.parse(await this.store.getData(this.resolveKey(Stores.TemporaryData, userId)) ?? null);
3393
+ const data = await this.store.getData(this.resolveKey(Stores.TemporaryData, userId));
3394
+ if (data) try {
3395
+ return JSON.parse(data);
3396
+ } catch (error$1) {
3397
+ logger_default.error(`StorageManager: Failed to parse temporary data for key ${this.resolveKey(Stores.TemporaryData, userId)}`, error$1);
3398
+ return {};
3399
+ }
3400
+ return {};
3401
+ }
3402
+ async getHybridData(userId) {
3403
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3404
+ if (StorageManager.isLocalStorageAvailable()) {
3405
+ const storeDataJSON$1 = localStorage.getItem(resolvedKey);
3406
+ if (storeDataJSON$1) try {
3407
+ return JSON.parse(storeDataJSON$1);
3408
+ } catch (error$1) {
3409
+ logger_default.error(`StorageManager: Failed to parse hybrid data from local storage for key ${resolvedKey}`, error$1);
3410
+ return {};
3411
+ }
3412
+ return {};
3413
+ }
3414
+ const storeDataJSON = await this.store.getData(resolvedKey) ?? null;
3415
+ if (storeDataJSON) try {
3416
+ return JSON.parse(storeDataJSON);
3417
+ } catch (error$1) {
3418
+ logger_default.error(`StorageManager: Failed to parse hybrid data from store for key ${resolvedKey}`, error$1);
3419
+ return {};
3420
+ }
3421
+ return {};
3331
3422
  }
3332
3423
  async getPersistedData(userId) {
3333
3424
  return JSON.parse(await this.store.getData(this.resolveKey(Stores.PersistedData, userId)) ?? null);
@@ -3359,6 +3450,11 @@ var StorageManager = class StorageManager {
3359
3450
  async removeTemporaryData(userId) {
3360
3451
  await this.store.removeData(this.resolveKey(Stores.TemporaryData, userId));
3361
3452
  }
3453
+ async removeHybridData(userId) {
3454
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3455
+ if (StorageManager.isLocalStorageAvailable()) localStorage.removeItem(resolvedKey);
3456
+ else await this.store.removeData(resolvedKey);
3457
+ }
3362
3458
  async removeSessionData(userId) {
3363
3459
  await this.store.removeData(this.resolveKey(Stores.SessionData, userId));
3364
3460
  }
@@ -3374,6 +3470,15 @@ var StorageManager = class StorageManager {
3374
3470
  const data = await this.store.getData(this.resolveKey(Stores.TemporaryData, userId));
3375
3471
  return data && JSON.parse(data)[key];
3376
3472
  }
3473
+ async getHybridDataParameter(key, userId) {
3474
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3475
+ if (StorageManager.isLocalStorageAvailable()) {
3476
+ const existingDataJSON = localStorage.getItem(resolvedKey);
3477
+ return (existingDataJSON ? JSON.parse(existingDataJSON) : {})[key];
3478
+ }
3479
+ const data = await this.store.getData(resolvedKey);
3480
+ return data && JSON.parse(data)[key];
3481
+ }
3377
3482
  async getSessionDataParameter(key, userId) {
3378
3483
  const data = await this.store.getData(this.resolveKey(Stores.SessionData, userId));
3379
3484
  return data && JSON.parse(data)[key];
@@ -3387,6 +3492,17 @@ var StorageManager = class StorageManager {
3387
3492
  async setTemporaryDataParameter(key, value, userId) {
3388
3493
  await this.setValue(this.resolveKey(Stores.TemporaryData, userId), key, value);
3389
3494
  }
3495
+ async setHybridDataParameter(key, value, userId) {
3496
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3497
+ if (StorageManager.isLocalStorageAvailable()) {
3498
+ const existingDataJSON = localStorage.getItem(resolvedKey);
3499
+ const dataToBeSaved = {
3500
+ ...existingDataJSON ? JSON.parse(existingDataJSON) : {},
3501
+ [key]: value
3502
+ };
3503
+ localStorage.setItem(resolvedKey, JSON.stringify(dataToBeSaved));
3504
+ } else await this.setValue(resolvedKey, key, value);
3505
+ }
3390
3506
  async setSessionDataParameter(key, value, userId) {
3391
3507
  await this.setValue(this.resolveKey(Stores.SessionData, userId), key, value);
3392
3508
  }
@@ -3399,56 +3515,21 @@ var StorageManager = class StorageManager {
3399
3515
  async removeTemporaryDataParameter(key, userId) {
3400
3516
  await this.removeValue(this.resolveKey(Stores.TemporaryData, userId), key);
3401
3517
  }
3518
+ async removeHybridDataParameter(key, userId) {
3519
+ const resolvedKey = this.resolveKey(Stores.HybridData, userId);
3520
+ if (StorageManager.isLocalStorageAvailable()) {
3521
+ const existingDataJSON = localStorage.getItem(resolvedKey);
3522
+ const existingData = existingDataJSON ? JSON.parse(existingDataJSON) : {};
3523
+ delete existingData[key];
3524
+ localStorage.setItem(resolvedKey, JSON.stringify(existingData));
3525
+ } else await this.removeValue(resolvedKey, key);
3526
+ }
3402
3527
  async removeSessionDataParameter(key, userId) {
3403
3528
  await this.removeValue(this.resolveKey(Stores.SessionData, userId), key);
3404
3529
  }
3405
3530
  };
3406
3531
  var StorageManager_default = StorageManager;
3407
3532
 
3408
- //#endregion
3409
- //#region src/constants/TokenExchangeConstants.ts
3410
- /**
3411
- * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3412
- *
3413
- * WSO2 LLC. licenses this file to you under the Apache License,
3414
- * Version 2.0 (the "License"); you may not use this file except
3415
- * in compliance with the License.
3416
- * You may obtain a copy of the License at
3417
- *
3418
- * http://www.apache.org/licenses/LICENSE-2.0
3419
- *
3420
- * Unless required by applicable law or agreed to in writing,
3421
- * software distributed under the License is distributed on an
3422
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
3423
- * KIND, either express or implied. See the License for the
3424
- * specific language governing permissions and limitations
3425
- * under the License.
3426
- */
3427
- /**
3428
- * Constants for OAuth 2.0 Token Exchange operations.
3429
- * This object contains placeholders used in token exchange requests
3430
- * and responses for dynamic value substitution.
3431
- *
3432
- * @remarks
3433
- * These placeholders are used in token exchange templates and are replaced
3434
- * with actual values during request processing. They help in creating
3435
- * flexible and reusable token exchange configurations.
3436
- *
3437
- * @example
3438
- * ```typescript
3439
- * // Using placeholders in a token exchange template
3440
- * const template = `grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=${TokenExchangeConstants.Placeholders.TOKEN}`;
3441
- * ```
3442
- */
3443
- const TokenExchangeConstants = { Placeholders: {
3444
- ACCESS_TOKEN: "{{accessToken}}",
3445
- CLIENT_ID: "{{clientId}}",
3446
- CLIENT_SECRET: "{{clientSecret}}",
3447
- SCOPES: "{{scopes}}",
3448
- USERNAME: "{{username}}"
3449
- } };
3450
- var TokenExchangeConstants_default = TokenExchangeConstants;
3451
-
3452
3533
  //#endregion
3453
3534
  //#region src/utils/extractUserClaimsFromIdToken.ts
3454
3535
  /**
@@ -3544,6 +3625,50 @@ const processOpenIDScopes = (scopes) => {
3544
3625
  };
3545
3626
  var processOpenIDScopes_default = processOpenIDScopes;
3546
3627
 
3628
+ //#endregion
3629
+ //#region src/constants/TokenExchangeConstants.ts
3630
+ /**
3631
+ * Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3632
+ *
3633
+ * WSO2 LLC. licenses this file to you under the Apache License,
3634
+ * Version 2.0 (the "License"); you may not use this file except
3635
+ * in compliance with the License.
3636
+ * You may obtain a copy of the License at
3637
+ *
3638
+ * http://www.apache.org/licenses/LICENSE-2.0
3639
+ *
3640
+ * Unless required by applicable law or agreed to in writing,
3641
+ * software distributed under the License is distributed on an
3642
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
3643
+ * KIND, either express or implied. See the License for the
3644
+ * specific language governing permissions and limitations
3645
+ * under the License.
3646
+ */
3647
+ /**
3648
+ * Constants for OAuth 2.0 Token Exchange operations.
3649
+ * This object contains placeholders used in token exchange requests
3650
+ * and responses for dynamic value substitution.
3651
+ *
3652
+ * @remarks
3653
+ * These placeholders are used in token exchange templates and are replaced
3654
+ * with actual values during request processing. They help in creating
3655
+ * flexible and reusable token exchange configurations.
3656
+ *
3657
+ * @example
3658
+ * ```typescript
3659
+ * // Using placeholders in a token exchange template
3660
+ * const template = `grant_type=urn:ietf:params:oauth:grant-type:token-exchange&subject_token=${TokenExchangeConstants.Placeholders.TOKEN}`;
3661
+ * ```
3662
+ */
3663
+ const TokenExchangeConstants = { Placeholders: {
3664
+ ACCESS_TOKEN: "{{accessToken}}",
3665
+ CLIENT_ID: "{{clientId}}",
3666
+ CLIENT_SECRET: "{{clientSecret}}",
3667
+ SCOPES: "{{scopes}}",
3668
+ USERNAME: "{{username}}"
3669
+ } };
3670
+ var TokenExchangeConstants_default = TokenExchangeConstants;
3671
+
3547
3672
  //#endregion
3548
3673
  //#region src/utils/AuthenticationHelper.ts
3549
3674
  /**
@@ -3669,7 +3794,7 @@ var AuthenticationHelper = class {
3669
3794
  const { issuer } = await this.oidcProviderMetaData();
3670
3795
  const { keys } = await response.json();
3671
3796
  const jwk = await this.cryptoHelper.getJWKForTheIdToken(idToken.split(".")[0], keys);
3672
- 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);
3797
+ 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);
3673
3798
  }
3674
3799
  /**
3675
3800
  * Extracts user information from a decoded ID token payload.
@@ -3711,7 +3836,7 @@ var AuthenticationHelper = class {
3711
3836
  } else sessionData = await this.storageManager.getSessionData(userId);
3712
3837
  const scope = processOpenIDScopes_default(configData.scopes);
3713
3838
  if (typeof text !== "string") return text;
3714
- 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 ?? "");
3839
+ 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 ?? "");
3715
3840
  }
3716
3841
  /**
3717
3842
  * Clears all temporary and session data for the given user.
@@ -3960,7 +4085,7 @@ const getAuthorizeRequestUrlParams = (options, pkceOptions, customParams) => {
3960
4085
  const authorizeRequestParams = /* @__PURE__ */ new Map();
3961
4086
  authorizeRequestParams.set("response_type", "code");
3962
4087
  authorizeRequestParams.set("client_id", clientId);
3963
- authorizeRequestParams.set("scope", scopes);
4088
+ authorizeRequestParams.set("scope", scopes ?? "");
3964
4089
  authorizeRequestParams.set("redirect_uri", redirectUri);
3965
4090
  if (responseMode) authorizeRequestParams.set("response_mode", responseMode);
3966
4091
  const pkceKey = pkceOptions?.key;
@@ -4027,13 +4152,11 @@ var ThunderIDJavaScriptClient = class {
4027
4152
  if (persistedData?.["applicationId"]) resolvedApplicationId = persistedData["applicationId"];
4028
4153
  }
4029
4154
  const resolvedEndpoints = endpoints ? { ...endpoints } : {};
4030
- await this.storageManager.setConfigData({
4031
- ...DEFAULT_CONFIG,
4032
- ...fullConfig,
4155
+ await this.storageManager.setConfigData(deepMerge_default({}, DEFAULT_CONFIG, fullConfig, {
4033
4156
  applicationId: resolvedApplicationId,
4034
4157
  endpoints: resolvedEndpoints,
4035
4158
  scope: processOpenIDScopes_default(fullConfig.scopes)
4036
- });
4159
+ }));
4037
4160
  this.baseURL = fullConfig.baseUrl ?? "";
4038
4161
  return true;
4039
4162
  }
@@ -4181,19 +4304,19 @@ var ThunderIDJavaScriptClient = class {
4181
4304
  if (configData.enablePKCE) {
4182
4305
  codeVerifier = this.cryptoHelper?.getCodeVerifier();
4183
4306
  codeChallenge = await this.cryptoHelper?.getCodeChallenge(codeVerifier);
4184
- await this.storageManager.setTemporaryDataParameter(pkceKey, codeVerifier, userId);
4307
+ await this.storageManager.setHybridDataParameter(pkceKey, codeVerifier, userId);
4185
4308
  }
4186
- if (authRequestConfig["client_secret"]) authRequestConfig["client_secret"] = configData.clientSecret;
4187
- const authorizeRequestParams = getAuthorizeRequestUrlParams_default({
4188
- clientId: configData.clientId,
4309
+ if (authRequestConfig["client_secret"]) authRequestConfig["client_secret"] = configData.clientSecret ?? "";
4310
+ const authorizeRequestParams = getAuthorizeRequestUrlParams_default(Object.fromEntries(Object.entries({
4311
+ clientId: configData.clientId ?? "",
4189
4312
  codeChallenge,
4190
4313
  codeChallengeMethod: PKCEConstants_default.DEFAULT_CODE_CHALLENGE_METHOD,
4191
4314
  instanceId: this.getInstanceId().toString(),
4192
4315
  prompt: configData.prompt,
4193
- redirectUri: configData.afterSignInUrl,
4316
+ redirectUri: configData.afterSignInUrl ?? "",
4194
4317
  responseMode: configData.responseMode,
4195
4318
  scopes: processOpenIDScopes_default(configData.scopes)
4196
- }, { key: pkceKey }, authRequestConfig);
4319
+ }).filter(([, v]) => v !== void 0)), { key: pkceKey }, authRequestConfig);
4197
4320
  Array.from(authorizeRequestParams.entries()).forEach(([paramKey, paramValue]) => {
4198
4321
  authorizeRequest.searchParams.append(paramKey, paramValue);
4199
4322
  });
@@ -4209,19 +4332,19 @@ var ThunderIDJavaScriptClient = class {
4209
4332
  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.");
4210
4333
  if (sessionState) await this.storageManager.setSessionDataParameter(OIDCRequestConstants_default.Params.SESSION_STATE, sessionState, userId);
4211
4334
  const body = new URLSearchParams();
4212
- body.set("client_id", configData.clientId);
4335
+ body.set("client_id", configData.clientId ?? "");
4213
4336
  const hasSecret = Boolean(configData.clientSecret && configData.clientSecret.trim().length > 0);
4214
4337
  const tokenEndpointAuthMethod = configData.tokenRequest?.authMethod ?? "client_secret_basic";
4215
4338
  if (hasSecret && tokenEndpointAuthMethod === "client_secret_post") body.set("client_secret", configData.clientSecret);
4216
4339
  body.set("code", authorizationCode);
4217
4340
  body.set("grant_type", "authorization_code");
4218
- body.set("redirect_uri", configData.afterSignInUrl);
4341
+ body.set("redirect_uri", configData.afterSignInUrl ?? "");
4219
4342
  if (tokenRequestConfig?.params) Object.entries(tokenRequestConfig.params).forEach(([key, value]) => {
4220
4343
  body.append(key, value);
4221
4344
  });
4222
4345
  if (configData.enablePKCE) {
4223
- body.set("code_verifier", `${await this.storageManager.getTemporaryDataParameter(extractPkceStorageKeyFromState_default(state), userId)}`);
4224
- await this.storageManager.removeTemporaryDataParameter(extractPkceStorageKeyFromState_default(state), userId);
4346
+ body.set("code_verifier", `${await this.storageManager.getHybridDataParameter(extractPkceStorageKeyFromState_default(state), userId)}`);
4347
+ await this.storageManager.removeHybridDataParameter(extractPkceStorageKeyFromState_default(state), userId);
4225
4348
  }
4226
4349
  const tokenRequestHeaders = {
4227
4350
  Accept: "application/json",
@@ -4254,7 +4377,7 @@ var ThunderIDJavaScriptClient = class {
4254
4377
  const idToken = (await this.storageManager.getSessionData(userId))?.id_token;
4255
4378
  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.");
4256
4379
  queryParams.set("id_token_hint", idToken);
4257
- } else queryParams.set("client_id", configData.clientId);
4380
+ } else queryParams.set("client_id", configData.clientId ?? "");
4258
4381
  queryParams.set("state", OIDCRequestConstants_default.Params.SIGN_OUT_SUCCESS);
4259
4382
  return `${logoutEndpoint}?${queryParams.toString()}`;
4260
4383
  }
@@ -4349,10 +4472,10 @@ var ThunderIDJavaScriptClient = class {
4349
4472
  return response;
4350
4473
  }
4351
4474
  async getPKCECode(state, userId) {
4352
- return await this.storageManager.getTemporaryDataParameter(extractPkceStorageKeyFromState_default(state), userId);
4475
+ return await this.storageManager.getHybridDataParameter(extractPkceStorageKeyFromState_default(state), userId);
4353
4476
  }
4354
4477
  async setPKCECode(pkce, state, userId) {
4355
- return this.storageManager.setTemporaryDataParameter(extractPkceStorageKeyFromState_default(state), pkce, userId);
4478
+ return this.storageManager.setHybridDataParameter(extractPkceStorageKeyFromState_default(state), pkce, userId);
4356
4479
  }
4357
4480
  getInstanceId() {
4358
4481
  return this.instanceIdValue;
@@ -4683,12 +4806,15 @@ const toCssVariables = (theme) => {
4683
4806
  if (theme.typography?.lineHeights?.tight !== void 0) cssVars[`--${prefix}-typography-lineHeight-tight`] = theme.typography.lineHeights.tight.toString();
4684
4807
  if (theme.typography?.lineHeights?.normal !== void 0) cssVars[`--${prefix}-typography-lineHeight-normal`] = theme.typography.lineHeights.normal.toString();
4685
4808
  if (theme.typography?.lineHeights?.relaxed !== void 0) cssVars[`--${prefix}-typography-lineHeight-relaxed`] = theme.typography.lineHeights.relaxed.toString();
4686
- if (theme.images) Object.keys(theme.images).forEach((imageKey) => {
4687
- const imageConfig = theme.images[imageKey];
4688
- if (imageConfig?.url) cssVars[`--${prefix}-image-${imageKey}-url`] = imageConfig.url;
4689
- if (imageConfig?.title) cssVars[`--${prefix}-image-${imageKey}-title`] = imageConfig.title;
4690
- if (imageConfig?.alt) cssVars[`--${prefix}-image-${imageKey}-alt`] = imageConfig.alt;
4691
- });
4809
+ if (theme.images) {
4810
+ const themeImages = theme.images;
4811
+ Object.keys(themeImages).forEach((imageKey) => {
4812
+ const imageConfig = themeImages[imageKey];
4813
+ if (imageConfig?.url) cssVars[`--${prefix}-image-${imageKey}-url`] = imageConfig.url;
4814
+ if (imageConfig?.title) cssVars[`--${prefix}-image-${imageKey}-title`] = imageConfig.title;
4815
+ if (imageConfig?.alt) cssVars[`--${prefix}-image-${imageKey}-alt`] = imageConfig.alt;
4816
+ });
4817
+ }
4692
4818
  if (theme.components?.Button?.styleOverrides?.root?.borderRadius) cssVars[`--${prefix}-component-button-root-borderRadius`] = theme.components.Button.styleOverrides.root.borderRadius;
4693
4819
  if (theme.components?.Field?.styleOverrides?.root?.borderRadius) cssVars[`--${prefix}-component-field-root-borderRadius`] = theme.components.Field.styleOverrides.root.borderRadius;
4694
4820
  return cssVars;
@@ -4785,9 +4911,11 @@ const toThemeVars = (theme) => {
4785
4911
  };
4786
4912
  if (theme.images) {
4787
4913
  themeVars.images = {};
4788
- Object.keys(theme.images).forEach((imageKey) => {
4789
- const imageConfig = theme.images[imageKey];
4790
- themeVars.images[imageKey] = {
4914
+ const themeImages = theme.images;
4915
+ const imageVars = themeVars.images;
4916
+ Object.keys(themeImages).forEach((imageKey) => {
4917
+ const imageConfig = themeImages[imageKey];
4918
+ imageVars[imageKey] = {
4791
4919
  alt: imageConfig?.alt ? `var(--${prefix}-image-${imageKey}-alt)` : void 0,
4792
4920
  title: imageConfig?.title ? `var(--${prefix}-image-${imageKey}-title)` : void 0,
4793
4921
  url: imageConfig?.url ? `var(--${prefix}-image-${imageKey}-url)` : void 0
@@ -5081,13 +5209,9 @@ var formatDate_default = formatDate;
5081
5209
  //#endregion
5082
5210
  //#region src/utils/deriveOrganizationHandleFromBaseUrl.ts
5083
5211
  /**
5084
- * Extracts the organization handle from an ThunderID base URL.
5212
+ * Extracts the organization handle from a ThunderID base URL.
5085
5213
  *
5086
- * This function parses ThunderID URLs with the standard pattern:
5087
- * - https://dev.asgardeo.io/t/{orgHandle}
5088
- * - https://stage.asgardeo.io/t/{orgHandle}
5089
- * - https://prod.asgardeo.io/t/{orgHandle}
5090
- * - https://{subdomain}.asgardeo.io/t/{orgHandle}
5214
+ * Parses URLs following the `/t/{orgHandle}` pattern.
5091
5215
  *
5092
5216
  * @param baseUrl - The base URL of the ThunderID identity server
5093
5217
  * @returns The extracted organization handle
@@ -5096,13 +5220,9 @@ var formatDate_default = formatDate;
5096
5220
  *
5097
5221
  * @example
5098
5222
  * ```typescript
5099
- * // Standard ThunderID URLs
5100
- * const handle1 = deriveOrganizationHandleFromBaseUrl('https://dev.asgardeo.io/t/dxlab');
5223
+ * const handle = deriveOrganizationHandleFromBaseUrl('https://localhost:8090/t/dxlab');
5101
5224
  * // Returns: 'dxlab'
5102
5225
  *
5103
- * const handle2 = deriveOrganizationHandleFromBaseUrl('https://stage.asgardeo.io/t/myorg');
5104
- * // Returns: 'myorg'
5105
- *
5106
5226
  * // Custom domain - returns empty string with a warning
5107
5227
  * const handle2 = deriveOrganizationHandleFromBaseUrl('https://custom.example.com/auth');
5108
5228
  * // Returns: '' and logs a warning
@@ -5927,7 +6047,7 @@ var withVendorCSSClassPrefix_default = withVendorCSSClassPrefix;
5927
6047
  //#endregion
5928
6048
  //#region src/utils/transformBrandingPreferenceToTheme.ts
5929
6049
  const extractColorValue = (colorVariant, preferDark = false) => {
5930
- if (preferDark && colorVariant?.dark && colorVariant.dark.trim()) return colorVariant.dark;
6050
+ if (preferDark && colorVariant?.dark?.trim()) return colorVariant.dark;
5931
6051
  return colorVariant?.main;
5932
6052
  };
5933
6053
  /**
@@ -5960,47 +6080,47 @@ const transformThemeVariant = (themeVariant, isDark = false) => {
5960
6080
  background: {
5961
6081
  body: {
5962
6082
  dark: (colors?.background?.body)?.dark || (colors?.background?.body)?.main,
5963
- main: extractColorValue(colors?.background?.body, isDark)
6083
+ main: extractColorValue(colors?.background?.body, isDark) ?? ""
5964
6084
  },
5965
6085
  dark: (colors?.background?.surface)?.dark || (colors?.background?.surface)?.main,
5966
- disabled: extractColorValue(colors?.background?.surface, isDark),
5967
- surface: extractColorValue(colors?.background?.surface, isDark)
6086
+ disabled: extractColorValue(colors?.background?.surface, isDark) ?? "",
6087
+ surface: extractColorValue(colors?.background?.surface, isDark) ?? ""
5968
6088
  },
5969
- border: colors?.outlined?.default,
6089
+ border: colors?.outlined?.default ?? "",
5970
6090
  error: {
5971
- contrastText: extractContrastText(colors?.alerts?.error),
6091
+ contrastText: extractContrastText(colors?.alerts?.error) ?? "",
5972
6092
  dark: (colors?.alerts?.error)?.dark || (colors?.alerts?.error)?.main,
5973
- main: extractColorValue(colors?.alerts?.error, isDark)
6093
+ main: extractColorValue(colors?.alerts?.error, isDark) ?? ""
5974
6094
  },
5975
6095
  info: {
5976
- contrastText: extractContrastText(colors?.alerts?.info),
6096
+ contrastText: extractContrastText(colors?.alerts?.info) ?? "",
5977
6097
  dark: (colors?.alerts?.info)?.dark || (colors?.alerts?.info)?.main,
5978
- main: extractColorValue(colors?.alerts?.info, isDark)
6098
+ main: extractColorValue(colors?.alerts?.info, isDark) ?? ""
5979
6099
  },
5980
6100
  primary: {
5981
- contrastText: extractContrastText(colors?.primary),
6101
+ contrastText: extractContrastText(colors?.primary) ?? "",
5982
6102
  dark: colors?.primary?.dark || (colors?.primary)?.main,
5983
- main: extractColorValue(colors?.primary, isDark)
6103
+ main: extractColorValue(colors?.primary, isDark) ?? ""
5984
6104
  },
5985
6105
  secondary: {
5986
- contrastText: extractContrastText(colors?.secondary),
6106
+ contrastText: extractContrastText(colors?.secondary) ?? "",
5987
6107
  dark: colors?.secondary?.dark || (colors?.secondary)?.main,
5988
- main: extractColorValue(colors?.secondary, isDark)
6108
+ main: extractColorValue(colors?.secondary, isDark) ?? ""
5989
6109
  },
5990
6110
  success: {
5991
- contrastText: extractContrastText(colors?.alerts?.neutral),
6111
+ contrastText: extractContrastText(colors?.alerts?.neutral) ?? "",
5992
6112
  dark: (colors?.alerts?.neutral)?.dark || (colors?.alerts?.neutral)?.main,
5993
- main: extractColorValue(colors?.alerts?.neutral, isDark)
6113
+ main: extractColorValue(colors?.alerts?.neutral, isDark) ?? ""
5994
6114
  },
5995
6115
  text: {
5996
6116
  dark: (colors?.text)?.dark || (colors?.text)?.primary,
5997
- primary: (colors?.text)?.primary,
5998
- secondary: (colors?.text)?.secondary
6117
+ primary: (colors?.text)?.primary ?? "",
6118
+ secondary: (colors?.text)?.secondary ?? ""
5999
6119
  },
6000
6120
  warning: {
6001
- contrastText: extractContrastText(colors?.alerts?.warning),
6121
+ contrastText: extractContrastText(colors?.alerts?.warning) ?? "",
6002
6122
  dark: (colors?.alerts?.warning)?.dark || (colors?.alerts?.warning)?.main,
6003
- main: extractColorValue(colors?.alerts?.warning, isDark)
6123
+ main: extractColorValue(colors?.alerts?.warning, isDark) ?? ""
6004
6124
  }
6005
6125
  },
6006
6126
  images: {
@@ -6138,7 +6258,7 @@ var HttpClient = class HttpClient {
6138
6258
  return (array) => callback(...array);
6139
6259
  }
6140
6260
  async requestHandler(config) {
6141
- await this.attachToken(config);
6261
+ if (config.attachToken !== false) await this.attachToken(config);
6142
6262
  if (config.shouldEncodeToFormData && config.data) {
6143
6263
  const formData = new FormData();
6144
6264
  Object.keys(config.data).forEach((key) => formData.append(key, config.data[key]));