UNPKG

@asgardeo/react

Version:
1,554 lines (1,524 loc) 442 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 } from "@asgardeo/browser"; import { useEffect as useEffect5, useMemo as useMemo6, useRef, useState as useState7, useCallback as useCallback7 } from "react"; // src/contexts/Asgardeo/AsgardeoContext.ts import { createContext } from "react"; var AsgardeoContext = createContext({ organizationHandle: void 0, applicationId: void 0, signInUrl: void 0, signUpUrl: void 0, afterSignInUrl: void 0, baseUrl: void 0, isInitialized: false, isLoading: true, isSignedIn: false, organization: null, signIn: null, signInSilently: null, signOut: null, signUp: null, user: null, http: { request: () => null, requestAll: () => null }, signInOptions: {}, getDecodedIdToken: null, getAccessToken: null, exchangeToken: null, storage: "sessionStorage" }); AsgardeoContext.displayName = "AsgardeoContext"; var AsgardeoContext_default = AsgardeoContext; // src/AsgardeoReactClient.ts import { AsgardeoBrowserClient, flattenUserSchema, generateFlattenedUserProfile, generateUserProfile, AsgardeoRuntimeError, executeEmbeddedSignUpFlow, executeEmbeddedSignInFlow, deriveOrganizationHandleFromBaseUrl, extractUserClaimsFromIdToken, navigate, getRedirectBasedSignUpUrl } from "@asgardeo/browser"; // src/__temp__/api.ts import { AsgardeoSPAClient, Hooks } from "@asgardeo/browser"; var _AuthAPI = class _AuthAPI { constructor(spaClient) { __publicField(this, "_authState", _AuthAPI.DEFAULT_STATE); __publicField(this, "_client"); __publicField(this, "_isLoading"); this._client = spaClient ?? AsgardeoSPAClient.getInstance(); 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); } _setIsLoading(isLoading) { this._isLoading = isLoading; } _getIsLoading() { return this._isLoading; } isLoading() { return this._getIsLoading(); } /** * 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(); } /** * 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, isSignedIn: true, isLoading: false, isSigningOut: false, username: response.username }; this.updateState(stateToUpdate); this._setIsLoading(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, isSignedIn: true, isLoading: false }); } 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 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)); } }; __publicField(_AuthAPI, "DEFAULT_STATE"); var AuthAPI = _AuthAPI; AuthAPI.DEFAULT_STATE = { displayName: "", email: "", isSignedIn: false, isLoading: true, username: "" }; var api_default = AuthAPI; // src/api/getMeOrganizations.ts import { AsgardeoSPAClient as AsgardeoSPAClient2, getMeOrganizations as baseGetMeOrganizations } from "@asgardeo/browser"; var httpClient = AsgardeoSPAClient2.getInstance().httpRequest.bind(AsgardeoSPAClient2.getInstance()); var getMeOrganizations = async ({ fetcher, ...requestConfig }) => { const defaultFetcher = async (url, config) => { const response = await httpClient({ url, method: config.method || "GET", headers: config.headers }); return { ok: response.status >= 200 && response.status < 300, status: response.status, statusText: response.statusText || "", json: () => Promise.resolve(response.data), 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/getScim2Me.ts import { AsgardeoSPAClient as AsgardeoSPAClient3, getScim2Me as baseGetScim2Me } from "@asgardeo/browser"; var httpClient2 = AsgardeoSPAClient3.getInstance().httpRequest.bind(AsgardeoSPAClient3.getInstance()); var getScim2Me = async ({ fetcher, ...requestConfig }) => { const defaultFetcher = async (url, config) => { const response = await httpClient2({ url, method: config.method || "GET", headers: config.headers }); return { ok: response.status >= 200 && response.status < 300, status: response.status, statusText: response.statusText || "", json: () => Promise.resolve(response.data), text: () => Promise.resolve(typeof response.data === "string" ? response.data : JSON.stringify(response.data)) }; }; return baseGetScim2Me({ ...requestConfig, fetcher: fetcher || defaultFetcher }); }; var getScim2Me_default = getScim2Me; // src/api/getSchemas.ts import { AsgardeoSPAClient as AsgardeoSPAClient4, getSchemas as baseGetSchemas } from "@asgardeo/browser"; var httpClient3 = AsgardeoSPAClient4.getInstance().httpRequest.bind(AsgardeoSPAClient4.getInstance()); var getSchemas = async ({ fetcher, ...requestConfig }) => { const defaultFetcher = async (url, config) => { const response = await httpClient3({ url, method: config.method || "GET", headers: config.headers }); return { ok: response.status >= 200 && response.status < 300, status: response.status, statusText: response.statusText || "", json: () => Promise.resolve(response.data), 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/getAllOrganizations.ts import { AsgardeoSPAClient as AsgardeoSPAClient5, getAllOrganizations as baseGetAllOrganizations } from "@asgardeo/browser"; var httpClient4 = AsgardeoSPAClient5.getInstance().httpRequest.bind(AsgardeoSPAClient5.getInstance()); var getAllOrganizations = async ({ fetcher, ...requestConfig }) => { const defaultFetcher = async (url, config) => { const response = await httpClient4({ url, method: config.method || "GET", headers: config.headers }); return { ok: response.status >= 200 && response.status < 300, status: response.status, statusText: response.statusText || "", json: () => Promise.resolve(response.data), text: () => Promise.resolve(typeof response.data === "string" ? response.data : JSON.stringify(response.data)) }; }; return baseGetAllOrganizations({ ...requestConfig, fetcher: fetcher || defaultFetcher }); }; var getAllOrganizations_default = getAllOrganizations; // src/AsgardeoReactClient.ts var AsgardeoReactClient = class extends AsgardeoBrowserClient { constructor() { super(); __publicField(this, "asgardeo"); __publicField(this, "_isLoading", false); this.asgardeo = new api_default(); } /** * Set the loading state of the client * @param loading - Boolean indicating if the client is in a loading state */ setLoading(loading) { this._isLoading = 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, storage) { let resolvedOrganizationHandle = config?.organizationHandle; if (!resolvedOrganizationHandle) { resolvedOrganizationHandle = deriveOrganizationHandleFromBaseUrl(config?.baseUrl); } return this.withLoading(async () => { return this.asgardeo.init({ ...config, organizationHandle: resolvedOrganizationHandle }); }); } async updateUserProfile(payload, userId) { 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.withLoading(async () => { return this.asgardeo.getDecodedIdToken(sessionId); }); } 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 }); const schemas = await getSchemas_default({ baseUrl }); const processedSchemas = flattenUserSchema(schemas); const output = { schemas: processedSchemas, flattenedProfile: generateFlattenedUserProfile(profile, processedSchemas), profile }; return output; } catch (error) { return { schemas: [], flattenedProfile: extractUserClaimsFromIdToken(await this.getDecodedIdToken()), profile: extractUserClaimsFromIdToken(await this.getDecodedIdToken()) }; } }); } async getMyOrganizations(options, sessionId) { try { let baseUrl = options?.baseUrl; if (!baseUrl) { const configData = await this.asgardeo.getConfigData(); baseUrl = configData?.baseUrl; } return getMeOrganizations_default({ baseUrl }); } 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, sessionId) { try { let baseUrl = options?.baseUrl; if (!baseUrl) { const configData = await this.asgardeo.getConfigData(); baseUrl = configData?.baseUrl; } return getAllOrganizations_default({ baseUrl }); } 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() { return this.withLoading(async () => { const idToken = await this.getDecodedIdToken(); return { orgHandle: idToken?.org_handle, name: idToken?.org_name, id: idToken?.org_id }; }); } async switchOrganization(organization, sessionId) { return this.withLoading(async () => { try { const configData = await this.asgardeo.getConfigData(); 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, (user) => { }); } 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._isLoading || this.asgardeo.isLoading(); } async isInitialized() { return this.asgardeo.isInitialized(); } async isSignedIn() { return await this.asgardeo.isSignedIn(); } getConfiguration() { return this.asgardeo.getConfigData(); } async exchangeToken(config, sessionId) { return this.withLoading(async () => { return this.asgardeo.exchangeToken(config, (user) => { }); }); } async signIn(...args) { return this.withLoading(async () => { const arg1 = args[0]; const arg2 = args[1]; 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.withLoading(async () => { 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 response = await this.asgardeo.signOut(args[1]); return Promise.resolve(String(response)); } async signUp(...args) { const configData = await this.asgardeo.getConfigData(); const firstArg = args[0]; if (typeof firstArg === "object" && "flowType" in firstArg) { const baseUrl = configData?.baseUrl; return executeEmbeddedSignUpFlow({ baseUrl, payload: firstArg }); } navigate(getRedirectBasedSignUpUrl(configData)); } async request(requestConfig) { return this.asgardeo.httpRequest(requestConfig); } async requestAll(requestConfigs) { return this.asgardeo.httpRequestAll(requestConfigs); } async getAccessToken(sessionId) { return this.withLoading(async () => { return this.asgardeo.getAccessToken(sessionId); }); } }; var AsgardeoReactClient_default = AsgardeoReactClient; // src/hooks/useBrowserUrl.ts import { hasAuthParamsInUrl } 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; return { hasAuthParams }; }; var useBrowserUrl_default = useBrowserUrl; // src/contexts/Flow/FlowProvider.tsx import { useCallback, useMemo, useState } from "react"; // src/contexts/Flow/FlowContext.ts import { createContext as createContext2 } from "react"; var FlowContext = createContext2(void 0); FlowContext.displayName = "FlowContext"; var FlowContext_default = FlowContext; // src/contexts/Flow/FlowProvider.tsx import { jsx } from "react/jsx-runtime"; var FlowProvider = ({ children, initialStep = null, initialTitle = "", initialSubtitle, onFlowChange }) => { const [currentStep, setCurrentStepState] = useState(initialStep); const [title, setTitle] = useState(initialTitle); const [subtitle, setSubtitle] = useState(initialSubtitle); const [messages, setMessages] = useState([]); const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(false); const [showBackButton, setShowBackButton] = useState(false); const [onGoBack, setOnGoBack] = useState(void 0); const setCurrentStep = useCallback( (step) => { setCurrentStepState(step); if (step) { setTitle(step.title); setSubtitle(step.subtitle); setShowBackButton(step.canGoBack ?? false); } onFlowChange?.(step); }, [onFlowChange] ); const addMessage = useCallback((message) => { const messageWithId = { ...message, id: message.id ?? `msg-${Date.now()}-${Math.random().toString(36).substr(2, 9)}` }; setMessages((prev) => [...prev, messageWithId]); }, []); const removeMessage = useCallback((messageId) => { setMessages((prev) => prev.filter((msg) => msg.id !== messageId)); }, []); const clearMessages = useCallback(() => { setMessages([]); }, []); const reset = useCallback(() => { setCurrentStepState(initialStep); setTitle(initialTitle); setSubtitle(initialSubtitle); setMessages([]); setError(null); setIsLoading(false); setShowBackButton(false); setOnGoBack(void 0); }, [initialStep, initialTitle, initialSubtitle]); const navigateToFlow = useCallback( (flowType, options) => { const stepId = `${flowType}-${Date.now()}`; const step = { id: stepId, type: flowType, title: options?.title, subtitle: options?.subtitle, canGoBack: flowType !== "signin", // Usually allow going back except for main signin metadata: options?.metadata }; setCurrentStep(step); clearMessages(); setError(null); }, [setCurrentStep, clearMessages] ); const contextValue = useMemo( () => ({ currentStep, setCurrentStep, title, setTitle, subtitle, setSubtitle, messages, addMessage, removeMessage, clearMessages, error, setError, isLoading, setIsLoading, showBackButton, setShowBackButton, onGoBack, setOnGoBack, reset, navigateToFlow }), [ currentStep, setCurrentStep, title, subtitle, messages, addMessage, removeMessage, clearMessages, error, isLoading, showBackButton, onGoBack, reset, navigateToFlow ] ); return /* @__PURE__ */ jsx(FlowContext_default.Provider, { value: contextValue, children }); }; var FlowProvider_default = FlowProvider; // src/contexts/I18n/I18nProvider.tsx import { useCallback as useCallback2, useEffect, useMemo as useMemo2, useState as useState2 } from "react"; import { deepMerge } from "@asgardeo/browser"; import { getI18nBundles } from "@asgardeo/browser"; // src/contexts/I18n/I18nContext.ts import { createContext as createContext3 } from "react"; var I18nContext = createContext3(null); I18nContext.displayName = "I18nContext"; var I18nContext_default = I18nContext; // src/contexts/I18n/I18nProvider.tsx import { jsx as jsx2 } from "react/jsx-runtime"; 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) { console.warn("Failed to store language preference:", error); } } }; var I18nProvider = ({ children, preferences }) => { const defaultBundles = getI18nBundles(); 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] = useState2(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], translations: deepMerge(merged[key].translations, userBundle.translations), metadata: userBundle.metadata ? { ...merged[key].metadata, ...userBundle.metadata } : merged[key].metadata }; } else { merged[key] = userBundle; } }); } return merged; }, [defaultBundles, preferences?.bundles]); const fallbackLanguage = preferences?.fallbackLanguage || "en-US"; useEffect(() => { storeLanguage(currentLanguage); }, [currentLanguage]); const t = useCallback2( (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]) => { return acc.replace(new RegExp(`\\{${paramKey}\\}`, "g"), String(paramValue)); }, translation); } return translation; }, [mergedBundles, currentLanguage, fallbackLanguage] ); const setLanguage = useCallback2( (language) => { if (mergedBundles[language]) { setCurrentLanguage(language); } else { console.warn( `Language '${language}' is not available. Available languages: ${Object.keys(mergedBundles).join(", ")}` ); } }, [mergedBundles] ); const contextValue = useMemo2( () => ({ currentLanguage, fallbackLanguage, bundles: mergedBundles, setLanguage, t }), [currentLanguage, fallbackLanguage, mergedBundles, setLanguage, t] ); return /* @__PURE__ */ jsx2(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 useCallback3, useMemo as useMemo3, useState as useState3 } from "react"; // src/contexts/Organization/OrganizationContext.ts import { createContext as createContext4 } from "react"; var OrganizationContext = createContext4({ 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 jsx3 } from "react/jsx-runtime"; var OrganizationProvider = ({ children, currentOrganization, onError, myOrganizations, onOrganizationSwitch, revalidateMyOrganizations, getAllOrganizations: getAllOrganizations2, createOrganization: createOrganization2 }) => { const [isLoading, setIsLoading] = useState3(false); const [error, setError] = useState3(null); const switchOrganization = useCallback3( 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__ */ jsx3(OrganizationContext_default.Provider, { value: contextValue, children }); }; var OrganizationProvider_default = OrganizationProvider; // src/contexts/Theme/ThemeProvider.tsx import { useEffect as useEffect2, useMemo as useMemo4, useState as useState4, useCallback as useCallback4 } from "react"; import { createTheme, detectThemeMode, createClassObserver, createMediaQueryListener, DEFAULT_THEME } from "@asgardeo/browser"; // src/contexts/Theme/ThemeContext.ts import { createContext as createContext5 } from "react"; var ThemeContext = createContext5(null); ThemeContext.displayName = "ThemeContext"; var ThemeContext_default = ThemeContext; // src/contexts/Branding/useBrandingContext.ts import { useContext } from "react"; // src/contexts/Branding/BrandingContext.ts import { createContext as createContext6 } from "react"; var BrandingContext = createContext6(null); BrandingContext.displayName = "BrandingContext"; var BrandingContext_default = BrandingContext; // src/contexts/Branding/useBrandingContext.ts var useBrandingContext = () => { const context = useContext(BrandingContext_default); if (!context) { throw new Error("useBrandingContext must be used within a BrandingProvider"); } return context; }; var useBrandingContext_default = useBrandingContext; // src/contexts/Theme/ThemeProvider.tsx import { jsx as jsx4 } from "react/jsx-runtime"; var applyThemeToDOM = (theme) => { Object.entries(theme.cssVariables).forEach(([key, value]) => { document.documentElement.style.setProperty(key, value); }); }; var ThemeProvider = ({ children, theme: themeConfig, mode = DEFAULT_THEME, detection = {}, inheritFromBranding = true }) => { const [colorScheme, setColorScheme] = useState4(() => { 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) { console.warn( "ThemeProvider: inheritFromBranding is enabled but BrandingProvider is not available. Make sure to wrap your app with BrandingProvider or AsgardeoProvider with branding preferences." ); } } useEffect2(() => { if (inheritFromBranding && brandingActiveTheme) { if (mode === "branding") { setColorScheme(brandingActiveTheme); } else if (mode === "system" && !isBrandingLoading) { setColorScheme(brandingActiveTheme); } } }, [inheritFromBranding, brandingActiveTheme, mode, isBrandingLoading]); const finalThemeConfig = useMemo4(() => { if (!inheritFromBranding || !brandingTheme) { return themeConfig; } const brandingThemeConfig = { colors: brandingTheme.colors, borderRadius: brandingTheme.borderRadius, shadows: brandingTheme.shadows, spacing: brandingTheme.spacing, images: brandingTheme.images, components: brandingTheme.components }; return { ...brandingThemeConfig, ...themeConfig, colors: { ...brandingThemeConfig.colors, ...themeConfig?.colors }, borderRadius: { ...brandingThemeConfig.borderRadius, ...themeConfig?.borderRadius }, shadows: { ...brandingThemeConfig.shadows, ...themeConfig?.shadows }, spacing: { ...brandingThemeConfig.spacing, ...themeConfig?.spacing }, images: { ...brandingThemeConfig.images, ...themeConfig?.images }, components: { ...brandingThemeConfig.components, ...themeConfig?.components } }; }, [inheritFromBranding, brandingTheme, themeConfig]); const theme = useMemo4(() => createTheme(finalThemeConfig, colorScheme === "dark"), [finalThemeConfig, colorScheme]); const handleThemeChange = useCallback4((isDark) => { setColorScheme(isDark ? "dark" : "light"); }, []); const toggleTheme = useCallback4(() => { setColorScheme((prev) => prev === "light" ? "dark" : "light"); }, []); useEffect2(() => { let observer = null; let mediaQuery = null; if (mode === "branding") { return null; } if (mode === "class") { const targetElement = detection.targetElement || document.documentElement; if (targetElement) { observer = createClassObserver(targetElement, handleThemeChange, detection); } } else if (mode === "system") { if (!inheritFromBranding || !brandingActiveTheme) { mediaQuery = createMediaQueryListener(handleThemeChange); } } return () => { if (observer) { observer.disconnect(); } if (mediaQuery) { if (mediaQuery.removeEventListener) { mediaQuery.removeEventListener("change", handleThemeChange); } else { mediaQuery.removeListener(handleThemeChange); } } }; }, [mode, detection, handleThemeChange, inheritFromBranding, brandingActiveTheme]); useEffect2(() => { applyThemeToDOM(theme); }, [theme]); const value = { theme, colorScheme, toggleTheme, isBrandingLoading, brandingError, inheritFromBranding }; return /* @__PURE__ */ jsx4(ThemeContext_default.Provider, { value, children }); }; var ThemeProvider_default = ThemeProvider; // src/contexts/Branding/BrandingProvider.tsx import { useCallback as useCallback5, useEffect as useEffect3, useState as useState5 } from "react"; import { transformBrandingPreferenceToTheme } from "@asgardeo/browser"; import { jsx as jsx5 } from "react/jsx-runtime"; var BrandingProvider = ({ children, brandingPreference: externalBrandingPreference, forceTheme, enabled = true, isLoading: externalIsLoading = false, error: externalError = null, refetch: externalRefetch }) => { const [theme, setTheme] = useState5(null); const [activeTheme, setActiveTheme] = useState5(null); useEffect3(() => { 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]); useEffect3(() => { if (!enabled) { setTheme(null); setActiveTheme(null); } }, [enabled]); const fetchBranding = useCallback5(async () => { if (externalRefetch) { await externalRefetch(); } }, [externalRefetch]); const value = { brandingPreference: externalBrandingPreference || null, theme, activeTheme, isLoading: externalIsLoading, error: externalError, fetchBranding, refetch: externalRefetch || fetchBranding }; return /* @__PURE__ */ jsx5(BrandingContext_default.Provider, { value, children }); }; var BrandingProvider_default = BrandingProvider; // src/contexts/User/UserProvider.tsx import { useMemo as useMemo5 } from "react"; // src/contexts/User/UserContext.ts import { createContext as createContext7 } from "react"; var UserContext = createContext7({ profile: null, schemas: null, flattenedProfile: null, revalidateProfile: () => null, updateProfile: () => null, onUpdateProfile: () => null }); UserContext.displayName = "UserContext"; var UserContext_default = UserContext; // src/contexts/User/UserProvider.tsx import { jsx as jsx6 } from "react/jsx-runtime"; var UserProvider = ({ children, profile, revalidateProfile, onUpdateProfile, updateProfile }) => { const contextValue = useMemo5( () => ({ schemas: profile?.schemas, profile: profile?.profile, flattenedProfile: profile?.flattenedProfile, revalidateProfile, updateProfile, onUpdateProfile }), [profile, onUpdateProfile, revalidateProfile, updateProfile] ); return /* @__PURE__ */ jsx6(UserContext_default.Provider, { value: contextValue, children }); }; var UserProvider_default = UserProvider; // src/contexts/Asgardeo/AsgardeoProvider.tsx import { jsx as jsx7 } from "react/jsx-runtime"; var AsgardeoProvider = ({ afterSignInUrl = window.location.origin, afterSignOutUrl = window.location.origin, baseUrl: _baseUrl, clientId, children, scopes, preferences, signInUrl, signUpUrl, organizationHandle, applicationId, signInOptions, syncSession, ...rest }) => { const reRenderCheckRef = useRef(false); const asgardeo = useMemo6(() => new AsgardeoReactClient_default(), []); const { hasAuthParams } = useBrowserUrl_default(); const [user, setUser] = useState7(null); const [currentOrganization, setCurrentOrganization] = useState7(null); const [isSignedInSync, setIsSignedInSync] = useState7(false); const [isInitializedSync, setIsInitializedSync] = useState7(false); const [isLoadingSync, setIsLoadingSync] = useState7(true); const [myOrganizations, setMyOrganizations] = useState7([]); const [userProfile, setUserProfile] = useState7(null); const [baseUrl, setBaseUrl] = useState7(_baseUrl); const [config, setConfig] = useState7({ applicationId, organizationHandle, afterSignInUrl, afterSignOutUrl, baseUrl, clientId, scopes, signUpUrl, signInUrl, signInOptions, syncSession, ...rest }); const [isUpdatingSession, setIsUpdatingSession] = useState7(false); const [brandingPreference, setBrandingPreference] = useState7(null); const [isBrandingLoading, setIsBrandingLoading] = useState7(false); const [brandingError, setBrandingError] = useState7(null); const [hasFetchedBranding, setHasFetchedBranding] = useState7(false); useEffect5(() => { setBaseUrl(_baseUrl); if (_baseUrl !== baseUrl) { setHasFetchedBranding(false); setBrandingPreference(null); setBrandingError(null); } }, [_baseUrl, baseUrl]); useEffect5(() => { (async () => { await asgardeo.initialize(config); setConfig(await asgardeo.getConfiguration()); })(); }, []); useEffect5(() => { if (reRenderCheckRef.current) { return; } reRenderCheckRef.current = true; (async () => { const isAlreadySignedIn = await asgardeo.isSignedIn(); if (isAlreadySignedIn) { await updateSession(); return; } const currentUrl = new URL(window.location.href); const hasAuthParamsResult = hasAuthParams(currentUrl, afterSignInUrl); if (hasAuthParamsResult) { try { await signIn( { callOnlyOnRedirect: true } // authParams?.authorizationCode, // authParams?.sessionState, // authParams?.state, ); } catch (error) { if (error && Object.prototype.hasOwnProperty.call(error, "code")) { } } } else { } })(); }, []); useEffect5(() => { let interval; (async () => { try { const status = await asgardeo.isSignedIn(); setIsSignedInSync(status); if (!status) { interval = setInterval(async () => { const newStatus = await asgardeo.isSignedIn(); if (newStatus) { setIsSignedInSync(true); clearInterval(interval); } }, 1e3); } else { } } catch (error) { setIsSignedInSync(false); } })(); return () => { if (interval) { clearInterval(interval); } }; }, [asgardeo]); useEffect5(() => { (async () => { try { const status = await asgardeo.isInitialized(); setIsInitializedSync(status); } catch (error) { setIsInitializedSync(false); } })(); }, [asgardeo]); useEffect5(() => { const checkLoadingState = () => { if (isUpdatingSession) { return; } setIsLoadingSync(asgardeo.isLoading()); }; checkLoadingState(); const interval = setInterval(checkLoadingState, 100); return () => { clearInterval(interval); }; }, [asgardeo, isLoadingSync, isSignedInSync, isUpdatingSession]); const updateSession = async () => { try { setIsUpdatingSession(true); setIsLoadingSync(true); let _baseUrl2 = baseUrl; const decodedToken = await asgardeo.getDecodedIdToken(); if (decodedToken?.["user_org"]) { _baseUrl2 = `${(await asgardeo.getConfiguration()).baseUrl}/o`; setBaseUrl(_baseUrl2); } const user2 = await asgardeo.getUser({ baseUrl: _baseUrl2 }); const userProfile2 = await asgardeo.getUserProfile({ baseUrl: _baseUrl2 }); const currentOrganization2 = await asgardeo.getCurrentOrganization(); const myOrganizations2 = await asgardeo.getMyOrganizations(); setUser(user2); setUserProfile(userProfile2); setCurrentOrganization(currentOrganization2); setMyOrganizations(myOrganizations2); const currentSignInStatus = await asgardeo.isSignedIn(); setIsSignedInSync(await asgardeo.isSignedIn()); } catch (error) { } finally { setIsUpdatingSession(false); setIsLoadingSync(asgardeo.isLoading()); } }; const fetchBranding = useCallback7(async () => { if (!baseUrl) { return; } if (isBrandingLoading) { return; } setIsBrandingLoading(true); setBrandingError(null); try { const getBrandingConfig = { baseUrl, locale: preferences?.i18n?.language // Add other branding config options as needed }; const brandingData = await getBrandingPreference(getBrandingConfig); setBrandingPreference(brandingData); setHasFetchedBranding(true); } catch (err) { const errorMessage = err instance