207 lines
No EOL
5.9 KiB
JavaScript
207 lines
No EOL
5.9 KiB
JavaScript
/**
|
|
* Runtime configuration loader
|
|
* Fetches configuration from public/config.json at application startup
|
|
*/
|
|
|
|
let cachedConfig = null;
|
|
let configPromise = null;
|
|
|
|
/**
|
|
* Loads configuration from the public config.json file
|
|
* @returns {Promise<Object>} The configuration object
|
|
*/
|
|
export const loadConfig = async () => {
|
|
if (cachedConfig) {
|
|
return cachedConfig;
|
|
}
|
|
|
|
if (configPromise) {
|
|
return configPromise;
|
|
}
|
|
|
|
configPromise = (async () => {
|
|
try {
|
|
console.log('Loading runtime configuration...');
|
|
|
|
// Check if config was already loaded by config.js script
|
|
if (typeof window !== 'undefined' && window.__APP_CONFIG__) {
|
|
console.log('Using config from window.__APP_CONFIG__');
|
|
const config = window.__APP_CONFIG__;
|
|
|
|
// Validate required configuration
|
|
if (!config.msal) {
|
|
throw new Error('Missing MSAL configuration in config');
|
|
}
|
|
|
|
if (!config.msal.clientId || !config.msal.authority) {
|
|
throw new Error('Missing required MSAL configuration fields (clientId, authority)');
|
|
}
|
|
|
|
console.log('Runtime configuration loaded successfully from script');
|
|
cachedConfig = config;
|
|
return config;
|
|
}
|
|
|
|
// Fallback to fetch config.json if not loaded by script
|
|
console.log('Fetching config.json as fallback...');
|
|
const response = await fetch('./config.json');
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to load config: ${response.status} ${response.statusText}`);
|
|
}
|
|
|
|
const config = await response.json();
|
|
|
|
// Validate required configuration
|
|
if (!config.msal) {
|
|
throw new Error('Missing MSAL configuration in config.json');
|
|
}
|
|
|
|
if (!config.msal.clientId || !config.msal.authority || !config.msal.redirectUri) {
|
|
throw new Error('Missing required MSAL configuration fields (clientId, authority, redirectUri)');
|
|
}
|
|
|
|
console.log('Runtime configuration loaded successfully');
|
|
cachedConfig = config;
|
|
return config;
|
|
|
|
} catch (error) {
|
|
console.error('Error loading configuration:', error);
|
|
throw error;
|
|
}
|
|
})();
|
|
|
|
return configPromise;
|
|
};
|
|
|
|
/**
|
|
* Gets the cached configuration (synchronous)
|
|
* Must call loadConfig() first to ensure config is loaded
|
|
* @returns {Object|null} The cached configuration or null if not loaded
|
|
*/
|
|
export const getConfig = () => {
|
|
return cachedConfig;
|
|
};
|
|
|
|
/**
|
|
* Clears the cached configuration (useful for testing)
|
|
*/
|
|
export const clearConfig = () => {
|
|
cachedConfig = null;
|
|
configPromise = null;
|
|
};
|
|
|
|
/**
|
|
* Gets MSAL configuration from the loaded config
|
|
* @returns {Object} MSAL configuration object
|
|
*/
|
|
export const getMsalConfig = () => {
|
|
if (!cachedConfig) {
|
|
throw new Error('Configuration not loaded. Call loadConfig() first.');
|
|
}
|
|
|
|
// Import pathUtils here to avoid circular dependencies
|
|
const { getRedirectUri } = require('./pathUtils');
|
|
|
|
return {
|
|
auth: {
|
|
clientId: cachedConfig.msal.clientId,
|
|
authority: cachedConfig.msal.authority,
|
|
redirectUri: getRedirectUri('/'),
|
|
postLogoutRedirectUri: getRedirectUri('/'),
|
|
navigateToLoginRequestUrl: true
|
|
},
|
|
cache: {
|
|
cacheLocation: "sessionStorage",
|
|
storeAuthStateInCookie: true,
|
|
},
|
|
system: {
|
|
allowRedirectInIframe: true,
|
|
tokenRenewalOffsetSeconds: 300,
|
|
loggerOptions: {
|
|
loggerCallback: (level, message) => {
|
|
console.log(`MSAL: ${message}`);
|
|
},
|
|
logLevel: 4 // Verbose
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Gets API configuration from the loaded config
|
|
* @returns {Object} API configuration object
|
|
*/
|
|
export const getApiConfig = () => {
|
|
if (!cachedConfig) {
|
|
throw new Error('Configuration not loaded. Call loadConfig() first.');
|
|
}
|
|
|
|
return cachedConfig.api || {};
|
|
};
|
|
|
|
/**
|
|
* Gets the tenant ID for manual auth flows
|
|
* @returns {string} The tenant ID
|
|
*/
|
|
export const getTenantId = () => {
|
|
if (!cachedConfig) {
|
|
throw new Error('Configuration not loaded. Call loadConfig() first.');
|
|
}
|
|
|
|
return cachedConfig.msal.tenantId || cachedConfig.msal.authority.split('/').pop();
|
|
};
|
|
|
|
/**
|
|
* Gets the base path from configuration
|
|
* @returns {string|undefined} The configured base path
|
|
*/
|
|
export const getBasePath = () => {
|
|
if (!cachedConfig) {
|
|
return undefined;
|
|
}
|
|
return cachedConfig.basePath;
|
|
};
|
|
|
|
/**
|
|
* Gets the domain from configuration
|
|
* @returns {string|undefined} The configured domain
|
|
*/
|
|
export const getDomain = () => {
|
|
if (!cachedConfig) {
|
|
return undefined;
|
|
}
|
|
return cachedConfig.domain;
|
|
};
|
|
|
|
/**
|
|
* Constructs a redirect URI using configuration
|
|
* @param {string} path - Optional path to append (defaults to '/')
|
|
* @returns {string} Complete redirect URI
|
|
*/
|
|
export const getRedirectUri = (path = '/') => {
|
|
if (!cachedConfig) {
|
|
throw new Error('Configuration not loaded. Call loadConfig() first.');
|
|
}
|
|
|
|
// Import pathUtils here to avoid circular dependencies
|
|
const { getFullUrl } = require('./pathUtils');
|
|
return getFullUrl(path);
|
|
};
|
|
|
|
/**
|
|
* Gets configuration for manual authentication flows (Login.js)
|
|
* @returns {Object} Configuration for constructing auth URLs
|
|
*/
|
|
export const getManualAuthConfig = () => {
|
|
if (!cachedConfig) {
|
|
throw new Error('Configuration not loaded. Call loadConfig() first.');
|
|
}
|
|
|
|
return {
|
|
tenantId: getTenantId(),
|
|
clientId: cachedConfig.msal.clientId,
|
|
redirectUri: getRedirectUri('/'),
|
|
authority: cachedConfig.msal.authority
|
|
};
|
|
}; |