{"version":3,"sources":["../src/main.ts"],"sourcesContent":["import { spawn } from 'node:child_process'\nimport { npmRunPathEnv, type ProcessEnv } from 'npm-run-path'\nimport colors from 'picocolors'\n\nimport type { ConfigEnv, Logger, Plugin } from 'vite'\nimport { Checker } from './Checker.js'\nimport {\n composePreambleCode,\n RUNTIME_CLIENT_ENTRY_PATH,\n RUNTIME_CLIENT_RUNTIME_PATH,\n runtimeCode,\n WS_CHECKER_RECONNECT_EVENT,\n wrapVirtualPrefix,\n} from './client/index.js'\nimport {\n ACTION_TYPES,\n type Action,\n type BuildCheckBinStr,\n type BuildInCheckerNames,\n type ClientDiagnosticPayload,\n type ClientReconnectPayload,\n type PluginConfig,\n type ServeAndBuildChecker,\n type UserPluginConfig,\n} from './types.js'\n\nconst buildInCheckerKeys: BuildInCheckerNames[] = [\n 'typescript',\n 'vueTsc',\n 'eslint',\n 'stylelint',\n 'biome',\n 'oxlint',\n]\n\nasync function createCheckers(\n userConfig: UserPluginConfig,\n env: ConfigEnv,\n): Promise {\n const serveAndBuildCheckers: ServeAndBuildChecker[] = []\n const { enableBuild, overlay } = userConfig\n const sharedConfig = { enableBuild, overlay }\n\n // buildInCheckerKeys.forEach(async (name: BuildInCheckerNames) => {\n for (const name of buildInCheckerKeys) {\n if (!userConfig[name]) continue\n const { createServeAndBuild } = await import(`./checkers/${name}/main.js`)\n serveAndBuildCheckers.push(\n createServeAndBuild({ [name]: userConfig[name], ...sharedConfig }, env),\n )\n }\n\n return serveAndBuildCheckers\n}\n\nexport function checker(userConfig: UserPluginConfig): Plugin {\n const enableBuild = userConfig?.enableBuild ?? true\n const enableOverlay = userConfig?.overlay !== false\n const enableTerminal = userConfig?.terminal !== false\n const overlayConfig =\n typeof userConfig?.overlay === 'object' ? userConfig?.overlay : {}\n let initialized = false\n let initializeCounter = 0\n let checkers: ServeAndBuildChecker[] = []\n let isProduction = false\n let baseWithOrigin: string\n let viteMode: ConfigEnv['command'] | undefined\n let buildWatch = false\n let logger: Logger | null = null\n let checkerPromise: Promise | null = null\n\n return {\n name: 'vite-plugin-checker',\n enforce: 'pre',\n // @ts-expect-error\n __internal__checker: Checker,\n config: async (_config, env) => {\n // for dev mode (1/2)\n // Initialize checker with config\n viteMode = env.command\n // avoid running twice when running in SSR\n if (initializeCounter === 0) {\n initializeCounter++\n } else {\n initialized = true\n return\n }\n\n checkers = await createCheckers(userConfig || {}, env)\n if (viteMode !== 'serve') return\n\n for (const checker of checkers) {\n const workerConfig = checker.serve.config\n workerConfig({\n enableOverlay,\n enableTerminal,\n env,\n })\n }\n },\n configResolved(config) {\n logger = config.logger\n baseWithOrigin = config.server.origin\n ? config.server.origin + config.base\n : config.base\n isProduction ||= config.isProduction || config.command === 'build'\n buildWatch = !!config.build.watch\n },\n async buildEnd() {\n if (viteMode !== 'serve') {\n await checkerPromise\n }\n\n if (initialized) return\n\n if (viteMode === 'serve') {\n for (const checker of checkers) {\n const { worker } = checker.serve\n worker.terminate()\n }\n }\n },\n resolveId(id) {\n if (\n id === RUNTIME_CLIENT_RUNTIME_PATH ||\n id === RUNTIME_CLIENT_ENTRY_PATH\n ) {\n return wrapVirtualPrefix(id)\n }\n\n return\n },\n load(id) {\n if (id === wrapVirtualPrefix(RUNTIME_CLIENT_RUNTIME_PATH)) {\n return runtimeCode\n }\n\n if (id === wrapVirtualPrefix(RUNTIME_CLIENT_ENTRY_PATH)) {\n return composePreambleCode({ baseWithOrigin, overlayConfig })\n }\n\n return\n },\n transformIndexHtml() {\n if (initialized) return\n if (isProduction) return\n\n return [\n {\n tag: 'script',\n attrs: { type: 'module' },\n children: composePreambleCode({ baseWithOrigin, overlayConfig }),\n },\n ]\n },\n buildStart: () => {\n if (initialized) return\n // only run in build mode\n // run a bin command in a separated process\n if (!isProduction || !enableBuild) return\n\n const localEnv = npmRunPathEnv({\n env: process.env,\n cwd: process.cwd(),\n execPath: process.execPath,\n })\n\n const spawnedCheckers = checkers.map((checker) =>\n spawnChecker(checker, userConfig, localEnv),\n )\n\n // wait for checker states while avoiding blocking the build from continuing in parallel\n checkerPromise = Promise.all(spawnedCheckers).then((exitCodes) => {\n const exitCode = exitCodes.find((code) => code !== 0) ?? 0\n // do not exit the process if run `vite build --watch`\n if (exitCode !== 0 && !buildWatch) {\n process.exit(exitCode)\n }\n })\n },\n configureServer(server) {\n if (initialized) return\n\n const latestOverlayErrors: ClientReconnectPayload['data'] = new Array(\n checkers.length,\n )\n // for dev mode (2/2)\n // Get the server instance and keep reference in a closure\n checkers.forEach((checker, index) => {\n const { worker, configureServer: workerConfigureServer } = checker.serve\n workerConfigureServer({ root: userConfig.root || server.config.root })\n worker.on('message', (action: Action) => {\n if (action.type === ACTION_TYPES.overlayError) {\n latestOverlayErrors[index] =\n action.payload as ClientDiagnosticPayload\n if (action.payload) {\n server.ws.send('vite-plugin-checker', action.payload)\n }\n } else if (action.type === ACTION_TYPES.console) {\n if (Checker.logger.length) {\n // for test injection and customize logger in the future\n Checker.log(action)\n } else {\n logger![action.level](action.payload)\n }\n }\n })\n })\n\n if (server.ws.on) {\n server.watcher.on('change', () => {\n logger!.clearScreen('error')\n })\n server.ws.on('vite-plugin-checker', (data) => {\n // NOTE: sync modification with packages /packages/runtime/src/ws.js\n if (data.event === 'runtime-loaded') {\n server.ws.send('vite-plugin-checker', {\n event: WS_CHECKER_RECONNECT_EVENT,\n data: latestOverlayErrors.filter(Boolean),\n })\n }\n })\n } else {\n setTimeout(() => {\n logger!.warn(\n colors.yellow(\n '[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.',\n ),\n )\n // make a delay to avoid flush by Vite's console\n }, 5000)\n }\n },\n }\n}\n\nfunction spawnChecker(\n checker: ServeAndBuildChecker,\n userConfig: Partial,\n localEnv: ProcessEnv,\n) {\n return new Promise((resolve) => {\n const buildBin = checker.build.buildBin\n const finalBin: BuildCheckBinStr =\n typeof buildBin === 'function' ? buildBin(userConfig) : buildBin\n\n const [command, args] = finalBin\n const commandWithArgs = [command, ...args].join(' ')\n\n const proc = spawn(commandWithArgs, {\n cwd: process.cwd(),\n stdio: 'inherit',\n env: localEnv,\n // shell is necessary on windows to get the process to even start.\n // Command line args constructed by checkers therefore need to escape double quotes\n // to have them not striped out by cmd.exe. Using shell on all platforms lets us avoid\n // having to perform platform-specific logic around escaping quotes since all platform\n // shells will strip out unescaped double quotes. E.g. shell=false on linux only would\n // result in escaped quotes not being unescaped.\n shell: true,\n })\n\n proc.on('exit', (code) => {\n if (code !== null && code !== 0) {\n resolve(code)\n } else {\n resolve(0)\n }\n })\n })\n}\n\nexport default checker\n"],"mappings":"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","names":["checker"]}