refactor(ts): better DX for typescript support (#5079)

Breaking change : `build.useForkTsChecker` renamed to `build.typescript.typeCheck`
This commit is contained in:
Kevin Marrec 2019-03-14 11:07:47 +01:00 committed by Pooya Parsa
parent 821676511b
commit 920f444b6e
39 changed files with 299 additions and 257 deletions

View File

@ -9,6 +9,7 @@ coverage
## cofeescript
examples/coffeescript/pages/index.vue
examples/pug-stylus-coffee/
examples/typescript-eslint/
# Packages
# vue-app

View File

@ -1,21 +1,8 @@
#!/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' : ''
const errorHandler = (error) => {
require('@nuxt/cli' + suffix).run()
.catch((error) => {
require('consola').fatal(error)
process.exit(2)
}
require('@nuxt/typescript' + suffix).setup(tsConfigPath).then(() => {
require('@nuxt/cli' + suffix).run().catch(errorHandler)
}).catch(errorHandler)
})

View File

@ -1,8 +1,8 @@
module.exports = {
apps: [
{
name: 'pm2-nuxt-ts',
script: './node_modules/.bin/nuxt-ts',
name: 'pm2-nuxt-typescript',
script: './node_modules/.bin/nuxt',
args: 'start',
instances: 2,
exec_mode: 'cluster',

View File

@ -2,17 +2,16 @@
"version": "1.0.0",
"private": true,
"dependencies": {
"nuxt-ts": "latest",
"nuxt": "latest",
"vue-property-decorator": "^7.3.0"
},
"scripts": {
"dev": "nuxt-ts",
"build": "nuxt-ts build",
"start": "nuxt-ts start",
"generate": "nuxt-ts generate",
"lint": "tslint --project ."
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate"
},
"devDependencies": {
"tslint-config-standard": "^8.0.1"
"@nuxt/typescript": "latest"
}
}

View File

@ -1,10 +1 @@
{
"extends": "@nuxt/typescript",
"compilerOptions": {
"baseUrl": ".",
"types": [
"@types/node",
"@nuxt/vue-app"
]
}
}
{}

View File

@ -1,9 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint-config-standard"
],
"rules": {
"prefer-const": true
}
}

View File

@ -0,0 +1,9 @@
module.exports = {
plugins: ['@typescript-eslint'],
parserOptions: {
parser: '@typescript-eslint/parser'
},
extends: [
'@nuxtjs'
]
}

15
examples/typescript-eslint/.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
# Dependencies
node_modules
# Logs
*.log*
# IDE
.idea
.vscode
# Nuxt build
.nuxt
# Nuxt generate
dist

View File

@ -0,0 +1,33 @@
# Nuxt with TypeScript & ESLint example
Use `yarn lint` or `npm run lint` to lint your TypeScript project !
## Why ESLint and not TSLint ?
See https://eslint.org/blog/2019/01/future-typescript-eslint
##
## VSCode settings
If you're using VSCode, we recommend using these settings :
```json
"eslint.autoFixOnSave": true,
"eslint.validate": [
{
"language": "javascript",
"autoFix": true
},
{
"language": "typescript",
"autoFix": true
},
{
"language": "vue",
"autoFix": true
}
]
```
It will lint your `.js`, `.ts` & `.vue` files whenever you're saving them.

View File

@ -0,0 +1 @@
export default {}

View File

@ -0,0 +1,30 @@
{
"version": "1.0.0",
"private": true,
"dependencies": {
"nuxt": "latest",
"vue-property-decorator": "^7.3.0"
},
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint": "eslint --ext .ts,.js,.vue --ignore-path .gitignore .",
"lint:fix": "yarn lint --fix",
"post-update": "yarn upgrade --latest"
},
"devDependencies": {
"@nuxt/typescript": "latest",
"@nuxtjs/eslint-config": "latest",
"@typescript-eslint/eslint-plugin": "^1.4.2",
"eslint": "^5.14.1",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.16.0",
"eslint-plugin-jest": "^22.3.0",
"eslint-plugin-node": "^8.0.1",
"eslint-plugin-promise": "^4.0.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^5.2.2"
}
}

View File

@ -0,0 +1,14 @@
<template>
<div>
<h1>{{ title }}</h1>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
@Component
export default class Home extends Vue {
title = 'TypeScript + ESLint example'
}
</script>

View File

@ -0,0 +1 @@
{}

View File

@ -3,20 +3,18 @@
"private": true,
"version": "1.0.0",
"scripts": {
"dev": "nuxt-ts",
"build": "nuxt-ts build",
"start": "nuxt-ts start",
"generate": "nuxt-ts generate",
"lint": "tslint --project .",
"lint:fix": "tslint --project . --fix",
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"post-update": "yarn upgrade --latest",
"watch:css": "tcm components -w"
},
"dependencies": {
"nuxt-ts": "latest"
"nuxt": "latest"
},
"devDependencies": {
"tslint-config-standard": "^8.0.1",
"@nuxt/typescript": "latest",
"typed-css-modules": "^0.3.7"
}
}

View File

@ -1,8 +1,6 @@
{
"extends": "@nuxt/typescript",
"compilerOptions": {
"baseUrl": ".",
"noImplicitThis": true,
"types": ["@types/node", "@nuxt/vue-app"]
"jsx": "preserve",
"noImplicitThis": true
}
}

View File

@ -1,7 +0,0 @@
{
"defaultSeverity": "error",
"extends": ["tslint-config-standard"],
"rules": {
"prefer-const": true
}
}

View File

@ -3,20 +3,19 @@
"private": true,
"dependencies": {
"axios": "^0.18.0",
"nuxt-ts": "latest",
"nuxt": "latest",
"tachyons": "^4.11.1",
"vue-property-decorator": "^7.3.0",
"vuex-class": "^0.3.1"
},
"scripts": {
"dev": "nuxt-ts",
"build": "nuxt-ts build",
"start": "nuxt-ts start",
"generate": "nuxt-ts generate",
"lint": "tslint --project .",
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"post-update": "yarn upgrade --latest"
},
"devDependencies": {
"tslint-config-standard": "^8.0.1"
"@nuxt/typescript": "latest"
}
}

View File

@ -1,11 +1 @@
{
"extends": "@nuxt/typescript",
"compilerOptions": {
"baseUrl": ".",
"noImplicitAny": false,
"types": [
"@types/node",
"@nuxt/vue-app"
]
}
}
{}

View File

@ -1,9 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint-config-standard"
],
"rules": {
"prefer-const": true
}
}

View File

@ -2,18 +2,17 @@
"version": "1.0.0",
"private": true,
"dependencies": {
"nuxt-ts": "latest",
"nuxt": "latest",
"vue-property-decorator": "^7.3.0"
},
"scripts": {
"dev": "nuxt-ts",
"build": "nuxt-ts build",
"start": "nuxt-ts start",
"generate": "nuxt-ts generate",
"lint": "tslint --project .",
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"post-update": "yarn upgrade --latest"
},
"devDependencies": {
"tslint-config-standard": "^8.0.1"
"@nuxt/typescript": "latest"
}
}

View File

@ -1,10 +1 @@
{
"extends": "@nuxt/typescript",
"compilerOptions": {
"baseUrl": ".",
"types": [
"@types/node",
"@nuxt/vue-app"
]
}
}
{}

View File

@ -1,9 +0,0 @@
{
"defaultSeverity": "error",
"extends": [
"tslint-config-standard"
],
"rules": {
"prefer-const": true
}
}

View File

@ -1,9 +1,12 @@
import path from 'path'
import consola from 'consola'
import minimist from 'minimist'
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 * as imports from './imports'
export default class NuxtCommand {
@ -73,7 +76,10 @@ export default class NuxtCommand {
return this._parsedArgv
}
async getNuxtConfig(extraOptions) {
async getNuxtConfig(extraOptions = {}) {
const rootDir = path.resolve(this.argv._[0] || '.')
extraOptions._typescript = await detectAndSetupTypeScriptSupport(rootDir, { transpileOnly: this.cmd.name === 'start' })
const config = await loadNuxtConfig(this.argv)
const options = Object.assign(config, extraOptions)

View File

@ -1,5 +1,4 @@
import path from 'path'
import { existsSync } from 'fs'
import consola from 'consola'
import esm from 'esm'
import exit from 'exit'
@ -11,14 +10,14 @@ import prettyBytes from 'pretty-bytes'
import env from 'std-env'
import { successBox, warningBox } from './formatting'
export const requireModule = process.env.NUXT_TS ? require : esm(module, {
const esmOptions = {
cache: false,
cjs: {
cache: true,
vars: true,
namedExports: true
}
})
}
export const eventsMapping = {
add: { icon: '+', color: 'green', action: 'Created' },
@ -26,18 +25,23 @@ export const eventsMapping = {
unlink: { icon: '-', color: 'red', action: 'Removed' }
}
const getRootDir = argv => path.resolve(argv._[0] || '.')
const getNuxtConfigFile = argv => path.resolve(getRootDir(argv), argv['config-file'])
export async function loadNuxtConfig(argv) {
const rootDir = getRootDir(argv)
const nuxtConfigFile = getNuxtConfigFile(argv)
const rootDir = path.resolve(argv._[0] || '.')
let nuxtConfigFile
let options = {}
if (existsSync(nuxtConfigFile)) {
delete require.cache[nuxtConfigFile]
options = requireModule(nuxtConfigFile) || {}
try {
nuxtConfigFile = require.resolve(path.resolve(rootDir, argv['config-file']))
} catch (e) {
if (e.code !== 'MODULE_NOT_FOUND') {
throw (e)
} else if (argv['config-file'] !== defaultNuxtConfigFile) {
consola.fatal('Could not load config file: ' + argv['config-file'])
}
}
if (nuxtConfigFile) {
options = (nuxtConfigFile.endsWith('.ts') ? require(nuxtConfigFile) : esm(module, esmOptions)(nuxtConfigFile)) || {}
if (options.default) {
options = options.default
}
@ -56,9 +60,8 @@ export async function loadNuxtConfig(argv) {
// Keep _nuxtConfigFile for watching
options._nuxtConfigFile = nuxtConfigFile
} else if (argv['config-file'] !== defaultNuxtConfigFile) {
consola.fatal('Could not load config file: ' + argv['config-file'])
}
if (typeof options.rootDir !== 'string') {
options.rootDir = rootDir
}

View File

@ -0,0 +1,38 @@
import path from 'path'
import { existsSync } from 'fs'
import chalk from 'chalk'
import consola from 'consola'
import { warningBox } from './formatting'
const dependencyNotFoundMessage =
`Please install @nuxt/typescript and rerun the command
${chalk.bold('Using yarn')}
yarn add -D @nuxt/typescript
${chalk.bold('Using npm')}
npm install -D @nuxt/typescript`
export async function detectAndSetupTypeScriptSupport(rootDir, options = {}) {
const tsConfigPath = path.resolve(rootDir, 'tsconfig.json')
if (!existsSync(tsConfigPath)) {
return false
}
consola.info(`${chalk.bold.blue('tsconfig.json')} found, enabling TypeScript runtime support`)
try {
const { setup } = require('@nuxt/typescript')
await setup(tsConfigPath, options)
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND') {
process.stdout.write(warningBox(dependencyNotFoundMessage, chalk.yellow('An external official dependency is needed to enable TS support')))
process.exit(1)
} else {
throw (e)
}
}
return true
}

View File

@ -14,7 +14,7 @@ exports[`cli/command builds help text 1`] = `
--universal, -u Launch in Universal
mode (default)
--config-file, -c Path to Nuxt.js
config file (default: nuxt.config.js)
config file (default: nuxt.config)
--modern, -m Build/Start app for
modern browsers, e.g. server, client and
false

View File

@ -54,7 +54,9 @@ export default () => ({
},
vueStyle: {}
},
useForkTsChecker: process.env.NUXT_TS === 'true',
typescript: {
typeCheck: true
},
styleResources: {},
plugins: [],
terser: {},

View File

@ -10,7 +10,7 @@ import router from './router'
import server from './server'
import cli from './cli'
export const defaultNuxtConfigFile = `nuxt.config${process.env.NUXT_TS === 'true' ? '.ts' : '.js'}`
export const defaultNuxtConfigFile = 'nuxt.config'
export function getDefaultNuxtConfig(options = {}) {
if (!options.env) {

View File

@ -84,7 +84,7 @@ export function getNuxtConfig(_options) {
// Default value for _nuxtConfigFile
if (!options._nuxtConfigFile) {
options._nuxtConfigFile = path.resolve(options.rootDir, defaultNuxtConfigFile)
options._nuxtConfigFile = path.resolve(options.rootDir, `${defaultNuxtConfigFile}.js`)
}
// Watch for _nuxtConfigFile changes

View File

@ -131,7 +131,9 @@ Object {
"templates": Array [],
"terser": Object {},
"transpile": Array [],
"useForkTsChecker": false,
"typescript": Object {
"typeCheck": true,
},
"watch": Array [],
},
"buildDir": "/var/nuxt/test/.nuxt",

View File

@ -121,7 +121,9 @@ Object {
"templates": Array [],
"terser": Object {},
"transpile": Array [],
"useForkTsChecker": false,
"typescript": Object {
"typeCheck": true,
},
"watch": Array [],
},
"buildDir": ".nuxt",
@ -450,7 +452,9 @@ Object {
"templates": Array [],
"terser": Object {},
"transpile": Array [],
"useForkTsChecker": false,
"typescript": Object {
"typeCheck": true,
},
"watch": Array [],
},
"buildDir": ".nuxt",

View File

@ -4,8 +4,7 @@
"repository": "nuxt/nuxt.js",
"license": "MIT",
"files": [
"dist",
"tsconfig.json"
"dist"
],
"main": "dist/typescript.js",
"dependencies": {
@ -22,15 +21,11 @@
"@types/webpack-bundle-analyzer": "^2.13.1",
"@types/webpack-dev-middleware": "^2.0.2",
"@types/webpack-hot-middleware": "^2.16.5",
"chalk": "^2.4.2",
"consola": "^2.5.6",
"enquirer": "^2.3.0",
"fork-ts-checker-webpack-plugin": "^1.0.0",
"fs-extra": "^7.0.1",
"std-env": "^2.2.1",
"lodash": "^4.17.11",
"ts-loader": "^5.3.3",
"ts-node": "^8.0.3",
"tslint": "^5.14.0",
"typescript": "^3.3.3333"
},
"publishConfig": {

View File

@ -1,53 +1,57 @@
import chalk from 'chalk'
import consola from 'consola'
import env from 'std-env'
import { prompt } from 'enquirer'
import { existsSync, writeJSON } from 'fs-extra'
import { readJSON, writeJSON } from 'fs-extra'
import { register } from 'ts-node'
import defaultsDeep from 'lodash/defaultsDeep'
async function generateTsConfig(tsConfigPath) {
const configToExtend = '@nuxt/typescript'
await writeJSON(tsConfigPath, {
extends: configToExtend,
export const defaultTsJsonConfig = {
compilerOptions: {
target: 'esnext',
module: 'esnext',
moduleResolution: 'node',
lib: [
'esnext',
'esnext.asynciterable',
'dom'
],
esModuleInterop: true,
experimentalDecorators: true,
allowJs: true,
sourceMap: true,
strict: true,
noImplicitAny: false,
noEmit: true,
baseUrl: '.',
paths: {
'~/*': [
'./*'
],
'@/*': [
'./*'
]
},
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) {
export async function setup(tsConfigPath, options = {}) {
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
})
const config = await readJSON(tsConfigPath)
await writeJSON(tsConfigPath, defaultsDeep(config, defaultTsJsonConfig), { spaces: 2 })
if (confirmGeneration) {
await generateTsConfig(tsConfigPath)
}
}
// https://github.com/TypeStrong/ts-node
register({
project: tsConfigPath,
compilerOptions: {
module: 'commonjs'
},
transpileOnly: process.argv[2] === 'start'
...options
})
}

View File

@ -1,12 +1,9 @@
import { resolve } from 'path'
import { exists, mkdirp, readJSON, remove } from 'fs-extra'
import { mkdirp, readJSON, remove, writeJSON } from 'fs-extra'
import { register } from 'ts-node'
import { setup as setupTypeScript } from '@nuxt/typescript'
import { defaultTsJsonConfig, setup as setupTypeScript } from '@nuxt/typescript'
jest.mock('ts-node')
jest.mock('enquirer', () => ({
prompt: jest.fn(() => ({ confirmGeneration: true }))
}))
describe('typescript setup', () => {
const rootDir = 'tmp'
@ -15,21 +12,12 @@ describe('typescript setup', () => {
beforeAll(async () => {
// We're assuming that rootDir provided to setupTypeScript is existing so we create the tested one
await mkdirp(rootDir)
await writeJSON(tsConfigPath, {})
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('tsconfig.json has been updated with defaults', async () => {
expect(await readJSON(tsConfigPath)).toEqual(defaultTsJsonConfig)
})
test('ts-node has been registered once', async () => {
@ -41,13 +29,12 @@ describe('typescript setup', () => {
project: tsConfigPath,
compilerOptions: {
module: 'commonjs'
},
transpileOnly: false
}
})
})
afterAll(async () => {
// Clean workspace by removing the temporary folder (and the generated tsconfig.json at the same time)
await remove(tsConfigPath)
await remove(rootDir)
})
})

View File

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

View File

@ -1,5 +1,4 @@
import path from 'path'
import fs from 'fs'
import querystring from 'querystring'
import consola from 'consola'
import webpack from 'webpack'
@ -77,7 +76,7 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
plugins() {
const plugins = super.plugins()
const { buildOptions, options: { appTemplatePath, buildDir, rootDir, modern } } = this.buildContext
const { buildOptions, options: { appTemplatePath, buildDir, modern, rootDir, _typescript } } = this.buildContext
// Generate output HTML for SSR
if (buildOptions.ssr) {
@ -140,21 +139,16 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
// TypeScript type checker
// Only performs once per client compilation and only if `ts-loader` checker is not used (transpileOnly: true)
if (!this.isModern && this.loaders.ts.transpileOnly && buildOptions.useForkTsChecker) {
const forkTsCheckerResolvedPath = this.buildContext.nuxt.resolver.resolveModule('fork-ts-checker-webpack-plugin')
if (forkTsCheckerResolvedPath) {
const ForkTsCheckerWebpackPlugin = require(forkTsCheckerResolvedPath)
if (_typescript && buildOptions.typescript && buildOptions.typescript.typeCheck && !this.isModern && this.loaders.ts.transpileOnly) {
// We assume that "_typescript" being truthy means @nuxt/typescript is installed <=> fork-ts-checker-webpack-plugin is installed
const ForkTsCheckerWebpackPlugin = require(this.buildContext.nuxt.resolver.resolveModule('fork-ts-checker-webpack-plugin'))
plugins.push(new ForkTsCheckerWebpackPlugin(Object.assign({
vue: true,
tsconfig: path.resolve(rootDir, 'tsconfig.json'),
// https://github.com/Realytics/fork-ts-checker-webpack-plugin#options - tslint: boolean | string - So we set it false if file not found
tslint: (tslintPath => fs.existsSync(tslintPath) && tslintPath)(path.resolve(rootDir, 'tslint.json')),
tslint: false, // We recommend using ESLint so we set this option to `false` by default
formatter: 'codeframe',
logger: consola
}, buildOptions.useForkTsChecker)))
} else {
consola.warn('You need to install `fork-ts-checker-webpack-plugin` as devDependency to enable TypeScript type checking !')
}
}, buildOptions.typescript.typeCheck)))
}
return plugins

View File

@ -1,8 +1,30 @@
{
"extends": "@nuxt/typescript",
"compilerOptions": {
"baseUrl": ".",
"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,
"baseUrl": ".",
"paths": {
"~/*": [
"./*"
],
"@/*": [
"./*"
]
},
"types": [
"@types/node",
"@nuxt/vue-app"

View File

@ -8,7 +8,7 @@ describe('typescript modern', () => {
beforeAll(async () => {
const options = await loadFixture('typescript')
nuxt = new Nuxt(Object.assign(options, { modern: true, build: { useForkTsChecker: true } }))
nuxt = new Nuxt(Object.assign(options, { modern: true, _typescript: true }))
await new Builder(nuxt, BundleBuilder).build()
})

View File

@ -2184,7 +2184,7 @@ ansi-align@^3.0.0:
dependencies:
string-width "^3.0.0"
ansi-colors@^3.0.0, ansi-colors@^3.2.1:
ansi-colors@^3.0.0:
version "3.2.4"
resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
@ -4284,13 +4284,6 @@ 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"