video-query/frontend/src/utils/configLoader.js

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
};
};