// static/shared/js/log-config.js // noqa: js-001 - This IS the centralized logger implementation /** * Centralized Logging Configuration for ALL Frontends * * This file provides a consistent logging system across: * - Admin Frontend * - Store Frontend * - Shop Frontend * * Each frontend can customize log levels while sharing the same logging infrastructure. * * Usage in any frontend: * ```javascript * // Use the global logger * log.info('Page loaded'); * log.error('Something went wrong', error); * * // Or use a pre-configured logger * const storeLog = window.LogConfig.loggers.stores; * storeLog.info('Stores loaded'); * * // Or create a custom logger * const pageLog = window.LogConfig.createLogger('MY-PAGE', 3); * pageLog.info('Page initialized'); * ``` */ // ============================================================================ // LOG LEVELS // ============================================================================ const LOG_LEVELS = { ERROR: 1, // Only errors WARN: 2, // Errors and warnings INFO: 3, // Errors, warnings, and info (default) DEBUG: 4 // Everything including debug messages }; // ============================================================================ // FRONTEND DETECTION // ============================================================================ /** * Detect which frontend we're in based on URL path * @returns {string} 'admin' | 'store' | 'merchant' | 'storefront' | 'unknown' */ function detectFrontend() { // Prefer server-injected value (set in base templates before this script loads) if (window.FRONTEND_TYPE) return window.FRONTEND_TYPE; return 'unknown'; } // ============================================================================ // ENVIRONMENT DETECTION // ============================================================================ /** * Detect environment based on hostname * @returns {string} 'development' | 'production' */ function detectEnvironment() { const hostname = window.location.hostname; // Development environments if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname.startsWith('192.168.') || hostname.endsWith('.local')) { return 'development'; } return 'production'; } // ============================================================================ // LOG LEVEL CONFIGURATION // ============================================================================ /** * Default log levels per frontend * Can be overridden by environment */ const DEFAULT_LOG_LEVELS = { admin: { development: LOG_LEVELS.DEBUG, // Show everything in development production: LOG_LEVELS.WARN // Only warnings and errors in production }, store: { development: LOG_LEVELS.DEBUG, production: LOG_LEVELS.INFO // Stores might need more logging }, merchant: { development: LOG_LEVELS.DEBUG, production: LOG_LEVELS.INFO // Merchant portal: same as store }, storefront: { development: LOG_LEVELS.DEBUG, production: LOG_LEVELS.ERROR // Storefront: minimal logging in production }, unknown: { development: LOG_LEVELS.DEBUG, production: LOG_LEVELS.WARN } }; // ============================================================================ // ACTIVE LOG LEVEL DETERMINATION // ============================================================================ const CURRENT_FRONTEND = detectFrontend(); const CURRENT_ENVIRONMENT = detectEnvironment(); const ACTIVE_LOG_LEVEL = DEFAULT_LOG_LEVELS[CURRENT_FRONTEND][CURRENT_ENVIRONMENT]; // ============================================================================ // LOGGING UTILITIES // ============================================================================ /** * Create a logger with a specific prefix and log level * * @param {string} prefix - Logger prefix (e.g., 'STORES', 'THEME', 'PRODUCTS') * @param {number} level - Log level (1-4, defaults to ACTIVE_LOG_LEVEL) * @param {string} context - Optional frontend context (defaults to CURRENT_FRONTEND) * @returns {Object} Logger object with error, warn, info, debug methods */ function createLogger(prefix = 'APP', level = ACTIVE_LOG_LEVEL, context = CURRENT_FRONTEND) { const frontendPrefix = context.toUpperCase(); const formatPrefix = (emoji, label) => `${emoji} [${frontendPrefix}:${prefix} ${label}]`; return { error: (...args) => { if (level >= LOG_LEVELS.ERROR) { console.error(formatPrefix('❌', 'ERROR'), ...args); } }, warn: (...args) => { if (level >= LOG_LEVELS.WARN) { console.warn(formatPrefix('⚠️', 'WARN'), ...args); } }, info: (...args) => { if (level >= LOG_LEVELS.INFO) { console.info(formatPrefix('ℹ️', 'INFO'), ...args); } }, debug: (...args) => { if (level >= LOG_LEVELS.DEBUG) { console.log(formatPrefix('🔍', 'DEBUG'), ...args); } }, // Additional utility methods group: (label) => { if (level >= LOG_LEVELS.INFO) { console.group(formatPrefix('📂', 'GROUP') + ' ' + label); } }, groupEnd: () => { if (level >= LOG_LEVELS.INFO) { console.groupEnd(); } }, table: (data) => { if (level >= LOG_LEVELS.DEBUG) { console.table(data); } }, time: (label) => { if (level >= LOG_LEVELS.DEBUG) { console.time(formatPrefix('⏱️', 'TIME') + ' ' + label); } }, timeEnd: (label) => { if (level >= LOG_LEVELS.DEBUG) { console.timeEnd(formatPrefix('⏱️', 'TIME') + ' ' + label); } } }; } // ============================================================================ // DEFAULT GLOBAL LOGGER // ============================================================================ /** * Default logger for general operations * Automatically prefixed with current frontend */ const log = createLogger('APP', ACTIVE_LOG_LEVEL); // ============================================================================ // PRE-CONFIGURED LOGGERS FOR ADMIN FRONTEND // ============================================================================ const adminLoggers = { // Store management stores: createLogger('STORES', ACTIVE_LOG_LEVEL), storeTheme: createLogger('THEME', ACTIVE_LOG_LEVEL), storeUsers: createLogger('STORE-USERS', ACTIVE_LOG_LEVEL), // Merchant management merchants: createLogger('COMPANIES', ACTIVE_LOG_LEVEL), // Product management products: createLogger('PRODUCTS', ACTIVE_LOG_LEVEL), inventory: createLogger('INVENTORY', ACTIVE_LOG_LEVEL), // Order management orders: createLogger('ORDERS', ACTIVE_LOG_LEVEL), // User management users: createLogger('USERS', ACTIVE_LOG_LEVEL), // Admin operations audit: createLogger('AUDIT', ACTIVE_LOG_LEVEL), dashboard: createLogger('DASHBOARD', ACTIVE_LOG_LEVEL), // Import operations imports: createLogger('IMPORTS', ACTIVE_LOG_LEVEL), marketplace: createLogger('MARKETPLACE', ACTIVE_LOG_LEVEL) }; // ============================================================================ // PRE-CONFIGURED LOGGERS FOR STORE FRONTEND // ============================================================================ const storeLoggers = { // Dashboard dashboard: createLogger('DASHBOARD', ACTIVE_LOG_LEVEL), // Product management storeProducts: createLogger('PRODUCTS', ACTIVE_LOG_LEVEL), storeInventory: createLogger('INVENTORY', ACTIVE_LOG_LEVEL), marketplace: createLogger('MARKETPLACE', ACTIVE_LOG_LEVEL), // Order management storeOrders: createLogger('ORDERS', ACTIVE_LOG_LEVEL), orderDetail: createLogger('ORDER-DETAIL', ACTIVE_LOG_LEVEL), // Theme customization theme: createLogger('THEME', ACTIVE_LOG_LEVEL), // Settings storeSettings: createLogger('SETTINGS', ACTIVE_LOG_LEVEL), // Analytics storeAnalytics: createLogger('ANALYTICS', ACTIVE_LOG_LEVEL), // Messaging messages: createLogger('MESSAGES', ACTIVE_LOG_LEVEL), // Team storeTeam: createLogger('TEAM', ACTIVE_LOG_LEVEL), // Notifications storeNotifications: createLogger('NOTIFICATIONS', ACTIVE_LOG_LEVEL), // Profile storeProfile: createLogger('PROFILE', ACTIVE_LOG_LEVEL), // Customers storeCustomers: createLogger('CUSTOMERS', ACTIVE_LOG_LEVEL), // Content pages contentPages: createLogger('CONTENT-PAGES', ACTIVE_LOG_LEVEL), contentPageEdit: createLogger('CONTENT-PAGE-EDIT', ACTIVE_LOG_LEVEL) }; // ============================================================================ // PRE-CONFIGURED LOGGERS FOR STOREFRONT // ============================================================================ const storefrontLoggers = { // Product browsing catalog: createLogger('CATALOG', ACTIVE_LOG_LEVEL), product: createLogger('PRODUCT', ACTIVE_LOG_LEVEL), search: createLogger('SEARCH', ACTIVE_LOG_LEVEL), // Shopping cart cart: createLogger('CART', ACTIVE_LOG_LEVEL), checkout: createLogger('CHECKOUT', ACTIVE_LOG_LEVEL), // User account account: createLogger('ACCOUNT', ACTIVE_LOG_LEVEL), orders: createLogger('ORDERS', ACTIVE_LOG_LEVEL), // Wishlist wishlist: createLogger('WISHLIST', ACTIVE_LOG_LEVEL) }; // ============================================================================ // SMART LOGGER SELECTION // ============================================================================ /** * Get the appropriate logger set for current frontend */ function getLoggers() { switch (CURRENT_FRONTEND) { case 'admin': return adminLoggers; case 'store': return storeLoggers; case 'merchant': return storeLoggers; // Merchant portal reuses store logger set case 'storefront': return storefrontLoggers; default: return {}; // Empty object, use createLogger instead } } // Export frontend-specific loggers const loggers = getLoggers(); // ============================================================================ // API CALL LOGGING // ============================================================================ /** * Log API calls with consistent formatting * * @param {string} method - HTTP method (GET, POST, PUT, DELETE) * @param {string} url - API endpoint URL * @param {*} data - Request/response data (optional) * @param {string} status - 'request' or 'response' */ function logApiCall(method, url, data = null, status = 'request') { const apiLogger = createLogger('API', ACTIVE_LOG_LEVEL); const emoji = status === 'request' ? '📤' : '📥'; const message = `${emoji} ${method} ${url}`; if (ACTIVE_LOG_LEVEL >= LOG_LEVELS.DEBUG) { if (data) { apiLogger.debug(message, data); } else { apiLogger.debug(message); } } else if (ACTIVE_LOG_LEVEL >= LOG_LEVELS.INFO) { apiLogger.info(message); } } // ============================================================================ // ERROR LOGGING // ============================================================================ /** * Log errors with stack traces * * @param {Error} error - Error object * @param {string} context - Context where error occurred */ function logError(error, context = 'Unknown') { const errorLogger = createLogger('ERROR', ACTIVE_LOG_LEVEL); errorLogger.error(`Error in ${context}:`, error.message); if (ACTIVE_LOG_LEVEL >= LOG_LEVELS.DEBUG && error.stack) { console.error('Stack trace:', error.stack); } } // ============================================================================ // PERFORMANCE LOGGING // ============================================================================ /** * Log performance metrics * * @param {string} operation - Operation name * @param {number} duration - Duration in milliseconds */ function logPerformance(operation, duration) { const perfLogger = createLogger('PERF', ACTIVE_LOG_LEVEL); if (ACTIVE_LOG_LEVEL >= LOG_LEVELS.DEBUG) { const emoji = duration < 100 ? '⚡' : duration < 500 ? '⏱️' : '🐌'; perfLogger.debug(`${emoji} ${operation} took ${duration}ms`); } } // ============================================================================ // EXPORTS (for modules) // ============================================================================ // For pages that use module imports if (typeof module !== 'undefined' && module.exports) { module.exports = { LOG_LEVELS, log, loggers, createLogger, logApiCall, logError, logPerformance, detectFrontend, detectEnvironment }; } // ============================================================================ // GLOBAL ACCESS (for inline scripts) // ============================================================================ // Make available globally for inline scripts window.LogConfig = { LOG_LEVELS, log, loggers, createLogger, logApiCall, logError, logPerformance, // Expose frontend/environment info frontend: CURRENT_FRONTEND, environment: CURRENT_ENVIRONMENT, logLevel: ACTIVE_LOG_LEVEL }; // ============================================================================ // INITIALIZATION // ============================================================================ // Log that logging system is initialized if (ACTIVE_LOG_LEVEL >= LOG_LEVELS.INFO) { const frontendName = CURRENT_FRONTEND.charAt(0).toUpperCase() + CURRENT_FRONTEND.slice(1); const envName = CURRENT_ENVIRONMENT.charAt(0).toUpperCase() + CURRENT_ENVIRONMENT.slice(1); const levelName = Object.keys(LOG_LEVELS).find(k => LOG_LEVELS[k] === ACTIVE_LOG_LEVEL); console.log( `%c🎛️ ${frontendName} Frontend Logging System Initialized`, 'font-weight: bold; font-size: 14px; color: #6366f1;' ); console.log( `%c Environment: ${envName}`, 'color: #8b5cf6;' ); console.log( `%c Log Level: ${ACTIVE_LOG_LEVEL} (${levelName})`, 'color: #8b5cf6;' ); } // ============================================================================ // USAGE EXAMPLES (for developers) // ============================================================================ /* EXAMPLE 1: Use global logger ============================= window.LogConfig.log.info('Application started'); window.LogConfig.log.error('Failed to load data', error); EXAMPLE 2: Use pre-configured logger (RECOMMENDED) =================================================== // In admin frontend const themeLog = window.LogConfig.loggers.storeTheme; themeLog.info('Theme editor loaded'); // In store frontend const dashLog = window.LogConfig.loggers.dashboard; dashLog.info('Dashboard initialized'); // In shop frontend const cartLog = window.LogConfig.loggers.cart; cartLog.info('Cart updated'); EXAMPLE 3: Create custom logger ================================ const myLog = window.LogConfig.createLogger('MY-FEATURE', 4); myLog.info('Feature initialized'); EXAMPLE 4: Check current frontend ================================== if (window.LogConfig.frontend === 'admin') { // Admin-specific code } EXAMPLE 5: API call logging ============================ window.LogConfig.logApiCall('GET', '/api/stores', null, 'request'); const data = await apiClient.get('/api/stores'); window.LogConfig.logApiCall('GET', '/api/stores', data, 'response'); EXAMPLE 6: Performance logging =============================== const start = performance.now(); await loadData(); const duration = performance.now() - start; window.LogConfig.logPerformance('Load Data', duration); EXAMPLE 7: Error logging ========================= try { await saveData(); } catch (error) { window.LogConfig.logError(error, 'Save Operation'); } */