{"version":3,"sources":["../../../src/checkers/eslint/main.ts"],"sourcesContent":["import Module from 'node:module'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { parentPort } from 'node:worker_threads'\nimport chokidar from 'chokidar'\nimport type { ESLint } from 'eslint'\nimport invariant from 'tiny-invariant'\n\nimport { Checker } from '../../Checker.js'\nimport { FileDiagnosticManager } from '../../FileDiagnosticManager.js'\nimport { createIgnore } from '../../glob.js'\nimport {\n composeCheckerSummary,\n consoleLog,\n diagnosticToConsoleLevel,\n diagnosticToRuntimeError,\n diagnosticToTerminalLog,\n filterLogLevel,\n normalizeEslintDiagnostic,\n toClientPayload,\n} from '../../logger.js'\nimport { ACTION_TYPES, DiagnosticLevel } from '../../types.js'\nimport { translateOptions } from './cli.js'\nimport { options as optionator } from './options.js'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst _require = Module.createRequire(import.meta.url)\n\nconst manager = new FileDiagnosticManager()\nlet createServeAndBuild: any\n\nimport type { CreateDiagnostic } from '../../types'\n\n/**\n * Detect the installed ESLint major version.\n */\nfunction getEslintMajorVersion(): number {\n try {\n const eslintPkg = _require('eslint/package.json')\n return Number.parseInt(eslintPkg.version.split('.')[0], 10)\n } catch {\n return 10 // assume latest if we can't detect\n }\n}\n\n/**\n * Resolve the correct ESLint class based on version and config mode.\n *\n * - ESLint v10+: Only flat config is supported, use `ESLint` directly.\n * - ESLint v9 with flat config (default): Use `ESLint` directly (it's the flat config class in v9).\n * - ESLint v9 with legacy eslintrc: Use `LegacyESLint` from `eslint/use-at-your-own-risk`.\n */\nasync function resolveEslintClass(\n useFlatConfig: boolean,\n majorVersion: number,\n): Promise {\n const { ESLint } = await import('eslint')\n if (majorVersion >= 10) {\n // v10+ only supports flat config\n return ESLint\n }\n\n if (useFlatConfig) {\n // v9 with flat config — the default `ESLint` export is already the flat config class\n return ESLint\n }\n\n // v9 with legacy eslintrc — need to load LegacyESLint\n try {\n const { LegacyESLint } = _require('eslint/use-at-your-own-risk')\n if (LegacyESLint) {\n return LegacyESLint\n }\n } catch {\n // fall through\n }\n\n throw new Error(\n 'Legacy eslintrc mode (useFlatConfig: false) requires ESLint v9. ' +\n 'ESLint v10+ only supports flat config. Please upgrade your config to flat config ' +\n 'or set useFlatConfig to true.',\n )\n}\n\nconst createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => {\n let overlay = true\n let terminal = true\n\n return {\n config: async ({ enableOverlay, enableTerminal }) => {\n overlay = enableOverlay\n terminal = enableTerminal\n },\n async configureServer({ root }) {\n if (!pluginConfig.eslint) return\n\n const majorVersion = getEslintMajorVersion()\n const useFlatConfig = pluginConfig.eslint.useFlatConfig ?? true\n\n if (!useFlatConfig && majorVersion >= 10) {\n console.warn(\n '[vite-plugin-checker] useFlatConfig: false is not supported with ESLint v10+. ' +\n 'Falling back to flat config mode.',\n )\n }\n\n const effectiveUseFlatConfig = majorVersion >= 10 ? true : useFlatConfig\n\n const options = optionator.parse(pluginConfig.eslint.lintCommand)\n invariant(\n !options.fix,\n 'Using `--fix` in `config.eslint.lintCommand` is not allowed in vite-plugin-checker, you could using `--fix` with editor.',\n )\n\n const translatedOptions = translateOptions(\n options,\n effectiveUseFlatConfig,\n ) as ESLint.Options\n\n const logLevel = (() => {\n if (typeof pluginConfig.eslint !== 'object') return undefined\n const userLogLevel = pluginConfig.eslint.dev?.logLevel\n if (!userLogLevel) return undefined\n const map = {\n error: DiagnosticLevel.Error,\n warning: DiagnosticLevel.Warning,\n } as const\n\n return userLogLevel.map((l) => map[l])\n })()\n\n const eslintOptions: ESLint.Options = {\n cwd: root,\n ...translatedOptions,\n ...pluginConfig.eslint.dev?.overrideConfig,\n }\n\n const EslintClass = await resolveEslintClass(\n effectiveUseFlatConfig,\n majorVersion,\n )\n const eslint = new EslintClass(eslintOptions)\n\n const dispatchDiagnostics = () => {\n const diagnostics = filterLogLevel(manager.getDiagnostics(), logLevel)\n if (terminal) {\n for (const d of diagnostics) {\n consoleLog(\n diagnosticToTerminalLog(d, 'ESLint'),\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('ESLint', errorCount, warningCount),\n errorCount ? 'error' : warningCount ? 'warn' : 'info',\n )\n }\n\n if (overlay) {\n parentPort?.postMessage({\n type: ACTION_TYPES.overlayError,\n payload: toClientPayload(\n 'eslint',\n diagnostics.map((d) => diagnosticToRuntimeError(d)),\n ),\n })\n }\n }\n\n const handleFileChange = async (\n filePath: string,\n type: 'change' | 'unlink',\n ) => {\n // In legacy mode, filter by file extension if --ext was provided\n if (!effectiveUseFlatConfig) {\n const extension = path.extname(filePath)\n const { extensions } = eslintOptions as any\n const hasExtensionsConfig = Array.isArray(extensions)\n if (hasExtensionsConfig && !extensions.includes(extension)) return\n }\n\n const isChangedFileIgnored = await eslint.isPathIgnored(filePath)\n if (isChangedFileIgnored) return\n\n const absPath = path.resolve(root, filePath)\n if (type === 'unlink') {\n manager.updateByFileId(absPath, [])\n } else if (type === 'change') {\n const diagnosticsOfChangedFile = await eslint.lintFiles(filePath)\n const newDiagnostics = diagnosticsOfChangedFile.flatMap((d) =>\n normalizeEslintDiagnostic(d),\n )\n manager.updateByFileId(absPath, newDiagnostics)\n }\n\n dispatchDiagnostics()\n }\n\n // initial lint\n const files = options._.slice(1) as string[]\n const diagnostics = await eslint.lintFiles(files)\n\n manager.initWith(diagnostics.flatMap((p) => normalizeEslintDiagnostic(p)))\n dispatchDiagnostics()\n\n // watch lint\n let watchTarget: string | string[] = root\n if (pluginConfig.eslint.watchPath) {\n if (Array.isArray(pluginConfig.eslint.watchPath)) {\n watchTarget = pluginConfig.eslint.watchPath.map((p) =>\n path.resolve(root, p),\n )\n } else {\n watchTarget = path.resolve(root, pluginConfig.eslint.watchPath)\n }\n }\n\n const watcher = chokidar.watch(watchTarget, {\n cwd: root,\n ignored: createIgnore(root, files),\n })\n\n watcher.on('change', async (filePath) => {\n handleFileChange(filePath, 'change')\n })\n watcher.on('unlink', async (filePath) => {\n handleFileChange(filePath, 'unlink')\n })\n },\n }\n}\n\nexport class EslintChecker extends Checker<'eslint'> {\n public constructor() {\n super({\n name: 'eslint',\n absFilePath: __filename,\n build: {\n buildBin: (pluginConfig) => {\n if (pluginConfig.eslint) {\n const { lintCommand } = pluginConfig.eslint\n return ['eslint', lintCommand.split(' ').slice(1)]\n }\n return ['eslint', ['']]\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 }\n\nconst eslintChecker = new EslintChecker()\neslintChecker.prepare()\neslintChecker.init()\n"],"mappings":"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","names":["_a","diagnostics"]}