{"version":3,"file":"main.js","names":["options","optionator"],"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 { ignoreTransientFsError } from '../../utils.js'\nimport { applyBatchedDiagnostics } from '../_shared/applyBatchedDiagnostics.js'\nimport {\n createLintScheduler,\n DEFAULT_DEBOUNCE_MS,\n} from '../_shared/lintScheduler.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()\n\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 scheduler = createLintScheduler({\n debounceMs: pluginConfig.eslint.dev?.debounceMs ?? DEFAULT_DEBOUNCE_MS,\n onBatch: async (files) => {\n const diagnosticsOfChangedFiles = await eslint.lintFiles(files)\n const newDiagnostics = diagnosticsOfChangedFiles.flatMap((d) =>\n normalizeEslintDiagnostic(d),\n )\n applyBatchedDiagnostics(manager, files, newDiagnostics, root)\n dispatchDiagnostics()\n },\n })\n\n const shouldLintPath = async (absPath: string): Promise => {\n // Legacy-mode extension filter (only meaningful if --ext was provided).\n if (!effectiveUseFlatConfig) {\n const extension = path.extname(absPath)\n const { extensions } = eslintOptions as any\n const hasExtensionsConfig = Array.isArray(extensions)\n if (hasExtensionsConfig && !extensions.includes(extension)) {\n return false\n }\n }\n // Honor .eslintignore / ignorePatterns.\n const isIgnored = await eslint.isPathIgnored(absPath)\n return !isIgnored\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', (filePath) => {\n const absPath = path.resolve(root, filePath)\n shouldLintPath(absPath)\n .then((shouldLint) => {\n if (shouldLint) scheduler.schedule(absPath)\n })\n .catch(ignoreTransientFsError)\n })\n watcher.on('unlink', (filePath) => {\n const absPath = path.resolve(root, filePath)\n manager.updateByFileId(absPath, [])\n dispatchDiagnostics()\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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"}