feat(ts): auto generate tsconfig.json (#4776)

* Bundle `@types/node` into `nuxt-ts` distribution

* feat(ts): Autogenerated tsconfig.json

* fix(examples): Update typescript examples

* fix(ts): Add `dist` & `tsconfig.json` to `pakage.json` files

* fix: add missing new line at the end of generated `tsconfig.json`

* add suffix if needed to `tsconfig.json` types during package build

* use `readJSON` over `readJSONSync`

* fix indentation in `nuxt-ts/tsconfig.json`

* use writeJson instead of writeFile

* split `nuxt-ts/src` in 2 functions + rootDir parametr + add tests

* add `fs-extra` to dependencies to prevent build warning

* JSON everywhere instead of JSON/Json

* fix: missing call to generateTsConfigIfMissing

* ask confirmation for tsconfig.json generation

* improvement: let compilerOptions.module as default

* improvements

* move from github link to friendly linkable local path

* add resolveJsonModule in default config

Co-Authored-By: kevinmarrec <kevin@marrec.io>

* Move `nuxt-ts` logic to `@nuxt/typescript`

* Upgrade to `ts-node@8.0.1`
This commit is contained in:
Kevin Marrec 2019-01-23 10:53:52 +01:00 committed by Sébastien Chopin
parent 06a18ca09e
commit 2a1ee96a4b
15 changed files with 202 additions and 95 deletions

View File

@ -3,16 +3,13 @@
// Globally indicate we are running in ts mode
process.env.NUXT_TS = 'true'
// https://github.com/TypeStrong/ts-node
require('ts-node').register({
compilerOptions: {
module: 'commonjs'
}
})
const rootDir = (process.argv[2] && process.argv[2] !== 'dev') ? process.argv[2] : process.cwd()
const suffix = require('../package.json').name.includes('-edge') ? '-edge' : ''
require('@nuxt/cli' + suffix).run()
.catch((error) => {
require('consola').fatal(error)
process.exit(2)
})
require('@nuxt/typescript' + suffix).setup(rootDir).then(() => {
require('@nuxt/cli' + suffix).run()
}).catch((error) => {
require('consola').fatal(error)
process.exit(2)
})

View File

@ -4,8 +4,11 @@
"description": "Nuxt With Runtime Typescript Support",
"keywords": [
"nuxt",
"nuxt-ts",
"nuxt.js",
"nuxt.ts",
"nuxtjs",
"nuxts",
"ssr",
"vue",
"vue isomorphic",
@ -37,6 +40,9 @@
},
{
"name": "Alexander Lichter (@manniL)"
},
{
"name": "Kevin Marrec (@kevinmarrec)"
}
],
"files": [
@ -52,12 +58,8 @@
"@nuxt/core": "2.3.4",
"@nuxt/generator": "2.3.4",
"@nuxt/opencollective": "^0.2.1",
"@nuxt/webpack": "2.3.4",
"fork-ts-checker-webpack-plugin": "^0.5.2",
"ts-loader": "^5.3.3",
"ts-node": "^7.0.1",
"tslint": "^5.12.1",
"typescript": "^3.2.4"
"@nuxt/typescript": "2.3.4",
"@nuxt/webpack": "2.3.4"
},
"engines": {
"node": ">=6.0.0",

View File

@ -17,7 +17,6 @@
"post-update": "yarn upgrade --latest"
},
"devDependencies": {
"@types/node": "^10.12.18",
"tslint-config-standard": "^8.0.1"
}
}

View File

@ -1,27 +1,7 @@
{
"extends": "@nuxt/typescript-edge",
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"lib": ["esnext", "esnext.asynciterable", "dom"],
"esModuleInterop": true,
"experimentalDecorators": true,
"allowJs": true,
"sourceMap": true,
"strict": true,
"allowSyntheticDefaultImports": true,
"noImplicitAny": false,
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": true,
"baseUrl": ".",
"paths": {
"~/*": ["./*"]
},
"types": [
"@types/node",
"@nuxt/vue-app-edge"
]
"noImplicitAny": false
}
}

View File

@ -14,7 +14,6 @@
"post-update": "yarn upgrade --latest"
},
"devDependencies": {
"@types/node": "^10.12.18",
"tslint-config-standard": "^8.0.1"
}
}

View File

@ -1,27 +1,6 @@
{
"extends": "@nuxt/typescript-edge",
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"lib": ["esnext", "esnext.asynciterable", "dom"],
"esModuleInterop": true,
"experimentalDecorators": true,
"allowJs": true,
"sourceMap": true,
"strict": true,
"allowSyntheticDefaultImports": true,
"noImplicitAny": false,
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": true,
"baseUrl": ".",
"paths": {
"~/*": ["./*"]
},
"types": [
"@types/node",
"@nuxt/vue-app-edge"
]
"baseUrl": "."
}
}

View File

@ -0,0 +1,19 @@
import { readJSON, writeJSON } from 'fs-extra'
export default {
build: true,
hooks: {
async 'build:done'(pkg) {
if (pkg.options.suffix && pkg.options.linkedDependencies) {
const tsconfig = await readJSON(pkg.resolvePath('tsconfig.json'))
tsconfig.compilerOptions.types = tsconfig.compilerOptions.types.map((type) => {
const suffix = pkg.options.linkedDependencies.includes(type) ? pkg.options.suffix : ''
return type + suffix
})
await writeJSON(pkg.resolvePath('tsconfig.json'), tsconfig, { spaces: 2 })
}
}
}
}

View File

@ -0,0 +1,26 @@
{
"name": "@nuxt/typescript",
"version": "2.3.4",
"repository": "nuxt/nuxt.js",
"license": "MIT",
"files": [
"dist"
],
"main": "dist/typescript.js",
"dependencies": {
"@types/node": "^10.12.18",
"chalk": "^2.4.2",
"consola": "^2.3.2",
"enquirer": "^2.3.0",
"fork-ts-checker-webpack-plugin": "^0.5.2",
"fs-extra": "^7.0.1",
"std-env": "^2.2.1",
"ts-loader": "^5.3.3",
"ts-node": "^8.0.1",
"tslint": "^5.12.1",
"typescript": "^3.2.4"
},
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,32 @@
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: '.'
}
}, { 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'))}`)
}
}
}

View File

@ -0,0 +1,7 @@
import { generateTsConfigIfMissing } from './config-generation'
import { registerTsNode } from './ts-node'
export async function setup(rootDir) {
await generateTsConfigIfMissing(rootDir)
registerTsNode()
}

View File

@ -0,0 +1,6 @@
import { register } from 'ts-node'
export function registerTsNode() {
// https://github.com/TypeStrong/ts-node
register()
}

View File

@ -0,0 +1,34 @@
{
"compilerOptions": {
"target": "esnext",
"moduleResolution": "node",
"lib": [
"esnext",
"esnext.asynciterable",
"dom"
],
"esModuleInterop": true,
"resolveJsonModule": true,
"experimentalDecorators": true,
"jsx": "preserve",
"sourceMap": true,
"strict": true,
"noImplicitAny": true,
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"baseUrl": ".",
"paths": {
"~/*": [
"./*"
],
"@/*": [
"./*"
]
},
"types": [
"@types/node",
"@nuxt/vue-app"
]
}
}

View File

@ -1,25 +1,6 @@
{
"extends": "@nuxt/typescript",
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"lib": ["esnext", "esnext.asynciterable", "dom"],
"esModuleInterop": true,
"experimentalDecorators": true,
"allowJs": true,
"jsx": "preserve",
"sourceMap": true,
"strict": true,
"noImplicitAny": false,
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"baseUrl": ".",
"paths": {
"~/*": ["./*"]
},
"types": [
"@nuxt/vue-app"
]
"noImplicitAny": false
}
}

View File

@ -0,0 +1,36 @@
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'
beforeAll(() => {
setupTypeScript(rootDir)
})
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',
compilerOptions: {
baseUrl: '.'
}
})
// 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()
})
})

View File

@ -1346,7 +1346,7 @@
resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
"@types/node@*", "@types/node@^10.11.7":
"@types/node@*", "@types/node@^10.11.7", "@types/node@^10.12.18":
version "10.12.18"
resolved "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67"
integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==
@ -1734,7 +1734,7 @@ ansi-align@^3.0.0:
dependencies:
string-width "^3.0.0"
ansi-colors@^3.0.0:
ansi-colors@^3.0.0, ansi-colors@^3.2.1:
version "3.2.3"
resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813"
integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==
@ -1809,6 +1809,11 @@ are-we-there-yet@~1.1.2:
delegates "^1.0.0"
readable-stream "^2.0.6"
arg@^4.1.0:
version "4.1.0"
resolved "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz#583c518199419e0037abb74062c37f8519e575f0"
integrity sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@ -2464,7 +2469,7 @@ bser@^2.0.0:
dependencies:
node-int64 "^0.4.0"
buffer-from@1.x, buffer-from@^1.0.0, buffer-from@^1.1.0:
buffer-from@1.x, buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
@ -4032,6 +4037,13 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
memory-fs "^0.4.0"
tapable "^1.0.0"
enquirer@^2.3.0:
version "2.3.0"
resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.0.tgz#c362c9d84984ebe854def63caaf12983a16af552"
integrity sha512-RNGUbRVlfnjmpxV+Ed+7CGu0rg3MK7MmlW+DW0v7V2zdAUBC1s4BxCRiIAozbYB2UJ+q4D+8tW9UFb11kF72/g==
dependencies:
ansi-colors "^3.2.1"
entities@^1.1.1, entities@~1.1.1:
version "1.1.2"
resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
@ -10859,17 +10871,15 @@ ts-loader@^5.3.3:
micromatch "^3.1.4"
semver "^5.0.1"
ts-node@^7.0.1:
version "7.0.1"
resolved "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf"
integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==
ts-node@^8.0.1:
version "8.0.1"
resolved "https://registry.npmjs.org/ts-node/-/ts-node-8.0.1.tgz#cad98e8d50f0474f0d763ca8dc4c1bf8b7554ae2"
integrity sha512-zER3Js6Iotp31ghen6nKjgX75UOipwTWX9T5fAVmHaaYAizWhOes4uAsLmDC8H51UG5tHL8gNjoa/wLFjo7wtA==
dependencies:
arg "^4.1.0"
arrify "^1.0.0"
buffer-from "^1.1.0"
diff "^3.1.0"
make-error "^1.1.1"
minimist "^1.2.0"
mkdirp "^0.5.1"
source-map-support "^0.5.6"
yn "^2.0.0"