UNPKG

@kubb/core

Version:

Core functionality for Kubb's plugin-based code generation system, providing the foundation for transforming OpenAPI specifications.

159 lines (126 loc) 3.7 kB
import seedrandom from 'seedrandom' import { colors } from 'consola/utils' import { EventEmitter } from './utils/EventEmitter.ts' import { resolve } from 'node:path' import { write } from './fs/index.ts' import { type ConsolaInstance, type LogLevel, createConsola } from 'consola' type DebugEvent = { date: Date; logs: string[]; fileName?: string } type Events = { start: [message: string] success: [message: string] error: [message: string, cause: Error] warning: [message: string] debug: [DebugEvent] info: [message: string] progress_start: [{ id: string; size: number; message?: string }] progressed: [{ id: string; message?: string }] progress_stop: [{ id: string }] } export const LogMapper = { silent: Number.NEGATIVE_INFINITY, info: 3, debug: 4, } as const export type Logger = { /** * Optional config name to show in CLI output */ name?: string logLevel: LogLevel consola?: ConsolaInstance on: EventEmitter<Events>['on'] emit: EventEmitter<Events>['emit'] writeLogs: () => Promise<string[]> } type Props = { name?: string logLevel?: LogLevel consola?: ConsolaInstance } export function createLogger({ logLevel = 3, name, consola: _consola }: Props = {}): Logger { const events = new EventEmitter<Events>() const startDate = Date.now() const cachedLogs = new Set<DebugEvent>() const consola = _consola || createConsola({ level: logLevel, formatOptions: { colors: true, date: true, columns: 80, compact: logLevel !== LogMapper.debug, }, }).withTag(name ? randomCliColour(name) : '') consola?.wrapConsole() events.on('start', (message) => { consola.start(message) }) events.on('success', (message) => { consola.success(message) }) events.on('warning', (message) => { consola.warn(colors.yellow(message)) }) events.on('info', (message) => { consola.info(colors.yellow(message)) }) events.on('debug', (message) => { if (message.logs.join('\n\n').length <= 100 && logLevel === LogMapper.debug) { console.log(message.logs.join('\n\n')) } cachedLogs.add(message) }) events.on('error', (message, cause) => { const error = new Error(message || 'Something went wrong') error.cause = cause throw error }) if (consola) { consola.level = logLevel } const logger: Logger = { name, logLevel, consola, on(...args) { return events.on(...args) }, emit(...args) { return events.emit(...args) }, async writeLogs() { const files: Record<string, string[]> = {} cachedLogs.forEach((log) => { const fileName = resolve(process.cwd(), '.kubb', log.fileName || `kubb-${startDate}.log`) if (!files[fileName]) { files[fileName] = [] } files[fileName] = [...files[fileName], `[${log.date.toLocaleString()}]: ${log.logs.join('\n\n')}`] }) await Promise.all( Object.entries(files).map(async ([fileName, logs]) => { return write(fileName, logs.join('\n')) }), ) return Object.keys(files) }, } return logger } export function randomColour(text?: string): keyof typeof colors { if (!text) { return 'white' } const defaultColours = ['black', 'red', 'green', 'yellow', 'blue', 'red', 'green', 'magenta', 'cyan', 'gray'] as const const random = seedrandom(text) const colour = defaultColours.at(Math.floor(random() * defaultColours.length)) || 'white' return colour } export function randomCliColour(text?: string): string { if (!text) { return '' } const colour = randomColour(text) return colors[colour]?.(text) }