feat: init

This commit is contained in:
2026-02-13 22:02:30 +01:00
commit 8f9ff830fb
16711 changed files with 3307340 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
const path = require('node:path')
const vueTscDir = path.dirname(require.resolve('vue-tsc/package.json'))
const vue =
/** @type {typeof import('@vue/language-core') & { resolveVueCompilerOptions?: any }} */ (
require(require.resolve('@vue/language-core', { paths: [vueTscDir] }))
)
const windowsPathReg = /\\/g
const removeEmitGlobalTypesRegexp =
/^[^\n]*__VLS_globalTypesStart[\w\W]*__VLS_globalTypesEnd[^\n]*\n?$/gm
/**
* @param dts {string}
* @returns {string}
*/
function removeEmitGlobalTypes(dts) {
return dts.replace(removeEmitGlobalTypesRegexp, '')
}
const getDefaultCompilerOptions =
vue.getDefaultCompilerOptions || (() => vue.resolveVueCompilerOptions({}))
// #region copied from https://github.com/vuejs/language-tools/blob/0781998a29f176ad52c30d3139d5c78a5688bd5d/packages/tsc/index.ts
/**
* @param {typeof import('typescript')} ts
* @param {import('typescript').CreateProgramOptions} options
*/
exports.getLanguagePlugins = (ts, options) => {
const { configFilePath } = options.options
const vueOptions =
typeof configFilePath === 'string'
? vue.createParsedCommandLine(
ts,
ts.sys,
configFilePath.replace(windowsPathReg, '/'),
).vueOptions
: getDefaultCompilerOptions()
if (vue.writeGlobalTypes) {
vue.writeGlobalTypes(vueOptions, ts.sys.writeFile)
} else {
const host = /** @type {import('typescript').CompilerHost} */ (options.host)
const writeFile = host.writeFile.bind(host)
host.writeFile = (fileName, contents, ...args) => {
return writeFile(fileName, removeEmitGlobalTypes(contents), ...args)
}
}
const vueLanguagePlugin = vue.createVueLanguagePlugin(
ts,
options.options,
vueOptions,
(id) => id,
)
return [vueLanguagePlugin]
}
// #endregion

View File

@@ -0,0 +1,18 @@
import { Checker } from '../../Checker.js';
import 'vite';
import '../../types.js';
import 'node:worker_threads';
import 'eslint';
import 'stylelint';
import '../vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
import '../../worker.js';
declare let createServeAndBuild: any;
declare class VueTscChecker extends Checker<'vueTsc'> {
constructor();
init(): void;
}
export { VueTscChecker, createServeAndBuild };

View File

@@ -0,0 +1,160 @@
import { createRequire } from "node:module";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { parentPort } from "node:worker_threads";
import invariant from "tiny-invariant";
import { Checker } from "../../Checker.js";
import {
consoleLog,
diagnosticToRuntimeError,
diagnosticToTerminalLog,
ensureCall,
normalizeVueTscDiagnostic,
toClientPayload,
wrapCheckerSummary
} from "../../logger.js";
import {
ACTION_TYPES
} from "../../types.js";
import { prepareVueTsc } from "./prepareVueTsc.js";
const _require = createRequire(import.meta.url);
const __filename = fileURLToPath(import.meta.url);
let createServeAndBuild;
const createDiagnostic = (pluginConfig) => {
let overlay = true;
let terminal = true;
let currDiagnostics = [];
return {
config: ({ enableOverlay, enableTerminal }) => {
overlay = enableOverlay;
terminal = enableTerminal;
},
async configureServer({ root }) {
invariant(pluginConfig.vueTsc, "config.vueTsc should be `false`");
const { targetTsDir } = await prepareVueTsc();
const vueTs = _require(path.resolve(targetTsDir, "lib/typescript.js"));
const finalConfig = pluginConfig.vueTsc === true ? { root, tsconfigPath: "tsconfig.json" } : {
root: pluginConfig.vueTsc.root ?? root,
tsconfigPath: pluginConfig.vueTsc.tsconfigPath ?? "tsconfig.json"
};
const configFile = vueTs.findConfigFile(
finalConfig.root,
vueTs.sys.fileExists,
finalConfig.tsconfigPath
);
if (configFile === void 0) {
throw Error(
`Failed to find a valid tsconfig.json: ${finalConfig.tsconfigPath} at ${finalConfig.root} is not a valid tsconfig`
);
}
let logChunk = "";
let prevLogChunk = "";
const reportDiagnostic = (diagnostic) => {
const normalizedDiagnostic = normalizeVueTscDiagnostic(diagnostic);
if (normalizedDiagnostic === null) {
return;
}
currDiagnostics.push(diagnosticToRuntimeError(normalizedDiagnostic));
logChunk += os.EOL + diagnosticToTerminalLog(normalizedDiagnostic, "vue-tsc");
};
const reportWatchStatusChanged = (diagnostic, _newLine, _options, errorCount) => {
var _a;
if (diagnostic.code === 6031) return;
switch (diagnostic.code) {
case 6031:
case 6032:
logChunk = "";
currDiagnostics = [];
return;
case 6193:
// 1 Error
case 6194:
if (overlay) {
(_a = parentPort) == null ? void 0 : _a.postMessage({
type: ACTION_TYPES.overlayError,
payload: toClientPayload("vue-tsc", currDiagnostics)
});
}
}
ensureCall(() => {
if (errorCount === 0) {
logChunk = "";
}
if (terminal) {
logChunk = logChunk + os.EOL + wrapCheckerSummary("vue-tsc", diagnostic.messageText.toString());
if (logChunk === prevLogChunk) {
return;
}
prevLogChunk = logChunk;
consoleLog(logChunk, errorCount ? "error" : "info");
}
});
};
const createProgram = vueTs.createEmitAndSemanticDiagnosticsBuilderProgram;
if (typeof pluginConfig.vueTsc === "object" && pluginConfig.vueTsc.buildMode) {
const host = vueTs.createSolutionBuilderWithWatchHost(
vueTs.sys,
createProgram,
reportDiagnostic,
void 0,
reportWatchStatusChanged
);
vueTs.createSolutionBuilderWithWatch(host, [configFile], {}).build();
} else {
const host = vueTs.createWatchCompilerHost(
configFile,
{ noEmit: true },
vueTs.sys,
createProgram,
reportDiagnostic,
reportWatchStatusChanged
);
vueTs.createWatchProgram(host);
}
}
};
};
class VueTscChecker extends Checker {
constructor() {
super({
name: "vueTsc",
absFilePath: __filename,
build: {
buildBin: (config) => {
if (typeof config.vueTsc === "object") {
const { root = "", tsconfigPath = "", buildMode } = config.vueTsc;
const args = [buildMode ? "-b" : "--noEmit"];
let projectPath = "";
if (root || tsconfigPath) {
projectPath = root ? path.join(root, tsconfigPath) : tsconfigPath;
}
if (projectPath) {
if (buildMode) {
args.push(projectPath);
} else {
args.push("-p", projectPath);
}
}
return ["vue-tsc", args];
}
return ["vue-tsc", ["--noEmit"]];
}
},
createDiagnostic
});
}
init() {
const _createServeAndBuild = super.initMainThread();
createServeAndBuild = _createServeAndBuild;
super.initWorkerThread();
}
}
const tscChecker = new VueTscChecker();
tscChecker.prepare();
tscChecker.init();
export {
VueTscChecker,
createServeAndBuild
};
//# sourceMappingURL=main.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
declare function prepareVueTsc(): Promise<{
targetTsDir: string;
}>;
export { prepareVueTsc };

View File

@@ -0,0 +1,108 @@
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";
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"];
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"
);
}
let shouldBuildFixture = true;
try {
await access(targetTsDir);
const targetTsVersion = _require(
path.resolve(targetTsDir, "package.json")
).version;
await access(vueTscFlagFile);
const fixtureFlagContent = await readFile(vueTscFlagFile, "utf8");
if (targetTsVersion === currTsVersion && fixtureFlagContent === proxyApiPath) {
shouldBuildFixture = false;
}
} catch {
shouldBuildFixture = true;
}
if (shouldBuildFixture) {
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"))
);
}
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

File diff suppressed because one or more lines are too long