Files
orion/static/shared/js/log-config.js
Samir Boulahtit b4f01210d9 fix(ui): inject window.FRONTEND_TYPE from server + rename SHOP→STOREFRONT
Server now injects window.FRONTEND_TYPE in all base templates via
get_context_for_frontend(). Both log-config.js and dev-toolbar.js read
this instead of guessing from URL paths, fixing:
- UNKNOWN prefix on merchant pages
- Incorrect detection on custom domains/subdomains in prod

Also adds frontend_type to login page contexts (admin, merchant, store).

Renames all [SHOP] logger prefixes to [STOREFRONT] across 7 files
(storefront-layout.js + 6 storefront templates).

Adds 'merchant' and 'storefront' to log-config.js frontend detection,
log levels, and logger selection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 21:08:59 +01:00

520 lines
16 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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');
}
*/