mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
fix(ts): better tsconfig.json
handling & improve tests (#4856)
* fix(ts): make ts-node register the right `tsconfig.json` * setup guard & change require in nuxt-ts bin * improve tests + test guard * remove typescript-custom fixture * Move TS unit test from `test/unit` to `packages/typescript/test` * fix tests
This commit is contained in:
parent
3d0bc199ed
commit
f18ce4e5d4
@ -1,14 +1,17 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { resolve } = require('path')
|
||||
|
||||
// Globally indicate we are running in ts mode
|
||||
process.env.NUXT_TS = 'true'
|
||||
|
||||
const nuxtCommands = ['dev', 'build', 'generate', 'start']
|
||||
const rootDir = (process.argv[2] && !nuxtCommands.includes(process.argv[2])) ? process.argv[2] : process.cwd()
|
||||
const tsConfigPath = resolve(rootDir, 'tsconfig.json')
|
||||
|
||||
const suffix = require('../package.json').name.includes('-edge') ? '-edge' : ''
|
||||
|
||||
require('@nuxt/typescript' + suffix).setup(rootDir).then(() => {
|
||||
require('@nuxt/typescript' + suffix).setup(tsConfigPath).then(() => {
|
||||
require('@nuxt/cli' + suffix).run()
|
||||
}).catch((error) => {
|
||||
require('consola').fatal(error)
|
||||
|
@ -1,36 +0,0 @@
|
||||
import { resolve } from 'path'
|
||||
import { prompt } from 'enquirer'
|
||||
import { existsSync, writeJSON } from 'fs-extra'
|
||||
import chalk from 'chalk'
|
||||
import consola from 'consola'
|
||||
import env from 'std-env'
|
||||
|
||||
export async function generateTsConfigIfMissing(rootDir) {
|
||||
const tsConfigPath = resolve(rootDir, 'tsconfig.json')
|
||||
|
||||
if (!existsSync(tsConfigPath)) {
|
||||
const { confirmGeneration } = await prompt({
|
||||
type: 'confirm',
|
||||
name: 'confirmGeneration',
|
||||
message: `Missing ${chalk.bold.blue('tsconfig.json')} in ${rootDir === process.cwd() ? 'current directory' : chalk.bold.green(resolve(rootDir))}, generate it ?`,
|
||||
initial: true,
|
||||
skip: env.minimal
|
||||
})
|
||||
|
||||
if (confirmGeneration) {
|
||||
const configToExtend = '@nuxt/typescript'
|
||||
await writeJSON(tsConfigPath, {
|
||||
extends: configToExtend,
|
||||
compilerOptions: {
|
||||
baseUrl: '.',
|
||||
types: [
|
||||
'@types/node',
|
||||
'@nuxt/vue-app'
|
||||
]
|
||||
}
|
||||
}, { spaces: 2 })
|
||||
consola.info(`Extending ${chalk.bold.blue(`node_modules/${configToExtend}/tsconfig.json`)}`)
|
||||
consola.success(`Generated successfully at ${chalk.bold.green(resolve(rootDir, 'tsconfig.json'))}`)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,49 @@
|
||||
import { generateTsConfigIfMissing } from './config-generation'
|
||||
import { registerTsNode } from './ts-node'
|
||||
import chalk from 'chalk'
|
||||
import consola from 'consola'
|
||||
import env from 'std-env'
|
||||
import { prompt } from 'enquirer'
|
||||
import { existsSync, writeJSON } from 'fs-extra'
|
||||
import { register } from 'ts-node'
|
||||
|
||||
export async function setup(rootDir) {
|
||||
await generateTsConfigIfMissing(rootDir)
|
||||
registerTsNode()
|
||||
async function generateTsConfig(tsConfigPath) {
|
||||
const configToExtend = '@nuxt/typescript'
|
||||
await writeJSON(tsConfigPath, {
|
||||
extends: configToExtend,
|
||||
compilerOptions: {
|
||||
baseUrl: '.',
|
||||
types: [
|
||||
'@types/node',
|
||||
'@nuxt/vue-app'
|
||||
]
|
||||
}
|
||||
}, { spaces: 2 })
|
||||
consola.info(`Extending ${chalk.bold.blue(`node_modules/${configToExtend}/tsconfig.json`)}`)
|
||||
consola.success(`Generated successfully at ${chalk.bold.green(tsConfigPath)}`)
|
||||
}
|
||||
|
||||
let _setup = false
|
||||
|
||||
export async function setup(tsConfigPath) {
|
||||
if (_setup) {
|
||||
return
|
||||
}
|
||||
_setup = true
|
||||
|
||||
if (!existsSync(tsConfigPath)) {
|
||||
const { confirmGeneration } = await prompt({
|
||||
type: 'confirm',
|
||||
name: 'confirmGeneration',
|
||||
message: `${chalk.bold.blue(tsConfigPath)} is missing, generate it ?`,
|
||||
initial: true,
|
||||
skip: env.minimal
|
||||
})
|
||||
|
||||
if (confirmGeneration) {
|
||||
await generateTsConfig(tsConfigPath)
|
||||
}
|
||||
}
|
||||
// https://github.com/TypeStrong/ts-node
|
||||
register({
|
||||
project: tsConfigPath
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
import { register } from 'ts-node'
|
||||
|
||||
export function registerTsNode() {
|
||||
// https://github.com/TypeStrong/ts-node
|
||||
register()
|
||||
}
|
46
packages/typescript/test/setup.test.js
Normal file
46
packages/typescript/test/setup.test.js
Normal file
@ -0,0 +1,46 @@
|
||||
import { resolve } from 'path'
|
||||
import { exists, mkdirp, readJSON, remove } from 'fs-extra'
|
||||
import { register } from 'ts-node'
|
||||
import { setup as setupTypeScript } from '@nuxt/typescript'
|
||||
|
||||
jest.mock('ts-node')
|
||||
|
||||
describe('typescript setup', () => {
|
||||
const rootDir = 'tmp'
|
||||
const tsConfigPath = resolve(rootDir, 'tsconfig.json')
|
||||
|
||||
beforeAll(async () => {
|
||||
// We're assuming that rootDir provided to setupTypeScript is existing so we create the tested one
|
||||
await mkdirp(rootDir)
|
||||
await setupTypeScript(tsConfigPath)
|
||||
})
|
||||
|
||||
test('tsconfig.json has been generated if missing', async () => {
|
||||
expect(await exists(tsConfigPath)).toBe(true)
|
||||
expect(await readJSON(tsConfigPath)).toEqual({
|
||||
extends: '@nuxt/typescript',
|
||||
compilerOptions: {
|
||||
baseUrl: '.',
|
||||
types: [
|
||||
'@types/node',
|
||||
'@nuxt/vue-app'
|
||||
]
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('ts-node has been registered once', async () => {
|
||||
// Call setupTypeScript a second time to test guard
|
||||
await setupTypeScript(tsConfigPath)
|
||||
|
||||
expect(register).toHaveBeenCalledTimes(1)
|
||||
expect(register).toHaveBeenCalledWith({
|
||||
project: tsConfigPath
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
// Clean workspace by removing the temporary folder (and the generated tsconfig.json at the same time)
|
||||
await remove(tsConfigPath)
|
||||
})
|
||||
})
|
@ -1,10 +0,0 @@
|
||||
<template>
|
||||
<Nuxt />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
|
||||
@Component
|
||||
export default class DefaultLayout extends Vue {}
|
||||
</script>
|
@ -1,32 +0,0 @@
|
||||
import path from 'path'
|
||||
import consola from 'consola'
|
||||
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'
|
||||
|
||||
export default function typeScriptModule() {
|
||||
// Add .ts extension for store, middleware and more
|
||||
this.nuxt.options.extensions.push('ts')
|
||||
|
||||
// Extend build
|
||||
this.extendBuild((config, { isClient }) => {
|
||||
// Add TypeScript loader
|
||||
config.module.rules.push({
|
||||
test: /\.ts$/,
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
transpileOnly: true,
|
||||
appendTsSuffixTo: ['\\.vue$']
|
||||
}
|
||||
})
|
||||
// Add .ts extension in webpack resolve
|
||||
config.resolve.extensions.push('.ts')
|
||||
|
||||
if (isClient) {
|
||||
config.plugins.push(new ForkTsCheckerWebpackPlugin({
|
||||
vue: true,
|
||||
tsconfig: path.resolve(this.options.srcDir, 'tsconfig.json'),
|
||||
tslint: false,
|
||||
logger: consola
|
||||
}))
|
||||
}
|
||||
})
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export default {
|
||||
modules: ['~/modules/typescript']
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
name: 'About',
|
||||
render (h) {
|
||||
return h('div', 'About Page')
|
||||
}
|
||||
})
|
12
test/fixtures/typescript-custom/pages/index.vue
vendored
12
test/fixtures/typescript-custom/pages/index.vue
vendored
@ -1,12 +0,0 @@
|
||||
<template>
|
||||
<div>{{ message }}</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator'
|
||||
|
||||
@Component
|
||||
export default class Index extends Vue {
|
||||
message: string = 'Index Page'
|
||||
}
|
||||
</script>
|
21
test/fixtures/typescript-custom/tsconfig.json
vendored
21
test/fixtures/typescript-custom/tsconfig.json
vendored
@ -1,21 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"lib": ["esnext", "esnext.asynciterable", "dom"],
|
||||
"esModuleInterop": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowJs": true,
|
||||
"sourceMap": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"noEmit": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"~/*": ["./*"]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
import { buildFixture } from '../../utils/build'
|
||||
|
||||
buildFixture('typescript-custom')
|
@ -1,27 +0,0 @@
|
||||
import { loadFixture, getPort, Nuxt } from '../utils'
|
||||
|
||||
let nuxt = null
|
||||
|
||||
describe('typescript-custom', () => {
|
||||
beforeAll(async () => {
|
||||
const options = await loadFixture('typescript-custom')
|
||||
nuxt = new Nuxt(options)
|
||||
const port = await getPort()
|
||||
await nuxt.server.listen(port, '0.0.0.0')
|
||||
})
|
||||
|
||||
test('/', async () => {
|
||||
const { html } = await nuxt.server.renderRoute('/')
|
||||
expect(html).toContain('<div>Index Page</div>')
|
||||
})
|
||||
|
||||
test('/about', async () => {
|
||||
const { html } = await nuxt.server.renderRoute('/about')
|
||||
expect(html).toContain('<div>About Page</div>')
|
||||
})
|
||||
|
||||
// Close server and ask nuxt to stop listening to file changes
|
||||
afterAll(async () => {
|
||||
await nuxt.close()
|
||||
})
|
||||
})
|
@ -7,17 +7,15 @@ jest.mock('ts-node')
|
||||
|
||||
describe('typescript setup', () => {
|
||||
const rootDir = 'tmp'
|
||||
const tsConfigPath = resolve(rootDir, 'tsconfig.json')
|
||||
|
||||
beforeAll(() => {
|
||||
setupTypeScript(rootDir)
|
||||
beforeAll(async () => {
|
||||
// We're assuming that rootDir provided to setupTypeScript is existing so we create the tested one
|
||||
await mkdirp(rootDir)
|
||||
await setupTypeScript(tsConfigPath)
|
||||
})
|
||||
|
||||
test('tsconfig.json has been generated if missing', async () => {
|
||||
// We're assuming that rootDir provided to setupTypeScript is existing so we create the tested one
|
||||
await mkdirp(rootDir)
|
||||
|
||||
const tsConfigPath = resolve(rootDir, 'tsconfig.json')
|
||||
|
||||
expect(await exists(tsConfigPath)).toBe(true)
|
||||
expect(await readJSON(tsConfigPath)).toEqual({
|
||||
extends: '@nuxt/typescript',
|
||||
@ -29,12 +27,20 @@ describe('typescript setup', () => {
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
// Clean workspace by removing the temporary folder (and the generated tsconfig.json at the same time)
|
||||
await remove(rootDir)
|
||||
})
|
||||
|
||||
test('ts-node has been registered', () => {
|
||||
expect(register).toHaveBeenCalled()
|
||||
test('ts-node has been registered once', async () => {
|
||||
// Call setupTypeScript a second time to test guard
|
||||
await setupTypeScript(tsConfigPath)
|
||||
|
||||
expect(register).toHaveBeenCalledTimes(1)
|
||||
expect(register).toHaveBeenCalledWith({
|
||||
project: tsConfigPath
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
// Clean workspace by removing the temporary folder (and the generated tsconfig.json at the same time)
|
||||
await remove(tsConfigPath)
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user