From 088a8bd21b5421a609a65f8fdb6e3d6498ddeba3 Mon Sep 17 00:00:00 2001 From: fi3ework Date: Wed, 9 Jun 2021 03:52:13 +0800 Subject: [PATCH] fix: checker can read shared and own config --- examples/vue2-vls/vite.config.ts | 2 +- examples/vue3-vue-tsc/vite.config.ts | 2 +- presets/vls/src/main.ts | 35 ++++++++++++------------- src/main.ts | 36 ++++++++++++------------- src/presets/tsc.ts | 34 ++++++++++-------------- src/presets/vue-tsc.ts | 21 +++++---------- src/types.ts | 34 ++++++++++-------------- src/worker.ts | 39 ++++++++++++++++++---------- 8 files changed, 96 insertions(+), 107 deletions(-) diff --git a/examples/vue2-vls/vite.config.ts b/examples/vue2-vls/vite.config.ts index b690320d..74e23c06 100644 --- a/examples/vue2-vls/vite.config.ts +++ b/examples/vue2-vls/vite.config.ts @@ -18,7 +18,7 @@ const config = defineConfig({ plugins: [ createVuePlugin({}), ViteComponents({ transformer: 'vue2' }), - Checker({ tsc: true, vls: VlsChecker({}) }), + Checker({ typescript: true, vls: VlsChecker({}) }), ], server: { port: 8080, diff --git a/examples/vue3-vue-tsc/vite.config.ts b/examples/vue3-vue-tsc/vite.config.ts index 3396e820..b57e75a3 100644 --- a/examples/vue3-vue-tsc/vite.config.ts +++ b/examples/vue3-vue-tsc/vite.config.ts @@ -4,5 +4,5 @@ import Checker from 'vite-plugin-checker' // https://vitejs.dev/config/ export default defineConfig({ - plugins: [vue(), Checker({ checker: 'vue-tsc' })], + plugins: [vue(), Checker({ vueTsc: true })], }) diff --git a/presets/vls/src/main.ts b/presets/vls/src/main.ts index 3b17969a..287ed46f 100644 --- a/presets/vls/src/main.ts +++ b/presets/vls/src/main.ts @@ -1,11 +1,10 @@ import { - BuildCheckBin, - ServeCheckerFactory, + SharedConfig, CreateDiagnostic, createScript, lspDiagnosticToViteError, uriToAbsPath, - ServeAndBuildConfig, + ServeAndBuildChecker, } from 'vite-plugin-checker' import { isMainThread, parentPort } from 'worker_threads' @@ -50,24 +49,22 @@ export const createDiagnostic: CreateDiagnostic = (userOptions = {}) => { } } -const vlsCheckerFactory: ServeCheckerFactory = () => { - return { - createDiagnostic, - } -} - -export const buildBin: BuildCheckBin = ['vite-plugin-checker-preset-vls', ['diagnostics']] - -const { mainScript, workerScript } = createScript({ +const { mainScript, workerScript } = createScript<{ vls: VlsConfig }>({ absFilename: __filename, - buildBin, - checkerFactory: vlsCheckerFactory, + buildBin: ['vite-plugin-checker-preset-vls', ['diagnostics']], + serverChecker: { createDiagnostic }, })! if (isMainThread) { - const { createServeAndBuild } = mainScript() - module.exports.VlsChecker = createServeAndBuild - module.exports.createServeAndBuild = createServeAndBuild + const createChecker = mainScript() + const configCurryFn = (vlsConfig: VlsConfig) => { + return (sharedConfig: SharedConfig) => { + return createChecker({ vls: vlsConfig, ...sharedConfig }) + } + } + + module.exports.VlsChecker = configCurryFn + module.exports.createServeAndBuild = configCurryFn } else { workerScript() } @@ -77,7 +74,9 @@ type VlsConfig = Partial<{ root: string }> -declare const VlsChecker: (options?: VlsConfig) => ServeAndBuildConfig +declare const VlsChecker: ( + options?: VlsConfig +) => (config: VlsConfig & SharedConfig) => ServeAndBuildChecker export { VlsChecker } export type { VlsConfig } diff --git a/src/main.ts b/src/main.ts index bb5c3800..6ba49bc5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,39 +2,39 @@ import { spawn } from 'child_process' import npmRunPath from 'npm-run-path' import { ConfigEnv, Plugin } from 'vite' -import { ServeAndBuildConfig, OverlayErrorAction, PluginOptions } from './types' +import { ServeAndBuildChecker, OverlayErrorAction, UserPluginConfig } from './types' export * from './types' export * from './codeFrame' export * from './utils' export * from './worker' -function createServeAndBuild(userOptions: Partial): ServeAndBuildConfig[] { - const checkers: ServeAndBuildConfig[] = [] - const { typescript, vueTsc, vls } = userOptions +function createCheckers(userConfig: UserPluginConfig): ServeAndBuildChecker[] { + const serveAndBuildCheckers: ServeAndBuildChecker[] = [] + const { typescript, vueTsc, vls: vlsCurry, ...sharedConfig } = userConfig if (typescript) { // eslint-disable-next-line @typescript-eslint/no-require-imports const { createServeAndBuild } = require('./presets/tsc') - checkers.push(createServeAndBuild(userOptions.typescript)) + serveAndBuildCheckers.push(createServeAndBuild({ typescript, ...sharedConfig })) } if (vueTsc) { // eslint-disable-next-line @typescript-eslint/no-require-imports const { createServeAndBuild } = require('./presets/vue-tsc') - checkers.push(createServeAndBuild(userOptions.vueTsc)) + serveAndBuildCheckers.push(createServeAndBuild({ vueTsc, ...sharedConfig })) } - if (vls) { - checkers.push(vls) + if (vlsCurry) { + serveAndBuildCheckers.push(vlsCurry(sharedConfig)) } - return checkers + return serveAndBuildCheckers } -export default function Plugin(userOptions?: Partial): Plugin { - const serveAndBuilds = createServeAndBuild(userOptions || {}) - const enableBuild = userOptions?.enableBuild ?? true +export default function Plugin(userConfig?: UserPluginConfig): Plugin { + const checkers = createCheckers(userConfig || {}) + const enableBuild = userConfig?.enableBuild ?? true let viteMode: ConfigEnv['command'] | undefined return { @@ -45,8 +45,8 @@ export default function Plugin(userOptions?: Partial): Plugin { viteMode = env.command if (viteMode !== 'serve') return - serveAndBuilds.forEach((serveAndBuild) => { - const workerConfig = serveAndBuild.serve.config + checkers.forEach((checker) => { + const workerConfig = checker.serve.config workerConfig({ hmr: config.server?.hmr, env, @@ -64,8 +64,8 @@ export default function Plugin(userOptions?: Partial): Plugin { execPath: process.execPath, }) - serveAndBuilds.forEach((serveAndBuild) => { - const buildBin = serveAndBuild.build.buildBin + checkers.forEach((checker) => { + const buildBin = checker.build.buildBin const proc = spawn(buildBin[0], buildBin[1], { cwd: process.cwd(), stdio: 'inherit', @@ -84,8 +84,8 @@ export default function Plugin(userOptions?: Partial): Plugin { configureServer(server) { // for dev mode (2/2) // Get the server instance and keep reference in a closure - serveAndBuilds.forEach((serveAndBuild) => { - const { worker, configureServer: workerConfigureServer } = serveAndBuild.serve + checkers.forEach((checker) => { + const { worker, configureServer: workerConfigureServer } = checker.serve workerConfigureServer({ root: server.config.root }) worker.on('message', (action: OverlayErrorAction) => { server.ws.send(action.payload) diff --git a/src/presets/tsc.ts b/src/presets/tsc.ts index 45ef633d..ffc4b7d4 100644 --- a/src/presets/tsc.ts +++ b/src/presets/tsc.ts @@ -3,17 +3,16 @@ import ts from 'typescript' import { ErrorPayload } from 'vite' import { isMainThread, parentPort } from 'worker_threads' -import { TscConfig } from '../types' import { ensureCall, formatHost, tsDiagnosticToViteError } from '../utils' import { createScript } from '../worker' -import type { CreateDiagnostic, ServeCheckerFactory, BuildCheckBin } from '../types' +import type { CreateDiagnostic, PluginConfig } from '../types' /** * Prints a diagnostic every time the watch status changes. * This is mainly for messages like "Starting compilation" or "Compilation completed". */ -const createDiagnostic: CreateDiagnostic = (userOptions = {}) => { +const createDiagnostic: CreateDiagnostic> = (checkerConfig) => { let overlay = true // Vite defaults to true let currErr: ErrorPayload['err'] | null = null @@ -21,15 +20,18 @@ const createDiagnostic: CreateDiagnostic = (userOptions = {}) => { config: ({ hmr }) => { const viteOverlay = !(typeof hmr === 'object' && hmr.overlay === false) - if (userOptions.overlay === false || !viteOverlay) { + if (checkerConfig.overlay === false || !viteOverlay) { overlay = false } }, configureServer({ root }) { - const finalConfig = { - root: userOptions.root ?? root, - tsconfigPath: userOptions.tsconfigPath ?? 'tsconfig.json', - } + const finalConfig = + typeof checkerConfig.typescript === 'boolean' + ? { root, tsconfigPath: 'tsconfig.json' } + : { + root: checkerConfig.typescript.root ?? root, + tsconfigPath: checkerConfig.typescript.tsconfigPath ?? 'tsconfig.json', + } let configFile: string | undefined @@ -103,22 +105,14 @@ const createDiagnostic: CreateDiagnostic = (userOptions = {}) => { } } -const checkerFactory: ServeCheckerFactory = () => { - return { - createDiagnostic, - } -} - -export const buildBin: BuildCheckBin = ['tsc', ['--noEmit']] - -const { mainScript, workerScript } = createScript({ +const { mainScript, workerScript } = createScript>({ absFilename: __filename, - buildBin, - checkerFactory, + buildBin: ['tsc', ['--noEmit']], + serverChecker: { createDiagnostic }, })! if (isMainThread) { - const { createServeAndBuild } = mainScript() + const createServeAndBuild = mainScript() module.exports.createServeAndBuild = createServeAndBuild } else { workerScript() diff --git a/src/presets/vue-tsc.ts b/src/presets/vue-tsc.ts index e83a648a..f3645aef 100644 --- a/src/presets/vue-tsc.ts +++ b/src/presets/vue-tsc.ts @@ -2,7 +2,7 @@ import { isMainThread } from 'worker_threads' import { createScript } from '../worker' -import type { VueTscConfig, ServeCheckerFactory, CreateDiagnostic, BuildCheckBin } from '../types' +import type { PluginConfig, CreateDiagnostic } from '../types' import type { UserConfig, ViteDevServer } from 'vite' // TODO: watch mode is not supported for now @@ -14,7 +14,7 @@ import type { UserConfig, ViteDevServer } from 'vite' * */ // @ts-ignore -export const createDiagnostic: CreateDiagnostic = (userOptions = {}) => { +export const createDiagnostic: CreateDiagnostic> = (checkerConfig) => { return { config: (config: UserConfig) => { // @@ -25,23 +25,14 @@ export const createDiagnostic: CreateDiagnostic = (userOptions = {}) => { } } -export const buildBin: BuildCheckBin = ['vue-tsc', ['--noEmit']] - -export const checkerFactory: ServeCheckerFactory = () => { - return { - buildBin: ['vue-tsc', ['--noEmit']], - createDiagnostic: createDiagnostic, - } -} - -const { mainScript, workerScript } = createScript({ +const { mainScript, workerScript } = createScript>({ absFilename: __filename, - buildBin, - checkerFactory, + buildBin: ['vue-tsc', ['--noEmit']], + serverChecker: { createDiagnostic }, })! if (isMainThread) { - const { createServeAndBuild } = mainScript() + const createServeAndBuild = mainScript() module.exports.createServeAndBuild = createServeAndBuild } else { workerScript() diff --git a/src/types.ts b/src/types.ts index a9107c2a..cd340602 100644 --- a/src/types.ts +++ b/src/types.ts @@ -13,7 +13,7 @@ export type TscConfig = root: string }> -/** vue-tsc configuration */ +/** vue-tsc checker configuration */ export type VueTscConfig = | boolean | Partial<{ @@ -21,10 +21,8 @@ export type VueTscConfig = root: string }> -export interface PluginOptions { - typescript: TscConfig - vueTsc: VueTscConfig - vls: ServeAndBuildConfig +/** checkers shared configuration */ +export interface SharedConfig { /** * Enable checking in build mode * @defaultValue `true` @@ -36,19 +34,17 @@ export interface PluginOptions { * Same as [Vite config](https://vitejs.dev/config/#root) */ overlay: boolean - // /** - // * Root path to find tsconfig file - // * @defaultValue - // * Same as [Vite config](https://vitejs.dev/config/#root) - // */ - // root: string - // /** - // * Relative tsconfig path to {@link (PluginOptions:interface).root} - // * @defaultValue `"tsconfig.json"` - // */ - // tsconfigPath: string } +export interface PluginConfig extends SharedConfig { + typescript: TscConfig + vueTsc: VueTscConfig + vls: (vlsConfig: any) => ServeAndBuildChecker +} + +/** Userland plugin configuration */ +export type UserPluginConfig = Partial + /* ----------------------------- worker actions ----------------------------- */ export enum ACTION_TYPES { @@ -93,15 +89,13 @@ export interface ConfigureServeChecker { configureServer: (serverConfig: ConfigureServerAction['payload']) => void } -export interface ServeAndBuildConfig { +export interface ServeAndBuildChecker { serve: ConfigureServeChecker build: { buildBin: BuildCheckBin } } // create serve & build checker -export type ServeCheckerFactory = (options?: unknown) => ServeChecker - export interface ServeChecker { createDiagnostic: CreateDiagnostic } @@ -111,4 +105,4 @@ export interface CheckerDiagnostic { configureServer: (options: { root: string }) => unknown } -export type CreateDiagnostic = (config?: Partial) => CheckerDiagnostic +export type CreateDiagnostic = (config: T & SharedConfig) => CheckerDiagnostic diff --git a/src/worker.ts b/src/worker.ts index 7c3d58b1..0a335d83 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,27 +1,40 @@ import { parentPort, Worker, workerData } from 'worker_threads' import type { - ServeCheckerFactory, + // ServeCheckerFactory, + ServeChecker, ConfigureServeChecker, ConfigAction, ConfigureServerAction, CheckerDiagnostic, BuildCheckBin, + ServeAndBuildChecker, + SharedConfig, } from './types' import { ACTION_TYPES } from './types' interface WorkerScriptOptions { absFilename: string buildBin: BuildCheckBin - checkerFactory: ServeCheckerFactory + serverChecker: ServeChecker } -export function createScript({ absFilename, buildBin, checkerFactory }: WorkerScriptOptions) { +interface Script { + mainScript: () => (config: T & SharedConfig) => ServeAndBuildChecker + workerScript: () => void +} + +export function createScript({ + absFilename, + buildBin, + serverChecker, +}: WorkerScriptOptions): Script { + type CheckerConfig = T & SharedConfig return { mainScript: () => { // initialized in main thread - const createWorker = (checkerConfigs?: T): ConfigureServeChecker => { + const createWorker = (checkerConfig?: CheckerConfig): ConfigureServeChecker => { const worker = new Worker(absFilename, { - workerData: checkerConfigs, + workerData: checkerConfig, }) // eslint-disable-next-line @typescript-eslint/consistent-type-assertions @@ -41,12 +54,10 @@ export function createScript({ absFilename, buildBin, checkerFactory }: Worke } } - return { - createServeAndBuild: (config: T) => ({ - serve: createWorker(config), - build: buildBin, - }), - } + return (config) => ({ + serve: createWorker(config), + build: { buildBin }, + }) }, workerScript: () => { // runs in worker thread @@ -55,9 +66,9 @@ export function createScript({ absFilename, buildBin, checkerFactory }: Worke parentPort.on('message', (action: ConfigAction | ConfigureServerAction) => { if (action.type === ACTION_TYPES.config) { - const checker = checkerFactory() - const checkerConfig = workerData - diagnostic = checker.createDiagnostic(checkerConfig) + // const checker = checkerFactory() + const checkerConfig: T = workerData + diagnostic = serverChecker.createDiagnostic(checkerConfig) diagnostic.config(action.payload) } else if (action.type === ACTION_TYPES.configureServer) { if (!diagnostic) throw Error('diagnostic should be initialized in `config` hook of Vite')