@asgardeo/react
Version:
React implementation of Asgardeo JavaScript SDK.
1,554 lines (1,524 loc) • 442 kB
JavaScript
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