Skip to content

Commit

Permalink
refactor: types
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Jun 1, 2021
1 parent 5d8149f commit d6e602d
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 13 deletions.
4 changes: 2 additions & 2 deletions presets/vls/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { UserConfig, ViteDevServer } from 'vite'
import { CheckerFactory, CreateDiagnostic, PluginOptions } from 'vite-plugin-ts-checker'

export const createDiagnostic: CreateDiagnostic<Partial<PluginOptions>> = (userOptions = {}) => {
export const createDiagnostic: CreateDiagnostic = (userOptions = {}) => {
return {
config: (config: UserConfig) => {
// TODO:
Expand All @@ -12,7 +12,7 @@ export const createDiagnostic: CreateDiagnostic<Partial<PluginOptions>> = (userO
}
}

export const vlsCheckerFactory: CheckerFactory<any> = () => {
export const vlsCheckerFactory: CheckerFactory = () => {
return {
buildBin: ['vite-plugin-ts-checker-preset-vls', ['diagnostics']],
createDiagnostic: createDiagnostic,
Expand Down
8 changes: 7 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ import { Checker, CreateDiagnostic, PluginOptions } from './types'

export * from './types'

// type GetCheckerOptions<T extends PluginOptions['checker']> = T extends 'tsc'
// ? TscCheckerOptions
// : T extends 'vue-tsc'
// ? VueTscCheckerOptions
// : any

function makeChecker(
checker: PluginOptions['checker'],
userOptions?: Partial<PluginOptions>
): Checker<any> {
): Checker {
if (checker === 'tsc') {
// TODO: better use import.meta.require
// eslint-disable-next-line @typescript-eslint/no-require-imports
Expand Down
10 changes: 6 additions & 4 deletions src/presets/tsc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import os from 'os'
import ts from 'typescript'
import { ErrorPayload } from 'vite'

import { PluginOptions, CreateDiagnostic } from '../types'
import { CreateDiagnostic } from '../types'
import { ensureCall, formatHost, toViteError } from '../utils'

import type { CheckerFactory } from '../types'
Expand All @@ -12,7 +12,7 @@ import type { UserConfig, ViteDevServer } from 'vite'
* Prints a diagnostic every time the watch status changes.
* This is mainly for messages like "Starting compilation" or "Compilation completed".
*/
export const createDiagnostic: CreateDiagnostic<Partial<PluginOptions>> = (userOptions = {}) => {
export const createDiagnostic: CreateDiagnostic = (userOptions = {}) => {
let overlay = true // Vite defaults to true
let currErr: ErrorPayload['err'] | null = null

Expand Down Expand Up @@ -100,9 +100,11 @@ export const createDiagnostic: CreateDiagnostic<Partial<PluginOptions>> = (userO
}
}

export const tsCheckerFactory: CheckerFactory<any> = () => {
export const tsCheckerFactory: CheckerFactory = () => {
return {
buildBin: ['tsc', ['--noEmit']],
createDiagnostic: createDiagnostic,
createDiagnostic,
}
}

export type TscCheckerOptions = Record<string, never>
110 changes: 110 additions & 0 deletions src/presets/vue-tsc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import os from 'os'
import ts from 'typescript'
import { ErrorPayload } from 'vite'

import { CreateDiagnostic } from '../types'
import { ensureCall, formatHost, toViteError } from '../utils'

import type { CheckerFactory } from '../types'
import type { UserConfig, ViteDevServer } from 'vite'

/**
* Prints a diagnostic every time the watch status changes.
* This is mainly for messages like "Starting compilation" or "Compilation completed".
*/
export const createDiagnostic: CreateDiagnostic = (userOptions = {}) => {
let overlay = true // Vite defaults to true
let currErr: ErrorPayload['err'] | null = null

return {
config: (config: UserConfig) => {
const hmr = config.server?.hmr
const viteOverlay = !(typeof hmr === 'object' && hmr.overlay === false)

if (userOptions.overlay === false || !viteOverlay) {
overlay = false
}
},
configureServer(server: ViteDevServer) {
const finalConfig = {
root: userOptions.root ?? server.config.root,
tsconfigPath: userOptions.tsconfigPath ?? 'tsconfig.json',
}

let configFile: string | undefined

configFile = ts.findConfigFile(finalConfig.root, ts.sys.fileExists, finalConfig.tsconfigPath)

if (configFile === undefined) {
throw Error(
`Failed to find a valid tsconfig.json: ${finalConfig.tsconfigPath} at ${finalConfig.root} is not a valid tsconfig`
)
}

// https://github.com/microsoft/TypeScript/blob/a545ab1ac2cb24ff3b1aaf0bfbfb62c499742ac2/src/compiler/watch.ts#L12-L28
const reportDiagnostic = (diagnostic: ts.Diagnostic) => {
const originalDiagnostic = ts.formatDiagnosticsWithColorAndContext([diagnostic], formatHost)

if (!currErr) {
currErr = toViteError(diagnostic)
}

ensureCall(() => {
ts.sys.write(originalDiagnostic)
})
}

const reportWatchStatusChanged: ts.WatchStatusReporter = (
diagnostic
// newLine,
// options,
// errorCount
// eslint-disable-next-line max-params
) => {
// https://github.com/microsoft/TypeScript/issues/32542
switch (diagnostic.code) {
case 6032: // Incremental build
// clear current error and use the newer errors
currErr = null
break
case 6031: // Initial build
case 6193: // 1 Error
case 6194: // 0 errors or 2+ errors
if (currErr && overlay) {
server.ws.send({
type: 'error',
err: currErr,
})
}

ensureCall(() => {
ts.sys.write(os.EOL + os.EOL + diagnostic.messageText.toString())
})
}
}

// https://github.com/microsoft/TypeScript/issues/32385
// https://github.com/microsoft/TypeScript/pull/33082/files
const createProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram
const host = ts.createWatchCompilerHost(
configFile,
{ noEmit: true },
ts.sys,
createProgram,
reportDiagnostic,
reportWatchStatusChanged
)

ts.createWatchProgram(host)
},
}
}

export const tsCheckerFactory: CheckerFactory = () => {
return {
buildBin: ['tsc', ['--noEmit']],
createDiagnostic: createDiagnostic,
}
}

export type VueTscCheckerOptions = Record<string, never>
13 changes: 7 additions & 6 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import type { Plugin } from 'vite'

export type CheckerFactory<T = unknown> = (options?: T) => Checker<T>
export type CreateDiagnostic<T = unknown> = (
config?: T
) => Required<Pick<Plugin, 'config' | 'configureServer'>>
export type CheckerFactory = (options?: unknown) => Checker

export interface Checker<T = unknown> {
export interface Checker {
buildBin: [string, ReadonlyArray<string>]
createDiagnostic: CreateDiagnostic<T>
createDiagnostic: CreateDiagnostic
}

export type CreateDiagnostic = (
config?: Partial<PluginOptions>
) => Required<Pick<Plugin, 'config' | 'configureServer'>>

export interface PluginOptions {
/**
* Use `"tsc"` or `"vue-tsc"` or an custom checker
Expand Down

0 comments on commit d6e602d

Please sign in to comment.