Skip to content

Commit

Permalink
feat: support custom tsconfig
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Mar 31, 2021
1 parent 88c3662 commit 6bfd83b
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 72 deletions.
40 changes: 27 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,21 @@ export default {
## Options

```ts
interface PluginOptions {
export interface PluginOptions {
/**
* [WIP] Use `tsc` or `vue-tsc`
* @default if vue-tsc is installed, then true, otherwise false
* Use `"tsc"` or `"vue-tsc"`
* @defaultValue `"tcs"`
*/
vueTsc: boolean
checker: 'tsc' | 'vue-tsc'
/**
* Show TypeScript error overlay
* @default Same as Vite config - `server.hmr.overlay`
* Throw in build mode if has error
* @defaultValue `true`
*/
enableBuild: boolean
/**
* Show overlay when has TypeScript error
* @defaultValue
* Same as [Vite config](https://vitejs.dev/config/#root)
*/
overlay: boolean
/**
Expand All @@ -59,14 +65,21 @@ interface PluginOptions {
* - Support overlay
* - Almost the same console output as original
*
* @default if `vueTsc` is true, then force set to 'cli', otherwise default to 'api'
* @defaultValue
* if 'vueTsc' is true, then force set to 'cli', otherwise default to 'api'
*/
mode: 'cli' | 'api'
/**
* Run in build mode ()
* @default true
* Root path to find tsconfig file
* @defaultValue
* Same as Vite https://vitejs.dev/config/#root
*/
root: string
/**
* Relative tsconfig path to {@link (PluginOptions:interface).root}
* @defaultValue `"tsconfig.json"`
*/
build: boolean | {}
tsconfigPath: string
}
```

Expand All @@ -84,10 +97,11 @@ npm run dev

- [x] release alpha version
- [x] support build mode
- [x] custom tsconfig path
- [x] no tsconfig file error
- [x] examples
- [ ] custom command
- [ ] custom tsconfig path
- [ ] no tsconfig file error
- [x] examples (codesandbox?)
- [ ] project references
- [ ] release stable version

## License
Expand Down
43 changes: 21 additions & 22 deletions src/apiMode.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { ErrorPayload } from 'vite'
import { createFrame } from './codeFrame'
import ts from 'typescript'
import os from 'os'
import strip from 'strip-ansi'
import ts from 'typescript'
import { ErrorPayload } from 'vite'

import { createFrame } from './codeFrame'
import { PluginOptions } from './types'

import type { UserConfig, ViteDevServer } from 'vite'
interface DiagnoseOptions {
root: string
tsconfigPath: string
}

const formatHost: ts.FormatDiagnosticsHost = {
getCanonicalFileName: (path) => path,
Expand Down Expand Up @@ -67,32 +65,33 @@ function toViteError(d: ts.Diagnostic): ErrorPayload['err'] {
* Prints a diagnostic every time the watch status changes.
* This is mainly for messages like "Starting compilation" or "Compilation completed".
*/
export function createDiagnosis(userOptions: Partial<DiagnoseOptions> = {}) {
export function createDiagnosis(userOptions: Partial<PluginOptions> = {}) {
let overlay = true // Vite defaults to true
let currErr: ErrorPayload['err'] | null = null

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

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

const configFile = ts.findConfigFile(
finalConfig.root,
ts.sys.fileExists,
finalConfig.tsconfigPath
)
let configFile: string | undefined

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

if (!configFile) {
throw new Error("Could not find a valid 'tsconfig.json'.")
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
Expand Down Expand Up @@ -123,7 +122,7 @@ export function createDiagnosis(userOptions: Partial<DiagnoseOptions> = {}) {
case 6031: // Initial build
case 6193: // 1 Error
case 6194: // 0 errors or 2+ errors
if (currErr) {
if (currErr && overlay) {
server.ws.send({
type: 'error',
err: currErr,
Expand Down
50 changes: 13 additions & 37 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,19 @@
import { spawn, exec } from 'child_process'
import { spawn } from 'child_process'
import npmRunPath from 'npm-run-path'
import { ConfigEnv, Plugin } from 'vite'
import { PluginOptions } from './types'

import { diagnose } from './apiMode'
import { createDiagnosis } from './apiMode'
import { tscProcess } from './cliMode'

const exitHook = require('async-exit-hook')

interface PluginOptions {
/**
* Use `tsc` or `vue-tsc`
* @default 'tcs'
*/
checker: 'tsc' | 'vue-tsc'
/**
* Throw error in build mode
* @default false
*/
ignoreInBuild: boolean
/**
* Show TypeScript error overlay
* @default Same as Vite config - `server.hmr.overlay`
*/
overlay: boolean
/**
* [WIP]
* 'cli': use `tsc --noEmit` or `vue-tsc --noEmit`
* - No overlay support
* - Original console output
*
* 'api': use TypeScript programmatic API
* - Support overlay
* - Almost the same console output as original
*
* @default if `vueTsc` is true, then force set to 'cli', otherwise default to 'api'
*/
mode: 'cli' | 'api'
}
// const exitHook = require('async-exit-hook')

export default function Plugin(userOptions?: Partial<PluginOptions>): Plugin {
const mode = userOptions?.mode ?? 'api'
const checker = userOptions?.checker ?? 'tsc'
const ignoreOnBuild = userOptions?.ignoreInBuild ?? false
const enableBuild = userOptions?.enableBuild ?? true
let viteMode: ConfigEnv['command'] | undefined
let diagnose: ReturnType<typeof createDiagnosis> | null = null

return {
name: 'ts-checker',
Expand All @@ -51,6 +22,11 @@ export default function Plugin(userOptions?: Partial<PluginOptions>): Plugin {
if (mode === 'cli') {
tscProcess.config(config)
} else {
diagnose = createDiagnosis({
root: userOptions?.root,
tsconfigPath: userOptions?.tsconfigPath,
})

diagnose.config(config)
}
},
Expand All @@ -68,7 +44,7 @@ export default function Plugin(userOptions?: Partial<PluginOptions>): Plugin {
env: localEnv,
})

if (!ignoreOnBuild) {
if (!enableBuild) {
proc.on('exit', (code) => {
if (code !== null && code !== 0) {
process.exit(code)
Expand All @@ -81,7 +57,7 @@ export default function Plugin(userOptions?: Partial<PluginOptions>): Plugin {
if (mode === 'cli') {
tscProcess.configureServer(server)
} else {
diagnose.configureServer(server)
diagnose?.configureServer(server)
}
return () => {
server.middlewares.use((req, res, next) => {
Expand Down
43 changes: 43 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export interface PluginOptions {
/**
* Use `"tsc"` or `"vue-tsc"`
* @defaultValue `"tcs"`
*/
checker: 'tsc' | 'vue-tsc'
/**
* Throw in build mode if has error
* @defaultValue `true`
*/
enableBuild: boolean
/**
* Show overlay when has TypeScript error
* @defaultValue
* Same as [Vite config](https://vitejs.dev/config/#root)
*/
overlay: boolean
/**
* [WIP]
* 'cli': use `tsc --noEmit` or `vue-tsc --noEmit`
* - No overlay support
* - Original console output
*
* 'api': use TypeScript programmatic API
* - Support overlay
* - Almost the same console output as original
*
* @defaultValue
* if 'vueTsc' is true, then force set to 'cli', otherwise default to 'api'
*/
mode: 'cli' | 'api'
/**
* Root path to find tsconfig file
* @defaultValue
* Same as Vite https://vitejs.dev/config/#root
*/
root: string
/**
* Relative tsconfig path to {@link (PluginOptions:interface).root}
* @defaultValue `"tsconfig.json"`
*/
tsconfigPath: string
}

0 comments on commit 6bfd83b

Please sign in to comment.