Website Structure

This commit is contained in:
supalerk-ar66 2026-01-13 10:46:40 +07:00
parent 62812f2090
commit 71f0676a62
22365 changed files with 4265753 additions and 791 deletions

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 fi3ework
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,21 @@
# Visit [documentation](https://vite-plugin-checker.netlify.app) for usage
A Vite plugin that can run TypeScript, VLS, vue-tsc, ESLint, Biome, Stylelint in worker thread.
<p align="center">
<img alt="screenshot" src="https://user-images.githubusercontent.com/12322740/152739742-7444ee62-9ca7-4379-8f02-495c612ecc5c.png">
</p>
## Online playground
| Examples | StackBlitz |
| ------------------ | ---------------------------------------------------------------- |
| Vue3 + vue-tsc | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-e8pddl) |
| React + TypeScript | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-b4zcev) |
| ESLint | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-l1ritu) |
| Vue2 + VLS | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-kpffk5) |
| Multiple | [⚡️ StackBlitz](https://stackblitz.com/edit/vitejs-vite-mb4ea6) |
## License
MIT License © 2022 [fi3ework](https://github.com/fi3ework)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,32 @@
import * as vite from 'vite';
import { BuildInCheckerNames, CreateDiagnostic, ServeAndBuildChecker, BuildInCheckers } from './types.js';
import { Script } from './worker.js';
import 'node:worker_threads';
import 'eslint';
import 'stylelint';
import './checkers/vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
interface CheckerMeta<T extends BuildInCheckerNames> {
name: T;
absFilePath: string;
createDiagnostic: CreateDiagnostic<T>;
build: ServeAndBuildChecker['build'];
script?: Script<any>;
}
declare abstract class Checker<T extends BuildInCheckerNames> implements CheckerMeta<T> {
static logger: ((...v: string[]) => unknown)[];
static log(...args: any[]): void;
name: T;
absFilePath: string;
createDiagnostic: CreateDiagnostic<T>;
build: ServeAndBuildChecker['build'];
script?: Script<any>;
constructor({ name, absFilePath, createDiagnostic, build, }: CheckerMeta<T>);
prepare(): Script<Pick<BuildInCheckers, T>>;
initMainThread(): ((config: any, env: vite.ConfigEnv) => ServeAndBuildChecker) | undefined;
initWorkerThread(): void;
}
export { Checker };

View file

@ -0,0 +1,64 @@
import invariant from "tiny-invariant";
import { isInVitestEntryThread, isMainThread } from "./utils.js";
import { createScript } from "./worker.js";
if (!(isMainThread || isInVitestEntryThread)) {
process.stdout.isTTY = true;
}
class Checker {
static logger = [];
static log(...args) {
for (const fn of Checker.logger) {
fn(...args);
}
}
name;
absFilePath;
createDiagnostic;
build;
script;
constructor({
name,
absFilePath,
createDiagnostic,
build
}) {
this.name = name;
this.absFilePath = absFilePath;
this.build = build;
this.createDiagnostic = createDiagnostic;
this.build = build;
}
prepare() {
const script = createScript({
absFilename: this.absFilePath,
buildBin: this.build.buildBin,
serverChecker: { createDiagnostic: this.createDiagnostic }
});
this.script = script;
return script;
}
initMainThread() {
invariant(
this.script,
`script should be created in 'prepare', but got ${this.script}`
);
if (isMainThread || isInVitestEntryThread) {
const createServeAndBuild = this.script.mainScript();
return createServeAndBuild;
}
return;
}
initWorkerThread() {
invariant(
this.script,
`script should be created in 'prepare', but got ${this.script}`
);
if (!(isMainThread || isInVitestEntryThread)) {
this.script.workerScript();
}
}
}
export {
Checker
};
//# sourceMappingURL=Checker.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../src/Checker.ts"],"sourcesContent":["import invariant from 'tiny-invariant'\nimport type {\n BuildInCheckerNames,\n BuildInCheckers,\n CreateDiagnostic,\n ServeAndBuildChecker,\n} from './types.js'\nimport { isInVitestEntryThread, isMainThread } from './utils.js'\nimport { createScript, type Script } from './worker.js'\n\nif (!(isMainThread || isInVitestEntryThread)) {\n process.stdout.isTTY = true\n}\n\ninterface CheckerMeta<T extends BuildInCheckerNames> {\n name: T\n absFilePath: string\n createDiagnostic: CreateDiagnostic<T>\n build: ServeAndBuildChecker['build']\n script?: Script<any>\n}\n\nexport abstract class Checker<T extends BuildInCheckerNames>\n implements CheckerMeta<T>\n{\n public static logger: ((...v: string[]) => unknown)[] = []\n\n public static log(...args: any[]) {\n for (const fn of Checker.logger) {\n fn(...args)\n }\n }\n\n public name: T\n public absFilePath: string\n public createDiagnostic: CreateDiagnostic<T>\n public build: ServeAndBuildChecker['build']\n public script?: Script<any>\n\n public constructor({\n name,\n absFilePath,\n createDiagnostic,\n build,\n }: CheckerMeta<T>) {\n this.name = name\n this.absFilePath = absFilePath\n this.build = build\n this.createDiagnostic = createDiagnostic\n this.build = build\n }\n\n public prepare() {\n const script = createScript<Pick<BuildInCheckers, T>>({\n absFilename: this.absFilePath,\n buildBin: this.build.buildBin,\n serverChecker: { createDiagnostic: this.createDiagnostic },\n })!\n\n this.script = script\n return script\n }\n\n public initMainThread() {\n invariant(\n this.script,\n `script should be created in 'prepare', but got ${this.script}`,\n )\n\n if (isMainThread || isInVitestEntryThread) {\n const createServeAndBuild = this.script.mainScript()\n return createServeAndBuild\n }\n\n return\n }\n\n public initWorkerThread() {\n invariant(\n this.script,\n `script should be created in 'prepare', but got ${this.script}`,\n )\n\n if (!(isMainThread || isInVitestEntryThread)) {\n this.script.workerScript()\n }\n }\n}\n"],"mappings":"AAAA,OAAO,eAAe;AAOtB,SAAS,uBAAuB,oBAAoB;AACpD,SAAS,oBAAiC;AAE1C,IAAI,EAAE,gBAAgB,wBAAwB;AAC5C,UAAQ,OAAO,QAAQ;AACzB;AAUO,MAAe,QAEtB;AAAA,EACE,OAAc,SAA0C,CAAC;AAAA,EAEzD,OAAc,OAAO,MAAa;AAChC,eAAW,MAAM,QAAQ,QAAQ;AAC/B,SAAG,GAAG,IAAI;AAAA,IACZ;AAAA,EACF;AAAA,EAEO;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAmB;AACjB,SAAK,OAAO;AACZ,SAAK,cAAc;AACnB,SAAK,QAAQ;AACb,SAAK,mBAAmB;AACxB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEO,UAAU;AACf,UAAM,SAAS,aAAuC;AAAA,MACpD,aAAa,KAAK;AAAA,MAClB,UAAU,KAAK,MAAM;AAAA,MACrB,eAAe,EAAE,kBAAkB,KAAK,iBAAiB;AAAA,IAC3D,CAAC;AAED,SAAK,SAAS;AACd,WAAO;AAAA,EACT;AAAA,EAEO,iBAAiB;AACtB;AAAA,MACE,KAAK;AAAA,MACL,kDAAkD,KAAK,MAAM;AAAA,IAC/D;AAEA,QAAI,gBAAgB,uBAAuB;AACzC,YAAM,sBAAsB,KAAK,OAAO,WAAW;AACnD,aAAO;AAAA,IACT;AAEA;AAAA,EACF;AAAA,EAEO,mBAAmB;AACxB;AAAA,MACE,KAAK;AAAA,MACL,kDAAkD,KAAK,MAAM;AAAA,IAC/D;AAEA,QAAI,EAAE,gBAAgB,wBAAwB;AAC5C,WAAK,OAAO,aAAa;AAAA,IAC3B;AAAA,EACF;AACF;","names":[]}

View file

@ -0,0 +1,24 @@
import { NormalizedDiagnostic } from './logger.js';
import '@babel/code-frame';
import './types.js';
import 'node:worker_threads';
import 'eslint';
import 'stylelint';
import 'vite';
import './checkers/vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
import 'typescript';
import 'vscode-languageclient/node';
declare class FileDiagnosticManager {
diagnostics: NormalizedDiagnostic[];
/**
* Initialize and reset the diagnostics array
*/
initWith(diagnostics: NormalizedDiagnostic[]): void;
getDiagnostics(fileName?: string): NormalizedDiagnostic[];
updateByFileId(fileId: string, next: NormalizedDiagnostic[] | null): void;
}
export { FileDiagnosticManager };

View file

@ -0,0 +1,25 @@
class FileDiagnosticManager {
diagnostics = [];
/**
* Initialize and reset the diagnostics array
*/
initWith(diagnostics) {
this.diagnostics = [...diagnostics];
}
getDiagnostics(fileName) {
if (fileName) {
return this.diagnostics.filter((f) => f.id === fileName);
}
return this.diagnostics;
}
updateByFileId(fileId, next) {
this.diagnostics = this.diagnostics.filter((d) => d.id !== fileId);
if (next == null ? void 0 : next.length) {
this.diagnostics.push(...next);
}
}
}
export {
FileDiagnosticManager
};
//# sourceMappingURL=FileDiagnosticManager.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../src/FileDiagnosticManager.ts"],"sourcesContent":["import type { NormalizedDiagnostic } from './logger.js'\n\nclass FileDiagnosticManager {\n public diagnostics: NormalizedDiagnostic[] = []\n\n /**\n * Initialize and reset the diagnostics array\n */\n public initWith(diagnostics: NormalizedDiagnostic[]) {\n this.diagnostics = [...diagnostics]\n }\n\n public getDiagnostics(fileName?: string) {\n if (fileName) {\n return this.diagnostics.filter((f) => f.id === fileName)\n }\n\n return this.diagnostics\n }\n\n public updateByFileId(fileId: string, next: NormalizedDiagnostic[] | null) {\n this.diagnostics = this.diagnostics.filter((d) => d.id !== fileId)\n\n if (next?.length) {\n this.diagnostics.push(...next)\n }\n }\n}\n\nexport { FileDiagnosticManager }\n"],"mappings":"AAEA,MAAM,sBAAsB;AAAA,EACnB,cAAsC,CAAC;AAAA;AAAA;AAAA;AAAA,EAKvC,SAAS,aAAqC;AACnD,SAAK,cAAc,CAAC,GAAG,WAAW;AAAA,EACpC;AAAA,EAEO,eAAe,UAAmB;AACvC,QAAI,UAAU;AACZ,aAAO,KAAK,YAAY,OAAO,CAAC,MAAM,EAAE,OAAO,QAAQ;AAAA,IACzD;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,eAAe,QAAgB,MAAqC;AACzE,SAAK,cAAc,KAAK,YAAY,OAAO,CAAC,MAAM,EAAE,OAAO,MAAM;AAEjE,QAAI,6BAAM,QAAQ;AAChB,WAAK,YAAY,KAAK,GAAG,IAAI;AAAA,IAC/B;AAAA,EACF;AACF;","names":[]}

View file

@ -0,0 +1,22 @@
import { NormalizedDiagnostic } from '../../logger.js';
import { DiagnosticLevel } from '../../types.js';
import '@babel/code-frame';
import 'eslint';
import 'stylelint';
import 'typescript';
import 'vscode-languageclient/node';
import 'node:worker_threads';
import 'vite';
import '../vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
declare const severityMap: {
readonly error: DiagnosticLevel.Error;
readonly warning: DiagnosticLevel.Warning;
readonly info: DiagnosticLevel.Suggestion;
};
declare function getBiomeCommand(command: string, flags: string, files: string): string;
declare function runBiome(command: string, cwd: string): Promise<NormalizedDiagnostic[]>;
export { getBiomeCommand, runBiome, severityMap };

View file

@ -0,0 +1,87 @@
import { exec } from "node:child_process";
import path from "node:path";
import { stripVTControlCharacters as strip } from "node:util";
import { createFrame } from "../../codeFrame.js";
import { DiagnosticLevel } from "../../types.js";
const severityMap = {
error: DiagnosticLevel.Error,
warning: DiagnosticLevel.Warning,
info: DiagnosticLevel.Suggestion
};
function getBiomeCommand(command, flags, files) {
const defaultFlags = "--reporter json";
if (flags.includes("--flags")) {
throw Error(
`vite-plugin-checker will force append "--reporter json" to the flags in dev mode, please don't use "--flags" in "config.biome.flags".
If you need to customize "--flags" in build mode, please use "config.biome.build.flags" instead.`
);
}
return ["biome", command, flags, defaultFlags, files].filter(Boolean).join(" ");
}
function runBiome(command, cwd) {
return new Promise((resolve, _reject) => {
exec(
command,
{
cwd,
maxBuffer: Number.POSITIVE_INFINITY
},
(_error, stdout, _stderr) => {
resolve([...parseBiomeOutput(stdout, cwd)]);
}
);
});
}
function parseBiomeOutput(output, cwd) {
let parsed;
try {
parsed = JSON.parse(output);
} catch {
return [];
}
const diagnostics = parsed.diagnostics.map((d) => {
var _a, _b, _c;
let file = (_a = d.location.path) == null ? void 0 : _a.file;
if (file) {
file = path.isAbsolute(file) ? file : path.resolve(cwd, file);
file = path.normalize(file);
}
const loc = {
file: file || "",
start: getLineAndColumn(d.location.sourceCode, (_b = d.location.span) == null ? void 0 : _b[0]),
end: getLineAndColumn(d.location.sourceCode, (_c = d.location.span) == null ? void 0 : _c[1])
};
const codeFrame = createFrame(d.location.sourceCode || "", loc);
return {
message: `[${d.category}] ${d.description}`,
conclusion: "",
level: severityMap[d.severity] ?? DiagnosticLevel.Error,
checker: "Biome",
id: file,
codeFrame,
stripedCodeFrame: codeFrame && strip(codeFrame),
loc
};
});
return diagnostics;
}
function getLineAndColumn(text, offset) {
if (!text || !offset) return { line: 0, column: 0 };
let line = 1;
let column = 1;
for (let i = 0; i < offset; i++) {
if (text[i] === "\n") {
line++;
column = 1;
} else {
column++;
}
}
return { line, column };
}
export {
getBiomeCommand,
runBiome,
severityMap
};
//# sourceMappingURL=cli.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/checkers/biome/cli.ts"],"sourcesContent":["import { exec } from 'node:child_process'\nimport path from 'node:path'\nimport { stripVTControlCharacters as strip } from 'node:util'\nimport { createFrame } from '../../codeFrame.js'\nimport type { NormalizedDiagnostic } from '../../logger.js'\nimport { DiagnosticLevel } from '../../types.js'\nimport type { BiomeOutput } from './types.js'\n\nexport const severityMap = {\n error: DiagnosticLevel.Error,\n warning: DiagnosticLevel.Warning,\n info: DiagnosticLevel.Suggestion,\n} as const\n\nexport function getBiomeCommand(command: string, flags: string, files: string) {\n const defaultFlags = '--reporter json'\n if (flags.includes('--flags')) {\n throw Error(\n `vite-plugin-checker will force append \"--reporter json\" to the flags in dev mode, please don't use \"--flags\" in \"config.biome.flags\".\nIf you need to customize \"--flags\" in build mode, please use \"config.biome.build.flags\" instead.`,\n )\n }\n return ['biome', command, flags, defaultFlags, files]\n .filter(Boolean)\n .join(' ')\n}\n\nexport function runBiome(command: string, cwd: string) {\n return new Promise<NormalizedDiagnostic[]>((resolve, _reject) => {\n exec(\n command,\n {\n cwd,\n maxBuffer: Number.POSITIVE_INFINITY,\n },\n (_error, stdout, _stderr) => {\n resolve([...parseBiomeOutput(stdout, cwd)])\n },\n )\n })\n}\n\nfunction parseBiomeOutput(output: string, cwd: string) {\n let parsed: BiomeOutput\n try {\n parsed = JSON.parse(output)\n } catch {\n return []\n }\n\n const diagnostics: NormalizedDiagnostic[] = parsed.diagnostics.map((d) => {\n let file = d.location.path?.file\n if (file) {\n // Convert relative path to absolute path\n file = path.isAbsolute(file) ? file : path.resolve(cwd, file)\n file = path.normalize(file)\n }\n\n const loc = {\n file: file || '',\n start: getLineAndColumn(d.location.sourceCode, d.location.span?.[0]),\n end: getLineAndColumn(d.location.sourceCode, d.location.span?.[1]),\n }\n\n const codeFrame = createFrame(d.location.sourceCode || '', loc)\n\n return {\n message: `[${d.category}] ${d.description}`,\n conclusion: '',\n level:\n severityMap[d.severity as keyof typeof severityMap] ??\n DiagnosticLevel.Error,\n checker: 'Biome',\n id: file,\n codeFrame,\n stripedCodeFrame: codeFrame && strip(codeFrame),\n loc,\n }\n })\n\n return diagnostics\n}\n\nfunction getLineAndColumn(text?: string, offset?: number) {\n if (!text || !offset) return { line: 0, column: 0 }\n\n let line = 1\n let column = 1\n\n for (let i = 0; i < offset; i++) {\n if (text[i] === '\\n') {\n line++\n column = 1\n } else {\n column++\n }\n }\n\n return { line, column }\n}\n"],"mappings":"AAAA,SAAS,YAAY;AACrB,OAAO,UAAU;AACjB,SAAS,4BAA4B,aAAa;AAClD,SAAS,mBAAmB;AAE5B,SAAS,uBAAuB;AAGzB,MAAM,cAAc;AAAA,EACzB,OAAO,gBAAgB;AAAA,EACvB,SAAS,gBAAgB;AAAA,EACzB,MAAM,gBAAgB;AACxB;AAEO,SAAS,gBAAgB,SAAiB,OAAe,OAAe;AAC7E,QAAM,eAAe;AACrB,MAAI,MAAM,SAAS,SAAS,GAAG;AAC7B,UAAM;AAAA,MACJ;AAAA;AAAA,IAEF;AAAA,EACF;AACA,SAAO,CAAC,SAAS,SAAS,OAAO,cAAc,KAAK,EACjD,OAAO,OAAO,EACd,KAAK,GAAG;AACb;AAEO,SAAS,SAAS,SAAiB,KAAa;AACrD,SAAO,IAAI,QAAgC,CAAC,SAAS,YAAY;AAC/D;AAAA,MACE;AAAA,MACA;AAAA,QACE;AAAA,QACA,WAAW,OAAO;AAAA,MACpB;AAAA,MACA,CAAC,QAAQ,QAAQ,YAAY;AAC3B,gBAAQ,CAAC,GAAG,iBAAiB,QAAQ,GAAG,CAAC,CAAC;AAAA,MAC5C;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,SAAS,iBAAiB,QAAgB,KAAa;AACrD,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,MAAM;AAAA,EAC5B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,cAAsC,OAAO,YAAY,IAAI,CAAC,MAAM;AAlD5E;AAmDI,QAAI,QAAO,OAAE,SAAS,SAAX,mBAAiB;AAC5B,QAAI,MAAM;AAER,aAAO,KAAK,WAAW,IAAI,IAAI,OAAO,KAAK,QAAQ,KAAK,IAAI;AAC5D,aAAO,KAAK,UAAU,IAAI;AAAA,IAC5B;AAEA,UAAM,MAAM;AAAA,MACV,MAAM,QAAQ;AAAA,MACd,OAAO,iBAAiB,EAAE,SAAS,aAAY,OAAE,SAAS,SAAX,mBAAkB,EAAE;AAAA,MACnE,KAAK,iBAAiB,EAAE,SAAS,aAAY,OAAE,SAAS,SAAX,mBAAkB,EAAE;AAAA,IACnE;AAEA,UAAM,YAAY,YAAY,EAAE,SAAS,cAAc,IAAI,GAAG;AAE9D,WAAO;AAAA,MACL,SAAS,IAAI,EAAE,QAAQ,KAAK,EAAE,WAAW;AAAA,MACzC,YAAY;AAAA,MACZ,OACE,YAAY,EAAE,QAAoC,KAClD,gBAAgB;AAAA,MAClB,SAAS;AAAA,MACT,IAAI;AAAA,MACJ;AAAA,MACA,kBAAkB,aAAa,MAAM,SAAS;AAAA,MAC9C;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEA,SAAS,iBAAiB,MAAe,QAAiB;AACxD,MAAI,CAAC,QAAQ,CAAC,OAAQ,QAAO,EAAE,MAAM,GAAG,QAAQ,EAAE;AAElD,MAAI,OAAO;AACX,MAAI,SAAS;AAEb,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,QAAI,KAAK,CAAC,MAAM,MAAM;AACpB;AACA,eAAS;AAAA,IACX,OAAO;AACL;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,OAAO;AACxB;","names":[]}

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 BiomeChecker extends Checker<'biome'> {
constructor();
init(): void;
}
export { BiomeChecker, createServeAndBuild };

View file

@ -0,0 +1,153 @@
import path from "node:path";
import { fileURLToPath } from "node:url";
import { parentPort } from "node:worker_threads";
import chokidar from "chokidar";
import { Checker } from "../../Checker.js";
import { FileDiagnosticManager } from "../../FileDiagnosticManager.js";
import {
composeCheckerSummary,
consoleLog,
diagnosticToConsoleLevel,
diagnosticToRuntimeError,
diagnosticToTerminalLog,
filterLogLevel,
toClientPayload
} from "../../logger.js";
import {
ACTION_TYPES,
DiagnosticLevel
} from "../../types.js";
import { getBiomeCommand, runBiome, severityMap } from "./cli.js";
const __filename = fileURLToPath(import.meta.url);
const manager = new FileDiagnosticManager();
let createServeAndBuild;
const createDiagnostic = (pluginConfig) => {
var _a, _b;
const biomeConfig = pluginConfig.biome;
let overlay = true;
let terminal = true;
let command = "lint";
let flags = "";
if (typeof biomeConfig === "object") {
command = ((_a = biomeConfig == null ? void 0 : biomeConfig.dev) == null ? void 0 : _a.command) || (biomeConfig == null ? void 0 : biomeConfig.command) || "lint";
flags = ((_b = biomeConfig == null ? void 0 : biomeConfig.dev) == null ? void 0 : _b.flags) || (biomeConfig == null ? void 0 : biomeConfig.flags) || "";
}
return {
config: async ({ enableOverlay, enableTerminal }) => {
overlay = enableOverlay;
terminal = enableTerminal;
},
async configureServer({ root }) {
if (!biomeConfig) return;
const logLevel = (() => {
var _a2;
if (typeof biomeConfig !== "object") return void 0;
const userLogLevel = (_a2 = biomeConfig.dev) == null ? void 0 : _a2.logLevel;
if (!userLogLevel) return void 0;
return userLogLevel.map((l) => severityMap[l]);
})();
const dispatchDiagnostics = () => {
var _a2;
const diagnostics2 = filterLogLevel(manager.getDiagnostics(), logLevel);
if (terminal) {
for (const d of diagnostics2) {
consoleLog(
diagnosticToTerminalLog(d, "Biome"),
diagnosticToConsoleLevel(d)
);
}
const errorCount = diagnostics2.filter(
(d) => d.level === DiagnosticLevel.Error
).length;
const warningCount = diagnostics2.filter(
(d) => d.level === DiagnosticLevel.Warning
).length;
consoleLog(
composeCheckerSummary("Biome", errorCount, warningCount),
errorCount ? "error" : warningCount ? "warn" : "info"
);
}
if (overlay) {
(_a2 = parentPort) == null ? void 0 : _a2.postMessage({
type: ACTION_TYPES.overlayError,
payload: toClientPayload(
"biome",
diagnostics2.map((d) => diagnosticToRuntimeError(d))
)
});
}
};
const handleFileChange = async (filePath, type) => {
const absPath = path.resolve(root, filePath);
if (type === "unlink") {
manager.updateByFileId(absPath, []);
} else if (type === "change") {
const isConfigFile = path.basename(absPath) === "biome.json";
if (isConfigFile) {
const runCommand2 = getBiomeCommand(command, flags, root);
const diagnostics2 = await runBiome(runCommand2, root);
manager.initWith(diagnostics2);
} else {
const runCommand2 = getBiomeCommand(command, flags, absPath);
const diagnosticsOfChangedFile = await runBiome(runCommand2, root);
manager.updateByFileId(absPath, diagnosticsOfChangedFile);
}
}
dispatchDiagnostics();
};
const runCommand = getBiomeCommand(command, flags, root);
const diagnostics = await runBiome(runCommand, root);
manager.initWith(diagnostics);
dispatchDiagnostics();
let watchTarget = root;
if (typeof biomeConfig === "object" && biomeConfig.watchPath) {
if (Array.isArray(biomeConfig.watchPath)) {
watchTarget = biomeConfig.watchPath.map((p) => path.resolve(root, p));
} else {
watchTarget = path.resolve(root, biomeConfig.watchPath);
}
}
const watcher = chokidar.watch(watchTarget, {
cwd: root,
ignored: (path2) => path2.includes("node_modules")
});
watcher.on("change", async (filePath) => {
handleFileChange(filePath, "change");
});
watcher.on("unlink", async (filePath) => {
handleFileChange(filePath, "unlink");
});
}
};
};
class BiomeChecker extends Checker {
constructor() {
super({
name: "biome",
absFilePath: __filename,
build: {
buildBin: (pluginConfig) => {
if (typeof pluginConfig.biome === "object") {
const { command, flags } = pluginConfig.biome;
return ["biome", [command || "check", flags || ""]];
}
return ["biome", ["check"]];
}
},
createDiagnostic
});
}
init() {
const _createServeAndBuild = super.initMainThread();
createServeAndBuild = _createServeAndBuild;
super.initWorkerThread();
}
}
const biomeChecker = new BiomeChecker();
biomeChecker.prepare();
biomeChecker.init();
export {
BiomeChecker,
createServeAndBuild
};
//# sourceMappingURL=main.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
//# sourceMappingURL=types.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}

View file

@ -0,0 +1,28 @@
declare function translateOptions({ cache, cacheFile, cacheLocation, cacheStrategy, config, env, errorOnUnmatchedPattern, eslintrc, ext, fix, fixDryRun, fixType, global, ignore, ignorePath, ignorePattern, inlineConfig, parser, parserOptions, plugin, quiet, reportUnusedDisableDirectives, resolvePluginsRelativeTo, rule, rulesdir, }: any): {
allowInlineConfig: any;
cache: any;
cacheLocation: any;
cacheStrategy: any;
errorOnUnmatchedPattern: any;
extensions: any;
fix: any;
fixTypes: any;
ignore: any;
ignorePath: any;
overrideConfig: {
env: any;
globals: any;
ignorePatterns: any;
parser: any;
parserOptions: any;
plugins: any;
rules: any;
};
overrideConfigFile: any;
reportUnusedDisableDirectives: string | undefined;
resolvePluginsRelativeTo: any;
rulePaths: any;
useEslintrc: any;
};
export { translateOptions };

View file

@ -0,0 +1,75 @@
function quietFixPredicate(message) {
return message.severity === 2;
}
function translateOptions({
cache,
cacheFile,
cacheLocation,
cacheStrategy,
config,
env,
errorOnUnmatchedPattern,
eslintrc,
ext,
fix,
fixDryRun,
fixType,
global,
ignore,
ignorePath,
ignorePattern,
inlineConfig,
parser,
parserOptions,
plugin,
quiet,
reportUnusedDisableDirectives,
resolvePluginsRelativeTo,
rule,
rulesdir
}) {
return {
allowInlineConfig: inlineConfig,
cache,
cacheLocation: cacheLocation || cacheFile,
cacheStrategy,
errorOnUnmatchedPattern,
extensions: ext,
fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
fixTypes: fixType,
ignore,
ignorePath,
overrideConfig: {
env: (
// @ts-expect-error
env == null ? void 0 : env.reduce((obj, name) => {
obj[name] = true;
return obj;
}, {})
),
// @ts-expect-error
globals: global == null ? void 0 : global.reduce((obj, name) => {
if (name.endsWith(":true")) {
obj[name.slice(0, -5)] = "writable";
} else {
obj[name] = "readonly";
}
return obj;
}, {}),
ignorePatterns: ignorePattern,
parser,
parserOptions,
plugins: plugin,
rules: rule
},
overrideConfigFile: config,
reportUnusedDisableDirectives: reportUnusedDisableDirectives ? "error" : void 0,
resolvePluginsRelativeTo,
rulePaths: rulesdir,
useEslintrc: eslintrc
};
}
export {
translateOptions
};
//# sourceMappingURL=cli.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/checkers/eslint/cli.ts"],"sourcesContent":["/* eslint-disable */\n\n/**\n * This file is directly copied from https://github.com/eslint/eslint/blob/6f940c3ce715327f282c197d0f71b91848e5d83d/lib/cli.js\n *\n * Usually, developer rarely use JS programming API to run ESLint. So we let\n * developers to write their own ESLint commands just like in CI or lint-staged.\n * And the config will be translated and pass to `new ESLint(translatedOptions)`.\n * So in build mode, it's the same as the command you pass in.\n * In dev mode, some flag will be ignored (such as `max-warnings`) because it\n * will be only respected in ESLint CLI.\n */\n\n// @ts-expect-error\nfunction quietFixPredicate(message) {\n return message.severity === 2\n}\n\nexport function translateOptions({\n cache,\n cacheFile,\n cacheLocation,\n cacheStrategy,\n config,\n env,\n errorOnUnmatchedPattern,\n eslintrc,\n ext,\n fix,\n fixDryRun,\n fixType,\n global,\n ignore,\n ignorePath,\n ignorePattern,\n inlineConfig,\n parser,\n parserOptions,\n plugin,\n quiet,\n reportUnusedDisableDirectives,\n resolvePluginsRelativeTo,\n rule,\n rulesdir,\n}: any) {\n return {\n allowInlineConfig: inlineConfig,\n cache,\n cacheLocation: cacheLocation || cacheFile,\n cacheStrategy,\n errorOnUnmatchedPattern,\n extensions: ext,\n fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),\n fixTypes: fixType,\n ignore,\n ignorePath,\n overrideConfig: {\n env:\n // @ts-expect-error\n env?.reduce((obj, name) => {\n obj[name] = true\n return obj\n }, {}),\n // @ts-expect-error\n globals: global?.reduce((obj, name) => {\n if (name.endsWith(':true')) {\n obj[name.slice(0, -5)] = 'writable'\n } else {\n obj[name] = 'readonly'\n }\n return obj\n }, {}),\n ignorePatterns: ignorePattern,\n parser,\n parserOptions,\n plugins: plugin,\n rules: rule,\n },\n overrideConfigFile: config,\n reportUnusedDisableDirectives: reportUnusedDisableDirectives\n ? 'error'\n : void 0,\n resolvePluginsRelativeTo,\n rulePaths: rulesdir,\n useEslintrc: eslintrc,\n }\n}\n"],"mappings":"AAcA,SAAS,kBAAkB,SAAS;AAClC,SAAO,QAAQ,aAAa;AAC9B;AAEO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAQ;AACN,SAAO;AAAA,IACL,mBAAmB;AAAA,IACnB;AAAA,IACA,eAAe,iBAAiB;AAAA,IAChC;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,MAAM,OAAO,eAAe,QAAQ,oBAAoB;AAAA,IACxD,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,MACd;AAAA;AAAA,QAEE,2BAAK,OAAO,CAAC,KAAK,SAAS;AACzB,cAAI,IAAI,IAAI;AACZ,iBAAO;AAAA,QACT,GAAG,CAAC;AAAA;AAAA;AAAA,MAEN,SAAS,iCAAQ,OAAO,CAAC,KAAK,SAAS;AACrC,YAAI,KAAK,SAAS,OAAO,GAAG;AAC1B,cAAI,KAAK,MAAM,GAAG,EAAE,CAAC,IAAI;AAAA,QAC3B,OAAO;AACL,cAAI,IAAI,IAAI;AAAA,QACd;AACA,eAAO;AAAA,MACT,GAAG,CAAC;AAAA,MACJ,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,IACA,oBAAoB;AAAA,IACpB,+BAA+B,gCAC3B,UACA;AAAA,IACJ;AAAA,IACA,WAAW;AAAA,IACX,aAAa;AAAA,EACf;AACF;","names":[]}

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 EslintChecker extends Checker<'eslint'> {
constructor();
init(): void;
}
export { EslintChecker, createServeAndBuild };

View file

@ -0,0 +1,186 @@
import Module from "node:module";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { parentPort } from "node:worker_threads";
import chokidar from "chokidar";
import { ESLint } from "eslint";
import invariant from "tiny-invariant";
import { Checker } from "../../Checker.js";
import { FileDiagnosticManager } from "../../FileDiagnosticManager.js";
import { createIgnore } from "../../glob.js";
import {
composeCheckerSummary,
consoleLog,
diagnosticToConsoleLevel,
diagnosticToRuntimeError,
diagnosticToTerminalLog,
filterLogLevel,
normalizeEslintDiagnostic,
toClientPayload
} from "../../logger.js";
import { ACTION_TYPES, DiagnosticLevel } from "../../types.js";
import { translateOptions } from "./cli.js";
import { options as optionator } from "./options.js";
const __filename = fileURLToPath(import.meta.url);
const require2 = Module.createRequire(import.meta.url);
const manager = new FileDiagnosticManager();
let createServeAndBuild;
const createDiagnostic = (pluginConfig) => {
let overlay = true;
let terminal = true;
return {
config: async ({ enableOverlay, enableTerminal }) => {
overlay = enableOverlay;
terminal = enableTerminal;
},
async configureServer({ root }) {
var _a;
if (!pluginConfig.eslint) return;
const options = optionator.parse(pluginConfig.eslint.lintCommand);
invariant(
!options.fix,
"Using `--fix` in `config.eslint.lintCommand` is not allowed in vite-plugin-checker, you could using `--fix` with editor."
);
const translatedOptions = translateOptions(options);
const logLevel = (() => {
var _a2;
if (typeof pluginConfig.eslint !== "object") return void 0;
const userLogLevel = (_a2 = pluginConfig.eslint.dev) == null ? void 0 : _a2.logLevel;
if (!userLogLevel) return void 0;
const map = {
error: DiagnosticLevel.Error,
warning: DiagnosticLevel.Warning
};
return userLogLevel.map((l) => map[l]);
})();
const eslintOptions = {
cwd: root,
...translatedOptions,
...(_a = pluginConfig.eslint.dev) == null ? void 0 : _a.overrideConfig
};
let eslint;
if (pluginConfig.eslint.useFlatConfig) {
const {
FlatESLint,
shouldUseFlatConfig
} = require2("eslint/use-at-your-own-risk");
if (shouldUseFlatConfig == null ? void 0 : shouldUseFlatConfig()) {
eslint = new FlatESLint({
cwd: root
});
} else {
throw Error(
"Please upgrade your eslint to latest version to use `useFlatConfig` option."
);
}
} else {
eslint = new ESLint(eslintOptions);
}
const dispatchDiagnostics = () => {
var _a2;
const diagnostics2 = filterLogLevel(manager.getDiagnostics(), logLevel);
if (terminal) {
for (const d of diagnostics2) {
consoleLog(
diagnosticToTerminalLog(d, "ESLint"),
diagnosticToConsoleLevel(d)
);
}
const errorCount = diagnostics2.filter(
(d) => d.level === DiagnosticLevel.Error
).length;
const warningCount = diagnostics2.filter(
(d) => d.level === DiagnosticLevel.Warning
).length;
consoleLog(
composeCheckerSummary("ESLint", errorCount, warningCount),
errorCount ? "error" : warningCount ? "warn" : "info"
);
}
if (overlay) {
(_a2 = parentPort) == null ? void 0 : _a2.postMessage({
type: ACTION_TYPES.overlayError,
payload: toClientPayload(
"eslint",
diagnostics2.map((d) => diagnosticToRuntimeError(d))
)
});
}
};
const handleFileChange = async (filePath, type) => {
const extension = path.extname(filePath);
const { extensions } = eslintOptions;
const hasExtensionsConfig = Array.isArray(extensions);
if (hasExtensionsConfig && !extensions.includes(extension)) return;
const isChangedFileIgnored = await eslint.isPathIgnored(filePath);
if (isChangedFileIgnored) return;
const absPath = path.resolve(root, filePath);
if (type === "unlink") {
manager.updateByFileId(absPath, []);
} else if (type === "change") {
const diagnosticsOfChangedFile = await eslint.lintFiles(filePath);
const newDiagnostics = diagnosticsOfChangedFile.flatMap(
(d) => normalizeEslintDiagnostic(d)
);
manager.updateByFileId(absPath, newDiagnostics);
}
dispatchDiagnostics();
};
const files = options._.slice(1);
const diagnostics = await eslint.lintFiles(files);
manager.initWith(diagnostics.flatMap((p) => normalizeEslintDiagnostic(p)));
dispatchDiagnostics();
let watchTarget = root;
if (pluginConfig.eslint.watchPath) {
if (Array.isArray(pluginConfig.eslint.watchPath)) {
watchTarget = pluginConfig.eslint.watchPath.map(
(p) => path.resolve(root, p)
);
} else {
watchTarget = path.resolve(root, pluginConfig.eslint.watchPath);
}
}
const watcher = chokidar.watch(watchTarget, {
cwd: root,
ignored: createIgnore(root, files)
});
watcher.on("change", async (filePath) => {
handleFileChange(filePath, "change");
});
watcher.on("unlink", async (filePath) => {
handleFileChange(filePath, "unlink");
});
}
};
};
class EslintChecker extends Checker {
constructor() {
super({
name: "eslint",
absFilePath: __filename,
build: {
buildBin: (pluginConfig) => {
if (pluginConfig.eslint) {
const { lintCommand } = pluginConfig.eslint;
return ["eslint", lintCommand.split(" ").slice(1)];
}
return ["eslint", [""]];
}
},
createDiagnostic
});
}
init() {
const _createServeAndBuild = super.initMainThread();
createServeAndBuild = _createServeAndBuild;
super.initWorkerThread();
}
}
const eslintChecker = new EslintChecker();
eslintChecker.prepare();
eslintChecker.init();
export {
EslintChecker,
createServeAndBuild
};
//# sourceMappingURL=main.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,45 @@
/**
* The options object parsed by Optionator.
* @typedef {Object} ParsedCLIOptions
* @property {boolean} cache Only check changed files
* @property {string} cacheFile Path to the cache file. Deprecated: use --cache-location
* @property {string} [cacheLocation] Path to the cache file or directory
* @property {"metadata" | "content"} cacheStrategy Strategy to use for detecting changed files in the cache
* @property {boolean} [color] Force enabling/disabling of color
* @property {string} [config] Use this configuration, overriding .eslintrc.* config options if present
* @property {boolean} debug Output debugging information
* @property {string[]} [env] Specify environments
* @property {boolean} envInfo Output execution environment information
* @property {boolean} errorOnUnmatchedPattern Prevent errors when pattern is unmatched
* @property {boolean} eslintrc Disable use of configuration from .eslintrc.*
* @property {string[]} [ext] Specify JavaScript file extensions
* @property {boolean} fix Automatically fix problems
* @property {boolean} fixDryRun Automatically fix problems without saving the changes to the file system
* @property {("directive" | "problem" | "suggestion" | "layout")[]} [fixType] Specify the types of fixes to apply (directive, problem, suggestion, layout)
* @property {string} format Use a specific output format
* @property {string[]} [global] Define global variables
* @property {boolean} [help] Show help
* @property {boolean} ignore Disable use of ignore files and patterns
* @property {string} [ignorePath] Specify path of ignore file
* @property {string[]} [ignorePattern] Pattern of files to ignore (in addition to those in .eslintignore)
* @property {boolean} init Run config initialization wizard
* @property {boolean} inlineConfig Prevent comments from changing config or rules
* @property {number} maxWarnings Number of warnings to trigger nonzero exit code
* @property {string} [outputFile] Specify file to write report to
* @property {string} [parser] Specify the parser to be used
* @property {Object} [parserOptions] Specify parser options
* @property {string[]} [plugin] Specify plugins
* @property {string} [printConfig] Print the configuration for the given file
* @property {boolean | undefined} reportUnusedDisableDirectives Adds reported errors for unused eslint-disable directives
* @property {string} [resolvePluginsRelativeTo] A folder where plugins should be resolved from, CWD by default
* @property {Object} [rule] Specify rules
* @property {string[]} [rulesdir] Load additional rules from this directory. Deprecated: Use rules from plugins
* @property {boolean} stdin Lint code provided on <STDIN>
* @property {string} [stdinFilename] Specify filename to process STDIN as
* @property {boolean} quiet Report errors only
* @property {boolean} [version] Output the version number
* @property {string[]} _ Positional filenames or patterns
*/
declare const options: any;
export { options };

View file

@ -0,0 +1,273 @@
import { createRequire } from "node:module";
const _require = createRequire(import.meta.url);
import { dirname } from "node:path";
const eslintDir = dirname(_require.resolve("eslint/package.json"));
const optionatorPath = _require.resolve("optionator", {
paths: [eslintDir]
});
const optionator = _require(optionatorPath);
const options = optionator({
prepend: "eslint [options] file.js [file.js] [dir]",
defaults: {
concatRepeatedArrays: true,
mergeRepeatedObjects: true
},
options: [
{
heading: "Basic configuration"
},
{
option: "eslintrc",
type: "Boolean",
default: "true",
description: "Disable use of configuration from .eslintrc.*"
},
{
option: "config",
alias: "c",
type: "path::String",
description: "Use this configuration, overriding .eslintrc.* config options if present"
},
{
option: "env",
type: "[String]",
description: "Specify environments"
},
{
option: "ext",
type: "[String]",
description: "Specify JavaScript file extensions"
},
{
option: "global",
type: "[String]",
description: "Define global variables"
},
{
option: "parser",
type: "String",
description: "Specify the parser to be used"
},
{
option: "parser-options",
type: "Object",
description: "Specify parser options"
},
{
option: "resolve-plugins-relative-to",
type: "path::String",
description: "A folder where plugins should be resolved from, CWD by default"
},
{
heading: "Specifying rules and plugins"
},
{
option: "plugin",
type: "[String]",
description: "Specify plugins"
},
{
option: "rule",
type: "Object",
description: "Specify rules"
},
{
option: "rulesdir",
type: "[path::String]",
description: "Load additional rules from this directory. Deprecated: Use rules from plugins"
},
{
heading: "Fixing problems"
},
{
option: "fix",
type: "Boolean",
default: false,
description: "Automatically fix problems"
},
{
option: "fix-dry-run",
type: "Boolean",
default: false,
description: "Automatically fix problems without saving the changes to the file system"
},
{
option: "fix-type",
type: "Array",
description: "Specify the types of fixes to apply (directive, problem, suggestion, layout)"
},
{
heading: "Ignoring files"
},
{
option: "ignore-path",
type: "path::String",
description: "Specify path of ignore file"
},
{
option: "ignore",
type: "Boolean",
default: "true",
description: "Disable use of ignore files and patterns"
},
{
option: "ignore-pattern",
type: "[String]",
description: "Pattern of files to ignore (in addition to those in .eslintignore)",
concatRepeatedArrays: [
true,
{
oneValuePerFlag: true
}
]
},
{
heading: "Using stdin"
},
{
option: "stdin",
type: "Boolean",
default: "false",
description: "Lint code provided on <STDIN>"
},
{
option: "stdin-filename",
type: "String",
description: "Specify filename to process STDIN as"
},
{
heading: "Handling warnings"
},
{
option: "quiet",
type: "Boolean",
default: "false",
description: "Report errors only"
},
{
option: "max-warnings",
type: "Int",
default: "-1",
description: "Number of warnings to trigger nonzero exit code"
},
{
heading: "Output"
},
{
option: "output-file",
alias: "o",
type: "path::String",
description: "Specify file to write report to"
},
{
option: "format",
alias: "f",
type: "String",
default: "stylish",
description: "Use a specific output format"
},
{
option: "color",
type: "Boolean",
alias: "no-color",
description: "Force enabling/disabling of color"
},
{
heading: "Inline configuration comments"
},
{
option: "inline-config",
type: "Boolean",
default: "true",
description: "Prevent comments from changing config or rules"
},
{
option: "report-unused-disable-directives",
type: "Boolean",
default: void 0,
description: "Adds reported errors for unused eslint-disable directives"
},
{
heading: "Caching"
},
{
option: "cache",
type: "Boolean",
default: "false",
description: "Only check changed files"
},
{
option: "cache-file",
type: "path::String",
default: ".eslintcache",
description: "Path to the cache file. Deprecated: use --cache-location"
},
{
option: "cache-location",
type: "path::String",
description: "Path to the cache file or directory"
},
{
option: "cache-strategy",
dependsOn: ["cache"],
type: "String",
default: "metadata",
enum: ["metadata", "content"],
description: "Strategy to use for detecting changed files in the cache"
},
{
heading: "Miscellaneous"
},
{
option: "init",
type: "Boolean",
default: "false",
description: "Run config initialization wizard"
},
{
option: "env-info",
type: "Boolean",
default: "false",
description: "Output execution environment information"
},
{
option: "error-on-unmatched-pattern",
type: "Boolean",
default: "true",
description: "Prevent errors when pattern is unmatched"
},
{
option: "exit-on-fatal-error",
type: "Boolean",
default: "false",
description: "Exit with exit code 2 in case of fatal error"
},
{
option: "debug",
type: "Boolean",
default: false,
description: "Output debugging information"
},
{
option: "help",
alias: "h",
type: "Boolean",
description: "Show help"
},
{
option: "version",
alias: "v",
type: "Boolean",
description: "Output the version number"
},
{
option: "print-config",
type: "path::String",
description: "Print the configuration for the given file"
}
]
});
export {
options
};
//# sourceMappingURL=options.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,18 @@
import { NormalizedDiagnostic } from '../../logger.js';
import { DiagnosticLevel } from '../../types.js';
import '@babel/code-frame';
import 'eslint';
import 'stylelint';
import 'typescript';
import 'vscode-languageclient/node';
import 'node:worker_threads';
import 'vite';
import '../vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
declare function mapSeverity(s: string): DiagnosticLevel;
declare function getOxlintCommand(command: string): string[];
declare function runOxlint(command: string, cwd: string): Promise<NormalizedDiagnostic[]>;
export { getOxlintCommand, mapSeverity, runOxlint };

View file

@ -0,0 +1,135 @@
import { exec } from "node:child_process";
import fs from "node:fs/promises";
import path from "node:path";
import { stripVTControlCharacters as strip } from "node:util";
import colors from "picocolors";
import { createFrame, offsetRangeToBabelLocation } from "../../codeFrame.js";
import { consoleLog } from "../../logger.js";
import { DiagnosticLevel } from "../../types.js";
import { parseArgsStringToArgv } from "../stylelint/argv.js";
const severityMap = {
error: DiagnosticLevel.Error,
warning: DiagnosticLevel.Warning,
info: DiagnosticLevel.Suggestion
};
function mapSeverity(s) {
return severityMap[s] ?? DiagnosticLevel.Error;
}
function getOxlintCommand(command) {
const parsed = parseArgsStringToArgv(command);
const index = parsed.findIndex((p) => p === "--format" || p === "-f");
if (index === -1) {
parsed.push("--format", "json");
} else {
consoleLog(
colors.yellow(
`vite-plugin-checker will force append "--format json" to the flags in dev mode, please don't use "--format" or "-f" flag in "config.oxlint.lintCommand".`
),
"warn"
);
parsed.splice(index, 2, "--format", "json");
}
return parsed;
}
function runOxlint(command, cwd) {
return new Promise((resolve, _reject) => {
exec(
command,
{
cwd,
maxBuffer: Number.POSITIVE_INFINITY
},
(_error, stdout, _stderr) => {
parseOxlintOutput(stdout, cwd).then(resolve).catch(() => resolve([]));
}
);
});
}
async function parseOxlintOutput(output, cwd) {
const parsed = safeParseOxlint(output);
if (!parsed) return [];
const entries = getEntries(parsed, cwd);
if (entries.length === 0) return [];
const files = getUniqueFiles(entries);
const sourceCache = await readSources(files);
return buildDiagnostics(entries, sourceCache);
}
function safeParseOxlint(output) {
try {
return JSON.parse(output);
} catch {
return null;
}
}
function getEntries(parsed, cwd) {
return parsed.diagnostics.flatMap(
({ filename, labels, code, message, severity }) => {
const file = normalizePath(filename, cwd);
const [label] = labels;
if (!label) return [];
return [
{
file,
span: label.span,
code,
message,
severity
}
];
}
);
}
function getUniqueFiles(entries) {
return [...new Set(entries.map((e) => e.file))];
}
async function readSources(files) {
const cache = /* @__PURE__ */ new Map();
await Promise.all(
files.map(async (file) => {
try {
const source = await fs.readFile(file, "utf8");
cache.set(file, source);
} catch {
}
})
);
return cache;
}
function buildDiagnostics(entries, sources) {
return entries.flatMap((entry) => {
const source = sources.get(entry.file);
if (!source) return [];
const loc = offsetRangeToBabelLocation(
source,
entry.span.offset,
entry.span.length
);
const codeFrame = createFrame(source, loc);
return [
{
message: `${entry.code}: ${entry.message}`,
conclusion: "",
level: mapSeverity(entry.severity),
checker: "oxlint",
id: entry.file,
codeFrame,
stripedCodeFrame: codeFrame && strip(codeFrame),
loc
}
];
});
}
function normalizePath(p, cwd) {
let filename = p;
if (filename) {
filename = path.isAbsolute(filename) ? filename : path.resolve(cwd, filename);
filename = path.normalize(filename);
}
return filename;
}
export {
getOxlintCommand,
mapSeverity,
runOxlint
};
//# sourceMappingURL=cli.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,18 @@
import { NormalizedDiagnostic } from '../../logger.js';
import { CreateDiagnostic } from '../../types.js';
import { DisplayTarget } from './types.js';
import '@babel/code-frame';
import 'eslint';
import 'stylelint';
import 'typescript';
import 'vscode-languageclient/node';
import 'node:worker_threads';
import 'vite';
import '../vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
declare const createDiagnostic: CreateDiagnostic<'oxlint'>;
declare function dispatchDiagnostics(diagnostics: NormalizedDiagnostic[], targets: Set<DisplayTarget>): void;
export { createDiagnostic, dispatchDiagnostics };

View file

@ -0,0 +1,75 @@
import { parentPort } from "node:worker_threads";
import { FileDiagnosticManager } from "../../FileDiagnosticManager.js";
import {
composeCheckerSummary,
consoleLog,
diagnosticToConsoleLevel,
diagnosticToRuntimeError,
diagnosticToTerminalLog,
toClientPayload
} from "../../logger.js";
import {
ACTION_TYPES,
DiagnosticLevel
} from "../../types.js";
import { resolveOptions } from "./options.js";
import { setupDevServer } from "./server.js";
const createDiagnostic = (pluginConfig) => {
const manager = new FileDiagnosticManager();
const oxlintConfig = pluginConfig.oxlint;
const displayTargets = /* @__PURE__ */ new Set();
return {
config: async ({ enableOverlay, enableTerminal }) => {
displayTargets.clear();
if (enableOverlay) displayTargets.add("overlay");
if (enableTerminal) displayTargets.add("terminal");
},
async configureServer({ root }) {
if (!oxlintConfig) return;
const options = resolveOptions(root, oxlintConfig);
await setupDevServer(root, options, manager, displayTargets);
}
};
};
function dispatchDiagnostics(diagnostics, targets) {
if (targets.size === 0) return;
if (targets.has("terminal")) {
dispatchTerminalDiagnostics(diagnostics);
}
if (targets.has("overlay")) {
dispatchOverlayDiagnostics(diagnostics);
}
}
function dispatchTerminalDiagnostics(diagnostics) {
for (const d of diagnostics) {
consoleLog(
diagnosticToTerminalLog(d, "oxlint"),
diagnosticToConsoleLevel(d)
);
}
const errorCount = diagnostics.filter(
(d) => d.level === DiagnosticLevel.Error
).length;
const warningCount = diagnostics.filter(
(d) => d.level === DiagnosticLevel.Warning
).length;
consoleLog(
composeCheckerSummary("oxlint", errorCount, warningCount),
errorCount ? "error" : warningCount ? "warn" : "info"
);
}
function dispatchOverlayDiagnostics(diagnostics) {
var _a;
(_a = parentPort) == null ? void 0 : _a.postMessage({
type: ACTION_TYPES.overlayError,
payload: toClientPayload(
"oxlint",
diagnostics.map((d) => diagnosticToRuntimeError(d))
)
});
}
export {
createDiagnostic,
dispatchDiagnostics
};
//# sourceMappingURL=diagnostics.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/checkers/oxlint/diagnostics.ts"],"sourcesContent":["import { parentPort } from 'node:worker_threads'\nimport { FileDiagnosticManager } from '../../FileDiagnosticManager.js'\nimport {\n composeCheckerSummary,\n consoleLog,\n diagnosticToConsoleLevel,\n diagnosticToRuntimeError,\n diagnosticToTerminalLog,\n type NormalizedDiagnostic,\n toClientPayload,\n} from '../../logger.js'\nimport {\n ACTION_TYPES,\n type CreateDiagnostic,\n DiagnosticLevel,\n} from '../../types.js'\nimport { resolveOptions } from './options.js'\nimport { setupDevServer } from './server.js'\nimport type { DisplayTarget } from './types'\n\nexport const createDiagnostic: CreateDiagnostic<'oxlint'> = (pluginConfig) => {\n const manager = new FileDiagnosticManager()\n\n const oxlintConfig = pluginConfig.oxlint\n const displayTargets = new Set<DisplayTarget>()\n\n return {\n config: async ({ enableOverlay, enableTerminal }) => {\n displayTargets.clear()\n if (enableOverlay) displayTargets.add('overlay')\n if (enableTerminal) displayTargets.add('terminal')\n },\n async configureServer({ root }) {\n if (!oxlintConfig) return\n\n const options = resolveOptions(root, oxlintConfig)\n await setupDevServer(root, options, manager, displayTargets)\n },\n }\n}\n\nexport function dispatchDiagnostics(\n diagnostics: NormalizedDiagnostic[],\n targets: Set<DisplayTarget>,\n) {\n if (targets.size === 0) return\n\n if (targets.has('terminal')) {\n dispatchTerminalDiagnostics(diagnostics)\n }\n if (targets.has('overlay')) {\n dispatchOverlayDiagnostics(diagnostics)\n }\n}\n\nfunction dispatchTerminalDiagnostics(diagnostics: NormalizedDiagnostic[]) {\n for (const d of diagnostics) {\n consoleLog(\n diagnosticToTerminalLog(d, 'oxlint'),\n diagnosticToConsoleLevel(d),\n )\n }\n\n const errorCount = diagnostics.filter(\n (d) => d.level === DiagnosticLevel.Error,\n ).length\n const warningCount = diagnostics.filter(\n (d) => d.level === DiagnosticLevel.Warning,\n ).length\n consoleLog(\n composeCheckerSummary('oxlint', errorCount, warningCount),\n errorCount ? 'error' : warningCount ? 'warn' : 'info',\n )\n}\n\nfunction dispatchOverlayDiagnostics(diagnostics: NormalizedDiagnostic[]) {\n parentPort?.postMessage({\n type: ACTION_TYPES.overlayError,\n payload: toClientPayload(\n 'oxlint',\n diagnostics.map((d) => diagnosticToRuntimeError(d)),\n ),\n })\n}\n"],"mappings":"AAAA,SAAS,kBAAkB;AAC3B,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EAEA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAGxB,MAAM,mBAA+C,CAAC,iBAAiB;AAC5E,QAAM,UAAU,IAAI,sBAAsB;AAE1C,QAAM,eAAe,aAAa;AAClC,QAAM,iBAAiB,oBAAI,IAAmB;AAE9C,SAAO;AAAA,IACL,QAAQ,OAAO,EAAE,eAAe,eAAe,MAAM;AACnD,qBAAe,MAAM;AACrB,UAAI,cAAe,gBAAe,IAAI,SAAS;AAC/C,UAAI,eAAgB,gBAAe,IAAI,UAAU;AAAA,IACnD;AAAA,IACA,MAAM,gBAAgB,EAAE,KAAK,GAAG;AAC9B,UAAI,CAAC,aAAc;AAEnB,YAAM,UAAU,eAAe,MAAM,YAAY;AACjD,YAAM,eAAe,MAAM,SAAS,SAAS,cAAc;AAAA,IAC7D;AAAA,EACF;AACF;AAEO,SAAS,oBACd,aACA,SACA;AACA,MAAI,QAAQ,SAAS,EAAG;AAExB,MAAI,QAAQ,IAAI,UAAU,GAAG;AAC3B,gCAA4B,WAAW;AAAA,EACzC;AACA,MAAI,QAAQ,IAAI,SAAS,GAAG;AAC1B,+BAA2B,WAAW;AAAA,EACxC;AACF;AAEA,SAAS,4BAA4B,aAAqC;AACxE,aAAW,KAAK,aAAa;AAC3B;AAAA,MACE,wBAAwB,GAAG,QAAQ;AAAA,MACnC,yBAAyB,CAAC;AAAA,IAC5B;AAAA,EACF;AAEA,QAAM,aAAa,YAAY;AAAA,IAC7B,CAAC,MAAM,EAAE,UAAU,gBAAgB;AAAA,EACrC,EAAE;AACF,QAAM,eAAe,YAAY;AAAA,IAC/B,CAAC,MAAM,EAAE,UAAU,gBAAgB;AAAA,EACrC,EAAE;AACF;AAAA,IACE,sBAAsB,UAAU,YAAY,YAAY;AAAA,IACxD,aAAa,UAAU,eAAe,SAAS;AAAA,EACjD;AACF;AAEA,SAAS,2BAA2B,aAAqC;AA3EzE;AA4EE,0CAAY,YAAY;AAAA,IACtB,MAAM,aAAa;AAAA,IACnB,SAAS;AAAA,MACP;AAAA,MACA,YAAY,IAAI,CAAC,MAAM,yBAAyB,CAAC,CAAC;AAAA,IACpD;AAAA,EACF;AACF;","names":[]}

View file

@ -0,0 +1,17 @@
import { ServeAndBuildChecker } from '../../types.js';
import * as vite from 'vite';
import { Checker } from '../../Checker.js';
import 'node:worker_threads';
import 'eslint';
import 'stylelint';
import '../vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
import '../../worker.js';
declare class OxlintChecker extends Checker<'oxlint'> {
constructor();
}
declare const createServeAndBuild: ((config: any, env: vite.ConfigEnv) => ServeAndBuildChecker) | undefined;
export { OxlintChecker, createServeAndBuild };

View file

@ -0,0 +1,30 @@
import { fileURLToPath } from "node:url";
import { Checker } from "../../Checker.js";
import parseArgsStringToArgv from "../stylelint/argv.js";
import { createDiagnostic } from "./diagnostics.js";
const __filename = fileURLToPath(import.meta.url);
class OxlintChecker extends Checker {
constructor() {
super({
name: "oxlint",
absFilePath: __filename,
build: {
buildBin: ({ oxlint: oxlint2 }) => {
const commandStr = typeof oxlint2 === "boolean" ? "oxlint" : (oxlint2 == null ? void 0 : oxlint2.lintCommand) ?? "oxlint";
const command = parseArgsStringToArgv(commandStr);
return [command[0], command.slice(1)];
}
},
createDiagnostic
});
}
}
const oxlint = new OxlintChecker();
oxlint.prepare();
oxlint.initWorkerThread();
const createServeAndBuild = oxlint.initMainThread();
export {
OxlintChecker,
createServeAndBuild
};
//# sourceMappingURL=main.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/checkers/oxlint/main.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url'\nimport { Checker } from '../../Checker.js'\nimport parseArgsStringToArgv from '../stylelint/argv.js'\nimport { createDiagnostic } from './diagnostics.js'\n\nconst __filename = fileURLToPath(import.meta.url)\n\nexport class OxlintChecker extends Checker<'oxlint'> {\n public constructor() {\n super({\n name: 'oxlint',\n absFilePath: __filename,\n build: {\n buildBin: ({ oxlint }) => {\n const commandStr =\n typeof oxlint === 'boolean'\n ? 'oxlint'\n : (oxlint?.lintCommand ?? 'oxlint')\n const command = parseArgsStringToArgv(commandStr)\n return [command[0]!, command.slice(1)]\n },\n },\n createDiagnostic,\n })\n }\n}\n\nconst oxlint = new OxlintChecker()\noxlint.prepare()\noxlint.initWorkerThread()\n\nexport const createServeAndBuild = oxlint.initMainThread()\n"],"mappings":"AAAA,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AACxB,OAAO,2BAA2B;AAClC,SAAS,wBAAwB;AAEjC,MAAM,aAAa,cAAc,YAAY,GAAG;AAEzC,MAAM,sBAAsB,QAAkB;AAAA,EAC5C,cAAc;AACnB,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,OAAO;AAAA,QACL,UAAU,CAAC,EAAE,QAAAA,QAAO,MAAM;AACxB,gBAAM,aACJ,OAAOA,YAAW,YACd,YACCA,WAAA,gBAAAA,QAAQ,gBAAe;AAC9B,gBAAM,UAAU,sBAAsB,UAAU;AAChD,iBAAO,CAAC,QAAQ,CAAC,GAAI,QAAQ,MAAM,CAAC,CAAC;AAAA,QACvC;AAAA,MACF;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,MAAM,SAAS,IAAI,cAAc;AACjC,OAAO,QAAQ;AACf,OAAO,iBAAiB;AAEjB,MAAM,sBAAsB,OAAO,eAAe;","names":["oxlint"]}

View file

@ -0,0 +1,17 @@
import { DiagnosticLevel, OxlintConfig } from '../../types.js';
import 'node:worker_threads';
import 'eslint';
import 'stylelint';
import 'vite';
import '../vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
interface ResolvedOptions {
watchTarget: string | string[];
logLevel?: DiagnosticLevel[];
command: string;
}
declare function resolveOptions(root: string, config: Exclude<OxlintConfig, false>): ResolvedOptions;
export { type ResolvedOptions, resolveOptions };

View file

@ -0,0 +1,22 @@
import path from "node:path";
import { DiagnosticLevel } from "../../types.js";
import { getOxlintCommand, mapSeverity } from "./cli.js";
function resolveOptions(root, config) {
var _a, _b;
const options = config === true ? { lintCommand: "oxlint" } : config;
return {
watchTarget: resolveWatchTarget(root, options.watchPath),
logLevel: ((_b = (_a = options.dev) == null ? void 0 : _a.logLevel) == null ? void 0 : _b.map((l) => mapSeverity(l))) ?? [
DiagnosticLevel.Warning,
DiagnosticLevel.Error
],
command: getOxlintCommand(options.lintCommand ?? "oxlint").join(" ")
};
}
function resolveWatchTarget(root, watchPath) {
return Array.isArray(watchPath) ? watchPath.map((p) => path.resolve(root, p)) : typeof watchPath === "string" ? path.resolve(root, watchPath) : root;
}
export {
resolveOptions
};
//# sourceMappingURL=options.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/checkers/oxlint/options.ts"],"sourcesContent":["import path from 'node:path'\nimport { DiagnosticLevel, type OxlintConfig } from '../../types.js'\nimport { getOxlintCommand, mapSeverity } from './cli.js'\n\nexport interface ResolvedOptions {\n watchTarget: string | string[]\n logLevel?: DiagnosticLevel[]\n command: string\n}\n\nexport function resolveOptions(\n root: string,\n config: Exclude<OxlintConfig, false>,\n): ResolvedOptions {\n const options = config === true ? { lintCommand: 'oxlint' } : config\n return {\n watchTarget: resolveWatchTarget(root, options.watchPath),\n logLevel: options.dev?.logLevel?.map((l) => mapSeverity(l)) ?? [\n DiagnosticLevel.Warning,\n DiagnosticLevel.Error,\n ],\n command: getOxlintCommand(options.lintCommand ?? 'oxlint').join(' '),\n }\n}\n\nfunction resolveWatchTarget(\n root: string,\n watchPath?: string | string[],\n): string | string[] {\n return Array.isArray(watchPath)\n ? watchPath.map((p) => path.resolve(root, p))\n : typeof watchPath === 'string'\n ? path.resolve(root, watchPath)\n : root\n}\n"],"mappings":"AAAA,OAAO,UAAU;AACjB,SAAS,uBAA0C;AACnD,SAAS,kBAAkB,mBAAmB;AAQvC,SAAS,eACd,MACA,QACiB;AAbnB;AAcE,QAAM,UAAU,WAAW,OAAO,EAAE,aAAa,SAAS,IAAI;AAC9D,SAAO;AAAA,IACL,aAAa,mBAAmB,MAAM,QAAQ,SAAS;AAAA,IACvD,YAAU,mBAAQ,QAAR,mBAAa,aAAb,mBAAuB,IAAI,CAAC,MAAM,YAAY,CAAC,OAAM;AAAA,MAC7D,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,IAClB;AAAA,IACA,SAAS,iBAAiB,QAAQ,eAAe,QAAQ,EAAE,KAAK,GAAG;AAAA,EACrE;AACF;AAEA,SAAS,mBACP,MACA,WACmB;AACnB,SAAO,MAAM,QAAQ,SAAS,IAC1B,UAAU,IAAI,CAAC,MAAM,KAAK,QAAQ,MAAM,CAAC,CAAC,IAC1C,OAAO,cAAc,WACnB,KAAK,QAAQ,MAAM,SAAS,IAC5B;AACR;","names":[]}

View file

@ -0,0 +1,19 @@
import { FileDiagnosticManager } from '../../FileDiagnosticManager.js';
import { ResolvedOptions } from './options.js';
import { DisplayTarget } from './types.js';
import '../../logger.js';
import '@babel/code-frame';
import '../../types.js';
import 'node:worker_threads';
import 'eslint';
import 'stylelint';
import 'vite';
import '../vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
import 'typescript';
import 'vscode-languageclient/node';
declare function setupDevServer(root: string, options: ResolvedOptions, manager: FileDiagnosticManager, displayTargets: Set<DisplayTarget>): Promise<void>;
export { setupDevServer };

View file

@ -0,0 +1,51 @@
import path from "node:path";
import chokidar from "chokidar";
import { filterLogLevel } from "../../logger.js";
import { runOxlint } from "./cli.js";
import { dispatchDiagnostics } from "./diagnostics.js";
async function setupDevServer(root, options, manager, displayTargets) {
const initial = await runOxlint(options.command, root);
manager.initWith(initial);
dispatchDiagnostics(
filterLogLevel(manager.getDiagnostics(), options.logLevel),
displayTargets
);
const watcher = chokidar.watch(options.watchTarget, {
cwd: root,
ignored: (path2) => path2.includes("node_modules")
});
watcher.on("change", async (filePath) => {
await handleFileChange(root, options.command, filePath, manager);
dispatchDiagnostics(
filterLogLevel(manager.getDiagnostics(), options.logLevel),
displayTargets
);
});
watcher.on("unlink", (filePath) => {
handleFileUnlink(root, filePath, manager);
dispatchDiagnostics(
filterLogLevel(manager.getDiagnostics(), options.logLevel),
displayTargets
);
});
watcher.add(".");
}
function handleFileUnlink(root, filePath, manager) {
const absPath = path.resolve(root, filePath);
manager.updateByFileId(absPath, []);
}
async function handleFileChange(root, command, filePath, manager) {
const absPath = path.resolve(root, filePath);
const isConfigFile = path.basename(absPath) === ".oxlintrc.json";
if (isConfigFile) {
const diagnostics = await runOxlint(`${command} ${root}`, root);
manager.initWith(diagnostics);
} else {
const diagnostics = await runOxlint(`${command} ${absPath}`, root);
manager.updateByFileId(absPath, diagnostics);
}
}
export {
setupDevServer
};
//# sourceMappingURL=server.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/checkers/oxlint/server.ts"],"sourcesContent":["import path from 'node:path'\nimport chokidar from 'chokidar'\nimport type { FileDiagnosticManager } from '../../FileDiagnosticManager.js'\nimport { filterLogLevel } from '../../logger.js'\nimport { runOxlint } from './cli.js'\nimport { dispatchDiagnostics } from './diagnostics.js'\nimport type { ResolvedOptions } from './options.js'\nimport type { DisplayTarget } from './types'\n\nexport async function setupDevServer(\n root: string,\n options: ResolvedOptions,\n manager: FileDiagnosticManager,\n displayTargets: Set<DisplayTarget>,\n): Promise<void> {\n const initial = await runOxlint(options.command, root)\n manager.initWith(initial)\n dispatchDiagnostics(\n filterLogLevel(manager.getDiagnostics(), options.logLevel),\n displayTargets,\n )\n\n const watcher = chokidar.watch(options.watchTarget, {\n cwd: root,\n ignored: (path: string) => path.includes('node_modules'),\n })\n\n watcher.on('change', async (filePath) => {\n await handleFileChange(root, options.command, filePath, manager)\n dispatchDiagnostics(\n filterLogLevel(manager.getDiagnostics(), options.logLevel),\n displayTargets,\n )\n })\n\n watcher.on('unlink', (filePath) => {\n handleFileUnlink(root, filePath, manager)\n dispatchDiagnostics(\n filterLogLevel(manager.getDiagnostics(), options.logLevel),\n displayTargets,\n )\n })\n\n watcher.add('.')\n}\n\nfunction handleFileUnlink(\n root: string,\n filePath: string,\n manager: FileDiagnosticManager,\n) {\n const absPath = path.resolve(root, filePath)\n manager.updateByFileId(absPath, [])\n}\n\nasync function handleFileChange(\n root: string,\n command: string,\n filePath: string,\n manager: FileDiagnosticManager,\n) {\n const absPath = path.resolve(root, filePath)\n\n const isConfigFile = path.basename(absPath) === '.oxlintrc.json'\n if (isConfigFile) {\n const diagnostics = await runOxlint(`${command} ${root}`, root)\n manager.initWith(diagnostics)\n } else {\n const diagnostics = await runOxlint(`${command} ${absPath}`, root)\n manager.updateByFileId(absPath, diagnostics)\n }\n}\n"],"mappings":"AAAA,OAAO,UAAU;AACjB,OAAO,cAAc;AAErB,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB;AAC1B,SAAS,2BAA2B;AAIpC,eAAsB,eACpB,MACA,SACA,SACA,gBACe;AACf,QAAM,UAAU,MAAM,UAAU,QAAQ,SAAS,IAAI;AACrD,UAAQ,SAAS,OAAO;AACxB;AAAA,IACE,eAAe,QAAQ,eAAe,GAAG,QAAQ,QAAQ;AAAA,IACzD;AAAA,EACF;AAEA,QAAM,UAAU,SAAS,MAAM,QAAQ,aAAa;AAAA,IAClD,KAAK;AAAA,IACL,SAAS,CAACA,UAAiBA,MAAK,SAAS,cAAc;AAAA,EACzD,CAAC;AAED,UAAQ,GAAG,UAAU,OAAO,aAAa;AACvC,UAAM,iBAAiB,MAAM,QAAQ,SAAS,UAAU,OAAO;AAC/D;AAAA,MACE,eAAe,QAAQ,eAAe,GAAG,QAAQ,QAAQ;AAAA,MACzD;AAAA,IACF;AAAA,EACF,CAAC;AAED,UAAQ,GAAG,UAAU,CAAC,aAAa;AACjC,qBAAiB,MAAM,UAAU,OAAO;AACxC;AAAA,MACE,eAAe,QAAQ,eAAe,GAAG,QAAQ,QAAQ;AAAA,MACzD;AAAA,IACF;AAAA,EACF,CAAC;AAED,UAAQ,IAAI,GAAG;AACjB;AAEA,SAAS,iBACP,MACA,UACA,SACA;AACA,QAAM,UAAU,KAAK,QAAQ,MAAM,QAAQ;AAC3C,UAAQ,eAAe,SAAS,CAAC,CAAC;AACpC;AAEA,eAAe,iBACb,MACA,SACA,UACA,SACA;AACA,QAAM,UAAU,KAAK,QAAQ,MAAM,QAAQ;AAE3C,QAAM,eAAe,KAAK,SAAS,OAAO,MAAM;AAChD,MAAI,cAAc;AAChB,UAAM,cAAc,MAAM,UAAU,GAAG,OAAO,IAAI,IAAI,IAAI,IAAI;AAC9D,YAAQ,SAAS,WAAW;AAAA,EAC9B,OAAO;AACL,UAAM,cAAc,MAAM,UAAU,GAAG,OAAO,IAAI,OAAO,IAAI,IAAI;AACjE,YAAQ,eAAe,SAAS,WAAW;AAAA,EAC7C;AACF;","names":["path"]}

View file

@ -0,0 +1,3 @@
type DisplayTarget = 'overlay' | 'terminal';
export type { DisplayTarget };

View file

@ -0,0 +1 @@
//# sourceMappingURL=types.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}

View file

@ -0,0 +1,3 @@
declare function parseArgsStringToArgv(value: string, env?: string, file?: string): string[];
export { parseArgsStringToArgv as default, parseArgsStringToArgv };

View file

@ -0,0 +1,36 @@
function parseArgsStringToArgv(value, env, file) {
const myRegexp = (
// @ts-expect-error Bypass typescript validation
// biome-ignore lint/complexity/noUselessEscapeInRegex: Bypass validation
/([^\s'"]([^\s'"]*(['"])([^\3]*?)\3)+[^\s'"]*)|[^\s'"]+|(['"])([^\5]*?)\5/gi
);
const myString = value;
const myArray = [];
if (env) {
myArray.push(env);
}
if (file) {
myArray.push(file);
}
let match;
do {
match = myRegexp.exec(myString);
if (match !== null) {
myArray.push(firstString(match[1], match[6], match[0]));
}
} while (match !== null);
return myArray;
}
function firstString(...args) {
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (typeof arg === "string") {
return arg;
}
}
}
export {
parseArgsStringToArgv as default,
parseArgsStringToArgv
};
//# sourceMappingURL=argv.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/checkers/stylelint/argv.ts"],"sourcesContent":["// copied from https://github.com/jonschlinkert/is-plain-object/blob/master/is-plain-object.js\n// to make less breaking change, we'll make it a dependency before v1.0.0\n\nexport { parseArgsStringToArgv as default, parseArgsStringToArgv }\nfunction parseArgsStringToArgv(\n value: string,\n env?: string,\n file?: string,\n): string[] {\n // ([^\\s'\"]([^\\s'\"]*(['\"])([^\\3]*?)\\3)+[^\\s'\"]*) Matches nested quotes until the first space outside of quotes\n\n // [^\\s'\"]+ or Match if not a space ' or \"\n\n // (['\"])([^\\5]*?)\\5 or Match \"quoted text\" without quotes\n // `\\3` and `\\5` are a backreference to the quote style (' or \") captured\n const myRegexp =\n // @ts-expect-error Bypass typescript validation\n // biome-ignore lint/complexity/noUselessEscapeInRegex: Bypass validation\n /([^\\s'\"]([^\\s'\"]*(['\"])([^\\3]*?)\\3)+[^\\s'\"]*)|[^\\s'\"]+|(['\"])([^\\5]*?)\\5/gi\n const myString = value\n const myArray: string[] = []\n if (env) {\n myArray.push(env)\n }\n if (file) {\n myArray.push(file)\n }\n let match: RegExpExecArray | null\n do {\n // Each call to exec returns the next regex match as an array\n match = myRegexp.exec(myString)\n if (match !== null) {\n // Index 1 in the array is the captured group if it exists\n // Index 0 is the matched text, which we use if no captured group exists\n myArray.push(firstString(match[1], match[6], match[0])!)\n }\n } while (match !== null)\n\n return myArray\n}\n\n// Accepts any number of arguments, and returns the first one that is a string\n// (even an empty string)\n// @ts-ignore\nfunction firstString(...args: Array<any>): string | undefined {\n // eslint-disable-next-line @typescript-eslint/prefer-for-of\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]\n if (typeof arg === 'string') {\n return arg\n }\n }\n}\n"],"mappings":"AAIA,SAAS,sBACP,OACA,KACA,MACU;AAOV,QAAM;AAAA;AAAA;AAAA,IAGJ;AAAA;AACF,QAAM,WAAW;AACjB,QAAM,UAAoB,CAAC;AAC3B,MAAI,KAAK;AACP,YAAQ,KAAK,GAAG;AAAA,EAClB;AACA,MAAI,MAAM;AACR,YAAQ,KAAK,IAAI;AAAA,EACnB;AACA,MAAI;AACJ,KAAG;AAED,YAAQ,SAAS,KAAK,QAAQ;AAC9B,QAAI,UAAU,MAAM;AAGlB,cAAQ,KAAK,YAAY,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE;AAAA,IACzD;AAAA,EACF,SAAS,UAAU;AAEnB,SAAO;AACT;AAKA,SAAS,eAAe,MAAsC;AAE5D,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,OAAO,QAAQ,UAAU;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}

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 StylelintChecker extends Checker<'stylelint'> {
constructor();
init(): void;
}
export { StylelintChecker, createServeAndBuild };

View file

@ -0,0 +1,161 @@
import path from "node:path";
import { fileURLToPath } from "node:url";
import { parentPort } from "node:worker_threads";
import chokidar from "chokidar";
import stylelint from "stylelint";
import { Checker } from "../../Checker.js";
import { FileDiagnosticManager } from "../../FileDiagnosticManager.js";
import { createIgnore } from "../../glob.js";
import {
composeCheckerSummary,
consoleLog,
diagnosticToConsoleLevel,
diagnosticToRuntimeError,
diagnosticToTerminalLog,
filterLogLevel,
normalizeStylelintDiagnostic,
toClientPayload
} from "../../logger.js";
import { ACTION_TYPES, DiagnosticLevel } from "../../types.js";
import { translateOptions } from "./options.js";
const manager = new FileDiagnosticManager();
let createServeAndBuild;
const __filename = fileURLToPath(import.meta.url);
const createDiagnostic = (pluginConfig) => {
let overlay = true;
let terminal = true;
return {
config: async ({ enableOverlay, enableTerminal }) => {
overlay = enableOverlay;
terminal = enableTerminal;
},
async configureServer({ root }) {
var _a;
if (!pluginConfig.stylelint) return;
const translatedOptions = await translateOptions(
pluginConfig.stylelint.lintCommand
);
const baseConfig = {
cwd: root,
...translatedOptions
};
const logLevel = (() => {
var _a2;
if (typeof pluginConfig.stylelint !== "object") return void 0;
const userLogLevel = (_a2 = pluginConfig.stylelint.dev) == null ? void 0 : _a2.logLevel;
if (!userLogLevel) return void 0;
const map = {
error: DiagnosticLevel.Error,
warning: DiagnosticLevel.Warning
};
return userLogLevel.map((l) => map[l]);
})();
const dispatchDiagnostics = () => {
var _a2;
const diagnostics2 = filterLogLevel(manager.getDiagnostics(), logLevel);
if (terminal) {
for (const d of diagnostics2) {
consoleLog(
diagnosticToTerminalLog(d, "Stylelint"),
diagnosticToConsoleLevel(d)
);
}
const errorCount = diagnostics2.filter(
(d) => d.level === DiagnosticLevel.Error
).length;
const warningCount = diagnostics2.filter(
(d) => d.level === DiagnosticLevel.Warning
).length;
consoleLog(
composeCheckerSummary("Stylelint", errorCount, warningCount),
errorCount ? "error" : warningCount ? "warn" : "info"
);
}
if (overlay) {
(_a2 = parentPort) == null ? void 0 : _a2.postMessage({
type: ACTION_TYPES.overlayError,
payload: toClientPayload(
"stylelint",
diagnostics2.map((d) => diagnosticToRuntimeError(d))
)
});
}
};
const handleFileChange = async (filePath, type) => {
const absPath = path.resolve(root, filePath);
if (type === "unlink") {
manager.updateByFileId(absPath, []);
} else if (type === "change") {
const { results: diagnosticsOfChangedFile } = await stylelint.lint({
...baseConfig,
files: filePath
});
const newDiagnostics = diagnosticsOfChangedFile.flatMap(
(d) => normalizeStylelintDiagnostic(d)
);
manager.updateByFileId(absPath, newDiagnostics);
}
dispatchDiagnostics();
};
const { results: diagnostics } = await stylelint.lint({
...baseConfig,
...(_a = pluginConfig.stylelint.dev) == null ? void 0 : _a.overrideConfig
});
manager.initWith(
diagnostics.flatMap((p) => normalizeStylelintDiagnostic(p))
);
dispatchDiagnostics();
let watchTarget = root;
if (pluginConfig.stylelint.watchPath) {
if (Array.isArray(pluginConfig.stylelint.watchPath)) {
watchTarget = pluginConfig.stylelint.watchPath.map(
(p) => path.resolve(root, p)
);
} else {
watchTarget = path.resolve(root, pluginConfig.stylelint.watchPath);
}
}
const watcher = chokidar.watch(watchTarget, {
cwd: root,
ignored: createIgnore(root, translatedOptions.files)
});
watcher.on("change", async (filePath) => {
handleFileChange(filePath, "change");
});
watcher.on("unlink", async (filePath) => {
handleFileChange(filePath, "unlink");
});
}
};
};
class StylelintChecker extends Checker {
constructor() {
super({
name: "stylelint",
absFilePath: __filename,
build: {
buildBin: (pluginConfig) => {
if (pluginConfig.stylelint) {
const { lintCommand } = pluginConfig.stylelint;
return ["stylelint", lintCommand.split(" ").slice(1)];
}
return ["stylelint", [""]];
}
},
createDiagnostic
});
}
init() {
const _createServeAndBuild = super.initMainThread();
createServeAndBuild = _createServeAndBuild;
super.initWorkerThread();
}
}
const stylelintChecker = new StylelintChecker();
stylelintChecker.prepare();
stylelintChecker.init();
export {
StylelintChecker,
createServeAndBuild
};
//# sourceMappingURL=main.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,5 @@
import Stylelint__default from 'stylelint';
declare const translateOptions: (command: string) => Promise<Stylelint__default.LinterOptions>;
export { translateOptions };

View file

@ -0,0 +1,233 @@
import meow from "meow";
import { parseArgsStringToArgv } from "./argv.js";
const EXIT_CODE_ERROR = 2;
const translateOptions = async (command) => {
const result = meow({
autoHelp: false,
autoVersion: false,
importMeta: import.meta,
help: `
Usage: stylelint [input] [options]
Input: Files(s), glob(s), or nothing to use stdin.
If an input argument is wrapped in quotation marks, it will be passed to
globby for cross-platform glob support. node_modules are always ignored.
You can also pass no input and use stdin, instead.
Options:
--config
Path to a specific configuration file (JSON, YAML, or CommonJS), or the
name of a module in node_modules that points to one. If no --config
argument is provided, stylelint will search for configuration files in
the following places, in this order:
- a stylelint property in package.json
- a .stylelintrc file (with or without filename extension:
.json, .yaml, .yml, and .js are available)
- a stylelint.config.js file exporting a JS object
The search will begin in the working directory and move up the directory
tree until a configuration file is found.
--config-basedir
An absolute path to the directory that relative paths defining "extends"
and "plugins" are *relative to*. Only necessary if these values are
relative paths.
--print-config
Print the configuration for the given path.
--ignore-path, -i
Path to a file containing patterns that describe files to ignore. The
path can be absolute or relative to process.cwd(). By default, stylelint
looks for .stylelintignore in process.cwd().
--ignore-pattern, --ip
Pattern of files to ignore (in addition to those in .stylelintignore)
--fix
Automatically fix problems of certain rules.
--custom-syntax
Module name or path to a JS file exporting a PostCSS-compatible syntax.
--stdin
Accept stdin input even if it is empty.
--stdin-filename
A filename to assign stdin input.
--ignore-disables, --id
Ignore stylelint-disable comments.
--disable-default-ignores, --di
Allow linting of node_modules.
--cache [default: false]
Store the info about processed files in order to only operate on the
changed ones the next time you run stylelint. By default, the cache
is stored in "./.stylelintcache". To adjust this, use --cache-location.
--cache-location [default: '.stylelintcache']
Path to a file or directory to be used for the cache location.
Default is "./.stylelintcache". If a directory is specified, a cache
file will be created inside the specified folder, with a name derived
from a hash of the current working directory.
If the directory for the cache does not exist, make sure you add a trailing "/"
on *nix systems or "\\" on Windows. Otherwise the path will be assumed to be a file.
--formatter, -f [default: "string"]
The output formatter: "compact", "json", "tap", "unix" or "verbose"
--custom-formatter
Path to a JS file exporting a custom formatting function.
--quiet, -q
Only register problems for rules with an "error"-level severity (ignore
"warning"-level).
--color
--no-color
Force enabling/disabling of color.
--report-needless-disables, --rd
Also report errors for stylelint-disable comments that are not blocking a lint warning.
The process will exit with code ${EXIT_CODE_ERROR} if needless disables are found.
--report-invalid-scope-disables, --risd
Report stylelint-disable comments that used for rules that don't exist within the configuration object.
The process will exit with code ${EXIT_CODE_ERROR} if invalid scope disables are found.
--report-descriptionless-disables, --rdd
Report stylelint-disable comments without a description.
The process will exit with code ${EXIT_CODE_ERROR} if descriptionless disables are found.
--max-warnings, --mw
Number of warnings above which the process will exit with code ${EXIT_CODE_ERROR}.
Useful when setting "defaultSeverity" to "warning" and expecting the
process to fail on warnings (e.g. CI build).
--output-file, -o
Path of file to write report.
--version, -v
Show the currently installed version of stylelint.
--allow-empty-input, --aei
When glob pattern matches no files, the process will exit without throwing an error.
`,
flags: {
allowEmptyInput: {
shortFlag: "aei",
type: "boolean"
},
cache: {
type: "boolean"
},
cacheLocation: {
type: "string"
},
cacheStrategy: {
type: "string"
},
color: {
type: "boolean"
},
config: {
type: "string"
},
configBasedir: {
type: "string"
},
customFormatter: {
type: "string"
},
customSyntax: {
type: "string"
},
disableDefaultIgnores: {
shortFlag: "di",
type: "boolean"
},
fix: {
type: "boolean"
},
formatter: {
shortFlag: "f",
default: "string",
type: "string"
},
help: {
shortFlag: "h",
type: "boolean"
},
ignoreDisables: {
shortFlag: "id",
type: "boolean"
},
ignorePath: {
shortFlag: "i",
type: "string",
isMultiple: true
},
ignorePattern: {
shortFlag: "ip",
type: "string",
isMultiple: true
},
maxWarnings: {
shortFlag: "mw",
type: "number"
},
outputFile: {
shortFlag: "o",
type: "string"
},
printConfig: {
type: "boolean"
},
quiet: {
shortFlag: "q",
type: "boolean"
},
reportDescriptionlessDisables: {
shortFlag: "rdd",
type: "boolean"
},
reportInvalidScopeDisables: {
shortFlag: "risd",
type: "boolean"
},
reportNeedlessDisables: {
shortFlag: "rd",
type: "boolean"
},
stdin: {
type: "boolean"
},
stdinFilename: {
type: "string"
},
version: {
shortFlag: "v",
type: "boolean"
},
globbyOptions: {
shortFlag: "go",
type: "string"
}
},
argv: parseArgsStringToArgv(command)
});
const optionsBase = {
...Object.fromEntries(
Object.entries(result.flags).filter(
([key]) => [
"files",
"globbyOptions",
"cache",
"cacheLocation",
"code",
"codeFilename",
"config",
"configFile",
"configBasedir",
"cwd",
"ignoreDisables",
"ignorePath",
"ignorePattern",
"reportDescriptionlessDisables",
"reportNeedlessDisables",
"reportInvalidScopeDisables",
"maxWarnings",
"customSyntax",
"formatter",
"disableDefaultIgnores",
"fix",
"allowEmptyInput",
"quiet"
].includes(key)
)
),
formatter: result.flags.formatter === "string" ? "json" : result.flags.formatter,
files: result.input[1]
};
return optionsBase;
};
export {
translateOptions
};
//# sourceMappingURL=options.js.map

File diff suppressed because one or more lines are too long

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 TscChecker extends Checker<'typescript'> {
constructor();
init(): void;
}
export { TscChecker, createServeAndBuild };

View file

@ -0,0 +1,170 @@
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { parentPort } from "node:worker_threads";
import colors from "picocolors";
import invariant from "tiny-invariant";
import { Checker } from "../../Checker.js";
import {
consoleLog,
diagnosticToRuntimeError,
diagnosticToTerminalLog,
ensureCall,
normalizeTsDiagnostic,
toClientPayload,
wrapCheckerSummary
} from "../../logger.js";
import {
ACTION_TYPES
} from "../../types.js";
const __filename = fileURLToPath(import.meta.url);
let createServeAndBuild;
const createDiagnostic = (pluginConfig) => {
let overlay = true;
let terminal = true;
let currDiagnostics = [];
return {
config: async ({ enableOverlay, enableTerminal }) => {
overlay = enableOverlay;
terminal = enableTerminal;
},
async configureServer({ root }) {
invariant(pluginConfig.typescript, "config.typescript should be `false`");
const finalConfig = pluginConfig.typescript === true ? {
root,
tsconfigPath: "tsconfig.json",
typescriptPath: "typescript"
} : {
root: pluginConfig.typescript.root ?? root,
tsconfigPath: pluginConfig.typescript.tsconfigPath ?? "tsconfig.json",
typescriptPath: pluginConfig.typescript.typescriptPath ?? "typescript"
};
let configFile;
const ts = await import(finalConfig.typescriptPath).then((r) => r.default || r);
configFile = ts.findConfigFile(
finalConfig.root,
ts.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 = "";
const reportDiagnostic = (diagnostic) => {
const normalizedDiagnostic = normalizeTsDiagnostic(diagnostic);
if (normalizedDiagnostic === null) {
return;
}
currDiagnostics.push(diagnosticToRuntimeError(normalizedDiagnostic));
logChunk += os.EOL + diagnosticToTerminalLog(normalizedDiagnostic, "TypeScript");
};
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("typescript", currDiagnostics)
});
}
}
ensureCall(() => {
if (errorCount === 0) {
logChunk = "";
}
if (terminal) {
const color = errorCount && errorCount > 0 ? "red" : "green";
consoleLog(
colors[color](
logChunk + os.EOL + wrapCheckerSummary(
"TypeScript",
diagnostic.messageText.toString()
)
),
errorCount ? "error" : "info"
);
}
});
};
const createProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram;
if (typeof pluginConfig.typescript === "object" && pluginConfig.typescript.buildMode) {
const host = ts.createSolutionBuilderWithWatchHost(
ts.sys,
createProgram,
reportDiagnostic,
void 0,
reportWatchStatusChanged
);
ts.createSolutionBuilderWithWatch(host, [configFile], {}).build();
} else {
const host = ts.createWatchCompilerHost(
configFile,
{ noEmit: true },
ts.sys,
createProgram,
reportDiagnostic,
reportWatchStatusChanged
);
ts.createWatchProgram(host);
}
}
};
};
class TscChecker extends Checker {
constructor() {
super({
name: "typescript",
absFilePath: __filename,
build: {
buildBin: (config) => {
if (typeof config.typescript === "object") {
const {
root = "",
tsconfigPath = "",
buildMode
} = config.typescript;
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 ["tsc", args];
}
return ["tsc", ["--noEmit"]];
}
},
createDiagnostic
});
}
init() {
const _createServeAndBuild = super.initMainThread();
createServeAndBuild = _createServeAndBuild;
super.initWorkerThread();
}
}
const tscChecker = new TscChecker();
tscChecker.prepare();
tscChecker.init();
export {
TscChecker,
createServeAndBuild
};
//# sourceMappingURL=main.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,53 @@
import * as vscode_languageserver from 'vscode-languageserver';
import { Duplex } from 'node:stream';
import { VLS } from 'vls';
import { DiagnosticSeverity, Logger } from 'vscode-languageserver/node.js';
import { URI } from 'vscode-uri';
import { NormalizedDiagnostic } from '../../logger.js';
import { DeepPartial } from '../../types.js';
import { VlsOptions } from './initParams.js';
import '@babel/code-frame';
import 'eslint';
import 'stylelint';
import 'typescript';
import 'vscode-languageclient/node';
import 'node:worker_threads';
import 'vite';
import 'vscode-languageserver/node';
type LogLevel = (typeof logLevels)[number];
declare const logLevels: readonly ["ERROR", "WARN", "INFO", "HINT"];
declare const logLevel2Severity: {
ERROR: 1;
WARN: 2;
INFO: 3;
HINT: 4;
};
interface DiagnosticOptions {
watch: boolean;
verbose: boolean;
config: DeepPartial<VlsOptions> | null;
onDispatchDiagnostics?: (normalized: NormalizedDiagnostic[]) => void;
onDispatchDiagnosticsSummary?: (errorCount: number, warningCount: number) => void;
}
declare function diagnostics(workspace: string | null, logLevel: LogLevel, options?: DiagnosticOptions): Promise<void>;
declare class NullLogger implements Logger {
error(_message: string): void;
warn(_message: string): void;
info(_message: string): void;
log(_message: string): void;
}
declare class TestStream extends Duplex {
_write(chunk: string, _encoding: string, done: () => void): void;
_read(_size: number): void;
}
declare function prepareClientConnection(workspaceUri: URI, severity: DiagnosticSeverity, options: DiagnosticOptions): Promise<{
clientConnection: vscode_languageserver.ProtocolConnection;
serverConnection: vscode_languageserver.Connection;
vls: VLS;
up: TestStream;
down: TestStream;
logger: NullLogger;
}>;
export { type DiagnosticOptions, TestStream, diagnostics, logLevel2Severity, logLevels, prepareClientConnection };

View file

@ -0,0 +1,330 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { Duplex } from "node:stream";
import chokidar from "chokidar";
import colors from "picocolors";
import { globSync } from "tinyglobby";
import { VLS } from "vls";
import {
createConnection,
createProtocolConnection,
DiagnosticSeverity,
DidChangeTextDocumentNotification,
DidChangeWatchedFilesNotification,
DidOpenTextDocumentNotification,
InitializeRequest,
StreamMessageReader,
StreamMessageWriter
} from "vscode-languageserver/node.js";
import { URI } from "vscode-uri";
import { FileDiagnosticManager } from "../../FileDiagnosticManager.js";
import {
diagnosticToTerminalLog,
normalizeLspDiagnostic,
normalizePublishDiagnosticParams
} from "../../logger.js";
import { getInitParams } from "./initParams.js";
var DOC_VERSION = /* @__PURE__ */ ((DOC_VERSION2) => {
DOC_VERSION2[DOC_VERSION2["init"] = -1] = "init";
return DOC_VERSION2;
})(DOC_VERSION || {});
const logLevels = ["ERROR", "WARN", "INFO", "HINT"];
let disposeSuppressConsole;
let initialVueFilesCount = 0;
let initialVueFilesTick = 0;
const fileDiagnosticManager = new FileDiagnosticManager();
const logLevel2Severity = {
ERROR: DiagnosticSeverity.Error,
WARN: DiagnosticSeverity.Warning,
INFO: DiagnosticSeverity.Information,
HINT: DiagnosticSeverity.Hint
};
async function diagnostics(workspace, logLevel, options = { watch: false, verbose: false, config: null }) {
var _a;
if (options.verbose) {
console.log("====================================");
console.log("Getting Vetur diagnostics");
}
let workspaceUri;
if (workspace) {
const absPath = path.resolve(process.cwd(), workspace);
console.log(`Loading Vetur in workspace path: ${colors.green(absPath)}`);
workspaceUri = URI.file(absPath);
} else {
console.log(
`Loading Vetur in current directory: ${colors.green(process.cwd())}`
);
workspaceUri = URI.file(process.cwd());
}
const result = await getDiagnostics(
workspaceUri,
logLevel2Severity[logLevel],
options
);
if (options.verbose) {
console.log("====================================");
}
if (!options.watch && typeof result === "object" && result !== null) {
const { initialErrorCount, initialWarningCount } = result;
(_a = options == null ? void 0 : options.onDispatchDiagnosticsSummary) == null ? void 0 : _a.call(
options,
initialErrorCount,
initialWarningCount
);
process.exit(initialErrorCount > 0 ? 1 : 0);
}
}
class NullLogger {
error(_message) {
}
warn(_message) {
}
info(_message) {
}
log(_message) {
}
}
class TestStream extends Duplex {
_write(chunk, _encoding, done) {
this.emit("data", chunk);
done();
}
_read(_size) {
}
}
function suppressConsole() {
let disposed = false;
const rawConsoleLog = console.log;
console.log = () => {
};
return () => {
if (disposed) return;
disposed = true;
console.log = rawConsoleLog;
};
}
async function prepareClientConnection(workspaceUri, severity, options) {
const up = new TestStream();
const down = new TestStream();
const logger = new NullLogger();
const clientConnection = createProtocolConnection(
new StreamMessageReader(down),
new StreamMessageWriter(up),
logger
);
const serverConnection = createConnection(
new StreamMessageReader(up),
new StreamMessageWriter(down)
);
serverConnection.sendDiagnostics = async (publishDiagnostics) => {
var _a, _b;
disposeSuppressConsole == null ? void 0 : disposeSuppressConsole();
if (publishDiagnostics.version === -1 /* init */) {
return;
}
const absFilePath = URI.parse(publishDiagnostics.uri).fsPath;
publishDiagnostics.diagnostics = filterDiagnostics(
publishDiagnostics.diagnostics,
severity
);
const nextDiagnosticInFile = await normalizePublishDiagnosticParams(publishDiagnostics);
fileDiagnosticManager.updateByFileId(absFilePath, nextDiagnosticInFile);
const normalized = fileDiagnosticManager.getDiagnostics();
const errorCount = normalized.filter(
(d) => d.level === DiagnosticSeverity.Error
).length;
const warningCount = normalized.filter(
(d) => d.level === DiagnosticSeverity.Warning
).length;
initialVueFilesTick++;
if (initialVueFilesTick >= initialVueFilesCount) {
(_a = options.onDispatchDiagnostics) == null ? void 0 : _a.call(options, normalized);
(_b = options.onDispatchDiagnosticsSummary) == null ? void 0 : _b.call(options, errorCount, warningCount);
}
};
const vls = new VLS(serverConnection);
vls.validateTextDocument = async (textDocument, cancellationToken) => {
const diagnostics2 = await vls.doValidate(textDocument, cancellationToken);
if (diagnostics2) {
vls.lspConnection.sendDiagnostics({
uri: textDocument.uri,
version: textDocument.version,
diagnostics: diagnostics2
});
}
};
serverConnection.onInitialize(
async (params) => {
await vls.init(params);
if (options.verbose) {
console.log("Vetur initialized");
console.log("====================================");
}
return {
capabilities: vls.capabilities
};
}
);
vls.listen();
clientConnection.listen();
const initParams = getInitParams(workspaceUri);
if (options.config) {
mergeDeep(initParams.initializationOptions.config, options.config);
}
await clientConnection.sendRequest(InitializeRequest.type, initParams);
return { clientConnection, serverConnection, vls, up, down, logger };
}
function extToGlobs(exts) {
return exts.map((e) => `**/*${e}`);
}
const watchedDidChangeContent = [".vue"];
const watchedDidChangeWatchedFiles = [".js", ".ts", ".json"];
const watchedDidChangeContentGlob = extToGlobs(watchedDidChangeContent);
async function getDiagnostics(workspaceUri, severity, options) {
const { clientConnection } = await prepareClientConnection(
workspaceUri,
severity,
options
);
const files = globSync([...watchedDidChangeContentGlob], {
cwd: workspaceUri.fsPath,
ignore: ["node_modules/**"]
});
if (files.length === 0) {
console.log("[VLS checker] No input files");
return { initialWarningCount: 0, initialErrorCount: 0 };
}
if (options.verbose) {
console.log("");
console.log("Getting diagnostics from: ", files, "\n");
}
const absFilePaths = files.map((f) => path.resolve(workspaceUri.fsPath, f));
disposeSuppressConsole = suppressConsole();
initialVueFilesCount = absFilePaths.length;
let initialErrorCount = 0;
let initialWarningCount = 0;
await Promise.all(
absFilePaths.map(async (absFilePath) => {
const fileText = await fs.promises.readFile(absFilePath, "utf-8");
clientConnection.sendNotification(DidOpenTextDocumentNotification.type, {
textDocument: {
languageId: "vue",
uri: URI.file(absFilePath).toString(),
version: -1 /* init */,
text: fileText
}
});
if (options.watch) return;
try {
let diagnostics2 = await clientConnection.sendRequest(
"$/getDiagnostics",
{
uri: URI.file(absFilePath).toString(),
version: -1 /* init */
}
);
diagnostics2 = filterDiagnostics(diagnostics2, severity);
let logChunk = "";
if (diagnostics2.length > 0) {
logChunk += os.EOL + diagnostics2.map(
(d) => diagnosticToTerminalLog(
normalizeLspDiagnostic({
diagnostic: d,
absFilePath,
fileText
}),
"VLS"
)
).join(os.EOL);
for (const d of diagnostics2) {
if (d.severity === DiagnosticSeverity.Error) {
initialErrorCount++;
}
if (d.severity === DiagnosticSeverity.Warning) {
initialWarningCount++;
}
}
}
console.log(logChunk);
return { initialErrorCount, initialWarningCount };
} catch (err) {
console.error(err.stack);
return { initialErrorCount, initialWarningCount };
}
})
);
if (!options.watch) {
return { initialErrorCount, initialWarningCount };
}
await Promise.all(
absFilePaths.map(async (absFilePath) => {
const fileText = await fs.promises.readFile(absFilePath, "utf-8");
clientConnection.sendNotification(DidOpenTextDocumentNotification.type, {
textDocument: {
languageId: "vue",
uri: URI.file(absFilePath).toString(),
version: -1 /* init */,
text: fileText
}
});
})
);
const watcher = chokidar.watch([], {
ignored: (path2) => path2.includes("node_modules")
});
watcher.add(workspaceUri.fsPath);
watcher.on("all", async (event, filePath) => {
const extname = path.extname(filePath);
if (!filePath.endsWith(".vue")) return;
const fileContent = await fs.promises.readFile(filePath, "utf-8");
clientConnection.sendNotification(DidChangeTextDocumentNotification.type, {
textDocument: {
uri: URI.file(filePath).toString(),
version: Date.now()
},
contentChanges: [{ text: fileContent }]
});
if (watchedDidChangeWatchedFiles.includes(extname)) {
clientConnection.sendNotification(
DidChangeWatchedFilesNotification.type,
{
changes: [
{
uri: URI.file(filePath).toString(),
type: event === "add" ? 1 : event === "unlink" ? 3 : 2
}
]
}
);
}
});
return null;
}
function isObject(item) {
return item && typeof item === "object" && !Array.isArray(item);
}
function mergeDeep(target, source) {
if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} });
mergeDeep(target[key], source[key]);
} else {
Object.assign(target, { [key]: source[key] });
}
}
}
return target;
}
function filterDiagnostics(diagnostics2, severity) {
return diagnostics2.filter((r) => r.source !== "eslint-plugin-vue").filter((r) => r.severity && r.severity <= severity);
}
export {
TestStream,
diagnostics,
logLevel2Severity,
logLevels,
prepareClientConnection
};
//# sourceMappingURL=diagnostics.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,72 @@
import { InitializeParams } from 'vscode-languageserver/node';
import { URI } from 'vscode-uri';
type VlsOptions = ReturnType<typeof getDefaultVLSConfig>;
declare function getInitParams(workspaceUri: URI): InitializeParams;
declare function getDefaultVLSConfig(): {
vetur: {
ignoreProjectWarning: boolean;
useWorkspaceDependencies: boolean;
validation: {
template: boolean;
templateProps: boolean;
interpolation: boolean;
style: boolean;
script: boolean;
};
completion: {
autoImport: boolean;
tagCasing: string;
scaffoldSnippetSources: {
workspace: string;
user: string;
vetur: string;
};
};
grammar: {
customBlocks: {};
};
format: {
enable: boolean;
options: {
tabSize: number;
useTabs: boolean;
};
defaultFormatter: {};
defaultFormatterOptions: {};
scriptInitialIndent: boolean;
styleInitialIndent: boolean;
};
languageFeatures: {
codeActions: boolean;
updateImportOnFileMove: boolean;
semanticTokens: boolean;
};
trace: {
server: string;
};
dev: {
vlsPath: string;
vlsPort: number;
logLevel: string;
};
experimental: {
templateInterpolationService: boolean;
};
};
css: {};
html: {
suggest: {};
};
javascript: {
format: {};
};
typescript: {
tsdk: null;
format: {};
};
emmet: {};
stylusSupremacy: {};
};
export { type VlsOptions, getDefaultVLSConfig, getInitParams };

View file

@ -0,0 +1,95 @@
function getInitParams(workspaceUri) {
const defaultVLSConfig = getDefaultVLSConfig();
defaultVLSConfig.vetur.validation = {
template: true,
style: true,
script: true,
interpolation: true,
templateProps: true
};
defaultVLSConfig.vetur.experimental = {
templateInterpolationService: true
};
const init = {
rootPath: workspaceUri.fsPath,
rootUri: workspaceUri.toString(),
processId: process.pid,
capabilities: {},
initializationOptions: {
config: defaultVLSConfig
}
};
return init;
}
function getDefaultVLSConfig() {
return {
vetur: {
ignoreProjectWarning: false,
useWorkspaceDependencies: false,
validation: {
template: true,
templateProps: true,
interpolation: true,
style: true,
script: true
},
completion: {
autoImport: false,
tagCasing: "initial",
scaffoldSnippetSources: {
workspace: "\u{1F4BC}",
user: "\u{1F5D2}\uFE0F",
vetur: "\u270C"
}
},
grammar: {
customBlocks: {}
},
format: {
enable: true,
options: {
tabSize: 2,
useTabs: false
},
defaultFormatter: {},
defaultFormatterOptions: {},
scriptInitialIndent: false,
styleInitialIndent: false
},
languageFeatures: {
codeActions: true,
updateImportOnFileMove: true,
semanticTokens: true
},
trace: {
server: "off"
},
dev: {
vlsPath: "",
vlsPort: -1,
logLevel: "INFO"
},
experimental: {
templateInterpolationService: false
}
},
css: {},
html: {
suggest: {}
},
javascript: {
format: {}
},
typescript: {
tsdk: null,
format: {}
},
emmet: {},
stylusSupremacy: {}
};
}
export {
getDefaultVLSConfig,
getInitParams
};
//# sourceMappingURL=initParams.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/checkers/vls/initParams.ts"],"sourcesContent":["import type { InitializeParams } from 'vscode-languageserver/node'\nimport type { URI } from 'vscode-uri'\n\nexport type VlsOptions = ReturnType<typeof getDefaultVLSConfig>\n\nexport function getInitParams(workspaceUri: URI): InitializeParams {\n const defaultVLSConfig = getDefaultVLSConfig()\n\n defaultVLSConfig.vetur.validation = {\n template: true,\n style: true,\n script: true,\n interpolation: true,\n templateProps: true,\n }\n defaultVLSConfig.vetur.experimental = {\n templateInterpolationService: true,\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const init: InitializeParams = {\n rootPath: workspaceUri.fsPath,\n rootUri: workspaceUri.toString(),\n processId: process.pid,\n capabilities: {},\n initializationOptions: {\n config: defaultVLSConfig,\n },\n } as InitializeParams\n\n return init\n}\n\nexport function getDefaultVLSConfig() {\n return {\n vetur: {\n ignoreProjectWarning: false,\n useWorkspaceDependencies: false,\n validation: {\n template: true,\n templateProps: true,\n interpolation: true,\n style: true,\n script: true,\n },\n completion: {\n autoImport: false,\n tagCasing: 'initial',\n scaffoldSnippetSources: {\n workspace: '💼',\n user: '🗒️',\n vetur: '✌',\n },\n },\n grammar: {\n customBlocks: {},\n },\n format: {\n enable: true,\n options: {\n tabSize: 2,\n useTabs: false,\n },\n defaultFormatter: {},\n defaultFormatterOptions: {},\n scriptInitialIndent: false,\n styleInitialIndent: false,\n },\n languageFeatures: {\n codeActions: true,\n updateImportOnFileMove: true,\n semanticTokens: true,\n },\n trace: {\n server: 'off',\n },\n dev: {\n vlsPath: '',\n vlsPort: -1,\n logLevel: 'INFO',\n },\n experimental: {\n templateInterpolationService: false,\n },\n },\n css: {},\n html: {\n suggest: {},\n },\n javascript: {\n format: {},\n },\n typescript: {\n tsdk: null,\n format: {},\n },\n emmet: {},\n stylusSupremacy: {},\n }\n}\n"],"mappings":"AAKO,SAAS,cAAc,cAAqC;AACjE,QAAM,mBAAmB,oBAAoB;AAE7C,mBAAiB,MAAM,aAAa;AAAA,IAClC,UAAU;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,eAAe;AAAA,EACjB;AACA,mBAAiB,MAAM,eAAe;AAAA,IACpC,8BAA8B;AAAA,EAChC;AAGA,QAAM,OAAyB;AAAA,IAC7B,UAAU,aAAa;AAAA,IACvB,SAAS,aAAa,SAAS;AAAA,IAC/B,WAAW,QAAQ;AAAA,IACnB,cAAc,CAAC;AAAA,IACf,uBAAuB;AAAA,MACrB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,sBAAsB;AACpC,SAAO;AAAA,IACL,OAAO;AAAA,MACL,sBAAsB;AAAA,MACtB,0BAA0B;AAAA,MAC1B,YAAY;AAAA,QACV,UAAU;AAAA,QACV,eAAe;AAAA,QACf,eAAe;AAAA,QACf,OAAO;AAAA,QACP,QAAQ;AAAA,MACV;AAAA,MACA,YAAY;AAAA,QACV,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,wBAAwB;AAAA,UACtB,WAAW;AAAA,UACX,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,SAAS;AAAA,QACP,cAAc,CAAC;AAAA,MACjB;AAAA,MACA,QAAQ;AAAA,QACN,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,QACA,kBAAkB,CAAC;AAAA,QACnB,yBAAyB,CAAC;AAAA,QAC1B,qBAAqB;AAAA,QACrB,oBAAoB;AAAA,MACtB;AAAA,MACA,kBAAkB;AAAA,QAChB,aAAa;AAAA,QACb,wBAAwB;AAAA,QACxB,gBAAgB;AAAA,MAClB;AAAA,MACA,OAAO;AAAA,QACL,QAAQ;AAAA,MACV;AAAA,MACA,KAAK;AAAA,QACH,SAAS;AAAA,QACT,SAAS;AAAA,QACT,UAAU;AAAA,MACZ;AAAA,MACA,cAAc;AAAA,QACZ,8BAA8B;AAAA,MAChC;AAAA,IACF;AAAA,IACA,KAAK,CAAC;AAAA,IACN,MAAM;AAAA,MACJ,SAAS,CAAC;AAAA,IACZ;AAAA,IACA,YAAY;AAAA,MACV,QAAQ,CAAC;AAAA,IACX;AAAA,IACA,YAAY;AAAA,MACV,MAAM;AAAA,MACN,QAAQ,CAAC;AAAA,IACX;AAAA,IACA,OAAO,CAAC;AAAA,IACR,iBAAiB,CAAC;AAAA,EACpB;AACF;","names":[]}

View file

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

View file

@ -0,0 +1,103 @@
import { fileURLToPath } from "node:url";
import { parentPort } from "node:worker_threads";
import { Checker } from "../../Checker.js";
import {
composeCheckerSummary,
consoleLog,
diagnosticToConsoleLevel,
diagnosticToRuntimeError,
diagnosticToTerminalLog,
toClientPayload
} from "../../logger.js";
import { ACTION_TYPES } from "../../types.js";
import { diagnostics } from "./diagnostics.js";
const __filename = fileURLToPath(import.meta.url);
let createServeAndBuild;
const createDiagnostic = (pluginConfig) => {
let overlay = true;
let terminal = true;
let command;
return {
config: ({ enableOverlay, enableTerminal, env }) => {
overlay = enableOverlay;
terminal = enableTerminal;
command = env.command;
},
async configureServer({ root }) {
const workDir = root;
const onDispatchDiagnosticsSummary = (errorCount, warningCount) => {
if (!terminal) return;
consoleLog(
composeCheckerSummary("VLS", errorCount, warningCount),
errorCount ? "error" : warningCount ? "warn" : "info"
);
};
const onDispatchDiagnostics = (normalized) => {
var _a;
if (overlay && command === "serve") {
(_a = parentPort) == null ? void 0 : _a.postMessage({
type: ACTION_TYPES.overlayError,
payload: toClientPayload(
"vls",
diagnosticToRuntimeError(normalized)
)
});
}
if (terminal) {
for (const d of normalized) {
consoleLog(
diagnosticToTerminalLog(d, "VLS"),
diagnosticToConsoleLevel(d)
);
}
}
};
const vlsConfig = pluginConfig == null ? void 0 : pluginConfig.vls;
await diagnostics(workDir, "WARN", {
onDispatchDiagnostics,
onDispatchDiagnosticsSummary,
watch: true,
verbose: false,
config: typeof vlsConfig === "object" ? vlsConfig : null
});
}
};
};
class VlsChecker extends Checker {
constructor() {
super({
name: "vls",
absFilePath: __filename,
build: {
buildBin: (config) => {
if (typeof config.vls === "object") {
return [
"vti",
[
"diagnostics",
// Escape quotes so that the system shell doesn't strip them out:
`"${JSON.stringify(config.vls).replace(/[\\"]/g, "\\$&")}"`
]
];
}
return ["vti", ["diagnostics"]];
}
},
createDiagnostic
});
}
init() {
const _createServeAndBuild = super.initMainThread();
createServeAndBuild = _createServeAndBuild;
super.initWorkerThread();
}
}
const vlsChecker = new VlsChecker();
vlsChecker.prepare();
vlsChecker.init();
export {
VlsChecker,
createDiagnostic,
createServeAndBuild
};
//# sourceMappingURL=main.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../../src/checkers/vls/main.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url'\nimport { parentPort } from 'node:worker_threads'\nimport type { ConfigEnv } from 'vite'\nimport { Checker } from '../../Checker.js'\nimport {\n composeCheckerSummary,\n consoleLog,\n diagnosticToConsoleLevel,\n diagnosticToRuntimeError,\n diagnosticToTerminalLog,\n toClientPayload,\n} from '../../logger.js'\nimport type { CreateDiagnostic } from '../../types.js'\nimport { ACTION_TYPES } from '../../types.js'\nimport { type DiagnosticOptions, diagnostics } from './diagnostics.js'\n\nconst __filename = fileURLToPath(import.meta.url)\n\nlet createServeAndBuild: any\n\nexport const createDiagnostic: CreateDiagnostic<'vls'> = (pluginConfig) => {\n let overlay = true\n let terminal = true\n let command: ConfigEnv['command']\n\n return {\n config: ({ enableOverlay, enableTerminal, env }) => {\n overlay = enableOverlay\n terminal = enableTerminal\n command = env.command\n },\n async configureServer({ root }) {\n const workDir: string = root\n\n const onDispatchDiagnosticsSummary: DiagnosticOptions['onDispatchDiagnosticsSummary'] =\n (errorCount, warningCount) => {\n if (!terminal) return\n\n consoleLog(\n composeCheckerSummary('VLS', errorCount, warningCount),\n errorCount ? 'error' : warningCount ? 'warn' : 'info',\n )\n }\n\n const onDispatchDiagnostics: DiagnosticOptions['onDispatchDiagnostics'] =\n (normalized) => {\n if (overlay && command === 'serve') {\n parentPort?.postMessage({\n type: ACTION_TYPES.overlayError,\n payload: toClientPayload(\n 'vls',\n diagnosticToRuntimeError(normalized),\n ),\n })\n }\n\n if (terminal) {\n for (const d of normalized) {\n consoleLog(\n diagnosticToTerminalLog(d, 'VLS'),\n diagnosticToConsoleLevel(d),\n )\n }\n }\n }\n\n const vlsConfig = pluginConfig?.vls\n await diagnostics(workDir, 'WARN', {\n onDispatchDiagnostics,\n onDispatchDiagnosticsSummary,\n watch: true,\n verbose: false,\n config: typeof vlsConfig === 'object' ? vlsConfig : null,\n })\n },\n }\n}\n\nexport class VlsChecker extends Checker<'vls'> {\n public constructor() {\n super({\n name: 'vls',\n absFilePath: __filename,\n build: {\n buildBin: (config) => {\n if (typeof config.vls === 'object') {\n return [\n 'vti',\n [\n 'diagnostics',\n // Escape quotes so that the system shell doesn't strip them out:\n `\"${JSON.stringify(config.vls).replace(/[\\\\\"]/g, '\\\\$&')}\"`,\n ],\n ]\n }\n\n return ['vti', ['diagnostics']]\n },\n },\n createDiagnostic,\n })\n }\n\n public init() {\n const _createServeAndBuild = super.initMainThread()\n createServeAndBuild = _createServeAndBuild\n super.initWorkerThread()\n }\n}\n\nexport { createServeAndBuild }\nconst vlsChecker = new VlsChecker()\nvlsChecker.prepare()\nvlsChecker.init()\n"],"mappings":"AAAA,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAE3B,SAAS,eAAe;AACxB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,oBAAoB;AAC7B,SAAiC,mBAAmB;AAEpD,MAAM,aAAa,cAAc,YAAY,GAAG;AAEhD,IAAI;AAEG,MAAM,mBAA4C,CAAC,iBAAiB;AACzE,MAAI,UAAU;AACd,MAAI,WAAW;AACf,MAAI;AAEJ,SAAO;AAAA,IACL,QAAQ,CAAC,EAAE,eAAe,gBAAgB,IAAI,MAAM;AAClD,gBAAU;AACV,iBAAW;AACX,gBAAU,IAAI;AAAA,IAChB;AAAA,IACA,MAAM,gBAAgB,EAAE,KAAK,GAAG;AAC9B,YAAM,UAAkB;AAExB,YAAM,+BACJ,CAAC,YAAY,iBAAiB;AAC5B,YAAI,CAAC,SAAU;AAEf;AAAA,UACE,sBAAsB,OAAO,YAAY,YAAY;AAAA,UACrD,aAAa,UAAU,eAAe,SAAS;AAAA,QACjD;AAAA,MACF;AAEF,YAAM,wBACJ,CAAC,eAAe;AA7CxB;AA8CU,YAAI,WAAW,YAAY,SAAS;AAClC,kDAAY,YAAY;AAAA,YACtB,MAAM,aAAa;AAAA,YACnB,SAAS;AAAA,cACP;AAAA,cACA,yBAAyB,UAAU;AAAA,YACrC;AAAA,UACF;AAAA,QACF;AAEA,YAAI,UAAU;AACZ,qBAAW,KAAK,YAAY;AAC1B;AAAA,cACE,wBAAwB,GAAG,KAAK;AAAA,cAChC,yBAAyB,CAAC;AAAA,YAC5B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEF,YAAM,YAAY,6CAAc;AAChC,YAAM,YAAY,SAAS,QAAQ;AAAA,QACjC;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP,SAAS;AAAA,QACT,QAAQ,OAAO,cAAc,WAAW,YAAY;AAAA,MACtD,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEO,MAAM,mBAAmB,QAAe;AAAA,EACtC,cAAc;AACnB,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,OAAO;AAAA,QACL,UAAU,CAAC,WAAW;AACpB,cAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,mBAAO;AAAA,cACL;AAAA,cACA;AAAA,gBACE;AAAA;AAAA,gBAEA,IAAI,KAAK,UAAU,OAAO,GAAG,EAAE,QAAQ,UAAU,MAAM,CAAC;AAAA,cAC1D;AAAA,YACF;AAAA,UACF;AAEA,iBAAO,CAAC,OAAO,CAAC,aAAa,CAAC;AAAA,QAChC;AAAA,MACF;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEO,OAAO;AACZ,UAAM,uBAAuB,MAAM,eAAe;AAClD,0BAAsB;AACtB,UAAM,iBAAiB;AAAA,EACzB;AACF;AAGA,MAAM,aAAa,IAAI,WAAW;AAClC,WAAW,QAAQ;AACnB,WAAW,KAAK;","names":[]}

View file

@ -0,0 +1,2 @@
export { }

View file

@ -0,0 +1 @@
//# sourceMappingURL=typings.d.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}

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

View file

@ -0,0 +1,22 @@
import { SharedConfig } from '../types.js';
import 'node:worker_threads';
import 'eslint';
import 'stylelint';
import 'vite';
import '../checkers/vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
declare const RUNTIME_CLIENT_RUNTIME_PATH = "/@vite-plugin-checker-runtime";
declare const RUNTIME_CLIENT_ENTRY_PATH = "/@vite-plugin-checker-runtime-entry";
declare const wrapVirtualPrefix: (id: `/${string}`) => `virtual:${string}`;
declare const composePreambleCode: ({ baseWithOrigin, overlayConfig, }: {
baseWithOrigin: string;
overlayConfig: SharedConfig["overlay"];
}) => string;
declare const WS_CHECKER_ERROR_EVENT = "vite-plugin-checker:error";
declare const WS_CHECKER_RECONNECT_EVENT = "vite-plugin-checker:reconnect";
declare const runtimeSourceFilePath: string;
declare const runtimeCode: string;
export { RUNTIME_CLIENT_ENTRY_PATH, RUNTIME_CLIENT_RUNTIME_PATH, WS_CHECKER_ERROR_EVENT, WS_CHECKER_RECONNECT_EVENT, composePreambleCode, runtimeCode, runtimeSourceFilePath, wrapVirtualPrefix };

View file

@ -0,0 +1,31 @@
import fs from "node:fs";
import { createRequire } from "node:module";
const _require = createRequire(import.meta.url);
const RUNTIME_CLIENT_RUNTIME_PATH = "/@vite-plugin-checker-runtime";
const RUNTIME_CLIENT_ENTRY_PATH = "/@vite-plugin-checker-runtime-entry";
const wrapVirtualPrefix = (id) => `virtual:${id.slice("/".length)}`;
const composePreambleCode = ({
baseWithOrigin = "/",
overlayConfig
}) => `
import { inject } from "${baseWithOrigin}${RUNTIME_CLIENT_RUNTIME_PATH.slice(1)}";
inject({
overlayConfig: ${JSON.stringify(overlayConfig)},
base: "${baseWithOrigin}",
});
`;
const WS_CHECKER_ERROR_EVENT = "vite-plugin-checker:error";
const WS_CHECKER_RECONNECT_EVENT = "vite-plugin-checker:reconnect";
const runtimeSourceFilePath = _require.resolve("../@runtime/main.js");
const runtimeCode = `${fs.readFileSync(runtimeSourceFilePath, "utf-8")};`;
export {
RUNTIME_CLIENT_ENTRY_PATH,
RUNTIME_CLIENT_RUNTIME_PATH,
WS_CHECKER_ERROR_EVENT,
WS_CHECKER_RECONNECT_EVENT,
composePreambleCode,
runtimeCode,
runtimeSourceFilePath,
wrapVirtualPrefix
};
//# sourceMappingURL=index.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../../src/client/index.ts"],"sourcesContent":["import fs from 'node:fs'\nimport { createRequire } from 'node:module'\nimport type { SharedConfig } from '../types'\n\nconst _require = createRequire(import.meta.url)\n\nexport const RUNTIME_CLIENT_RUNTIME_PATH = '/@vite-plugin-checker-runtime'\nexport const RUNTIME_CLIENT_ENTRY_PATH = '/@vite-plugin-checker-runtime-entry'\n\nexport const wrapVirtualPrefix = (id: `/${string}`): `virtual:${string}` =>\n `virtual:${id.slice('/'.length)}`\nexport const composePreambleCode = ({\n baseWithOrigin = '/',\n overlayConfig,\n}: {\n baseWithOrigin: string\n overlayConfig: SharedConfig['overlay']\n}) => `\nimport { inject } from \"${baseWithOrigin}${RUNTIME_CLIENT_RUNTIME_PATH.slice(1)}\";\ninject({\n overlayConfig: ${JSON.stringify(overlayConfig)},\n base: \"${baseWithOrigin}\",\n});\n`\n\n// #region\n// NOTE: sync modification with packages/runtime/src/ws.js\nexport const WS_CHECKER_ERROR_EVENT = 'vite-plugin-checker:error'\nexport const WS_CHECKER_RECONNECT_EVENT = 'vite-plugin-checker:reconnect'\n// #endregion\n\nexport const runtimeSourceFilePath = _require.resolve('../@runtime/main.js')\nexport const runtimeCode = `${fs.readFileSync(runtimeSourceFilePath, 'utf-8')};`\n"],"mappings":"AAAA,OAAO,QAAQ;AACf,SAAS,qBAAqB;AAG9B,MAAM,WAAW,cAAc,YAAY,GAAG;AAEvC,MAAM,8BAA8B;AACpC,MAAM,4BAA4B;AAElC,MAAM,oBAAoB,CAAC,OAChC,WAAW,GAAG,MAAM,IAAI,MAAM,CAAC;AAC1B,MAAM,sBAAsB,CAAC;AAAA,EAClC,iBAAiB;AAAA,EACjB;AACF,MAGM;AAAA,0BACoB,cAAc,GAAG,4BAA4B,MAAM,CAAC,CAAC;AAAA;AAAA,mBAE5D,KAAK,UAAU,aAAa,CAAC;AAAA,WACrC,cAAc;AAAA;AAAA;AAMlB,MAAM,yBAAyB;AAC/B,MAAM,6BAA6B;AAGnC,MAAM,wBAAwB,SAAS,QAAQ,qBAAqB;AACpE,MAAM,cAAc,GAAG,GAAG,aAAa,uBAAuB,OAAO,CAAC;","names":[]}

View file

@ -0,0 +1,27 @@
import { SourceLocation } from '@babel/code-frame';
/**
* Create a code frame from source code and location
* @param source source code
* @param location babel compatible location to highlight
*/
declare function createFrame(source: string, location: SourceLocation): string;
declare function tsLikeLocToBabelLoc(tsLoc: Record<'start' | 'end', {
line: number;
character: number;
} /** 0-based */>): SourceLocation;
declare function lineColLocToBabelLoc(d: {
line: number;
column: number;
endLine?: number;
endColumn?: number;
}): SourceLocation;
/**
* Convert a [startOffset, length] range into a Babel-compatible SourceLocation.
* - Lines/columns are 1-based.
* - Offsets and length are clamped to source bounds.
* - Single-pass up to the end offset, minimal allocations.
*/
declare function offsetRangeToBabelLocation(source: string, offset: number, length: number): SourceLocation;
export { createFrame, lineColLocToBabelLoc, offsetRangeToBabelLocation, tsLikeLocToBabelLoc };

View file

@ -0,0 +1,52 @@
import os from "node:os";
import { codeFrameColumns } from "@babel/code-frame";
function createFrame(source, location) {
return codeFrameColumns(source, location, {
// worker tty did not fork parent process stdout, let's make a workaround
forceColor: true
}).split("\n").map((line) => ` ${line}`).join(os.EOL);
}
function tsLikeLocToBabelLoc(tsLoc) {
return {
start: { line: tsLoc.start.line + 1, column: tsLoc.start.character + 1 },
end: { line: tsLoc.end.line + 1, column: tsLoc.end.character + 1 }
};
}
function lineColLocToBabelLoc(d) {
return {
start: { line: d.line, column: d.column },
end: { line: d.endLine || 0, column: d.endColumn }
};
}
function offsetRangeToBabelLocation(source, offset, length) {
const defaultPos = { line: 1, column: 1 };
if (!source || source.length === 0) {
return { start: { ...defaultPos }, end: { ...defaultPos } };
}
const startIndex = offset;
const endIndex = offset + length;
let line = 1;
let column = 1;
let start = null;
for (let i = 0; i < endIndex; i++) {
if (i === startIndex) {
start = { line, column };
}
if (source[i] === "\n") {
line++;
column = 1;
} else {
column++;
}
}
start ?? (start = { line, column });
const end = { line, column };
return { start, end };
}
export {
createFrame,
lineColLocToBabelLoc,
offsetRangeToBabelLocation,
tsLikeLocToBabelLoc
};
//# sourceMappingURL=codeFrame.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../src/codeFrame.ts"],"sourcesContent":["import os from 'node:os'\n\nimport { codeFrameColumns, type SourceLocation } from '@babel/code-frame'\n\n/**\n * Create a code frame from source code and location\n * @param source source code\n * @param location babel compatible location to highlight\n */\nexport function createFrame(source: string, location: SourceLocation): string {\n return codeFrameColumns(source, location, {\n // worker tty did not fork parent process stdout, let's make a workaround\n forceColor: true,\n })\n .split('\\n')\n .map((line) => ` ${line}`)\n .join(os.EOL)\n}\n\nexport function tsLikeLocToBabelLoc(\n tsLoc: Record<\n 'start' | 'end',\n { line: number; character: number } /** 0-based */\n >,\n): SourceLocation {\n return {\n start: { line: tsLoc.start.line + 1, column: tsLoc.start.character + 1 },\n end: { line: tsLoc.end.line + 1, column: tsLoc.end.character + 1 },\n }\n}\n\nexport function lineColLocToBabelLoc(d: {\n line: number\n column: number\n endLine?: number\n endColumn?: number\n}): SourceLocation {\n return {\n start: { line: d.line, column: d.column },\n end: { line: d.endLine || 0, column: d.endColumn },\n }\n}\n\n/**\n * Convert a [startOffset, length] range into a Babel-compatible SourceLocation.\n * - Lines/columns are 1-based.\n * - Offsets and length are clamped to source bounds.\n * - Single-pass up to the end offset, minimal allocations.\n */\nexport function offsetRangeToBabelLocation(\n source: string,\n offset: number,\n length: number,\n): SourceLocation {\n const defaultPos = { line: 1, column: 1 }\n\n if (!source || source.length === 0) {\n return { start: { ...defaultPos }, end: { ...defaultPos } }\n }\n\n const startIndex = offset\n const endIndex = offset + length\n\n let line = 1\n let column = 1\n\n let start: { line: number; column: number } | null = null\n\n for (let i = 0; i < endIndex; i++) {\n if (i === startIndex) {\n start = { line, column }\n }\n // '\\n' charCode is 10\n if (source[i] === '\\n') {\n line++\n column = 1\n } else {\n column++\n }\n }\n\n start ??= { line, column }\n const end = { line, column }\n\n return { start, end }\n}\n"],"mappings":"AAAA,OAAO,QAAQ;AAEf,SAAS,wBAA6C;AAO/C,SAAS,YAAY,QAAgB,UAAkC;AAC5E,SAAO,iBAAiB,QAAQ,UAAU;AAAA;AAAA,IAExC,YAAY;AAAA,EACd,CAAC,EACE,MAAM,IAAI,EACV,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,EACzB,KAAK,GAAG,GAAG;AAChB;AAEO,SAAS,oBACd,OAIgB;AAChB,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,MAAM,MAAM,OAAO,GAAG,QAAQ,MAAM,MAAM,YAAY,EAAE;AAAA,IACvE,KAAK,EAAE,MAAM,MAAM,IAAI,OAAO,GAAG,QAAQ,MAAM,IAAI,YAAY,EAAE;AAAA,EACnE;AACF;AAEO,SAAS,qBAAqB,GAKlB;AACjB,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,EAAE,OAAO;AAAA,IACxC,KAAK,EAAE,MAAM,EAAE,WAAW,GAAG,QAAQ,EAAE,UAAU;AAAA,EACnD;AACF;AAQO,SAAS,2BACd,QACA,QACA,QACgB;AAChB,QAAM,aAAa,EAAE,MAAM,GAAG,QAAQ,EAAE;AAExC,MAAI,CAAC,UAAU,OAAO,WAAW,GAAG;AAClC,WAAO,EAAE,OAAO,EAAE,GAAG,WAAW,GAAG,KAAK,EAAE,GAAG,WAAW,EAAE;AAAA,EAC5D;AAEA,QAAM,aAAa;AACnB,QAAM,WAAW,SAAS;AAE1B,MAAI,OAAO;AACX,MAAI,SAAS;AAEb,MAAI,QAAiD;AAErD,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,QAAI,MAAM,YAAY;AACpB,cAAQ,EAAE,MAAM,OAAO;AAAA,IACzB;AAEA,QAAI,OAAO,CAAC,MAAM,MAAM;AACtB;AACA,eAAS;AAAA,IACX,OAAO;AACL;AAAA,IACF;AAAA,EACF;AAEA,oBAAU,EAAE,MAAM,OAAO;AACzB,QAAM,MAAM,EAAE,MAAM,OAAO;AAE3B,SAAO,EAAE,OAAO,IAAI;AACtB;","names":[]}

View file

@ -0,0 +1,5 @@
import { Stats } from 'node:fs';
declare function createIgnore(_root: string, pattern?: string | string[]): (path: string, _stats?: Stats) => boolean;
export { createIgnore };

View file

@ -0,0 +1,35 @@
import { statSync } from "node:fs";
import { join, relative, resolve } from "node:path";
import picomatch from "picomatch";
function createIgnore(_root, pattern = []) {
const paths = Array.isArray(pattern) ? pattern : [pattern];
const root = _root.replace(/\\/g, "/");
const globs = paths.flatMap((f) => {
const resolvedPath = resolve(root, f);
const relativePath = relative(root, resolvedPath).replace(/\\/g, "/");
try {
const isDirectory = !relativePath.includes("*") && statSync(resolvedPath).isDirectory();
if (isDirectory) {
return [relativePath, join(relativePath, "**/*").replace(/\\/g, "/")];
}
} catch {
}
return [relativePath];
}).filter(Boolean);
const matcher = picomatch(globs, { cwd: root });
return (path, _stats) => {
if (path.includes("node_modules")) {
return true;
}
const relativePath = relative(root, path).replace(/\\/g, "/");
try {
return !!relativePath && !matcher(relativePath) && !(_stats ?? statSync(path)).isDirectory();
} catch {
return false;
}
};
}
export {
createIgnore
};
//# sourceMappingURL=glob.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../src/glob.ts"],"sourcesContent":["import { type Stats, statSync } from 'node:fs'\nimport { join, relative, resolve } from 'node:path'\nimport picomatch from 'picomatch'\n\nexport function createIgnore(_root: string, pattern: string | string[] = []) {\n const paths = Array.isArray(pattern) ? pattern : [pattern]\n const root = _root.replace(/\\\\/g, '/')\n\n const globs = paths\n .flatMap((f) => {\n const resolvedPath = resolve(root, f)\n const relativePath = relative(root, resolvedPath).replace(/\\\\/g, '/')\n try {\n const isDirectory =\n !relativePath.includes('*') && statSync(resolvedPath).isDirectory()\n if (isDirectory) {\n return [relativePath, join(relativePath, '**/*').replace(/\\\\/g, '/')]\n }\n } catch {}\n return [relativePath]\n })\n .filter(Boolean)\n\n const matcher = picomatch(globs, { cwd: root })\n\n return (path: string, _stats?: Stats) => {\n if (path.includes('node_modules')) {\n return true\n }\n const relativePath = relative(root, path).replace(/\\\\/g, '/')\n try {\n return (\n !!relativePath &&\n !matcher(relativePath) &&\n !(_stats ?? statSync(path)).isDirectory()\n )\n } catch {\n // do not ignore files that have been deleted as the watcher is iterating on them\n return false\n }\n }\n}\n"],"mappings":"AAAA,SAAqB,gBAAgB;AACrC,SAAS,MAAM,UAAU,eAAe;AACxC,OAAO,eAAe;AAEf,SAAS,aAAa,OAAe,UAA6B,CAAC,GAAG;AAC3E,QAAM,QAAQ,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AACzD,QAAM,OAAO,MAAM,QAAQ,OAAO,GAAG;AAErC,QAAM,QAAQ,MACX,QAAQ,CAAC,MAAM;AACd,UAAM,eAAe,QAAQ,MAAM,CAAC;AACpC,UAAM,eAAe,SAAS,MAAM,YAAY,EAAE,QAAQ,OAAO,GAAG;AACpE,QAAI;AACF,YAAM,cACJ,CAAC,aAAa,SAAS,GAAG,KAAK,SAAS,YAAY,EAAE,YAAY;AACpE,UAAI,aAAa;AACf,eAAO,CAAC,cAAc,KAAK,cAAc,MAAM,EAAE,QAAQ,OAAO,GAAG,CAAC;AAAA,MACtE;AAAA,IACF,QAAQ;AAAA,IAAC;AACT,WAAO,CAAC,YAAY;AAAA,EACtB,CAAC,EACA,OAAO,OAAO;AAEjB,QAAM,UAAU,UAAU,OAAO,EAAE,KAAK,KAAK,CAAC;AAE9C,SAAO,CAAC,MAAc,WAAmB;AACvC,QAAI,KAAK,SAAS,cAAc,GAAG;AACjC,aAAO;AAAA,IACT;AACA,UAAM,eAAe,SAAS,MAAM,IAAI,EAAE,QAAQ,OAAO,GAAG;AAC5D,QAAI;AACF,aACE,CAAC,CAAC,gBACF,CAAC,QAAQ,YAAY,KACrB,EAAE,UAAU,SAAS,IAAI,GAAG,YAAY;AAAA,IAE5C,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}

View file

@ -0,0 +1,56 @@
import { SourceLocation } from '@babel/code-frame';
import { DiagnosticLevel, DiagnosticToRuntime, ClientDiagnosticPayload } from './types.js';
import { ESLint } from 'eslint';
import Stylelint__default from 'stylelint';
import { Diagnostic } from 'typescript';
import { Diagnostic as Diagnostic$1, PublishDiagnosticsParams } from 'vscode-languageclient/node';
import 'node:worker_threads';
import 'vite';
import './checkers/vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
interface NormalizedDiagnostic {
/** error message */
message?: string;
/** error conclusion */
conclusion?: string;
/** error stack */
stack?: string | string[];
/** file name */
id?: string;
/** checker diagnostic source */
checker: string;
/** raw code frame generated by @babel/code-frame */
codeFrame?: string;
/** code frame, but striped */
stripedCodeFrame?: string;
/** error code location */
loc?: SourceLocation;
/** error level */
level?: DiagnosticLevel;
}
declare function filterLogLevel(diagnostics: NormalizedDiagnostic, level?: DiagnosticLevel[]): NormalizedDiagnostic | null;
declare function filterLogLevel(diagnostics: NormalizedDiagnostic[], level?: DiagnosticLevel[]): NormalizedDiagnostic[];
declare function diagnosticToTerminalLog(d: NormalizedDiagnostic, name?: 'TypeScript' | 'vue-tsc' | 'VLS' | 'ESLint' | 'Stylelint' | 'Biome' | 'oxlint'): string;
declare function diagnosticToConsoleLevel(d: NormalizedDiagnostic): "error" | "info" | "warn";
declare function diagnosticToRuntimeError(d: NormalizedDiagnostic): DiagnosticToRuntime;
declare function diagnosticToRuntimeError(d: NormalizedDiagnostic[]): DiagnosticToRuntime[];
declare function toClientPayload(id: string, diagnostics: DiagnosticToRuntime[]): ClientDiagnosticPayload;
declare function wrapCheckerSummary(checkerName: string, rawSummary: string): string;
declare function composeCheckerSummary(checkerName: string, errorCount: number, warningCount: number): string;
declare function normalizeTsDiagnostic(d: Diagnostic): NormalizedDiagnostic;
declare function normalizeLspDiagnostic({ diagnostic, absFilePath, fileText, }: {
diagnostic: Diagnostic$1;
absFilePath: string;
fileText: string;
}): NormalizedDiagnostic;
declare function normalizePublishDiagnosticParams(publishDiagnostics: PublishDiagnosticsParams): Promise<NormalizedDiagnostic[]>;
declare function uriToAbsPath(documentUri: string): string;
declare function normalizeVueTscDiagnostic(d: Diagnostic): NormalizedDiagnostic;
declare function normalizeEslintDiagnostic(diagnostic: ESLint.LintResult): NormalizedDiagnostic[];
declare function normalizeStylelintDiagnostic(diagnostic: Stylelint__default.LintResult): NormalizedDiagnostic[];
declare function ensureCall(callback: CallableFunction): void;
declare function consoleLog(value: string, level: 'info' | 'warn' | 'error'): void;
export { type NormalizedDiagnostic, composeCheckerSummary, consoleLog, diagnosticToConsoleLevel, diagnosticToRuntimeError, diagnosticToTerminalLog, ensureCall, filterLogLevel, normalizeEslintDiagnostic, normalizeLspDiagnostic, normalizePublishDiagnosticParams, normalizeStylelintDiagnostic, normalizeTsDiagnostic, normalizeVueTscDiagnostic, toClientPayload, uriToAbsPath, wrapCheckerSummary };

View file

@ -0,0 +1,294 @@
var _a;
import fs from "node:fs";
import { createRequire } from "node:module";
import os from "node:os";
import { stripVTControlCharacters as strip } from "node:util";
import colors from "picocolors";
import * as _vscodeUri from "vscode-uri";
const URI = ((_a = _vscodeUri == null ? void 0 : _vscodeUri.default) == null ? void 0 : _a.URI) ?? _vscodeUri.URI;
import { parentPort } from "node:worker_threads";
import { WS_CHECKER_ERROR_EVENT } from "./client/index.js";
import {
createFrame,
lineColLocToBabelLoc,
tsLikeLocToBabelLoc
} from "./codeFrame.js";
import {
ACTION_TYPES,
DiagnosticLevel
} from "./types.js";
import { isMainThread } from "./utils.js";
const _require = createRequire(import.meta.url);
const defaultLogLevel = [
DiagnosticLevel.Warning,
DiagnosticLevel.Error,
DiagnosticLevel.Suggestion,
DiagnosticLevel.Message
];
function filterLogLevel(diagnostics, level = defaultLogLevel) {
if (Array.isArray(diagnostics)) {
return diagnostics.filter((d) => {
if (typeof d.level !== "number") return false;
return level.includes(d.level);
});
}
if (!diagnostics.level) return null;
return level.includes(diagnostics.level) ? diagnostics : null;
}
function diagnosticToTerminalLog(d, name) {
const nameInLabel = name ? `(${name})` : "";
const boldBlack = (str) => colors.bold(colors.black(str));
const labelMap = {
[DiagnosticLevel.Error]: boldBlack(
colors.bgRedBright(` ERROR${nameInLabel} `)
),
[DiagnosticLevel.Warning]: boldBlack(
colors.bgYellowBright(` WARNING${nameInLabel} `)
),
[DiagnosticLevel.Suggestion]: boldBlack(
colors.bgBlueBright(` SUGGESTION${nameInLabel} `)
),
[DiagnosticLevel.Message]: boldBlack(
colors.bgCyanBright(` MESSAGE${nameInLabel} `)
)
};
const levelLabel = labelMap[d.level ?? DiagnosticLevel.Error];
const fileLabel = `${boldBlack(colors.bgCyanBright(" FILE "))} `;
const position = d.loc ? `${colors.yellow(d.loc.start.line)}:${colors.yellow(d.loc.start.column || "")}` : "";
return [
`${levelLabel} ${d.message}`,
`${fileLabel + d.id}:${position}${os.EOL}`,
d.codeFrame + os.EOL,
d.conclusion
].filter(Boolean).join(os.EOL);
}
function diagnosticToConsoleLevel(d) {
if (!d) return "error";
if (d.level === DiagnosticLevel.Message) return "info";
if (d.level === DiagnosticLevel.Suggestion) return "info";
if (d.level === DiagnosticLevel.Warning) return "warn";
return "error";
}
function diagnosticToRuntimeError(diagnostics) {
const diagnosticsArray = Array.isArray(diagnostics) ? diagnostics : [diagnostics];
const results = diagnosticsArray.map((d) => {
let loc;
if (d.loc) {
loc = {
file: d.id ?? "",
line: d.loc.start.line,
column: typeof d.loc.start.column === "number" ? d.loc.start.column : 0
};
}
return {
message: d.message ?? "",
stack: typeof d.stack === "string" ? d.stack : Array.isArray(d.stack) ? d.stack.join(os.EOL) : "",
id: d.id,
frame: d.stripedCodeFrame,
checkerId: d.checker,
level: d.level,
loc
};
});
return Array.isArray(diagnostics) ? results : results[0];
}
function toClientPayload(id, diagnostics) {
return {
event: WS_CHECKER_ERROR_EVENT,
data: {
checkerId: id,
diagnostics
}
};
}
function wrapCheckerSummary(checkerName, rawSummary) {
return `[${checkerName}] ${rawSummary}`;
}
function composeCheckerSummary(checkerName, errorCount, warningCount) {
const message = `Found ${errorCount} error${errorCount > 1 ? "s" : ""} and ${warningCount} warning${warningCount > 1 ? "s" : ""}`;
const hasError = errorCount > 0;
const hasWarning = warningCount > 0;
const color = hasError ? "red" : hasWarning ? "yellow" : "green";
return colors[color](wrapCheckerSummary(checkerName, message));
}
function normalizeTsDiagnostic(d) {
var _a2, _b, _c;
const fileName = (_a2 = d.file) == null ? void 0 : _a2.fileName;
const {
flattenDiagnosticMessageText
} = _require("typescript");
const message = flattenDiagnosticMessageText(d.messageText, os.EOL);
let loc;
const pos = d.start === void 0 ? null : (_c = (_b = d.file) == null ? void 0 : _b.getLineAndCharacterOfPosition) == null ? void 0 : _c.call(_b, d.start);
if (pos && d.file && typeof d.start === "number" && typeof d.length === "number") {
loc = tsLikeLocToBabelLoc({
start: pos,
end: d.file.getLineAndCharacterOfPosition(d.start + d.length)
});
}
let codeFrame;
if (loc) {
codeFrame = createFrame(d.file.text, loc);
}
return {
message,
conclusion: "",
codeFrame,
stripedCodeFrame: codeFrame && strip(codeFrame),
id: fileName,
checker: "TypeScript",
loc,
level: d.category
};
}
function normalizeLspDiagnostic({
diagnostic,
absFilePath,
fileText
}) {
let level = DiagnosticLevel.Error;
const loc = tsLikeLocToBabelLoc(diagnostic.range);
const codeFrame = createFrame(fileText, loc);
switch (diagnostic.severity) {
case 1:
level = DiagnosticLevel.Error;
break;
case 2:
level = DiagnosticLevel.Warning;
break;
case 3:
level = DiagnosticLevel.Message;
break;
case 4:
level = DiagnosticLevel.Suggestion;
break;
}
return {
message: diagnostic.message.trim(),
conclusion: "",
codeFrame,
stripedCodeFrame: codeFrame && strip(codeFrame),
id: absFilePath,
checker: "VLS",
loc,
level
};
}
async function normalizePublishDiagnosticParams(publishDiagnostics) {
const diagnostics = publishDiagnostics.diagnostics;
const absFilePath = uriToAbsPath(publishDiagnostics.uri);
const { readFile } = fs.promises;
const fileText = await readFile(absFilePath, "utf-8");
const res = diagnostics.map((d) => {
return normalizeLspDiagnostic({
diagnostic: d,
absFilePath,
fileText
});
});
return res;
}
function uriToAbsPath(documentUri) {
return URI.parse(documentUri).fsPath;
}
function normalizeVueTscDiagnostic(d) {
const diagnostic = normalizeTsDiagnostic(d);
diagnostic.checker = "vue-tsc";
return diagnostic;
}
const isNormalizedDiagnostic = (d) => {
return Boolean(d);
};
function normalizeEslintDiagnostic(diagnostic) {
return diagnostic.messages.map((d) => {
let level = DiagnosticLevel.Error;
switch (d.severity) {
case 0:
level = DiagnosticLevel.Error;
return null;
case 1:
level = DiagnosticLevel.Warning;
break;
case 2:
level = DiagnosticLevel.Error;
break;
}
const loc = lineColLocToBabelLoc(d);
const codeFrame = createFrame(diagnostic.source ?? "", loc);
return {
message: `${d.message} (${d.ruleId})`,
conclusion: "",
codeFrame,
stripedCodeFrame: codeFrame && strip(codeFrame),
id: diagnostic.filePath,
checker: "ESLint",
loc,
level
};
}).filter(isNormalizedDiagnostic);
}
function normalizeStylelintDiagnostic(diagnostic) {
return diagnostic.warnings.map((d) => {
var _a2;
let level = DiagnosticLevel.Error;
switch (d.severity) {
case "warning":
level = DiagnosticLevel.Warning;
break;
case "error":
level = DiagnosticLevel.Error;
break;
default:
level = DiagnosticLevel.Error;
return null;
}
const loc = lineColLocToBabelLoc(d);
const codeFrame = createFrame(((_a2 = diagnostic._postcssResult) == null ? void 0 : _a2.css) ?? "", loc);
return {
message: `${d.text} (${d.rule})`,
conclusion: "",
codeFrame,
stripedCodeFrame: codeFrame && strip(codeFrame),
id: diagnostic.source,
checker: "Stylelint",
loc,
level
};
}).filter(isNormalizedDiagnostic);
}
function ensureCall(callback) {
setTimeout(() => {
callback();
});
}
function consoleLog(value, level) {
var _a2;
if (isMainThread) {
console[level](value);
} else {
(_a2 = parentPort) == null ? void 0 : _a2.postMessage({
type: ACTION_TYPES.console,
level,
payload: value
});
}
}
export {
composeCheckerSummary,
consoleLog,
diagnosticToConsoleLevel,
diagnosticToRuntimeError,
diagnosticToTerminalLog,
ensureCall,
filterLogLevel,
normalizeEslintDiagnostic,
normalizeLspDiagnostic,
normalizePublishDiagnosticParams,
normalizeStylelintDiagnostic,
normalizeTsDiagnostic,
normalizeVueTscDiagnostic,
toClientPayload,
uriToAbsPath,
wrapCheckerSummary
};
//# sourceMappingURL=logger.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,12 @@
import { Plugin } from 'vite';
import { UserPluginConfig } from './types.js';
import 'node:worker_threads';
import 'eslint';
import 'stylelint';
import './checkers/vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
declare function checker(userConfig: UserPluginConfig): Plugin;
export { checker, checker as default };

View file

@ -0,0 +1,217 @@
import { spawn } from "node:child_process";
import { npmRunPathEnv } from "npm-run-path";
import colors from "picocolors";
import { Checker } from "./Checker.js";
import {
composePreambleCode,
RUNTIME_CLIENT_ENTRY_PATH,
RUNTIME_CLIENT_RUNTIME_PATH,
runtimeCode,
WS_CHECKER_RECONNECT_EVENT,
wrapVirtualPrefix
} from "./client/index.js";
import {
ACTION_TYPES
} from "./types.js";
const buildInCheckerKeys = [
"typescript",
"vueTsc",
"vls",
"eslint",
"stylelint",
"biome",
"oxlint"
];
async function createCheckers(userConfig, env) {
const serveAndBuildCheckers = [];
const { enableBuild, overlay } = userConfig;
const sharedConfig = { enableBuild, overlay };
for (const name of buildInCheckerKeys) {
if (!userConfig[name]) continue;
const { createServeAndBuild } = await import(`./checkers/${name}/main.js`);
serveAndBuildCheckers.push(
createServeAndBuild({ [name]: userConfig[name], ...sharedConfig }, env)
);
}
return serveAndBuildCheckers;
}
function checker(userConfig) {
const enableBuild = (userConfig == null ? void 0 : userConfig.enableBuild) ?? true;
const enableOverlay = (userConfig == null ? void 0 : userConfig.overlay) !== false;
const enableTerminal = (userConfig == null ? void 0 : userConfig.terminal) !== false;
const overlayConfig = typeof (userConfig == null ? void 0 : userConfig.overlay) === "object" ? userConfig == null ? void 0 : userConfig.overlay : {};
let initialized = false;
let initializeCounter = 0;
let checkers = [];
let isProduction = false;
let baseWithOrigin;
let viteMode;
let buildWatch = false;
let logger = null;
let checkerPromise = null;
return {
name: "vite-plugin-checker",
enforce: "pre",
// @ts-ignore
__internal__checker: Checker,
config: async (_config, env) => {
viteMode = env.command;
if (initializeCounter === 0) {
initializeCounter++;
} else {
initialized = true;
return;
}
checkers = await createCheckers(userConfig || {}, env);
if (viteMode !== "serve") return;
for (const checker2 of checkers) {
const workerConfig = checker2.serve.config;
workerConfig({
enableOverlay,
enableTerminal,
env
});
}
},
configResolved(config) {
logger = config.logger;
baseWithOrigin = config.server.origin ? config.server.origin + config.base : config.base;
isProduction || (isProduction = config.isProduction || config.command === "build");
buildWatch = !!config.build.watch;
},
async buildEnd() {
if (viteMode !== "serve") {
await checkerPromise;
}
if (initialized) return;
if (viteMode === "serve") {
for (const checker2 of checkers) {
const { worker } = checker2.serve;
worker.terminate();
}
}
},
resolveId(id) {
if (id === RUNTIME_CLIENT_RUNTIME_PATH || id === RUNTIME_CLIENT_ENTRY_PATH) {
return wrapVirtualPrefix(id);
}
return;
},
load(id) {
if (id === wrapVirtualPrefix(RUNTIME_CLIENT_RUNTIME_PATH)) {
return runtimeCode;
}
if (id === wrapVirtualPrefix(RUNTIME_CLIENT_ENTRY_PATH)) {
return composePreambleCode({ baseWithOrigin, overlayConfig });
}
return;
},
transformIndexHtml() {
if (initialized) return;
if (isProduction) return;
return [
{
tag: "script",
attrs: { type: "module" },
children: composePreambleCode({ baseWithOrigin, overlayConfig })
}
];
},
buildStart: () => {
if (initialized) return;
if (!isProduction || !enableBuild) return;
const localEnv = npmRunPathEnv({
env: process.env,
cwd: process.cwd(),
execPath: process.execPath
});
const spawnedCheckers = checkers.map(
(checker2) => spawnChecker(checker2, userConfig, localEnv)
);
checkerPromise = Promise.all(spawnedCheckers).then((exitCodes) => {
const exitCode = exitCodes.find((code) => code !== 0) ?? 0;
if (exitCode !== 0 && !buildWatch) {
process.exit(exitCode);
}
});
},
configureServer(server) {
if (initialized) return;
const latestOverlayErrors = new Array(
checkers.length
);
checkers.forEach((checker2, index) => {
const { worker, configureServer: workerConfigureServer } = checker2.serve;
workerConfigureServer({ root: userConfig.root || server.config.root });
worker.on("message", (action) => {
if (action.type === ACTION_TYPES.overlayError) {
latestOverlayErrors[index] = action.payload;
if (action.payload) {
server.ws.send("vite-plugin-checker", action.payload);
}
} else if (action.type === ACTION_TYPES.console) {
if (Checker.logger.length) {
Checker.log(action);
} else {
logger[action.level](action.payload);
}
}
});
});
if (server.ws.on) {
server.watcher.on("change", () => {
logger.clearScreen("error");
});
server.ws.on("vite-plugin-checker", (data) => {
if (data.event === "runtime-loaded") {
server.ws.send("vite-plugin-checker", {
event: WS_CHECKER_RECONNECT_EVENT,
data: latestOverlayErrors.filter(Boolean)
});
}
});
} else {
setTimeout(() => {
logger.warn(
colors.yellow(
"[vite-plugin-checker]: `server.ws.on` is introduced to Vite in 2.6.8, see [PR](https://github.com/vitejs/vite/pull/5273) and [changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#268-2021-10-18). \nvite-plugin-checker relies on `server.ws.on` to send overlay message to client. Support for Vite < 2.6.8 will be removed in the next major version release."
)
);
}, 5e3);
}
}
};
}
function spawnChecker(checker2, userConfig, localEnv) {
return new Promise((resolve) => {
const buildBin = checker2.build.buildBin;
const finalBin = typeof buildBin === "function" ? buildBin(userConfig) : buildBin;
const [command, args] = finalBin;
const commandWithArgs = [command, ...args].join(" ");
const proc = spawn(commandWithArgs, {
cwd: process.cwd(),
stdio: "inherit",
env: localEnv,
// shell is necessary on windows to get the process to even start.
// Command line args constructed by checkers therefore need to escape double quotes
// to have them not striped out by cmd.exe. Using shell on all platforms lets us avoid
// having to perform platform-specific logic around escaping quotes since all platform
// shells will strip out unescaped double quotes. E.g. shell=false on linux only would
// result in escaped quotes not being unescaped.
shell: true
});
proc.on("exit", (code) => {
if (code !== null && code !== 0) {
resolve(code);
} else {
resolve(0);
}
});
});
}
var main_default = checker;
export {
checker,
main_default as default
};
//# sourceMappingURL=main.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,302 @@
import { Worker } from 'node:worker_threads';
import { ESLint } from 'eslint';
import * as Stylelint from 'stylelint';
import { ConfigEnv, ErrorPayload } from 'vite';
import { VlsOptions } from './checkers/vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
interface TsConfigOptions {
/**
* path to tsconfig.json file
*/
tsconfigPath: string;
/**
* path to typescript package
*/
typescriptPath: string;
/**
* root path of cwd
*/
root: string;
/**
* root path of cwd
*/
buildMode: boolean;
}
/**
* TypeScript checker configuration
* @default true
*/
type TscConfig =
/**
* - set to `true` to enable type checking with default configuration
* - set to `false` to disable type checking, you can also remove `config.typescript` directly
*/
boolean | Partial<TsConfigOptions>;
/** vue-tsc checker configuration */
type VueTscConfig =
/**
* - set to `true` to enable type checking with default configuration
* - set to `false` to disable type checking, you can also remove `config.vueTsc` directly
*/
boolean | Partial<TsConfigOptions>;
/** vls checker configuration */
type VlsConfig = boolean | DeepPartial<VlsOptions>;
/** ESLint checker configuration */
type EslintConfig = false | {
/**
* Configure path to watch files
*/
watchPath?: string | string[];
/**
* lintCommand will be executed at build mode, and will also be used as
* default config for dev mode when options.eslint.dev.eslint is nullable.
*/
lintCommand: string;
/**
* @default false
*/
useFlatConfig?: boolean;
dev?: Partial<{
/** You can override the options of translated from lintCommand. */
overrideConfig: ESLint.Options;
/** which level of the diagnostic will be emitted from plugin */
logLevel: ('error' | 'warning')[];
}>;
};
/** Stylelint checker configuration */
type StylelintConfig = false | {
/**
* Configure path to watch files
*/
watchPath?: string | string[];
/**
* lintCommand will be executed at build mode, and will also be used as
* default config for dev mode when options.stylelint.dev.stylelint is nullable.
*/
lintCommand: string;
dev?: Partial<{
/** You can override the options of translated from lintCommand. */
overrideConfig: Stylelint.LinterOptions;
/** which level of the diagnostic will be emitted from plugin */
logLevel: ('error' | 'warning')[];
}>;
};
type BiomeCommand = 'lint' | 'check' | 'format' | 'ci';
/** Biome checker configuration */
type BiomeConfig = boolean | {
/**
* Command will be used in dev and build mode, will be override
* if `dev.command` or `build.command` is set their mode.
*/
command?: BiomeCommand;
/**
* Flags of the command, will be override if `dev.flags`
* or `build.command` is set their mode.
* */
flags?: string;
/**
* Configure path to watch files
*/
watchPath?: string | string[];
dev?: Partial<{
/** Command will be used in dev mode */
command: BiomeCommand;
/** Flags of the command */
flags?: string;
/** Which level of the diagnostic will be emitted from plugin */
logLevel: ('error' | 'warning' | 'info')[];
}>;
build?: Partial<{
/** Command will be used in build mode */
command: BiomeCommand;
/** Flags of the command */
flags?: string;
}>;
};
type OxlintConfig = boolean | {
/**
* `lintCommand` will be executed at build mode.
*/
lintCommand: string;
/**
* Configure path to watch files
*/
watchPath?: string | string[];
dev?: Partial<{
/** Specifies which level of the diagnostic will be emitted from the plugin */
logLevel: ('error' | 'warning')[];
}>;
};
declare enum DiagnosticLevel {
Warning = 0,
Error = 1,
Suggestion = 2,
Message = 3
}
type ErrorPayloadErr = ErrorPayload['err'];
interface DiagnosticToRuntime extends ErrorPayloadErr {
checkerId: string;
level?: DiagnosticLevel;
}
interface ClientDiagnosticPayload {
event: 'vite-plugin-checker:error';
data: {
checkerId: string;
diagnostics: DiagnosticToRuntime[];
};
}
interface ClientReconnectPayload {
event: 'vite-plugin-checker:reconnect';
data: ClientDiagnosticPayload[];
}
type ClientPayload = ClientDiagnosticPayload | ClientReconnectPayload;
/** checkers shared configuration */
interface SharedConfig {
/**
* Show overlay on UI view when there are errors or warnings in dev mode.
* - Set `true` to show overlay
* - Set `false` to disable overlay
* - Set with a object to customize overlay
*
* @defaultValue `true`
*/
overlay: boolean | {
/**
* Set this true if you want the overlay to default to being open if
* errors/warnings are found
* @defaultValue `true`
*/
initialIsOpen?: boolean | 'error';
/**
* The position of the vite-plugin-checker badge to open and close
* the diagnostics panel
* @default `bl`
*/
position?: 'tl' | 'tr' | 'bl' | 'br';
/**
* Use this to add extra style string to the badge button, the string format is
* [HTML element's style property](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style)
* For example, if you want to hide the badge,
* you can pass `display: none;` to the badgeStyle property
* @default no default value
*/
badgeStyle?: string;
/**
* Use this to add extra style string to the diagnostic panel, the string format is
* [HTML element's style property](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style)
* For example, if you want to change the opacity of the panel,
* you can pass `opacity: 0.8;` to the panelStyle property
* @default no default value
*/
panelStyle?: string;
};
/**
* stdout in terminal which starts the Vite server in dev mode.
* - Set `true` to enable
* - Set `false` to disable
*
* @defaultValue `true`
*/
terminal: boolean;
/**
* Enable checking in build mode
* @defaultValue `true`
*/
enableBuild: boolean;
/**
* Configure root directory of checkers
* @defaultValue no default value
*/
root?: string;
}
interface BuildInCheckers {
typescript: TscConfig;
vueTsc: VueTscConfig;
vls: VlsConfig;
eslint: EslintConfig;
stylelint: StylelintConfig;
biome: BiomeConfig;
oxlint: OxlintConfig;
}
type BuildInCheckerNames = keyof BuildInCheckers;
type PluginConfig = SharedConfig & BuildInCheckers;
/** Userland plugin configuration */
type UserPluginConfig = Partial<PluginConfig>;
declare enum ACTION_TYPES {
config = "config",
configureServer = "configureServer",
overlayError = "overlayError",
console = "console",
unref = "unref"
}
interface AbstractAction {
type: string;
payload: unknown;
}
interface OverlayErrorAction extends AbstractAction {
type: ACTION_TYPES.overlayError;
/**
* send `ClientPayload` to raise error overlay
* send `null` to clear overlay for current checker
*/
payload: ClientPayload;
}
interface ConfigAction extends AbstractAction {
type: ACTION_TYPES.config;
payload: ConfigActionPayload;
}
interface ConfigureServerAction extends AbstractAction {
type: ACTION_TYPES.configureServer;
payload: {
root: string;
};
}
interface ConsoleAction extends AbstractAction {
type: ACTION_TYPES.console;
level: 'info' | 'warn' | 'error';
payload: string;
}
interface UnrefAction extends AbstractAction {
type: ACTION_TYPES.unref;
}
interface ConfigActionPayload {
enableOverlay: boolean;
enableTerminal: boolean;
env: ConfigEnv;
}
type Action = ConfigAction | ConfigureServerAction | ConsoleAction | OverlayErrorAction | UnrefAction;
type BuildCheckBin = BuildCheckBinStr | BuildCheckBinFn;
type BuildCheckBinStr = [string, ReadonlyArray<string>];
type BuildCheckBinFn = (config: UserPluginConfig) => [string, ReadonlyArray<string>];
interface ConfigureServeChecker {
worker: Worker;
config: (config: ConfigAction['payload']) => void;
configureServer: (serverConfig: ConfigureServerAction['payload']) => void;
}
interface ServeAndBuildChecker {
serve: ConfigureServeChecker;
build: {
buildBin: BuildCheckBin;
buildFile?: string;
};
}
/**
* create serve & build checker
*/
interface ServeChecker<T extends BuildInCheckerNames = any> {
createDiagnostic: CreateDiagnostic<T>;
}
interface CheckerDiagnostic {
config: (options: ConfigActionPayload) => unknown;
configureServer: (options: {
root: string;
}) => unknown;
}
type CreateDiagnostic<T extends BuildInCheckerNames = any> = (config: Pick<BuildInCheckers, T> & SharedConfig) => CheckerDiagnostic;
type DeepPartial<T> = {
[P in keyof T]?: DeepPartial<T[P]>;
};
export { ACTION_TYPES, type Action, type BiomeConfig, type BuildCheckBin, type BuildCheckBinFn, type BuildCheckBinStr, type BuildInCheckerNames, type BuildInCheckers, type CheckerDiagnostic, type ClientDiagnosticPayload, type ClientPayload, type ClientReconnectPayload, type ConfigAction, type ConfigureServeChecker, type ConfigureServerAction, type ConsoleAction, type CreateDiagnostic, type DeepPartial, DiagnosticLevel, type DiagnosticToRuntime, type EslintConfig, type OverlayErrorAction, type OxlintConfig, type PluginConfig, type ServeAndBuildChecker, type ServeChecker, type SharedConfig, type StylelintConfig, type TscConfig, type UnrefAction, type UserPluginConfig, type VlsConfig, type VueTscConfig };

View file

@ -0,0 +1,20 @@
var DiagnosticLevel = /* @__PURE__ */ ((DiagnosticLevel2) => {
DiagnosticLevel2[DiagnosticLevel2["Warning"] = 0] = "Warning";
DiagnosticLevel2[DiagnosticLevel2["Error"] = 1] = "Error";
DiagnosticLevel2[DiagnosticLevel2["Suggestion"] = 2] = "Suggestion";
DiagnosticLevel2[DiagnosticLevel2["Message"] = 3] = "Message";
return DiagnosticLevel2;
})(DiagnosticLevel || {});
var ACTION_TYPES = /* @__PURE__ */ ((ACTION_TYPES2) => {
ACTION_TYPES2["config"] = "config";
ACTION_TYPES2["configureServer"] = "configureServer";
ACTION_TYPES2["overlayError"] = "overlayError";
ACTION_TYPES2["console"] = "console";
ACTION_TYPES2["unref"] = "unref";
return ACTION_TYPES2;
})(ACTION_TYPES || {});
export {
ACTION_TYPES,
DiagnosticLevel
};
//# sourceMappingURL=types.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,4 @@
declare const isInVitestEntryThread: string | false | undefined;
declare const isMainThread: string | boolean | undefined;
export { isInVitestEntryThread, isMainThread };

View file

@ -0,0 +1,8 @@
import { isMainThread as _isMainThread, threadId } from "node:worker_threads";
const isInVitestEntryThread = threadId === 0 && process.env.VITEST;
const isMainThread = _isMainThread || isInVitestEntryThread;
export {
isInVitestEntryThread,
isMainThread
};
//# sourceMappingURL=utils.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../src/utils.ts"],"sourcesContent":["import { isMainThread as _isMainThread, threadId } from 'node:worker_threads'\n\n// since vitest run all cases in worker thread, we should compatible with it to pass E2E tests\n\n// @ts-expect-error use Vitest\nexport const isInVitestEntryThread = threadId === 0 && process.env.VITEST\nexport const isMainThread = _isMainThread || isInVitestEntryThread\n"],"mappings":"AAAA,SAAS,gBAAgB,eAAe,gBAAgB;AAKjD,MAAM,wBAAwB,aAAa,KAAK,QAAQ,IAAI;AAC5D,MAAM,eAAe,iBAAiB;","names":[]}

View file

@ -0,0 +1,21 @@
import { ConfigEnv } from 'vite';
import { SharedConfig, ServeAndBuildChecker, BuildInCheckers, BuildCheckBin, ServeChecker } from './types.js';
import 'node:worker_threads';
import 'eslint';
import 'stylelint';
import './checkers/vls/initParams.js';
import 'vscode-languageserver/node';
import 'vscode-uri';
interface WorkerScriptOptions {
absFilename: string;
buildBin: BuildCheckBin;
serverChecker: ServeChecker;
}
interface Script<T> {
mainScript: () => (config: T & SharedConfig, env: ConfigEnv) => ServeAndBuildChecker;
workerScript: () => void;
}
declare function createScript<T extends Partial<BuildInCheckers>>({ absFilename, buildBin, serverChecker, }: WorkerScriptOptions): Script<T>;
export { type Script, createScript };

View file

@ -0,0 +1,78 @@
import { parentPort, Worker, workerData } from "node:worker_threads";
import { ACTION_TYPES } from "./types.js";
function createScript({
absFilename,
buildBin,
serverChecker
}) {
return {
mainScript: () => {
const createWorker = (checkerConfig, env) => {
const isBuild = env.command === "build";
const worker = new Worker(absFilename, {
workerData: { env, checkerConfig }
});
return {
worker,
config: (config) => {
if (isBuild) return;
const configAction = {
type: ACTION_TYPES.config,
payload: config
};
worker.postMessage(configAction);
},
configureServer: (serverConfig) => {
const configureServerAction = {
type: ACTION_TYPES.configureServer,
payload: serverConfig
};
worker.postMessage(configureServerAction);
}
};
};
return (config, env) => {
return {
serve: createWorker(config, env),
build: { buildBin }
};
};
},
workerScript: () => {
let diagnostic = null;
if (!parentPort)
throw Error("should have parentPort as file runs in worker thread");
const isBuild = workerData.env.command === "build";
const port = parentPort.on(
"message",
(action) => {
switch (action.type) {
case ACTION_TYPES.config: {
const checkerConfig = workerData.checkerConfig;
diagnostic = serverChecker.createDiagnostic(checkerConfig);
diagnostic.config(action.payload);
break;
}
case ACTION_TYPES.configureServer:
if (!diagnostic)
throw Error(
"diagnostic should be initialized in `config` hook of Vite"
);
diagnostic.configureServer(action.payload);
break;
case ACTION_TYPES.unref:
port.unref();
break;
}
}
);
if (isBuild) {
port.unref();
}
}
};
}
export {
createScript
};
//# sourceMappingURL=worker.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["../src/worker.ts"],"sourcesContent":["import { parentPort, Worker, workerData } from 'node:worker_threads'\nimport type { ConfigEnv } from 'vite'\nimport type {\n BuildCheckBin,\n BuildInCheckers,\n CheckerDiagnostic,\n ConfigAction,\n ConfigureServeChecker,\n ConfigureServerAction,\n ServeAndBuildChecker,\n ServeChecker,\n SharedConfig,\n UnrefAction,\n} from './types.js'\nimport { ACTION_TYPES } from './types.js'\n\ninterface WorkerScriptOptions {\n absFilename: string\n buildBin: BuildCheckBin\n serverChecker: ServeChecker\n}\n\nexport interface Script<T> {\n mainScript: () => (\n config: T & SharedConfig,\n env: ConfigEnv,\n ) => ServeAndBuildChecker\n workerScript: () => void\n}\n\nexport function createScript<T extends Partial<BuildInCheckers>>({\n absFilename,\n buildBin,\n serverChecker,\n}: WorkerScriptOptions): Script<T> {\n type CheckerConfig = T & SharedConfig\n\n return {\n mainScript: () => {\n // initialized in main thread\n const createWorker = (\n checkerConfig: CheckerConfig,\n env: ConfigEnv,\n ): ConfigureServeChecker => {\n const isBuild = env.command === 'build'\n const worker = new Worker(absFilename, {\n workerData: { env, checkerConfig },\n })\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return {\n worker,\n config: (config) => {\n if (isBuild) return // just run the command\n\n const configAction: ConfigAction = {\n type: ACTION_TYPES.config,\n payload: config,\n }\n worker.postMessage(configAction)\n },\n configureServer: (serverConfig) => {\n const configureServerAction: ConfigureServerAction = {\n type: ACTION_TYPES.configureServer,\n payload: serverConfig,\n }\n\n worker.postMessage(configureServerAction)\n },\n }\n }\n\n return (config, env) => {\n return {\n serve: createWorker(config, env),\n build: { buildBin },\n }\n }\n },\n workerScript: () => {\n // runs in worker thread\n let diagnostic: CheckerDiagnostic | null = null\n if (!parentPort)\n throw Error('should have parentPort as file runs in worker thread')\n const isBuild = workerData.env.command === 'build'\n // only run bin command and do not listen message in build mode\n\n const port = parentPort.on(\n 'message',\n (action: ConfigAction | ConfigureServerAction | UnrefAction) => {\n switch (action.type) {\n case ACTION_TYPES.config: {\n const checkerConfig: T & SharedConfig = workerData.checkerConfig\n diagnostic = serverChecker.createDiagnostic(checkerConfig)\n diagnostic.config(action.payload)\n break\n }\n case ACTION_TYPES.configureServer:\n if (!diagnostic)\n throw Error(\n 'diagnostic should be initialized in `config` hook of Vite',\n )\n diagnostic.configureServer(action.payload)\n break\n case ACTION_TYPES.unref:\n port.unref()\n break\n }\n },\n )\n\n if (isBuild) {\n port.unref()\n }\n },\n }\n}\n"],"mappings":"AAAA,SAAS,YAAY,QAAQ,kBAAkB;AAc/C,SAAS,oBAAoB;AAgBtB,SAAS,aAAiD;AAAA,EAC/D;AAAA,EACA;AAAA,EACA;AACF,GAAmC;AAGjC,SAAO;AAAA,IACL,YAAY,MAAM;AAEhB,YAAM,eAAe,CACnB,eACA,QAC0B;AAC1B,cAAM,UAAU,IAAI,YAAY;AAChC,cAAM,SAAS,IAAI,OAAO,aAAa;AAAA,UACrC,YAAY,EAAE,KAAK,cAAc;AAAA,QACnC,CAAC;AAGD,eAAO;AAAA,UACL;AAAA,UACA,QAAQ,CAAC,WAAW;AAClB,gBAAI,QAAS;AAEb,kBAAM,eAA6B;AAAA,cACjC,MAAM,aAAa;AAAA,cACnB,SAAS;AAAA,YACX;AACA,mBAAO,YAAY,YAAY;AAAA,UACjC;AAAA,UACA,iBAAiB,CAAC,iBAAiB;AACjC,kBAAM,wBAA+C;AAAA,cACnD,MAAM,aAAa;AAAA,cACnB,SAAS;AAAA,YACX;AAEA,mBAAO,YAAY,qBAAqB;AAAA,UAC1C;AAAA,QACF;AAAA,MACF;AAEA,aAAO,CAAC,QAAQ,QAAQ;AACtB,eAAO;AAAA,UACL,OAAO,aAAa,QAAQ,GAAG;AAAA,UAC/B,OAAO,EAAE,SAAS;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAAA,IACA,cAAc,MAAM;AAElB,UAAI,aAAuC;AAC3C,UAAI,CAAC;AACH,cAAM,MAAM,sDAAsD;AACpE,YAAM,UAAU,WAAW,IAAI,YAAY;AAG3C,YAAM,OAAO,WAAW;AAAA,QACtB;AAAA,QACA,CAAC,WAA+D;AAC9D,kBAAQ,OAAO,MAAM;AAAA,YACnB,KAAK,aAAa,QAAQ;AACxB,oBAAM,gBAAkC,WAAW;AACnD,2BAAa,cAAc,iBAAiB,aAAa;AACzD,yBAAW,OAAO,OAAO,OAAO;AAChC;AAAA,YACF;AAAA,YACA,KAAK,aAAa;AAChB,kBAAI,CAAC;AACH,sBAAM;AAAA,kBACJ;AAAA,gBACF;AACF,yBAAW,gBAAgB,OAAO,OAAO;AACzC;AAAA,YACF,KAAK,aAAa;AAChB,mBAAK,MAAM;AACX;AAAA,UACJ;AAAA,QACF;AAAA,MACF;AAEA,UAAI,SAAS;AACX,aAAK,MAAM;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;","names":[]}

Some files were not shown because too many files have changed in this diff Show more