UNPKG

@asgardeo/react

Version:
1,500 lines (1,466 loc) 577 kB
var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); // src/contexts/Asgardeo/AsgardeoProvider.tsx import { AsgardeoRuntimeError as AsgardeoRuntimeError3, generateFlattenedUserProfile as generateFlattenedUserProfile2, getBrandingPreference, getActiveTheme, Platform as Platform3, extractUserClaimsFromIdToken as extractUserClaimsFromIdToken2 } from "@asgardeo/browser"; import { useEffect as useEffect6, useMemo as useMemo7, useRef as useRef2, useState as useState8, useCallback as useCallback8 } from "react"; // src/contexts/Asgardeo/AsgardeoContext.ts import { createContext } from "react"; var AsgardeoContext = createContext({ afterSignInUrl: void 0, applicationId: void 0, baseUrl: void 0, clearSession: () => { }, exchangeToken: null, getAccessToken: null, getDecodedIdToken: null, getIdToken: null, http: { request: () => null, requestAll: () => null }, instanceId: 0, isInitialized: false, isLoading: true, isSignedIn: false, meta: null, organization: null, organizationHandle: void 0, platform: void 0, reInitialize: null, signIn: () => Promise.resolve({}), signInOptions: {}, signInSilently: () => Promise.resolve({}), signInUrl: void 0, signOut: () => Promise.resolve({}), signUp: () => Promise.resolve({}), signUpUrl: void 0, storage: "sessionStorage", switchOrganization: null, user: null }); AsgardeoContext.displayName = "AsgardeoContext"; var AsgardeoContext_default = AsgardeoContext; // src/AsgardeoReactClient.ts import { AsgardeoBrowserClient, flattenUserSchema, generateFlattenedUserProfile, generateUserProfile, AsgardeoRuntimeError, executeEmbeddedSignUpFlow, executeEmbeddedSignInFlow, executeEmbeddedSignInFlowV2, deriveOrganizationHandleFromBaseUrl, extractUserClaimsFromIdToken, navigate, getRedirectBasedSignUpUrl, Platform, isEmpty, executeEmbeddedSignUpFlowV2, EmbeddedSignInFlowStatusV2 } from "@asgardeo/browser"; // src/__temp__/api.ts import { AsgardeoSPAClient, Hooks } from "@asgardeo/browser"; var _AuthAPI = class _AuthAPI { constructor(spaClient, instanceId = 0) { __publicField(this, "authState", _AuthAPI.DEFAULT_STATE); __publicField(this, "client"); __publicField(this, "apiInstanceId"); __publicField(this, "loadingState"); this.apiInstanceId = instanceId; this.client = spaClient ?? AsgardeoSPAClient.getInstance(instanceId); this.getState = this.getState.bind(this); this.init = this.init.bind(this); this.signIn = this.signIn.bind(this); this.signOut = this.signOut.bind(this); this.updateState = this.updateState.bind(this); } /** * Get the instance ID for this AuthAPI instance. * @returns The instance ID used for multi-auth context support. */ getInstanceId() { return this.apiInstanceId; } setLoadingState(isLoading) { this.loadingState = isLoading; } getLoadingState() { return this.loadingState; } isLoading() { return this.getLoadingState(); } /** * Method to return Auth Client instance authentication state. * * @return {AuthStateInterface} Authentication State. */ getState() { return this.authState; } /** * Method to initialize the AuthClient instance. * * @param {Config} config - `dispatch` function from React Auth Context. */ async init(config) { return this.client.initialize(config); } /** * Method to get the configuration data. * * @returns {Promise<AuthClientConfig<Config>>} - A promise that resolves with the configuration data. */ async getConfigData() { return this.client.getConfigData(); } async getStorageManager() { return this.client.getStorageManager(); } /** * Method to get the configuration data. * * @returns {Promise<AuthClientConfig<Config>>} - A promise that resolves with the configuration data. */ async isInitialized() { return this.client.isInitialized(); } /** * Method to handle user Sign In requests. * * @param {any} dispatch - `dispatch` function from React Auth Context. * @param {AuthStateInterface} state - Current authentication state in React Auth Context. * @param {any} callback - Action to trigger on successful sign in. */ async signIn(config, authorizationCode, sessionState, authState, callback, tokenRequestConfig) { return this.client.signIn(config, authorizationCode, sessionState, authState, tokenRequestConfig).then(async (response) => { if (!response) { return null; } if (await this.client.isSignedIn()) { const stateToUpdate = { displayName: response.displayName, email: response.email, isLoading: false, isSignedIn: true, username: response.username }; this.updateState(stateToUpdate); this.setLoadingState(false); if (callback) { callback(response); } } return response; }).catch((error) => Promise.reject(error)); } /** * Method to handle user Sign Out requests. * * @param {any} dispatch - `dispatch` function from React Auth Context. * @param {AuthStateInterface} state - Current authentication state in React Auth Context. * @param {any} callback - Action to trigger on successful sign out. */ signOut(callback) { return this.client.signOut().then((response) => { if (callback) { callback(response); } return response; }).catch((error) => Promise.reject(error)); } /** * Method to update Auth Client instance authentication state. * * @param {AuthStateInterface} state - State values to update in authentication state. */ updateState(state) { this.authState = { ...this.authState, ...state }; } /** * This method returns a Promise that resolves with the basic user information obtained from the ID token. * * @return {Promise<User>} - A promise that resolves with the user information. */ async getUser() { return this.client.getUser(); } /** * This method sends an API request to a protected endpoint. * The access token is automatically attached to the header of the request. * This is the only way by which protected endpoints can be accessed * when the web worker is used to store session information. * * @param {HttpRequestConfig} config - The config object containing attributes necessary to send a request. * * @return {Promise<Response>} - Returns a Promise that resolves with the response to the request. */ async httpRequest(config) { return this.client.httpRequest(config); } /** * This method sends multiple API requests to a protected endpoint. * The access token is automatically attached to the header of the request. * This is the only way by which multiple requests can be sent to protected endpoints * when the web worker is used to store session information. * * @param {HttpRequestConfig[]} config - The config object containing attributes necessary to send a request. * * @return {Promise<Response>} - Returns a Promise that resolves with the responses to the requests. */ async httpRequestAll(configs) { return this.client.httpRequestAll(configs); } /** * This method allows you to send a request with a custom grant. * * @param {CustomGrantRequestParams} config - The request parameters. * * @return {Promise<Response | SignInResponse>} - A Promise that resolves with * the value returned by the custom grant request. */ exchangeToken(config, callback) { return this.client.exchangeToken(config).then((response) => { if (!response) { return null; } if (config.returnsSession) { this.updateState({ ...this.getState(), ...response, isLoading: false, isSignedIn: true }); } if (callback) { callback(response); } return response; }).catch((error) => Promise.reject(error)); } /** * This method ends a user session. The access token is revoked and the session information is destroyed. * * @return {Promise<boolean>} - A promise that resolves with `true` if the process is successful. */ async revokeAccessToken(dispatch) { return this.client.revokeAccessToken().then(() => { this.updateState({ ..._AuthAPI.DEFAULT_STATE, isLoading: false }); dispatch(_AuthAPI.DEFAULT_STATE); return true; }).catch((error) => Promise.reject(error)); } /** * This method returns a Promise that resolves with an object containing the service endpoints. * * @return {Promise<ServiceResourcesType} - A Promise that resolves with an object containing the service endpoints. */ async getOpenIDProviderEndpoints() { return this.client.getOpenIDProviderEndpoints(); } /** * This methods returns the Axios http client. * * @return {HttpClientInstance} - The Axios HTTP client. */ async getHttpClient() { return this.client.getHttpClient(); } /** * This method decodes a JWT token payload and returns it. * * @param token - The token to decode. * @returns The decoded token payload. */ async decodeJwtToken(token) { return this.client.decodeJwtToken(token); } /** * This method decodes the payload of the id token and returns it. * * @return {Promise<DecodedIDTokenPayloadInterface>} - A Promise that resolves with * the decoded payload of the id token. */ async getDecodedIdToken(sessionId) { return this.client.getDecodedIdToken(sessionId); } /** * This method decodes the payload of the idp id token and returns it. * * @return {Promise<DecodedIDTokenPayloadInterface>} - A Promise that resolves with * the decoded payload of the idp id token. */ async getDecodedIDPIDToken() { return this.client.getDecodedIdToken(); } /** * This method returns the ID token. * * @return {Promise<string>} - A Promise that resolves with the id token. */ async getIdToken() { return this.client.getIdToken(); } /** * This method return a Promise that resolves with the access token. * * **This method will not return the access token if the storage type is set to `webWorker`.** * * @return {Promise<string>} - A Promise that resolves with the access token. */ async getAccessToken(sessionId) { return this.client.getAccessToken(sessionId); } /** * This method return a Promise that resolves with the idp access token. * * **This method will not return the idp access token if the storage type is set to `webWorker`.** * **This can be used to access the IDP access token when custom auth grant functionalities are used** * * @return {Promise<string>} - A Promise that resolves with the idp access token. */ async getIDPAccessToken() { return this.client.getIDPAccessToken(); } /** * This method refreshes the access token. * * @return {TokenResponseInterface} - A Promise that resolves with an object containing * information about the refreshed access token. */ async refreshAccessToken() { return this.client.refreshAccessToken(); } /** * This method specifies if the user is authenticated or not. * * @return {Promise<boolean>} - A Promise that resolves with `true` if teh user is authenticated. */ async isSignedIn() { return this.client.isSignedIn(); } /** * This method specifies if the session is active or not. * * @return {Promise<boolean>} - A Promise that resolves with `true` if there is an active session. */ async isSessionActive() { return this.client.isSessionActive(); } /** * This method enables callback functions attached to the http client. * * @return {Promise<boolean>} - A promise that resolves with True. * */ async enableHttpHandler() { return this.client.enableHttpHandler(); } /** * This method disables callback functions attached to the http client. * * @return {Promise<boolean>} - A promise that resolves with True. */ async disableHttpHandler() { return this.client.disableHttpHandler(); } /** * This method updates the configuration that was passed into the constructor when instantiating this class. * * @param {Partial<AuthClientConfig<T>>} config - A config object to update the SDK configurations with. */ async reInitialize(config) { return this.client.reInitialize(config); } on(hook, callback, id) { if (hook === Hooks.CustomGrant) { return this.client.on(hook, callback, id); } return this.client.on(hook, callback); } /** * This method allows you to sign in silently. * First, this method sends a prompt none request to see if there is an active user session in the identity server. * If there is one, then it requests the access token and stores it. Else, it returns false. * * @return {Promise<User | boolean>} - A Promise that resolves with the user information after signing in * or with `false` if the user is not signed in. * * @example *``` * client.signInSilently() *``` */ async signInSilently(additionalParams, tokenRequestConfig) { return this.client.signInSilently(additionalParams, tokenRequestConfig).then(async (response) => { if (!response) { return false; } return response; }).catch((error) => Promise.reject(error)); } /** * This method clears the session for the specified session ID. * * @param sessionId - Optional session ID to clear the session for. * * @return void */ clearSession(sessionId) { this.client.clearSession(sessionId); } }; __publicField(_AuthAPI, "DEFAULT_STATE"); var AuthAPI = _AuthAPI; AuthAPI.DEFAULT_STATE = { displayName: "", email: "", isLoading: true, isSignedIn: false, username: "" }; var api_default = AuthAPI; // src/api/getAllOrganizations.ts import { AsgardeoSPAClient as AsgardeoSPAClient2, getAllOrganizations as baseGetAllOrganizations } from "@asgardeo/browser"; var getAllOrganizations = async ({ fetcher, instanceId = 0, ...requestConfig }) => { const defaultFetcher = async (url, config) => { const client = AsgardeoSPAClient2.getInstance(instanceId); const httpClient = client.httpRequest.bind(client); const response = await httpClient({ headers: config.headers, method: config.method || "GET", url }); return { json: () => Promise.resolve(response.data), ok: response.status >= 200 && response.status < 300, status: response.status, statusText: response.statusText || "", text: () => Promise.resolve(typeof response.data === "string" ? response.data : JSON.stringify(response.data)) }; }; return baseGetAllOrganizations({ ...requestConfig, fetcher: fetcher || defaultFetcher }); }; var getAllOrganizations_default = getAllOrganizations; // src/api/getMeOrganizations.ts import { AsgardeoSPAClient as AsgardeoSPAClient3, getMeOrganizations as baseGetMeOrganizations } from "@asgardeo/browser"; var getMeOrganizations = async ({ fetcher, instanceId = 0, ...requestConfig }) => { const defaultFetcher = async (url, config) => { const client = AsgardeoSPAClient3.getInstance(instanceId); const httpClient = client.httpRequest.bind(client); const response = await httpClient({ headers: config.headers, method: config.method || "GET", url }); return { json: () => Promise.resolve(response.data), ok: response.status >= 200 && response.status < 300, status: response.status, statusText: response.statusText || "", text: () => Promise.resolve(typeof response.data === "string" ? response.data : JSON.stringify(response.data)) }; }; return baseGetMeOrganizations({ ...requestConfig, fetcher: fetcher || defaultFetcher }); }; var getMeOrganizations_default = getMeOrganizations; // src/api/getSchemas.ts import { AsgardeoSPAClient as AsgardeoSPAClient4, getSchemas as baseGetSchemas } from "@asgardeo/browser"; var getSchemas = async ({ fetcher, instanceId = 0, ...requestConfig }) => { const defaultFetcher = async (url, config) => { const client = AsgardeoSPAClient4.getInstance(instanceId); const httpClient = client.httpRequest.bind(client); const response = await httpClient({ headers: config.headers, method: config.method || "GET", url }); return { json: () => Promise.resolve(response.data), ok: response.status >= 200 && response.status < 300, status: response.status, statusText: response.statusText || "", text: () => Promise.resolve(typeof response.data === "string" ? response.data : JSON.stringify(response.data)) }; }; return baseGetSchemas({ ...requestConfig, fetcher: fetcher || defaultFetcher }); }; var getSchemas_default = getSchemas; // src/api/getScim2Me.ts import { AsgardeoSPAClient as AsgardeoSPAClient5, getScim2Me as baseGetScim2Me } from "@asgardeo/browser"; var getScim2Me = async ({ fetcher, instanceId = 0, ...requestConfig }) => { const defaultFetcher = async (url, config) => { const client = AsgardeoSPAClient5.getInstance(instanceId); const httpClient = client.httpRequest.bind(client); const response = await httpClient({ headers: config.headers, method: config.method || "GET", url }); return { json: () => Promise.resolve(response.data), ok: response.status >= 200 && response.status < 300, status: response.status, statusText: response.statusText || "", text: () => Promise.resolve(typeof response.data === "string" ? response.data : JSON.stringify(response.data)) }; }; return baseGetScim2Me({ ...requestConfig, fetcher: fetcher || defaultFetcher }); }; var getScim2Me_default = getScim2Me; // src/AsgardeoReactClient.ts var AsgardeoReactClient = class extends AsgardeoBrowserClient { /** * Creates a new AsgardeoReactClient instance. * @param instanceId - Optional instance ID for multi-auth context support. Defaults to 0 for backward compatibility. */ constructor(instanceId = 0) { super(); __publicField(this, "asgardeo"); __publicField(this, "loadingState", false); __publicField(this, "clientInstanceId"); this.clientInstanceId = instanceId; this.asgardeo = new api_default(void 0, instanceId); } /** * Get the instance ID for this client. * @returns The instance ID used for multi-auth context support. */ getInstanceId() { return this.clientInstanceId; } /** * Set the loading state of the client * @param loading - Boolean indicating if the client is in a loading state */ setLoading(loading) { this.loadingState = loading; } /** * Wrap async operations with loading state management * @param operation - The async operation to execute * @returns Promise with the result of the operation */ async withLoading(operation) { this.setLoading(true); try { const result = await operation(); return result; } finally { this.setLoading(false); } } initialize(config) { let resolvedOrganizationHandle = config?.organizationHandle; if (!resolvedOrganizationHandle) { resolvedOrganizationHandle = deriveOrganizationHandleFromBaseUrl(config?.baseUrl); } return this.withLoading( async () => this.asgardeo.init({ ...config, organizationHandle: resolvedOrganizationHandle }) ); } reInitialize(config) { return this.withLoading(async () => { let isInitialized; try { await this.asgardeo.reInitialize(config); isInitialized = true; } catch (error) { throw new AsgardeoRuntimeError( `Failed to check if the client is initialized: ${error instanceof Error ? error.message : String(error)}`, "AsgardeoReactClient-reInitialize-RuntimeError-001", "react", "An error occurred while checking the initialization status of the client." ); } return isInitialized; }); } // eslint-disable-next-line class-methods-use-this async updateUserProfile() { throw new Error("Not implemented"); } async getUser(options) { try { let baseUrl = options?.baseUrl; if (!baseUrl) { const configData = await this.asgardeo.getConfigData(); baseUrl = configData?.baseUrl; } const profile = await getScim2Me_default({ baseUrl }); const schemas = await getSchemas_default({ baseUrl }); return generateUserProfile(profile, flattenUserSchema(schemas)); } catch (error) { return extractUserClaimsFromIdToken(await this.getDecodedIdToken()); } } async getDecodedIdToken(sessionId) { return this.asgardeo.getDecodedIdToken(sessionId); } async getIdToken() { return this.withLoading(async () => this.asgardeo.getIdToken()); } async getUserProfile(options) { return this.withLoading(async () => { try { let baseUrl = options?.baseUrl; if (!baseUrl) { const configData = await this.asgardeo.getConfigData(); baseUrl = configData?.baseUrl; } const profile = await getScim2Me_default({ baseUrl, instanceId: this.getInstanceId() }); const schemas = await getSchemas_default({ baseUrl, instanceId: this.getInstanceId() }); const processedSchemas = flattenUserSchema(schemas); const output = { flattenedProfile: generateFlattenedUserProfile(profile, processedSchemas), profile, schemas: processedSchemas }; return output; } catch (error) { return { flattenedProfile: extractUserClaimsFromIdToken(await this.getDecodedIdToken()), profile: extractUserClaimsFromIdToken(await this.getDecodedIdToken()), schemas: [] }; } }); } async getMyOrganizations(options) { try { let baseUrl = options?.baseUrl; if (!baseUrl) { const configData = await this.asgardeo.getConfigData(); baseUrl = configData?.baseUrl; } return await getMeOrganizations_default({ baseUrl, instanceId: this.getInstanceId() }); } catch (error) { throw new AsgardeoRuntimeError( `Failed to fetch the user's associated organizations: ${error instanceof Error ? error.message : String(error)}`, "AsgardeoReactClient-getMyOrganizations-RuntimeError-001", "react", "An error occurred while fetching associated organizations of the signed-in user." ); } } async getAllOrganizations(options) { try { let baseUrl = options?.baseUrl; if (!baseUrl) { const configData = await this.asgardeo.getConfigData(); baseUrl = configData?.baseUrl; } return await getAllOrganizations_default({ baseUrl, instanceId: this.getInstanceId() }); } catch (error) { throw new AsgardeoRuntimeError( `Failed to fetch all organizations: ${error instanceof Error ? error.message : String(error)}`, "AsgardeoReactClient-getAllOrganizations-RuntimeError-001", "react", "An error occurred while fetching all the organizations associated with the user." ); } } async getCurrentOrganization() { try { return await this.withLoading(async () => { const idToken = await this.getDecodedIdToken(); return { id: idToken?.org_id, name: idToken?.org_name, orgHandle: idToken?.org_handle }; }); } catch (error) { throw new AsgardeoRuntimeError( `Failed to fetch the current organization: ${error instanceof Error ? error.message : String(error)}`, "AsgardeoReactClient-getCurrentOrganization-RuntimeError-001", "react", "An error occurred while fetching the current organization of the signed-in user." ); } } async switchOrganization(organization) { return this.withLoading(async () => { try { if (!organization.id) { throw new AsgardeoRuntimeError( "Organization ID is required for switching organizations", "react-AsgardeoReactClient-SwitchOrganizationError-001", "react", "The organization object must contain a valid ID to perform the organization switch." ); } const exchangeConfig = { attachToken: false, data: { client_id: "{{clientId}}", grant_type: "organization_switch", scope: "{{scopes}}", switching_organization: organization.id, token: "{{accessToken}}" }, id: "organization-switch", returnsSession: true, signInRequired: true }; return await this.asgardeo.exchangeToken(exchangeConfig, () => { }); } catch (error) { throw new AsgardeoRuntimeError( `Failed to switch organization: ${error.message || error}`, "react-AsgardeoReactClient-SwitchOrganizationError-003", "react", "An error occurred while switching to the specified organization. Please try again." ); } }); } isLoading() { return this.loadingState || this.asgardeo.isLoading(); } async isInitialized() { return this.asgardeo.isInitialized(); } async isSignedIn() { return this.asgardeo.isSignedIn(); } getConfiguration() { return this.asgardeo.getConfigData(); } async exchangeToken(config) { return this.withLoading( async () => this.asgardeo.exchangeToken(config, () => { }) ); } async signIn(...args) { return this.withLoading(async () => { const arg1 = args[0]; const arg2 = args[1]; const config = await this.asgardeo.getConfigData(); const platformFromStorage = sessionStorage.getItem("asgardeo_platform"); const isV2Platform = config && config.platform === Platform.AsgardeoV2 || platformFromStorage === "AsgardeoV2"; if (isV2Platform && typeof arg1 === "object" && arg1 !== null && arg1.callOnlyOnRedirect === true) { return void 0; } if (isV2Platform && typeof arg1 === "object" && arg1 !== null && !isEmpty(arg1) && ("flowId" in arg1 || "applicationId" in arg1)) { const authIdFromUrl = new URL(window.location.href).searchParams.get("authId"); const authIdFromStorage = sessionStorage.getItem("asgardeo_auth_id"); const authId = authIdFromUrl || authIdFromStorage; const baseUrlFromStorage = sessionStorage.getItem("asgardeo_base_url"); const baseUrl = config?.baseUrl || baseUrlFromStorage; const response = await executeEmbeddedSignInFlowV2({ authId, baseUrl, payload: arg1, url: arg2?.url }); if (isV2Platform && response && typeof response === "object" && response["flowStatus"] === EmbeddedSignInFlowStatusV2.Complete && response["assertion"]) { const decodedAssertion = await this.decodeJwtToken(response["assertion"]); const createdAt = decodedAssertion.iat ? decodedAssertion.iat * 1e3 : Date.now(); const expiresIn = decodedAssertion.exp && decodedAssertion.iat ? decodedAssertion.exp - decodedAssertion.iat : 3600; await this.setSession({ access_token: response["assertion"], created_at: createdAt, expires_in: expiresIn, id_token: response["assertion"], scope: decodedAssertion.scope, token_type: "Bearer" }); } return response; } if (typeof arg1 === "object" && "flowId" in arg1 && typeof arg2 === "object" && "url" in arg2) { return executeEmbeddedSignInFlow({ payload: arg1, url: arg2.url }); } return await this.asgardeo.signIn(arg1); }); } async signInSilently(options) { return this.asgardeo.signInSilently(options); } async signOut(...args) { if (args[1] && typeof args[1] !== "function") { throw new Error("The second argument must be a function."); } const config = await this.asgardeo.getConfigData(); if (config.platform === Platform.AsgardeoV2) { this.asgardeo.clearSession(); args[1]?.(config.afterSignOutUrl || ""); return Promise.resolve(config.afterSignOutUrl || ""); } const response = await this.asgardeo.signOut(args[1]); return Promise.resolve(String(response)); } async signUp(...args) { const config = await this.asgardeo.getConfigData(); const firstArg = args[0]; const baseUrl = config?.baseUrl; if (config.platform === Platform.AsgardeoV2) { const authIdFromUrl = new URL(window.location.href).searchParams.get("authId"); const authIdFromStorage = sessionStorage.getItem("asgardeo_auth_id"); const authId = authIdFromUrl || authIdFromStorage; if (authIdFromUrl && !authIdFromStorage) { sessionStorage.setItem("asgardeo_auth_id", authIdFromUrl); } return executeEmbeddedSignUpFlowV2({ authId, baseUrl, payload: typeof firstArg === "object" && "flowType" in firstArg ? { ...firstArg, verbose: true } : firstArg }); } if (typeof firstArg === "object" && "flowType" in firstArg) { return executeEmbeddedSignUpFlow({ baseUrl, payload: firstArg }); } navigate(getRedirectBasedSignUpUrl(config)); return void 0; } async request(requestConfig) { return this.asgardeo.httpRequest(requestConfig); } async requestAll(requestConfigs) { return this.asgardeo.httpRequestAll(requestConfigs); } async getAccessToken(sessionId) { return this.asgardeo.getAccessToken(sessionId); } clearSession(sessionId) { this.asgardeo.clearSession(sessionId); } async setSession(sessionData, sessionId) { return (await this.asgardeo.getStorageManager()).setSessionData(sessionData, sessionId); } decodeJwtToken(token) { return this.asgardeo.decodeJwtToken(token); } }; var AsgardeoReactClient_default = AsgardeoReactClient; // src/hooks/useBrowserUrl.ts import { hasAuthParamsInUrl, hasCalledForThisInstanceInUrl } from "@asgardeo/browser"; var useBrowserUrl = () => { const hasAuthParams = (url, afterSignInUrl) => hasAuthParamsInUrl() && new URL(url.origin + url.pathname).toString() === new URL(afterSignInUrl).toString() || // authParams?.authorizationCode || // FIXME: These are sent externally. Need to see what we can do about this. url.searchParams.get("error") !== null; const hasCalledForThisInstance = (url, instanceId) => hasCalledForThisInstanceInUrl(instanceId, url.search); return { hasAuthParams, hasCalledForThisInstance }; }; var useBrowserUrl_default = useBrowserUrl; // src/contexts/Branding/BrandingProvider.tsx import { transformBrandingPreferenceToTheme } from "@asgardeo/browser"; import { useCallback, useEffect, useState } from "react"; // src/contexts/Branding/BrandingContext.ts import { createContext as createContext2 } from "react"; var BrandingContext = createContext2(null); BrandingContext.displayName = "BrandingContext"; var BrandingContext_default = BrandingContext; // src/contexts/Branding/BrandingProvider.tsx import { jsx } from "react/jsx-runtime"; var BrandingProvider = ({ children, brandingPreference: externalBrandingPreference, forceTheme, enabled = true, isLoading: externalIsLoading = false, error: externalError = null, refetch: externalRefetch }) => { const [theme, setTheme] = useState(null); const [activeTheme, setActiveTheme] = useState(null); useEffect(() => { if (!enabled || !externalBrandingPreference) { setTheme(null); setActiveTheme(null); return; } const activeThemeFromBranding = externalBrandingPreference?.preference?.theme?.activeTheme; let extractedActiveTheme = null; if (activeThemeFromBranding) { const themeMode = activeThemeFromBranding.toLowerCase(); if (themeMode === "light" || themeMode === "dark") { extractedActiveTheme = themeMode; } } setActiveTheme(extractedActiveTheme); const transformedTheme = transformBrandingPreferenceToTheme(externalBrandingPreference, forceTheme); setTheme(transformedTheme); }, [externalBrandingPreference, forceTheme, enabled]); useEffect(() => { if (!enabled) { setTheme(null); setActiveTheme(null); } }, [enabled]); const fetchBranding = useCallback(async () => { if (externalRefetch) { await externalRefetch(); } }, [externalRefetch]); const value = { activeTheme, brandingPreference: externalBrandingPreference || null, error: externalError, fetchBranding, isLoading: externalIsLoading, refetch: externalRefetch || fetchBranding, theme }; return /* @__PURE__ */ jsx(BrandingContext_default.Provider, { value, children }); }; var BrandingProvider_default = BrandingProvider; // src/contexts/Flow/FlowProvider.tsx import { useCallback as useCallback2, useMemo, useState as useState2 } from "react"; // src/contexts/Flow/FlowContext.ts import { createContext as createContext3 } from "react"; var FlowContext = createContext3(void 0); FlowContext.displayName = "FlowContext"; var FlowContext_default = FlowContext; // src/contexts/Flow/FlowProvider.tsx import { jsx as jsx2 } from "react/jsx-runtime"; var FlowProvider = ({ children, initialStep = null, initialTitle = "", initialSubtitle, onFlowChange }) => { const [currentStep, setCurrentStepState] = useState2(initialStep); const [title, setTitle] = useState2(initialTitle); const [subtitle, setSubtitle] = useState2(initialSubtitle); const [messages, setMessages] = useState2([]); const [error, setError] = useState2(null); const [isLoading, setIsLoading] = useState2(false); const [showBackButton, setShowBackButton] = useState2(false); const [onGoBack, setOnGoBack] = useState2(void 0); const setCurrentStep = useCallback2( (step) => { setCurrentStepState(step); if (step) { setTitle(step.title); setSubtitle(step.subtitle); setShowBackButton(step.canGoBack ?? false); } onFlowChange?.(step); }, [onFlowChange] ); const addMessage = useCallback2((message) => { const messageWithId = { ...message, id: message.id ?? `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}` }; setMessages((prev) => [...prev, messageWithId]); }, []); const removeMessage = useCallback2((messageId) => { setMessages((prev) => prev.filter((msg) => msg.id !== messageId)); }, []); const clearMessages = useCallback2(() => { setMessages([]); }, []); const reset = useCallback2(() => { setCurrentStepState(initialStep); setTitle(initialTitle); setSubtitle(initialSubtitle); setMessages([]); setError(null); setIsLoading(false); setShowBackButton(false); setOnGoBack(void 0); }, [initialStep, initialTitle, initialSubtitle]); const navigateToFlow = useCallback2( (flowType, options) => { const stepId = `${flowType}-${Date.now()}`; const step = { canGoBack: flowType !== "signin", // Usually allow going back except for main signin id: stepId, metadata: options?.metadata, subtitle: options?.subtitle, title: options?.title, type: flowType }; setCurrentStep(step); clearMessages(); setError(null); }, [setCurrentStep, clearMessages] ); const contextValue = useMemo( () => ({ addMessage, clearMessages, currentStep, error, isLoading, messages, navigateToFlow, onGoBack, removeMessage, reset, setCurrentStep, setError, setIsLoading, setOnGoBack, setShowBackButton, setSubtitle, setTitle, showBackButton, subtitle, title }), [ currentStep, setCurrentStep, title, subtitle, messages, addMessage, removeMessage, clearMessages, error, isLoading, showBackButton, onGoBack, reset, navigateToFlow ] ); return /* @__PURE__ */ jsx2(FlowContext_default.Provider, { value: contextValue, children }); }; var FlowProvider_default = FlowProvider; // src/contexts/FlowMeta/FlowMetaProvider.tsx import { FlowMetaType, getFlowMetaV2 } from "@asgardeo/browser"; import { useCallback as useCallback3, useEffect as useEffect2, useRef, useState as useState3 } from "react"; // src/contexts/FlowMeta/FlowMetaContext.ts import { createContext as createContext4 } from "react"; var FlowMetaContext = createContext4(null); FlowMetaContext.displayName = "FlowMetaContext"; var FlowMetaContext_default = FlowMetaContext; // src/contexts/Asgardeo/useAsgardeo.ts import { useContext } from "react"; var useAsgardeo = () => { const context = useContext(AsgardeoContext_default); if (!context) { throw new Error("useAsgardeo must be used within an AsgardeoProvider"); } const flowMetaContext = useContext(FlowMetaContext_default); return { ...context, meta: flowMetaContext?.meta ?? null }; }; var useAsgardeo_default = useAsgardeo; // src/contexts/FlowMeta/FlowMetaProvider.tsx import { jsx as jsx3 } from "react/jsx-runtime"; var FlowMetaProvider = ({ children, enabled = true }) => { const { baseUrl, applicationId } = useAsgardeo_default(); const [meta, setMeta] = useState3(null); const [isLoading, setIsLoading] = useState3(false); const [error, setError] = useState3(null); const hasFetchedRef = useRef(false); const fetchFlowMeta = useCallback3(async () => { if (!enabled) { setMeta(null); return; } setIsLoading(true); setError(null); try { const result = await getFlowMetaV2({ baseUrl, id: applicationId, type: FlowMetaType.App }); setMeta(result); } catch (err) { setError(err instanceof Error ? err : new Error(String(err))); } finally { setIsLoading(false); } }, [enabled, baseUrl, applicationId]); useEffect2(() => { if (!hasFetchedRef.current) { hasFetchedRef.current = true; fetchFlowMeta(); return; } fetchFlowMeta(); }, [fetchFlowMeta]); const value = { error, fetchFlowMeta, isLoading, meta }; return /* @__PURE__ */ jsx3(FlowMetaContext_default.Provider, { value, children }); }; var FlowMetaProvider_default = FlowMetaProvider; // src/contexts/I18n/I18nProvider.tsx import { deepMerge, createPackageComponentLogger } from "@asgardeo/browser"; import { getDefaultI18nBundles } from "@asgardeo/i18n"; import { useCallback as useCallback4, useEffect as useEffect3, useMemo as useMemo2, useState as useState4 } from "react"; // src/contexts/I18n/I18nContext.ts import { createContext as createContext5 } from "react"; var I18nContext = createContext5(null); I18nContext.displayName = "I18nContext"; var I18nContext_default = I18nContext; // src/contexts/I18n/I18nProvider.tsx import { jsx as jsx4 } from "react/jsx-runtime"; var logger = createPackageComponentLogger( "@asgardeo/react", "I18nProvider" ); var I18N_LANGUAGE_STORAGE_KEY = "asgardeo-i18n-language"; var detectBrowserLanguage = () => { if (typeof window !== "undefined" && window.navigator) { return window.navigator.language || "en-US"; } return "en-US"; }; var getStoredLanguage = () => { if (typeof window !== "undefined" && window.localStorage) { try { return window.localStorage.getItem(I18N_LANGUAGE_STORAGE_KEY); } catch (error) { return null; } } return null; }; var storeLanguage = (language) => { if (typeof window !== "undefined" && window.localStorage) { try { window.localStorage.setItem(I18N_LANGUAGE_STORAGE_KEY, language); } catch (error) { logger.warn("Failed to store language preference:"); } } }; var I18nProvider = ({ children, preferences }) => { const defaultBundles = getDefaultI18nBundles(); const determineInitialLanguage = () => { const configLanguage = preferences?.language; const storedLanguage = getStoredLanguage(); const browserLanguage = detectBrowserLanguage(); const fallbackLanguage2 = preferences?.fallbackLanguage || "en-US"; return configLanguage || storedLanguage || browserLanguage || fallbackLanguage2; }; const [currentLanguage, setCurrentLanguage] = useState4(determineInitialLanguage); const mergedBundles = useMemo2(() => { const merged = {}; Object.entries(defaultBundles).forEach(([key, bundle]) => { const languageKey = key.replace("_", "-"); merged[languageKey] = bundle; }); if (preferences?.bundles) { Object.entries(preferences.bundles).forEach(([key, userBundle]) => { if (merged[key]) { merged[key] = { ...merged[key], metadata: userBundle.metadata ? { ...merged[key].metadata, ...userBundle.metadata } : merged[key].metadata, translations: deepMerge(merged[key].translations, userBundle.translations) }; } else { merged[key] = userBundle; } }); } return merged; }, [defaultBundles, preferences?.bundles]); const fallbackLanguage = preferences?.fallbackLanguage || "en-US"; useEffect3(() => { storeLanguage(currentLanguage); }, [currentLanguage]); const t = useCallback4( (key, params) => { let translation; const currentBundle = mergedBundles[currentLanguage]; if (currentBundle?.translations[key]) { translation = currentBundle.translations[key]; } if (!translation && currentLanguage !== fallbackLanguage) { const fallbackBundle = mergedBundles[fallbackLanguage]; if (fallbackBundle?.translations[key]) { translation = fallbackBundle.translations[key]; } } if (!translation) { translation = key; } if (params && Object.keys(params).length > 0) { return Object.entries(params).reduce( (acc, [paramKey, paramValue]) => acc.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue)), translation ); } return translation; }, [mergedBundles, currentLanguage, fallbackLanguage] ); const setLanguage = useCallback4( (language) => { if (mergedBundles[language]) { setCurrentLanguage(language); } else { logger.warn( `Language '${language}' is not available. Available languages: ${Object.keys(mergedBundles).join(", ")}` ); } }, [mergedBundles] ); const contextValue = useMemo2( () => ({ bundles: mergedBundles, currentLanguage, fallbackLanguage, setLanguage, t }), [currentLanguage, fallbackLanguage, mergedBundles, setLanguage, t] ); return /* @__PURE__ */ jsx4(I18nContext_default.Provider, { value: contextValue, children }); }; var I18nProvider_default = I18nProvider; // src/contexts/Organization/OrganizationProvider.tsx import { AsgardeoRuntimeError as AsgardeoRuntimeError2 } from "@asgardeo/browser"; import { useCallback as useCallback5, useMemo as useMemo3, useState as useState5 } from "react"; // src/contexts/Organization/OrganizationContext.ts import { createContext as createContext6 } from "react"; var OrganizationContext = createContext6({ createOrganization: () => null, currentOrganization: null, error: null, getAllOrganizations: () => Promise.resolve({ count: 0, organizations: [] }), isLoading: false, myOrganizations: null, revalidateMyOrganizations: () => Promise.resolve([]), switchOrganization: () => Promise.resolve() }); OrganizationContext.displayName = "OrganizationContext"; var OrganizationContext_default = OrganizationContext; // src/contexts/Organization/OrganizationProvider.tsx import { jsx as jsx5 } from "react/jsx-runtime"; var OrganizationProvider = ({ children, currentOrganization, onError, myOrganizations, onOrganizationSwitch, revalidateMyOrganizations, getAllOrganizations: getAllOrganizations2, createOrganization: createOrganization2 }) => { const [isLoading, setIsLoading] = useState5(false); const [error, setError] = useState5(null); const switchOrganization = useCallback5( async (organization) => { if (!onOrganizationSwitch) { throw new AsgardeoRuntimeError2( "onOrganizationSwitch callback is required", "OrganizationProvider-SwitchError-001", "react", "The onOrganizationSwitch callback must be provided to handle organization switching." ); } setIsLoading(true); setError(null); try { await onOrganizationSwitch(organization); } catch (switchError) { const errorMessage = switchError instanceof Error ? switchError.message : "Failed to switch organization"; setError(errorMessage); if (onError) { onError(errorMessage); } throw switchError; } finally { setIsLoading(false); } }, [onOrganizationSwitch, onError] ); const contextValue = useMemo3( () => ({ createOrganization: createOrganization2, currentOrganization, error, getAllOrganizations: getAllOrganizations2, isLoading, myOrganizations, revalidateMyOrganizations, switchOrganization }), [ currentOrganization, error, isLoading, myOrganizations, switchOrganization, revalidateMyOrganizations, getAllOrganizations2, createOrganization2 ] ); return /* @__PURE__ */ jsx5(OrganizationContext_default.Provider, { value: contextValue, children }); }; var OrganizationProvider_default = OrganizationProvider; // src/contexts/Theme/ThemeProvider.tsx import { Platform as Platform2 } from "@asgardeo/browser"; // src/contexts/Theme/v1/ThemeProvider.tsx import { createTheme, detectThemeMode, createClassObserver, createMediaQueryListener, DEFAULT_THEME, createPackageComponentLogger as createPackageComponentLogger2 } from "@asgardeo/browser"; import { useEffect as useEffect4, useMemo as useMemo4, useState as useState6, useCallback as useCallback6 } from "react"; // src/utils/applyThemeToDOM.ts var applyThemeToDOM = (theme) => { Object.entries(theme.cssVariables).forEach(([key, value]) => { document.documentElement.style.setProperty(key, value); }); }; var applyThemeToDOM_default = applyThemeToDOM; // src/utils/normalizeThemeConfig.ts var normalizeColorValue = (color) => typeof color === "string" ? { main: color } : color; var normalizeThemeConfig = (config) => { if (!config?.colors) { return config; } const { primary, secondary, error, success, warning, info, ...restColors } = config.colors; return { ...config, colors: { ...restColors, ...primary !== void 0 ? { primary: normalizeColorValue(primary) } : {}, ...secondary !== void 0 ? { secondary: normalizeColorValue(secondary) } : {}, ...error !== void 0 ? { error: normalizeColorValue(error) } : {}, ...success !== void 0 ? { success: normalizeColorValue(success) } : {}, ...warning !== void 0 ? { warning: normalizeColorValue(warning) } : {}, ...info !== void 0 ? { info: normalizeColorValue(info) } : {} } }; }; var normalizeThemeConfig_default = normalizeThemeConfig; // src/contexts/Branding/useBrandingContext.ts import { useContext as useContext2 } from "react"; var useBrandingContext = () => { const context = useContext2(BrandingContext_default); if (!context) { throw new Error("useBrandingContext must be used within a BrandingProvider"); } return context; }; var useBrandingContext_default = useBrandingContext; // src/contexts/Theme/ThemeContext.ts import { createContext as createContext7 } from "react"; var ThemeContext = createContext7(null); ThemeContext.displayName = "ThemeContext"; var ThemeContext_default = ThemeContext; // src/contexts/Theme/v1/ThemeProvider.tsx import { jsx as jsx6 } from "react/jsx-runtime"; var logger2 = createPackageComponentLogger2( "@asgardeo/react", "ThemeProvider" ); var ThemeProvider = ({ children, theme: themeConfigProp, mode = DEFAULT_THEME, detection = {}, inheritFromBranding = true }) => { const themeConfig = normalizeThemeConfig_default(themeConfigProp); const [colorScheme, setColorScheme] = useState6(() => { if (mode === "light" || mode === "dark") { return mode; } if (mode === "branding") { return detectThemeMode("system", detection); } return detectThemeMode(mode, detection); }); let brandingTheme = null; let brandingActiveTheme = null; let isBrandingLoading = false; let brandingError = null; try { const brandingContext = useBrandingContext_default(); brandingTheme = brandingContext.theme; brandingActiveTheme = brandingContext.activeTheme; isBrandingLoading = brandingContext.isLoading; brandingError = brandingContext.error; } catch (error) { if (inheritFromBranding) { logger2.warn( "ThemeProvider: inheritFromBranding is enabled but BrandingProvider is not available. Make sure to wrap your app with BrandingProvider or AsgardeoProvider with branding preferences." ); } } useEffect4(() => { if (inheritFromBranding && brandingActiveTheme) { if (mode === "branding") { setColorScheme(brandingActiveTheme); } else if (mode === "system" && !isBrandingLoading) { setColorScheme(brandingActiveTheme);