mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-30 09:27:13 +00:00
feat(typescript): detect typescript based on tsconfig.json
(#5412)
This commit is contained in:
parent
82bde15622
commit
6ffc5c5792
25
package.json
25
package.json
@ -1,29 +1,34 @@
|
||||
{
|
||||
"name": "nuxt.js",
|
||||
"private": true,
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nuxt/nuxt.js.git"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
"distributions/*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "yarn clean && yarn pkg",
|
||||
"pkg": "node -r esm ./scripts/package",
|
||||
"clean": "yarn clean:build && yarn clean:examples && yarn clean:test",
|
||||
"clean:build": "rimraf distributions/*/dist packages/*/dist",
|
||||
"clean:examples": "rimraf examples/*/dist examples/*/.nuxt",
|
||||
"clean:test": "rimraf test/fixtures/*/dist test/fixtures/*/.nuxt*/",
|
||||
"dev": "node -r esm ./scripts/dev.js",
|
||||
"coverage": "codecov",
|
||||
"dev": "node -r esm ./scripts/dev.js",
|
||||
"postinstall": "lerna link && yarn dev",
|
||||
"lint": "eslint --ext .js,.mjs,.vue .",
|
||||
"lint:app": "eslint-multiplexer eslint --ignore-path packages/vue-app/template/.eslintignore 'test/fixtures/!(missing-plugin)/.nuxt!(-dev)/**' | eslint-multiplexer -b",
|
||||
"nuxt": "node -r esm ./packages/cli/bin/nuxt-cli.js",
|
||||
"pkg": "node -r esm ./scripts/package",
|
||||
"release": "./scripts/release",
|
||||
"test": "yarn test:fixtures && yarn test:unit && yarn test:types",
|
||||
"test:fixtures": "jest test/fixtures --forceExit",
|
||||
"test:e2e": "jest -i test/e2e --forceExit",
|
||||
"test:fixtures": "jest test/fixtures --forceExit",
|
||||
"test:lint": "yarn lint",
|
||||
"test:unit": "jest test/unit packages --forceExit",
|
||||
"test:types": "tsc -p test/types",
|
||||
"postinstall": "lerna link && yarn dev",
|
||||
"release": "./scripts/release"
|
||||
"test:unit": "jest test/unit packages --forceExit"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.4.0",
|
||||
@ -79,14 +84,10 @@
|
||||
"sort-package-json": "^1.22.1",
|
||||
"ts-jest": "^24.0.0",
|
||||
"ts-loader": "^5.3.3",
|
||||
"ts-node": "^8.0.3",
|
||||
"tslint": "^5.14.0",
|
||||
"typescript": "^3.4.1",
|
||||
"vue-jest": "^4.0.0-beta.2",
|
||||
"vue-property-decorator": "^8.1.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nuxt/nuxt.js.git"
|
||||
},
|
||||
"name": "nuxt.js"
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
"esm": "^3.2.22",
|
||||
"execa": "^1.0.0",
|
||||
"exit": "^0.1.2",
|
||||
"fs-extra": "^7.0.1",
|
||||
"minimist": "^1.2.0",
|
||||
"opener": "1.5.1",
|
||||
"pretty-bytes": "^5.1.0",
|
||||
|
@ -6,7 +6,7 @@ import { name, version } from '../package.json'
|
||||
import { loadNuxtConfig, forceExit } from './utils'
|
||||
import { indent, foldLines, colorize } from './utils/formatting'
|
||||
import { startSpaces, optionSpaces, forceExitTimeout } from './utils/constants'
|
||||
import { detectAndSetupTypeScriptSupport } from './utils/typescript'
|
||||
import { detectTypeScript } from './utils/typescript'
|
||||
import * as imports from './imports'
|
||||
|
||||
export default class NuxtCommand {
|
||||
@ -92,7 +92,11 @@ export default class NuxtCommand {
|
||||
|
||||
async getNuxtConfig(extraOptions = {}) {
|
||||
const rootDir = path.resolve(this.argv._[0] || '.')
|
||||
extraOptions._typescript = await detectAndSetupTypeScriptSupport(rootDir, { transpileOnly: this.cmd.name === 'start' })
|
||||
|
||||
// Typescript support
|
||||
extraOptions._typescript = await detectTypeScript(rootDir, {
|
||||
transpileOnly: this.cmd.name === 'start'
|
||||
})
|
||||
|
||||
const config = await loadNuxtConfig(this.argv)
|
||||
const options = Object.assign(config, extraOptions)
|
||||
|
@ -29,4 +29,8 @@ export const builder = () => _import('@nuxt/builder')
|
||||
export const webpack = () => _import('@nuxt/webpack')
|
||||
export const generator = () => _import('@nuxt/generator')
|
||||
export const core = () => _import('@nuxt/core')
|
||||
|
||||
export const tsNode = () => _import('ts-node')
|
||||
export const nuxtTypescript = () => _import('@nuxt/typescript')
|
||||
|
||||
export const importModule = _import
|
||||
|
@ -1,20 +1,49 @@
|
||||
import path from 'path'
|
||||
import consola from 'consola'
|
||||
import fs from 'fs-extra'
|
||||
import * as imports from '../imports'
|
||||
|
||||
export async function detectAndSetupTypeScriptSupport(rootDir, options = {}) {
|
||||
async function registerTSNode(tsConfigPath, options) {
|
||||
const { register } = await imports.tsNode()
|
||||
|
||||
// https://github.com/TypeStrong/ts-node
|
||||
register({
|
||||
project: tsConfigPath,
|
||||
compilerOptions: {
|
||||
module: 'commonjs'
|
||||
},
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
async function getNuxtTypeScript() {
|
||||
try {
|
||||
const { setup } = require('@nuxt/typescript')
|
||||
|
||||
consola.info('Initializing typeScript support')
|
||||
await setup(path.resolve(rootDir, 'tsconfig.json'), options)
|
||||
consola.success('TypeScript support enabled')
|
||||
} catch (e) {
|
||||
if (e.code === 'MODULE_NOT_FOUND') {
|
||||
return false
|
||||
} else {
|
||||
throw (e)
|
||||
return await imports.nuxtTypescript()
|
||||
} catch (error) {
|
||||
if (error.code !== 'MODULE_NOT_FOUND') {
|
||||
throw (error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function detectTypeScript(rootDir, options = {}) {
|
||||
// Check if tsconfig.json exists in project rootDir
|
||||
const tsConfigPath = path.resolve(rootDir, 'tsconfig.json')
|
||||
|
||||
// Skip if tsconfig.json not exists
|
||||
if (!await fs.exists(tsConfigPath)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Register runtime support
|
||||
await registerTSNode(tsConfigPath, options)
|
||||
|
||||
// Try to load @nuxt/typescript
|
||||
const nuxtTypeScript = await getNuxtTypeScript()
|
||||
|
||||
// If exists do additional setup
|
||||
if (nuxtTypeScript) {
|
||||
await nuxtTypeScript.setupDefaults(tsConfigPath)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
41
packages/cli/test/unit/typescript.test.js
Normal file
41
packages/cli/test/unit/typescript.test.js
Normal file
@ -0,0 +1,41 @@
|
||||
import { resolve } from 'path'
|
||||
import { mkdirp, writeFile, remove } from 'fs-extra'
|
||||
import { register } from 'ts-node'
|
||||
import { detectTypeScript } from '../../src/utils/typescript'
|
||||
|
||||
jest.mock('ts-node')
|
||||
|
||||
describe('Typescript Support', () => {
|
||||
const rootDir = 'tmp'
|
||||
const rootDir2 = 'tmp2'
|
||||
const tsConfigPath = resolve(rootDir, 'tsconfig.json')
|
||||
|
||||
beforeAll(async () => {
|
||||
await mkdirp(rootDir)
|
||||
await mkdirp(rootDir2)
|
||||
await writeFile(tsConfigPath, '{}', 'utf-8')
|
||||
})
|
||||
|
||||
test('detectTypeScript detects and registers runtime', async () => {
|
||||
register.mockReset()
|
||||
await detectTypeScript(rootDir)
|
||||
expect(register).toHaveBeenCalledTimes(1)
|
||||
expect(register).toHaveBeenCalledWith({
|
||||
project: tsConfigPath,
|
||||
compilerOptions: {
|
||||
module: 'commonjs'
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('detectTypeScript skips rootDir without tsconfig.json', async () => {
|
||||
register.mockReset()
|
||||
await detectTypeScript(rootDir2)
|
||||
expect(register).toHaveBeenCalledTimes(0)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await remove(rootDir)
|
||||
await remove(rootDir2)
|
||||
})
|
||||
})
|
@ -25,7 +25,6 @@
|
||||
"fork-ts-checker-webpack-plugin": "^1.0.1",
|
||||
"fs-extra": "^7.0.1",
|
||||
"ts-loader": "^5.3.3",
|
||||
"ts-node": "^8.0.3",
|
||||
"typescript": "^3.4.1"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { existsSync, writeJSON } from 'fs-extra'
|
||||
import { register } from 'ts-node'
|
||||
import { exists, readFile, writeJSON } from 'fs-extra'
|
||||
import consola from 'consola'
|
||||
|
||||
export const defaultTsJsonConfig = {
|
||||
@ -35,26 +34,15 @@ export const defaultTsJsonConfig = {
|
||||
}
|
||||
}
|
||||
|
||||
let _setup = false
|
||||
export async function setupDefaults(tsConfigPath) {
|
||||
let contents = ''
|
||||
|
||||
export async function setup(tsConfigPath, options = {}) {
|
||||
if (_setup) {
|
||||
return
|
||||
if (await exists(tsConfigPath)) {
|
||||
contents = await readFile(tsConfigPath, 'utf-8')
|
||||
}
|
||||
_setup = true
|
||||
|
||||
// Only create a default `tsconfig.json` if it doesn't exist
|
||||
if (!existsSync(tsConfigPath)) {
|
||||
consola.info(`Generating tsconfig.json (${tsConfigPath})`)
|
||||
if (!contents || contents === '{}') {
|
||||
consola.info(`Generating ${tsConfigPath.replace(process.cwd(), '')}`)
|
||||
await writeJSON(tsConfigPath, defaultTsJsonConfig, { spaces: 2 })
|
||||
}
|
||||
|
||||
// https://github.com/TypeStrong/ts-node
|
||||
register({
|
||||
project: tsConfigPath,
|
||||
compilerOptions: {
|
||||
module: 'commonjs'
|
||||
},
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
@ -1,39 +1,31 @@
|
||||
import { resolve } from 'path'
|
||||
import { mkdirp, readJSON, remove } from 'fs-extra'
|
||||
import { register } from 'ts-node'
|
||||
import { defaultTsJsonConfig, setup as setupTypeScript } from '@nuxt/typescript'
|
||||
|
||||
jest.mock('ts-node')
|
||||
import { mkdirp, readJSON, writeFile, remove, readFile } from 'fs-extra'
|
||||
import { defaultTsJsonConfig, setupDefaults } from '@nuxt/typescript'
|
||||
|
||||
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)
|
||||
await writeFile(tsConfigPath, '{}', 'utf-8')
|
||||
})
|
||||
|
||||
test('tsconfig.json has been created with defaults', async () => {
|
||||
test('Create tsconfig.json with defaults', async () => {
|
||||
await setupDefaults(tsConfigPath)
|
||||
expect(await readJSON(tsConfigPath)).toEqual(defaultTsJsonConfig)
|
||||
})
|
||||
|
||||
test('ts-node has been registered once', async () => {
|
||||
// Call setupTypeScript a second time to test guard
|
||||
await setupTypeScript(tsConfigPath)
|
||||
test('Do not override tsconfig.json', async () => {
|
||||
const fooJSON = '{ "foo": 123 }'
|
||||
await writeFile(tsConfigPath, fooJSON, 'utf-8')
|
||||
|
||||
expect(register).toHaveBeenCalledTimes(1)
|
||||
expect(register).toHaveBeenCalledWith({
|
||||
project: tsConfigPath,
|
||||
compilerOptions: {
|
||||
module: 'commonjs'
|
||||
}
|
||||
})
|
||||
await setupDefaults(tsConfigPath)
|
||||
|
||||
expect(await readFile(tsConfigPath, 'utf-8')).toEqual(fooJSON)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
// Clean workspace by removing the temporary folder (and the generated tsconfig.json at the same time)
|
||||
await remove(rootDir)
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user