UNPKG

vite-esbuild-typescript-checker

Version:

* Speeds up [TypeScript](https://github.com/Microsoft/TypeScript) type checking * Supports [Vue Single File Component](https://vuejs.org/v2/guide/single-file-components.html) * Displays nice error messages with the [code frame](https://babeljs.io/docs/en/

131 lines (130 loc) 4.52 kB
import { Worker } from 'worker_threads'; import path, { dirname } from 'path'; import moment from 'moment'; import pc from 'picocolors'; import { IssueError } from './functions.js'; import { fileURLToPath } from 'url'; const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); export class Helper { changedFiles = []; deletedFiles = []; startTime; worker; options; timeout = undefined; socket = undefined; constructor(workerData){ this.options = workerData; } workerStart(ws) { this.socket = ws; this.worker = new Worker(path.resolve(_dirname, 'worker.js'), { workerData: this.options }); this.startTime = new Date().getTime(); this.worker.on('message', (message)=>{ switch(message.type){ case 'diagnostic': const issues = message.data; issues.map((issue)=>{ const error = new IssueError(issue); const file = path.isAbsolute(error.file) ? error.file : path.resolve(this.options.basedir, error.file); console.log([ pc.red(`ERROR in ${file}`), `${error.message}` ].join('\n')); }); if (this.socket && issues.length) { this.socket.send(this.getPayloadError(issues)); } if (!this.options.watch) this.worker.postMessage({ type: 'kill' }); break; case 'info': console.log(message.data); break; case 'debug': const time = message.data - this.startTime; console.log(pc.bgBlue(`[${moment().format('Y-MM-DD H:mm:ss')}] DEBUG ${time}ms.`)); console.log(pc.bgBlue(message.data)); break; case 'done-time': if (this.startTime) { const time = message.data - this.startTime; console.log(pc.green(`[${moment().format('Y-MM-DD H:mm:ss')}] Types check done in ${time}ms.`)); this.startTime = null; } break; } }); this.worker.on('error', (e)=>{ console.error(e); process.exit(1); }); this.worker.on('exit', (code)=>{ process.exit(code); }); } getFilesChange() { return { changedFiles: this.changedFiles, deletedFiles: this.deletedFiles }; } clearFiles() { this.changedFiles = []; this.deletedFiles = []; if (this.timeout) clearTimeout(this.timeout); } addFile = (file)=>{ if (!file.endsWith('.vue') && !file.endsWith('.ts') && !file.endsWith('.js')) return; if (this.changedFiles.indexOf(file) === -1) { this.changedFiles.push(file); if (this.timeout) clearTimeout(this.timeout); this.timeout = setTimeout(this.changeFiles.bind(this), 300); } }; deleteFile = (file)=>{ if (!file.endsWith('.vue') && !file.endsWith('.ts') && !file.endsWith('.js') && !file.endsWith('vite.config.ts')) return; if (this.deletedFiles.indexOf(file) === -1) { this.deletedFiles.push(file); if (this.timeout) clearTimeout(this.timeout); this.timeout = setTimeout(this.changeFiles.bind(this), 300); } }; async changeFiles() { this.startTime = new Date().getTime(); this.worker.postMessage({ type: 'changeFiles', data: this.getFilesChange() }); this.clearFiles(); } getPayloadError(issues) { return { type: 'error', err: issueToViteError(issues[0]) }; } } export function issueToViteError(issue) { let loc; if (issue.location) { loc = { file: issue.file, line: issue.location.start.line, column: issue.location.start.column ?? 0 }; } return { message: issue.formatted ?? '', stack: '', id: issue.file, frame: 'issue.stripedCodeFrame', plugin: `vite-esbuild-typechecker-plugin`, loc }; } export default {};