UNPKG

type-compiler

Version:

A TypeScript compiler plugin for enhanced runtime type checking and analysis with Zod validation

327 lines (326 loc) 10.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.LoggerSchema = exports.LoggerConfigSchema = exports.LogLevelSchema = exports.logger = exports.Logger = exports.LogLevel = void 0; exports.getLogger = getLogger; const zod_1 = require("zod"); const typescript_1 = __importDefault(require("typescript")); /** * Log levels for the type compiler */ var LogLevel; (function (LogLevel) { LogLevel[LogLevel["ERROR"] = 0] = "ERROR"; LogLevel[LogLevel["WARN"] = 1] = "WARN"; LogLevel[LogLevel["INFO"] = 2] = "INFO"; LogLevel[LogLevel["DEBUG"] = 3] = "DEBUG"; LogLevel[LogLevel["TRACE"] = 4] = "TRACE"; // Very verbose logging })(LogLevel || (exports.LogLevel = LogLevel = {})); /** * Default logger configuration */ const DEFAULT_CONFIG = { level: LogLevel.INFO, useColors: true, includeTimestamps: true, logToFile: false }; /** * Colors for different log levels when useColors is true */ const COLORS = { [LogLevel.ERROR]: '\x1b[31m', // Red [LogLevel.WARN]: '\x1b[33m', // Yellow [LogLevel.INFO]: '\x1b[36m', // Cyan [LogLevel.DEBUG]: '\x1b[90m', // Gray [LogLevel.TRACE]: '\x1b[90m', // Gray RESET: '\x1b[0m' }; /** * Logger class for the type compiler */ class Logger { constructor(config = {}) { this.buffer = []; this.startTime = Date.now(); this.compilationMetrics = { typesProcessed: 0, filesProcessed: 0, cacheHits: 0, cacheMisses: 0, workerTasksProcessed: 0, errors: 0, warnings: 0 }; this.config = { ...DEFAULT_CONFIG, ...config }; } /** * Reconfigure the logger */ configure(config) { this.config = { ...this.config, ...config }; } /** * Configure the logger from TypeCompilerOptions */ configureFromOptions(options) { const level = this.getLogLevelFromOptions(options); this.configure({ level }); } /** * Map TypeCompilerOptions to LogLevel */ getLogLevelFromOptions(options) { if (options.logLevel !== undefined) { return options.logLevel; } // Determine log level based on other options if (options.debug === true) { return LogLevel.DEBUG; } if (options.verbose === true) { return LogLevel.INFO; } if (options.silent === true) { return LogLevel.ERROR; } return LogLevel.INFO; // Default log level } /** * Log a message at a specific level */ log(level, message, context) { if (level > this.config.level) { return; } if (this.config.filter && !this.config.filter(level, message, context)) { return; } let formattedMessage = ''; // Add timestamp if configured if (this.config.includeTimestamps) { const timestamp = new Date().toISOString(); formattedMessage += `[${timestamp}] `; } // Add log level indicator const levelNames = ['ERROR', 'WARN', 'INFO', 'DEBUG', 'TRACE']; const levelName = levelNames[level] || 'UNKNOWN'; // Add colors if configured if (this.config.useColors) { formattedMessage += `${COLORS[level]}[${levelName}]${COLORS.RESET} `; } else { formattedMessage += `[${levelName}] `; } // Add the message formattedMessage += message; // Add context if provided if (context && Object.keys(context).length > 0) { const contextStr = JSON.stringify(context, null, 2); formattedMessage += ` ${contextStr}`; } // Output to console if (level === LogLevel.ERROR) { console.error(formattedMessage); this.compilationMetrics.errors++; } else if (level === LogLevel.WARN) { console.warn(formattedMessage); this.compilationMetrics.warnings++; } else { console.log(formattedMessage); } // Store in buffer for later retrieval this.buffer.push(formattedMessage); // TODO: Log to file if configured // This would be implemented with Node.js fs functions } /** * Log an error message */ error(message, context) { this.log(LogLevel.ERROR, message, context); } /** * Log a warning message */ warn(message, context) { this.log(LogLevel.WARN, message, context); } /** * Log an info message */ info(message, context) { this.log(LogLevel.INFO, message, context); } /** * Log a debug message */ debug(message, context) { this.log(LogLevel.DEBUG, message, context); } /** * Log a trace message */ trace(message, context) { this.log(LogLevel.TRACE, message, context); } /** * Handle TypeScript diagnostics */ logDiagnostics(diagnostics) { if (diagnostics.length === 0) { return; } this.info(`Found ${diagnostics.length} TypeScript diagnostic messages`); for (const diagnostic of diagnostics) { const message = typescript_1.default.flattenDiagnosticMessageText(diagnostic.messageText, '\n'); if (diagnostic.category === typescript_1.default.DiagnosticCategory.Error) { this.error(message, this.formatDiagnosticLocation(diagnostic)); } else if (diagnostic.category === typescript_1.default.DiagnosticCategory.Warning) { this.warn(message, this.formatDiagnosticLocation(diagnostic)); } else { this.info(message, this.formatDiagnosticLocation(diagnostic)); } } } /** * Format diagnostic location information */ formatDiagnosticLocation(diagnostic) { if (!diagnostic.file || diagnostic.start === undefined) { return undefined; } const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); return { file: diagnostic.file.fileName, line: line + 1, character: character + 1 }; } /** * Update compilation metrics */ updateMetrics(metrics) { Object.assign(this.compilationMetrics, metrics); } /** * Increment a specific metric */ incrementMetric(metric, amount = 1) { if (this.compilationMetrics[metric] !== undefined) { this.compilationMetrics[metric] += amount; } else { this.compilationMetrics[metric] = amount; } } /** * Log compilation summary */ logCompilationSummary() { const elapsedTime = (Date.now() - this.startTime) / 1000; this.info('Compilation completed', { elapsedTime: `${elapsedTime.toFixed(2)}s`, ...this.compilationMetrics }); // Log performance information if (this.compilationMetrics.typesProcessed > 0) { const typesPerSecond = (this.compilationMetrics.typesProcessed / elapsedTime).toFixed(2); this.info(`Processed ${this.compilationMetrics.typesProcessed} types (${typesPerSecond} types/sec)`); } if (this.compilationMetrics.cacheHits > 0 || this.compilationMetrics.cacheMisses > 0) { const totalCacheRequests = this.compilationMetrics.cacheHits + this.compilationMetrics.cacheMisses; const cacheHitRate = (this.compilationMetrics.cacheHits / totalCacheRequests * 100).toFixed(2); this.info(`Cache hit rate: ${cacheHitRate}% (${this.compilationMetrics.cacheHits} hits, ${this.compilationMetrics.cacheMisses} misses)`); } // Log errors and warnings if (this.compilationMetrics.errors > 0 || this.compilationMetrics.warnings > 0) { this.info(`Encountered ${this.compilationMetrics.errors} errors and ${this.compilationMetrics.warnings} warnings`); } } /** * Start timing an operation */ startTimer(label) { const startTime = Date.now(); // Return a function that, when called, will end the timer and log the duration return () => { const duration = Date.now() - startTime; this.debug(`${label} completed in ${duration}ms`); }; } /** * Get the log buffer */ getBuffer() { return [...this.buffer]; } /** * Clear the log buffer */ clearBuffer() { this.buffer = []; } /** * Reset compilation metrics */ resetMetrics() { this.startTime = Date.now(); Object.keys(this.compilationMetrics).forEach(key => { this.compilationMetrics[key] = 0; }); } } exports.Logger = Logger; // Create a global logger instance with default configuration exports.logger = new Logger(); // Helper function to get the global logger function getLogger() { return exports.logger; } exports.LogLevelSchema = z.object({ toString: z.any(), toFixed: z.any(), toExponential: z.any(), toPrecision: z.any(), valueOf: z.any(), toLocaleString: z.any() }); exports.LoggerConfigSchema = z.object({ level: z.any(), useColors: z.any(), includeTimestamps: z.any(), logToFile: z.any(), logFilePath: z.any(), filter: z.any() }); exports.LoggerSchema = z.object({ config: z.any(), buffer: z.any(), startTime: z.any(), compilationMetrics: z.any(), configure: z.any(), configureFromOptions: z.any(), getLogLevelFromOptions: z.any(), log: z.any(), error: z.any(), warn: z.any(), info: z.any(), debug: z.any(), trace: z.any(), logDiagnostics: z.any(), formatDiagnosticLocation: z.any(), updateMetrics: z.any(), incrementMetric: z.any(), logCompilationSummary: z.any(), startTimer: z.any(), getBuffer: z.any(), clearBuffer: z.any(), resetMetrics: z.any() });