{"version":3,"file":"logger.js","names":["strip","isMainThread"],"sources":["../src/logger.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport os from 'node:os'\nimport { stripVTControlCharacters as strip } from 'node:util'\nimport { parentPort } from 'node:worker_threads'\nimport type { SourceLocation } from '@babel/code-frame'\nimport colors from 'picocolors'\n\nimport { WS_CHECKER_ERROR_EVENT } from './client/index.js'\nimport {\n createFrame,\n lineColLocToBabelLoc,\n tsLikeLocToBabelLoc,\n} from './codeFrame.js'\nimport {\n ACTION_TYPES,\n type ClientDiagnosticPayload,\n DiagnosticLevel,\n type DiagnosticToRuntime,\n} from './types.js'\nimport { isMainThread } from './utils.js'\n\nconst _require = createRequire(import.meta.url)\n\nimport type { ESLint } from 'eslint'\nimport type Stylelint from 'stylelint'\nimport type {\n flattenDiagnosticMessageText as flattenDiagnosticMessageTextType,\n Diagnostic as TsDiagnostic,\n} from 'typescript'\n\nexport interface NormalizedDiagnostic {\n /** error message */\n message?: string\n /** error conclusion */\n conclusion?: string\n /** error stack */\n stack?: string | string[]\n /** file name */\n id?: string\n /** checker diagnostic source */\n checker: string\n /** raw code frame generated by @babel/code-frame */\n codeFrame?: string\n /** code frame, but striped */\n stripedCodeFrame?: string\n /** error code location */\n loc?: SourceLocation\n /** error level */\n level?: DiagnosticLevel\n}\n\nconst defaultLogLevel = [\n DiagnosticLevel.Warning,\n DiagnosticLevel.Error,\n DiagnosticLevel.Suggestion,\n DiagnosticLevel.Message,\n]\n\nexport function filterLogLevel(\n diagnostics: NormalizedDiagnostic,\n level?: DiagnosticLevel[],\n): NormalizedDiagnostic | null\nexport function filterLogLevel(\n diagnostics: NormalizedDiagnostic[],\n level?: DiagnosticLevel[],\n): NormalizedDiagnostic[]\nexport function filterLogLevel(\n diagnostics: NormalizedDiagnostic | NormalizedDiagnostic[],\n level: DiagnosticLevel[] = defaultLogLevel,\n): NormalizedDiagnostic | null | NormalizedDiagnostic[] {\n if (Array.isArray(diagnostics)) {\n return diagnostics.filter((d) => {\n if (typeof d.level !== 'number') return false\n return level.includes(d.level)\n })\n }\n if (!diagnostics.level) return null\n return level.includes(diagnostics.level) ? diagnostics : null\n}\n\nexport function diagnosticToTerminalLog(\n d: NormalizedDiagnostic,\n name?: 'TypeScript' | 'vue-tsc' | 'ESLint' | 'Stylelint' | 'Biome' | 'oxlint',\n): string {\n const nameInLabel = name ? `(${name})` : ''\n const boldBlack = (str: string) => colors.bold(colors.black(str))\n\n const labelMap: Record = {\n [DiagnosticLevel.Error]: boldBlack(\n colors.bgRedBright(` ERROR${nameInLabel} `),\n ),\n [DiagnosticLevel.Warning]: boldBlack(\n colors.bgYellowBright(` WARNING${nameInLabel} `),\n ),\n [DiagnosticLevel.Suggestion]: boldBlack(\n colors.bgBlueBright(` SUGGESTION${nameInLabel} `),\n ),\n [DiagnosticLevel.Message]: boldBlack(\n colors.bgCyanBright(` MESSAGE${nameInLabel} `),\n ),\n }\n\n const levelLabel = labelMap[d.level ?? DiagnosticLevel.Error]\n const fileLabel = `${boldBlack(colors.bgCyanBright(' FILE '))} `\n const position = d.loc\n ? `${colors.yellow(d.loc.start.line)}:${colors.yellow(d.loc.start.column || '')}`\n : ''\n\n return [\n `${levelLabel} ${d.message}`,\n `${fileLabel + d.id}:${position}${os.EOL}`,\n d.codeFrame + os.EOL,\n d.conclusion,\n ]\n .filter(Boolean)\n .join(os.EOL)\n}\n\nexport function diagnosticToConsoleLevel(d: NormalizedDiagnostic) {\n if (!d) return 'error'\n if (d.level === DiagnosticLevel.Message) return 'info'\n if (d.level === DiagnosticLevel.Suggestion) return 'info'\n if (d.level === DiagnosticLevel.Warning) return 'warn'\n return 'error'\n}\n\nexport function diagnosticToRuntimeError(\n d: NormalizedDiagnostic,\n): DiagnosticToRuntime\nexport function diagnosticToRuntimeError(\n d: NormalizedDiagnostic[],\n): DiagnosticToRuntime[]\nexport function diagnosticToRuntimeError(\n diagnostics: NormalizedDiagnostic | NormalizedDiagnostic[],\n): DiagnosticToRuntime | DiagnosticToRuntime[] {\n const diagnosticsArray = Array.isArray(diagnostics)\n ? diagnostics\n : [diagnostics]\n\n const results: DiagnosticToRuntime[] = diagnosticsArray.map((d) => {\n let loc: DiagnosticToRuntime['loc']\n if (d.loc) {\n loc = {\n file: d.id ?? '',\n line: d.loc.start.line,\n column: typeof d.loc.start.column === 'number' ? d.loc.start.column : 0,\n }\n }\n\n return {\n message: d.message ?? '',\n stack:\n typeof d.stack === 'string'\n ? d.stack\n : Array.isArray(d.stack)\n ? d.stack.join(os.EOL)\n : '',\n id: d.id,\n frame: d.stripedCodeFrame,\n checkerId: d.checker,\n level: d.level,\n loc,\n }\n })\n\n return Array.isArray(diagnostics) ? results : results[0]!\n}\n\nexport function toClientPayload(\n id: string,\n diagnostics: DiagnosticToRuntime[],\n): ClientDiagnosticPayload {\n return {\n event: WS_CHECKER_ERROR_EVENT,\n data: {\n checkerId: id,\n diagnostics,\n },\n }\n}\n\nexport function wrapCheckerSummary(\n checkerName: string,\n rawSummary: string,\n): string {\n return `[${checkerName}] ${rawSummary}`\n}\n\nexport function composeCheckerSummary(\n checkerName: string,\n errorCount: number,\n warningCount: number,\n): string {\n const message = `Found ${errorCount} error${\n errorCount > 1 ? 's' : ''\n } and ${warningCount} warning${warningCount > 1 ? 's' : ''}`\n\n const hasError = errorCount > 0\n const hasWarning = warningCount > 0\n const color = hasError ? 'red' : hasWarning ? 'yellow' : 'green'\n return colors[color](wrapCheckerSummary(checkerName, message))\n}\n\n/* ------------------------------- TypeScript ------------------------------- */\n\nexport function normalizeTsDiagnostic(d: TsDiagnostic): NormalizedDiagnostic {\n const fileName = d.file?.fileName\n const {\n flattenDiagnosticMessageText,\n }: {\n flattenDiagnosticMessageText: typeof flattenDiagnosticMessageTextType\n } = _require('typescript')\n\n const message = flattenDiagnosticMessageText(d.messageText, os.EOL)\n\n let loc: SourceLocation | undefined\n const pos =\n d.start === undefined\n ? null\n : d.file?.getLineAndCharacterOfPosition?.(d.start)\n if (\n pos &&\n d.file &&\n typeof d.start === 'number' &&\n typeof d.length === 'number'\n ) {\n loc = tsLikeLocToBabelLoc({\n start: pos,\n end: d.file.getLineAndCharacterOfPosition(d.start + d.length),\n })\n }\n\n let codeFrame: string | undefined\n if (loc) {\n codeFrame = createFrame(d.file!.text, loc)\n }\n\n return {\n message,\n conclusion: '',\n codeFrame,\n stripedCodeFrame: codeFrame && strip(codeFrame),\n id: fileName,\n checker: 'TypeScript',\n loc,\n level: d.category as any as DiagnosticLevel,\n }\n}\n\n/* --------------------------------- vue-tsc -------------------------------- */\n\nexport function normalizeVueTscDiagnostic(\n d: TsDiagnostic,\n): NormalizedDiagnostic {\n const diagnostic = normalizeTsDiagnostic(d)\n diagnostic.checker = 'vue-tsc'\n return diagnostic\n}\n\n/* --------------------------------- ESLint --------------------------------- */\n\nconst isNormalizedDiagnostic = (\n d: NormalizedDiagnostic | null | undefined,\n): d is NormalizedDiagnostic => {\n return Boolean(d)\n}\n\nexport function normalizeEslintDiagnostic(\n diagnostic: ESLint.LintResult,\n): NormalizedDiagnostic[] {\n return diagnostic.messages\n .map((d) => {\n let level = DiagnosticLevel.Error\n switch (d.severity as number) {\n case 0: // off, ignore this\n level = DiagnosticLevel.Error\n return null\n case 1: // warn\n level = DiagnosticLevel.Warning\n break\n case 2: // error\n level = DiagnosticLevel.Error\n break\n }\n\n const loc = lineColLocToBabelLoc(d)\n\n const codeFrame = createFrame(diagnostic.source ?? '', loc)\n\n return {\n message: `${d.message} (${d.ruleId})`,\n conclusion: '',\n codeFrame,\n stripedCodeFrame: codeFrame && strip(codeFrame),\n id: diagnostic.filePath,\n checker: 'ESLint',\n loc,\n level,\n } as any as NormalizedDiagnostic\n })\n .filter(isNormalizedDiagnostic)\n}\n\n/* --------------------------------- Stylelint --------------------------------- */\n\nexport function normalizeStylelintDiagnostic(\n diagnostic: Stylelint.LintResult,\n): NormalizedDiagnostic[] {\n return diagnostic.warnings\n .map((d) => {\n let level = DiagnosticLevel.Error\n switch (d.severity) {\n case 'warning': // warn\n level = DiagnosticLevel.Warning\n break\n case 'error': // error\n level = DiagnosticLevel.Error\n break\n default:\n level = DiagnosticLevel.Error\n return null\n }\n\n const loc = lineColLocToBabelLoc(d)\n\n const codeFrame = createFrame(diagnostic._postcssResult?.css ?? '', loc)\n\n return {\n message: `${d.text} (${d.rule})`,\n conclusion: '',\n codeFrame,\n stripedCodeFrame: codeFrame && strip(codeFrame),\n id: diagnostic.source,\n checker: 'Stylelint',\n loc,\n level,\n } as any as NormalizedDiagnostic\n })\n .filter(isNormalizedDiagnostic)\n}\n\n/* ------------------------------ miscellaneous ----------------------------- */\nexport function ensureCall(callback: CallableFunction) {\n setTimeout(() => {\n callback()\n })\n}\n\nexport function consoleLog(value: string, level: 'info' | 'warn' | 'error') {\n if (isMainThread) {\n console[level](value)\n } else {\n parentPort?.postMessage({\n type: ACTION_TYPES.console,\n level: level,\n payload: value,\n })\n }\n}\n"],"mappings":"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"}