UNPKG

@gftdcojp/gftd-orm

Version:

Enterprise-grade real-time data platform with ksqlDB, inspired by Supabase architecture

293 lines 8.13 kB
/** * クライアントサイド専用ログ機能 * winston を使わず console ベースで実装 */ import { isBrowser } from './utils/env'; /** * デフォルト設定 */ const defaultConfig = { level: 'info', enableTimestamp: true, enableColors: true, enableStackTrace: false, prefix: '[GFTD-ORM]', }; /** * ログレベルの順序 */ const logLevels = { debug: 0, info: 1, warn: 2, error: 3, }; /** * ログ色 */ const logColors = { debug: '#6B7280', // gray info: '#3B82F6', // blue warn: '#F59E0B', // amber error: '#EF4444', // red }; /** * ログ絵文字 */ const logEmojis = { debug: '🐛', info: 'ℹ️', warn: '⚠️', error: '❌', }; /** * クライアント用ログ機能 */ export class ClientLogger { constructor(config = {}) { this.config = { ...defaultConfig, ...config }; // ブラウザ環境でのみ動作 if (!isBrowser()) { throw new Error('ClientLogger can only be used in browser environment'); } } /** * シングルトンインスタンスを取得 */ static getInstance(config) { if (!ClientLogger.instance) { ClientLogger.instance = new ClientLogger(config); } return ClientLogger.instance; } /** * 設定を更新 */ setConfig(config) { this.config = { ...this.config, ...config }; } /** * ログレベルを設定 */ setLevel(level) { this.config.level = level; } /** * ログを出力するかどうかを判定 */ shouldLog(level) { return logLevels[level] >= logLevels[this.config.level]; } /** * タイムスタンプを取得 */ getTimestamp() { if (!this.config.enableTimestamp) return ''; return new Date().toISOString(); } /** * フォーマットされたメッセージを作成 */ formatMessage(level, message, meta) { const timestamp = this.getTimestamp(); const prefix = this.config.prefix || ''; const emoji = logEmojis[level]; let formattedMessage = ''; if (timestamp) { formattedMessage += `[${timestamp}] `; } if (prefix) { formattedMessage += `${prefix} `; } formattedMessage += `${emoji} ${message}`; if (meta && Object.keys(meta).length > 0) { formattedMessage += ` ${JSON.stringify(meta)}`; } return formattedMessage; } /** * ログを出力 */ log(level, message, meta) { if (!this.shouldLog(level)) return; const formattedMessage = this.formatMessage(level, message, meta); // コンソールのスタイル設定 if (this.config.enableColors && typeof console !== 'undefined') { const color = logColors[level]; const style = `color: ${color}; font-weight: bold;`; switch (level) { case 'debug': console.debug(`%c${formattedMessage}`, style); break; case 'info': console.info(`%c${formattedMessage}`, style); break; case 'warn': console.warn(`%c${formattedMessage}`, style); break; case 'error': console.error(`%c${formattedMessage}`, style); break; } } else { // 色なしの場合 switch (level) { case 'debug': console.debug(formattedMessage); break; case 'info': console.info(formattedMessage); break; case 'warn': console.warn(formattedMessage); break; case 'error': console.error(formattedMessage); break; } } } /** * デバッグログ */ debug(message, meta) { this.log('debug', message, meta); } /** * 情報ログ */ info(message, meta) { this.log('info', message, meta); } /** * 警告ログ */ warn(message, meta) { this.log('warn', message, meta); } /** * エラーログ */ error(message, error, meta) { let errorMeta = meta || {}; if (error instanceof Error) { errorMeta = { ...errorMeta, error: error.message, stack: this.config.enableStackTrace ? error.stack : undefined, }; } else if (error) { errorMeta = { ...errorMeta, error: error, }; } this.log('error', message, errorMeta); } /** * 成功ログ */ success(message, meta) { this.info(`✅ ${message}`, meta); } /** * 失敗ログ */ failure(message, error, meta) { this.error(`❌ ${message}`, error, meta); } /** * グループ化されたログ */ group(label) { if (console.group) { console.group(`🔍 ${label}`); } } /** * グループ終了 */ groupEnd() { if (console.groupEnd) { console.groupEnd(); } } /** * テーブル形式のログ */ table(data) { if (console.table) { console.table(data); } else { this.info('Table data:', data); } } /** * 時間計測開始 */ time(label) { if (console.time) { console.time(label); } } /** * 時間計測終了 */ timeEnd(label) { if (console.timeEnd) { console.timeEnd(label); } } } // デフォルトのログ機能をエクスポート let _clientLog = null; export const clientLog = { get instance() { if (!_clientLog) { _clientLog = ClientLogger.getInstance(); } return _clientLog; }, debug: (message, meta) => clientLog.instance.debug(message, meta), info: (message, meta) => clientLog.instance.info(message, meta), warn: (message, meta) => clientLog.instance.warn(message, meta), error: (message, error, meta) => clientLog.instance.error(message, error, meta), success: (message, meta) => clientLog.instance.success(message, meta), failure: (message, error, meta) => clientLog.instance.failure(message, error, meta), group: (label) => clientLog.instance.group(label), groupEnd: () => clientLog.instance.groupEnd(), table: (data) => clientLog.instance.table(data), time: (label) => clientLog.instance.time(label), timeEnd: (label) => clientLog.instance.timeEnd(label), setLevel: (level) => clientLog.instance.setLevel(level), setConfig: (config) => clientLog.instance.setConfig(config), }; /** * ログ設定を初期化 */ export function initializeClientLogger(config = {}) { return ClientLogger.getInstance(config); } /** * 従来のコンソールログ代替機能 */ export const consoleLogger = { debug: (message, ...args) => clientLog.debug(message, { args }), info: (message, ...args) => clientLog.info(message, { args }), warn: (message, ...args) => clientLog.warn(message, { args }), error: (message, ...args) => clientLog.error(message, args[0], { args: args.slice(1) }), log: (message, ...args) => clientLog.info(message, { args }), success: (message, ...args) => clientLog.success(message, { args }), failure: (message, error, ...args) => clientLog.failure(message, error, { args }), group: (label) => clientLog.group(label), groupEnd: () => clientLog.groupEnd(), table: (data) => clientLog.table(data), time: (label) => clientLog.time(label), timeEnd: (label) => clientLog.timeEnd(label), }; //# sourceMappingURL=client-logger.js.map