Skip to content

Commit

Permalink
feat: support ESLint in build
Browse files Browse the repository at this point in the history
  • Loading branch information
fi3ework committed Jul 17, 2021
1 parent 0819997 commit a855866
Show file tree
Hide file tree
Showing 19 changed files with 166 additions and 48 deletions.
4 changes: 3 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ lib
node_modules
playground/react-ts
playground/vue2-vls
playground/vue3-vue-tsc
playground/vue3-vue-tsc
playground/vanilla-ts/__tests__
playground/vanilla-ts/dist
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,11 @@ export async function viteBuild({
unexpectedErrorMsg,
expectedErrorMsg,
cwd = process.cwd(),
}: { unexpectedErrorMsg?: string; expectedErrorMsg?: string; cwd?: string } = {}) {
}: {
unexpectedErrorMsg?: string | string[]
expectedErrorMsg?: string
cwd?: string
} = {}) {
const promise = execa(binPath, ['build'], {
cwd: cwd ?? testDir,
})
Expand Down
2 changes: 1 addition & 1 deletion packages/vite-plugin-checker/__tests__/e2e/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function editFile(
fs.writeFileSync(filePath, modified)
}

export function expectStdoutNotContains(str: string, unexpectedErrorMsg: string) {
export function expectStdoutNotContains(str: string, unexpectedErrorMsg: string | string[]) {
expect.objectContaining({
stdout: expect(str).not.toContain(unexpectedErrorMsg),
})
Expand Down
4 changes: 0 additions & 4 deletions packages/vite-plugin-checker/src/Checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import chokidar from 'chokidar'
import type {} from 'vite'
import type { CreateDiagnostic, BuildInCheckers } from './types'

export interface CheckerAbility {
sealConclusion: any
}

export interface CheckerMeta<T extends BuildInCheckerNames> {
name: string
absFilePath: string
Expand Down
18 changes: 12 additions & 6 deletions packages/vite-plugin-checker/src/checkers/eslint/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import invariant from 'tiny-invariant'
import { ESLint } from 'eslint'
import { parentPort } from 'worker_threads'

import { Checker, CheckerAbility } from '../../Checker'
import { Checker } from '../../Checker'
import {
diagnosticToTerminalLog,
diagnosticToViteError,
Expand All @@ -15,7 +15,7 @@ import {
import type { CreateDiagnostic } from '../../types'
import type { ErrorPayload } from 'vite'

const createDiagnostic: CreateDiagnostic<'typescript'> = (pluginConfig) => {
const createDiagnostic: CreateDiagnostic<'eslint'> = (pluginConfig) => {
let overlay = true // Vite defaults to true
let currErr: ErrorPayload['err'] | null = null

Expand All @@ -32,18 +32,24 @@ const createDiagnostic: CreateDiagnostic<'typescript'> = (pluginConfig) => {
}
}

export class EslintChecker extends Checker<'typescript'> implements CheckerAbility {
export class EslintChecker extends Checker<'eslint'> {
public constructor() {
super({
name: 'typescript',
absFilePath: __filename,
build: { buildBin: ['tsc', ['--noEmit']] },
build: {
buildBin: (userConfig) => {
invariant(
userConfig.eslint.files,
`eslint.files is required, but got ${userConfig.eslint.files}`
)
return ['eslint', ['--ext', userConfig.eslint.ext ?? '.js', userConfig.eslint.files]]
},
},
createDiagnostic,
})
}

public sealConclusion() {}

public init() {
const createServeAndBuild = super.initMainThread()
module.exports.createServeAndBuild = createServeAndBuild
Expand Down
6 changes: 2 additions & 4 deletions packages/vite-plugin-checker/src/checkers/typescript/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import invariant from 'tiny-invariant'
import ts from 'typescript'
import { parentPort } from 'worker_threads'

import { Checker, CheckerAbility } from '../../Checker'
import { Checker } from '../../Checker'
import {
diagnosticToTerminalLog,
diagnosticToViteError,
Expand Down Expand Up @@ -114,7 +114,7 @@ const createDiagnostic: CreateDiagnostic<'typescript'> = (pluginConfig) => {
}
}

export class TscChecker extends Checker<'typescript'> implements CheckerAbility {
export class TscChecker extends Checker<'typescript'> {
public constructor() {
super({
name: 'typescript',
Expand All @@ -124,8 +124,6 @@ export class TscChecker extends Checker<'typescript'> implements CheckerAbility
})
}

public sealConclusion() {}

public init() {
const createServeAndBuild = super.initMainThread()
module.exports.createServeAndBuild = createServeAndBuild
Expand Down
6 changes: 2 additions & 4 deletions packages/vite-plugin-checker/src/checkers/vls/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { parentPort } from 'worker_threads'

import { Checker, CheckerAbility } from '../../Checker'
import { Checker } from '../../Checker'
import { DiagnosticOptions, diagnostics } from './diagnostics'

import type { CreateDiagnostic } from '../../types'
Expand Down Expand Up @@ -36,7 +36,7 @@ export const createDiagnostic: CreateDiagnostic<'vls'> = (pluginConfig) => {
}
}

export class VlsChecker extends Checker<'vls'> implements CheckerAbility {
export class VlsChecker extends Checker<'vls'> {
public constructor() {
super({
name: 'vls',
Expand All @@ -46,8 +46,6 @@ export class VlsChecker extends Checker<'vls'> implements CheckerAbility {
})
}

public sealConclusion() {}

public init() {
const createServeAndBuild = super.initMainThread()
module.exports.createServeAndBuild = createServeAndBuild
Expand Down
6 changes: 2 additions & 4 deletions packages/vite-plugin-checker/src/checkers/vueTsc/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Checker, CheckerAbility } from '../../Checker'
import { Checker } from '../../Checker'

import type { CreateDiagnostic } from '../../types'

Expand All @@ -14,7 +14,7 @@ const createDiagnostic: CreateDiagnostic<'vueTsc'> = (pluginConfig) => {
}
}

export class VueTscChecker extends Checker<'vueTsc'> implements CheckerAbility {
export class VueTscChecker extends Checker<'vueTsc'> {
public constructor() {
super({
name: 'typescript',
Expand All @@ -24,8 +24,6 @@ export class VueTscChecker extends Checker<'vueTsc'> implements CheckerAbility {
})
}

public sealConclusion() {}

public init() {
const createServeAndBuild = super.initMainThread()
module.exports.createServeAndBuild = createServeAndBuild
Expand Down
7 changes: 5 additions & 2 deletions packages/vite-plugin-checker/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import pick from 'lodash.pick'
import npmRunPath from 'npm-run-path'
import os from 'os'
import { ConfigEnv, Plugin } from 'vite'
import { Checker } from './Checker'

import type {
OverlayErrorAction,
BuildInCheckerNames,
ServeAndBuildChecker,
UserPluginConfig,
SharedConfig,
BuildCheckBinStr,
} from './types'

export * from './types'
Expand Down Expand Up @@ -74,7 +74,10 @@ export default function Plugin(userConfig?: UserPluginConfig): Plugin {

checkers.forEach((checker) => {
const buildBin = checker.build.buildBin
const proc = spawn(buildBin[0], buildBin[1], {
const finalBin: BuildCheckBinStr =
typeof buildBin === 'function' ? buildBin(userConfig) : buildBin

const proc = spawn(...finalBin, {
cwd: process.cwd(),
stdio: 'inherit',
env: localEnv,
Expand Down
12 changes: 10 additions & 2 deletions packages/vite-plugin-checker/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ export type VlsConfig =
export type EslintConfig =
| boolean
| Partial<{
// TODO: support ESLint config
/** One or more glob patterns to the files that should be linted. Works the same as the eslint command. */
files: string | string[]
/**
* Specify JavaScript file extensions, e.g. '.jsx,.js'
* @defaultValue: .js
*/
ext?: string
}>

/** checkers shared configuration */
Expand Down Expand Up @@ -104,7 +110,9 @@ export type Actions = OverlayErrorAction | ConfigAction | ConfigureServerAction

// prepare for create serve & build checker

export type BuildCheckBin = [string, ReadonlyArray<string>]
export type BuildCheckBin = BuildCheckBinStr | BuildCheckBinFn
export type BuildCheckBinStr = [string, ReadonlyArray<string>]
export type BuildCheckBinFn = (config: any) => [string, ReadonlyArray<string>]

export interface ConfigureServeChecker {
worker: Worker
Expand Down
4 changes: 2 additions & 2 deletions playground/react-ts/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { defineConfig } from 'vite'
import reactRefresh from '@vitejs/plugin-react-refresh'
import Checker from 'vite-plugin-checker'
import checker from 'vite-plugin-checker'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [
reactRefresh(),
Checker({
checker({
typescript: true,
}),
],
Expand Down
106 changes: 106 additions & 0 deletions playground/vanilla-ts/__tests__/test.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import {
getHmrOverlay,
getHmrOverlayText,
killServer,
pollingUntil,
preTest,
viteBuild,
viteServe,
stripedLog,
resetTerminalLog,
} from '../../../packages/vite-plugin-checker/__tests__/e2e/Sandbox/Sandbox'
import {
editFile,
sleep,
testDir,
WORKER_CLEAN_TIMEOUT,
} from '../../../packages/vite-plugin-checker/__tests__/e2e/testUtils'
import { copyCode } from '../../../scripts/jestSetupFilesAfterEnv'

beforeAll(async () => {
await preTest()
})

afterAll(async () => {
await sleep(WORKER_CLEAN_TIMEOUT)
})

describe('eslint', () => {
describe('serve', () => {
beforeEach(async () => {
await copyCode()
})

afterEach(async () => {
await killServer()
})

const snapshot = {
errorCode1: `var hello = 'Hello'`,
errorCode2: '',
absPath: 'vanilla-ts/src/main.ts:3:1',
relativePath: 'src/main.ts:3:1',
errorMsg: `Unexpected var, use let or const instead.`,
}

// it('get initial error and subsequent error', async () => {
// await viteServe({ cwd: testDir })
// await pollingUntil(getHmrOverlay, (dom) => !!dom)
// const [message1, file1, frame1] = await getHmrOverlayText()
// expect(message1).toContain(snapshot.errorMsg)
// expect(file1).toContain(snapshot.absPath)
// expect(frame1).toContain(snapshot.errorCode1)
// expect(stripedLog).toContain(snapshot.errorCode1)
// expect(stripedLog).toContain(snapshot.errorMsg)
// expect(stripedLog).toContain(snapshot.relativePath)

// resetTerminalLog()
// editFile('src/App.tsx', (code) => code.replace('useState<string>(1)', 'useState<string>(2)'))
// await sleep(2000)
// const [, , frame2] = await getHmrOverlayText()
// expect(frame2).toContain(snapshot.errorCode2)
// expect(stripedLog).toContain(snapshot.errorCode2)
// })

it('overlay: false', async () => {
resetTerminalLog()
editFile('vite.config.ts', (code) =>
code.replace('eslint: true,', 'eslint: true, overlay: false,')
)

await viteServe({ cwd: testDir })
await sleep(6000)
await expect(getHmrOverlayText()).rejects.toThrow(
'<vite-error-overlay> shadow dom is expected to be found, but got null'
)

expect(stripedLog).toContain(snapshot.errorCode1)
expect(stripedLog).toContain(snapshot.errorMsg)
expect(stripedLog).toContain(snapshot.relativePath)

resetTerminalLog()
editFile('src/main.ts', (code) => code.replace('var hello', 'const hello'))
await sleep(2000)
expect(stripedLog).toContain(snapshot.errorCode2)
})
})

describe('build', () => {
beforeEach(async () => {
await copyCode()
})

const expectedMsg = 'Unexpected var, use let or const instead no-var'

it('enableBuild: true', async () => {
await viteBuild({ expectedErrorMsg: expectedMsg, cwd: testDir })
})

it('enableBuild: false', async () => {
editFile('vite.config.ts', (code) =>
code.replace('eslint: {', 'enableBuild: false, eslint: {')
)
await viteBuild({ unexpectedErrorMsg: expectedMsg, cwd: testDir })
})
})
})
2 changes: 1 addition & 1 deletion playground/vanilla-ts/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { text } from './text'

var hello: string = 'Hello'
var hello = 'Hello'

const rootDom = document.querySelector('#root')!
rootDom.innerHTML = hello + text
Expand Down
10 changes: 6 additions & 4 deletions playground/vanilla-ts/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { defineConfig } from 'vite'
import reactRefresh from '@vitejs/plugin-react-refresh'
import Checker from 'vite-plugin-checker'
import checker from 'vite-plugin-checker'

// https://vitejs.dev/config/
export default defineConfig({
plugins: [
reactRefresh(),
Checker({
typescript: true,
eslint: true,
checker({
eslint: {
files: ['./src'],
ext: '.ts',
},
}),
],
})
4 changes: 2 additions & 2 deletions playground/vue2-vls/__tests__/test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe('vue2-vls', () => {
it('overlay: false', async () => {
resetTerminalLog()
editFile('vite.config.ts', (code) =>
code.replace('Checker({ vls: {} }),', 'Checker({ vls: {}, overlay: false })')
code.replace('checker({ vls: {} })', 'checker({ vls: {}, overlay: false })')
)

await viteServe({ cwd: testDir, port: 8080, path: '/vue-template/' })
Expand Down Expand Up @@ -110,7 +110,7 @@ describe('vue2-vls', () => {

it('enableBuild: false', async () => {
editFile('vite.config.ts', (code) =>
code.replace('Checker({ vls: {} }),', 'Checker({ vls: {}, enableBuild: false })')
code.replace('checker({ vls: {} })', 'checker({ vls: {}, enableBuild: false })')
)
await viteBuild({
unexpectedErrorMsg: `Property 'msg1' does not exist on type`,
Expand Down
1 change: 1 addition & 0 deletions playground/vue2-vls/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"vite-plugin-components": "^0.10.2",
"vite-plugin-checker": "workspace:*",
"vite-plugin-vue2": "^1.2.1",
"vls": "^0.7.2",
"vue-template-compiler": "^2.6.12"
}
}
Loading

0 comments on commit a855866

Please sign in to comment.