UNPKG

vite-plugin-checker

Version:

Vite plugin that runs TypeScript type checker on a separate process.

136 lines 5.01 kB
import { access, cp, mkdir, readFile, rm, writeFile } from "node:fs/promises"; import { createRequire } from "node:module"; import path, { dirname } from "node:path"; import { fileURLToPath } from "node:url"; import lockfile from "proper-lockfile"; const _require = createRequire(import.meta.url); const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); const vueTscDir = dirname(_require.resolve("vue-tsc/package.json")); const proxyApiPath = _require.resolve( "@volar/typescript/lib/node/proxyCreateProgram", { paths: [vueTscDir] } ); const extraSupportedExtensions = [".vue"]; const LOCK_TIMEOUT_MS = 6e4; const STALE_TIMEOUT_MS = 3e4; async function isFixtureValid(targetTsDir, vueTscFlagFile, currTsVersion) { try { await access(targetTsDir); const targetTsVersion = JSON.parse( await readFile(path.resolve(targetTsDir, "package.json"), "utf8") ).version; await access(vueTscFlagFile); const fixtureFlagContent = await readFile(vueTscFlagFile, "utf8"); return targetTsVersion === currTsVersion && fixtureFlagContent === proxyApiPath; } catch { return false; } } async function prepareVueTsc() { const targetTsDir = path.resolve(_dirname, "typescript-vue-tsc"); const vueTscFlagFile = path.resolve(targetTsDir, "vue-tsc-resolve-path"); const currTsVersion = _require("typescript/package.json").version; const tsMajorVersion = Number(currTsVersion.split(".")[0]); if (tsMajorVersion < 5) { throw new Error( "\x1B[35m[vite-plugin-checker] Since 0.7.0, vue-tsc checkers requires TypeScript 5.0.0 or newer version.\nPlease upgrade TypeScript, or use v0.6.4 which works with vue-tsc^1 if you can't upgrade. Check the pull request https://github.com/fi3ework/vite-plugin-checker/pull/327 for detail.\x1B[39m\n" ); } if (await isFixtureValid(targetTsDir, vueTscFlagFile, currTsVersion)) { return { targetTsDir }; } let release; try { release = await lockfile.lock(_dirname, { lockfilePath: path.resolve(_dirname, ".vue-tsc-fixture.lock"), stale: STALE_TIMEOUT_MS, retries: { retries: Math.ceil(LOCK_TIMEOUT_MS / 1e3), factor: 1, minTimeout: 1e3, maxTimeout: 2e3, randomize: true } }); } catch (err) { throw new Error( "[vite-plugin-checker] Failed to acquire lock for vue-tsc fixture preparation. Another process may be holding the lock.\n" + String(err) ); } try { if (await isFixtureValid(targetTsDir, vueTscFlagFile, currTsVersion)) { return { targetTsDir }; } await rm(targetTsDir, { force: true, recursive: true }); await mkdir(targetTsDir, { recursive: true }); const sourceTsDir = path.resolve(_require.resolve("typescript"), "../.."); await cp(sourceTsDir, targetTsDir, { recursive: true }); await writeFile(vueTscFlagFile, proxyApiPath); await overrideTscJs( _require.resolve(path.resolve(targetTsDir, "lib/typescript.js")) ); } finally { await release(); } return { targetTsDir }; } async function overrideTscJs(tscJsPath) { const languagePluginsFile = path.resolve(_dirname, "languagePlugins.cjs"); let tsc = await readFile(tscJsPath, "utf8"); const extsText = extraSupportedExtensions.map((ext) => `"${ext}"`).join(", "); tsc = replace( tsc, /supportedTSExtensions = .*(?=;)/, (s) => s + `.map((group, i) => i === 0 ? group.splice(0, 0, ${extsText}) && group : group)` ); tsc = replace( tsc, /supportedJSExtensions = .*(?=;)/, (s) => s + `.map((group, i) => i === 0 ? group.splice(0, 0, ${extsText}) && group : group)` ); tsc = replace( tsc, /allSupportedExtensions = .*(?=;)/, (s) => s + `.map((group, i) => i === 0 ? group.splice(0, 0, ${extsText}) && group : group)` ); const extsText2 = extraSupportedExtensions.map((ext) => `"${ext}"`).join(", "); tsc = replace( tsc, /function changeExtension\(/, (s) => `function changeExtension(path, newExtension) { return [${extsText2}].some(ext => path.endsWith(ext)) ? path + newExtension : _changeExtension(path, newExtension) } ${s.replace("changeExtension", "_changeExtension")}` ); tsc = replace( tsc, /function createProgram\(.+\) {/, (s) => `var createProgram = require(${JSON.stringify( proxyApiPath )}).proxyCreateProgram(${[ "new Proxy({}, { get(_target, p, _receiver) { return eval(p); } } )", "_createProgram", `require(${JSON.stringify(languagePluginsFile)}).getLanguagePlugins` ].join(", ")}); ${s.replace("createProgram", "_createProgram")}` ); function replace(_text, ...[search, replace2]) { const before = _text; const text = _text.replace(search, replace2); const after = text; if (after === before) { throw `Search string not found: ${JSON.stringify(search.toString())}`; } return after; } await writeFile(tscJsPath, tsc); } export { prepareVueTsc }; //# sourceMappingURL=prepareVueTsc.js.map