diff --git a/packages/@vue/cli-plugin-babel/generator.js b/packages/@vue/cli-plugin-babel/generator.js new file mode 100644 index 000000000..d74cfa07c --- /dev/null +++ b/packages/@vue/cli-plugin-babel/generator.js @@ -0,0 +1,10 @@ +module.exports = api => { + api.extendPackage({ + devDependencies: { + 'babel-preset-vue-app': '^2.0.0' + }, + babel: { + presets: ['vue-app'] // TODO update babel-preset-vue-app + } + }) +} diff --git a/packages/@vue/cli-plugin-eslint/generator.js b/packages/@vue/cli-plugin-eslint/generator.js new file mode 100644 index 000000000..d5acc58cc --- /dev/null +++ b/packages/@vue/cli-plugin-eslint/generator.js @@ -0,0 +1,3 @@ +module.exports = (api, options) => { + +} diff --git a/packages/@vue/cli-plugin-eslint/index.js b/packages/@vue/cli-plugin-eslint/index.js new file mode 100644 index 000000000..d5acc58cc --- /dev/null +++ b/packages/@vue/cli-plugin-eslint/index.js @@ -0,0 +1,3 @@ +module.exports = (api, options) => { + +} diff --git a/packages/@vue/cli-plugin-unit-jest/generator/files/test/unit/HelloWorld.spec.js b/packages/@vue/cli-plugin-unit-jest/generator/files/test/unit/HelloWorld.spec.js new file mode 100644 index 000000000..2dac23f16 --- /dev/null +++ b/packages/@vue/cli-plugin-unit-jest/generator/files/test/unit/HelloWorld.spec.js @@ -0,0 +1,12 @@ +import { shallow } from 'vue-test-utils' +import HelloWorld from '@/components/HelloWorld.vue' + +describe('Hello.vue', () => { + it('renders props.msg when passed', () => { + const msg = 'new message' + const wrapper = shallow(HelloWorld, { + context: { props: { msg } } + }) + expect(wrapper.text()).toBe(msg) + }) +}) diff --git a/packages/@vue/cli/lib/generators/unit/jest.js b/packages/@vue/cli-plugin-unit-jest/generator/index.js similarity index 95% rename from packages/@vue/cli/lib/generators/unit/jest.js rename to packages/@vue/cli-plugin-unit-jest/generator/index.js index 3a34f7120..f6aba9a9e 100644 --- a/packages/@vue/cli/lib/generators/unit/jest.js +++ b/packages/@vue/cli-plugin-unit-jest/generator/index.js @@ -5,7 +5,6 @@ module.exports = (api, options) => { test: 'jest' }, devDependencies: { - '@vue/cli-plugin-unit-jest': '^0.1.0', 'jest': '^22.0.4', 'vue-test-utils': '^1.0.0-beta.9' }, diff --git a/packages/@vue/cli/lib/generators/unit/files/test/unit/HelloWorld.spec.js b/packages/@vue/cli-plugin-unit-mocha-webpack/generator/files/test/unit/HelloWorld.spec.js similarity index 79% rename from packages/@vue/cli/lib/generators/unit/files/test/unit/HelloWorld.spec.js rename to packages/@vue/cli-plugin-unit-mocha-webpack/generator/files/test/unit/HelloWorld.spec.js index 5252e2f12..d32d48808 100644 --- a/packages/@vue/cli/lib/generators/unit/files/test/unit/HelloWorld.spec.js +++ b/packages/@vue/cli-plugin-unit-mocha-webpack/generator/files/test/unit/HelloWorld.spec.js @@ -1,5 +1,5 @@ import { shallow } from 'vue-test-utils' -<%_ if (options.assertionLibrary === 'expect' && options.unit !== 'jest') { _%> +<%_ if (options.assertionLibrary === 'expect') { _%> import { expect } from 'expect' <%_ } _%> <%_ if (options.assertionLibrary === 'chai') { _%> @@ -13,7 +13,7 @@ describe('Hello.vue', () => { const wrapper = shallow(HelloWorld, { context: { props: { msg } } }) - <%_ if (options.assertionLibrary === 'expect' || options.unit === 'jest') { _%> + <%_ if (options.assertionLibrary === 'expect') { _%> expect(wrapper.text()).toBe(msg) <%_ } else if (options.assertionLibrary === 'chai') { _%> expect(wrapper.text()).to.equal(msg) diff --git a/packages/@vue/cli/lib/generators/unit/mocha-webpack.js b/packages/@vue/cli-plugin-unit-mocha-webpack/generator/index.js similarity index 89% rename from packages/@vue/cli/lib/generators/unit/mocha-webpack.js rename to packages/@vue/cli-plugin-unit-mocha-webpack/generator/index.js index eefab5397..e64297be1 100644 --- a/packages/@vue/cli/lib/generators/unit/mocha-webpack.js +++ b/packages/@vue/cli-plugin-unit-mocha-webpack/generator/index.js @@ -1,6 +1,7 @@ module.exports = (api, options) => { + api.renderFiles('./files') + const devDependencies = { - '@vue/cli-plugin-unit-mocha-webpack': '^0.1.0', 'vue-test-utils': '^1.0.0-beta.9' } if (options.assertionLibrary === 'chai') { @@ -15,6 +16,4 @@ module.exports = (api, options) => { test: 'vue-cli-service test' } }) - - api.renderFiles('./files') } diff --git a/packages/@vue/cli-service/bin/vue-cli-service b/packages/@vue/cli-service/bin/vue-cli-service index 29d0ac1ea..02ff26e7f 100755 --- a/packages/@vue/cli-service/bin/vue-cli-service +++ b/packages/@vue/cli-service/bin/vue-cli-service @@ -2,12 +2,12 @@ const semver = require('semver') const { error } = require('@vue/cli-shared-utils') -const requiredVersion = require('../package.json').engine.node +const requiredVersion = require('../package.json').engines.node if (!semver.satisfies(process.version, requiredVersion)) { error( - `You are using Node ${process.version}, but vue-cli-service\n` + - `requires Node ${requiredVersion}. Please upgrade your Node version.` + `You are using Node ${process.version}, but vue-cli-service ` + + `requires Node ${requiredVersion}.\nPlease upgrade your Node version.` ) process.exit(1) } diff --git a/packages/@vue/cli/lib/generators/core/files/.gitignore b/packages/@vue/cli-service/generator/files/.gitignore similarity index 100% rename from packages/@vue/cli/lib/generators/core/files/.gitignore rename to packages/@vue/cli-service/generator/files/.gitignore diff --git a/packages/@vue/cli/lib/generators/core/files/public/index.html b/packages/@vue/cli-service/generator/files/public/index.html similarity index 100% rename from packages/@vue/cli/lib/generators/core/files/public/index.html rename to packages/@vue/cli-service/generator/files/public/index.html diff --git a/packages/@vue/cli/lib/generators/core/files/src/App.vue b/packages/@vue/cli-service/generator/files/src/App.vue similarity index 100% rename from packages/@vue/cli/lib/generators/core/files/src/App.vue rename to packages/@vue/cli-service/generator/files/src/App.vue diff --git a/packages/@vue/cli/lib/generators/core/files/src/assets/logo.png b/packages/@vue/cli-service/generator/files/src/assets/logo.png similarity index 100% rename from packages/@vue/cli/lib/generators/core/files/src/assets/logo.png rename to packages/@vue/cli-service/generator/files/src/assets/logo.png diff --git a/packages/@vue/cli/lib/generators/core/files/src/components/HelloWorld.vue b/packages/@vue/cli-service/generator/files/src/components/HelloWorld.vue similarity index 100% rename from packages/@vue/cli/lib/generators/core/files/src/components/HelloWorld.vue rename to packages/@vue/cli-service/generator/files/src/components/HelloWorld.vue diff --git a/packages/@vue/cli/lib/generators/core/files/src/main.js b/packages/@vue/cli-service/generator/files/src/main.js similarity index 100% rename from packages/@vue/cli/lib/generators/core/files/src/main.js rename to packages/@vue/cli-service/generator/files/src/main.js diff --git a/packages/@vue/cli-service/generator/index.js b/packages/@vue/cli-service/generator/index.js new file mode 100644 index 000000000..527452894 --- /dev/null +++ b/packages/@vue/cli-service/generator/index.js @@ -0,0 +1,32 @@ +module.exports = (generatorAPI, options) => { + generatorAPI.renderFiles('./files') + generatorAPI.extendPackage({ + scripts: { + 'dev': 'vue-cli-service serve' + ( + // only auto open browser on MacOS where applescript + // can avoid dupilcate window opens + process.platform === 'darwin' + ? ' --open' + : '' + ), + 'build': 'vue-cli-service build', + 'start': 'vue-cli-service serve --prod' + }, + dependencies: { + 'vue': '^2.5.13' + }, + devDependencies: { + 'vue-template-compiler': '^2.5.13' + }, + 'postcss': { + 'plugins': { + 'autoprefixer': {} + } + }, + browserslist: [ + '> 1%', + 'last 2 versions', + 'not ie <= 8' + ] + }) +} diff --git a/packages/@vue/cli/bin/vue-create b/packages/@vue/cli/bin/vue-create index 5261cc2b6..58ec371a0 100755 --- a/packages/@vue/cli/bin/vue-create +++ b/packages/@vue/cli/bin/vue-create @@ -2,12 +2,12 @@ const semver = require('semver') const { error } = require('@vue/cli-shared-utils') -const requiredVersion = require('../package.json').engine.node +const requiredVersion = require('../package.json').engines.node if (!semver.satisfies(process.version, requiredVersion)) { error( - `You are using Node ${process.version}, but this version of vue-cli\n` + - `requires Node ${requiredVersion}. Please upgrade your Node version.` + `You are using Node ${process.version}, but this version of vue-cli ` + + `requires Node ${requiredVersion}.\nPlease upgrade your Node version.` ) process.exit(1) } else { diff --git a/packages/@vue/cli/lib/Creator.js b/packages/@vue/cli/lib/Creator.js index eddecf121..fbb818de4 100644 --- a/packages/@vue/cli/lib/Creator.js +++ b/packages/@vue/cli/lib/Creator.js @@ -1,106 +1,115 @@ const fs = require('fs') const os = require('os') -const ejs = require('ejs') const path = require('path') const chalk = require('chalk') +const debug = require('debug') const inquirer = require('inquirer') -const GeneratorAPI = require('./GeneratorAPI') +const Generator = require('./Generator') const installDeps = require('./util/installDeps') +const PromptModuleAPI = require('./PromptModuleAPI') const writeFileTree = require('./util/writeFileTree') const { info, error, - success, hasYarn, clearConsole } = require('@vue/cli-shared-utils') -const debug = require('debug') const rcPath = path.join(os.homedir(), '.vuerc') const isMode = _mode => ({ mode }) => _mode === mode const defaultOptions = { - features: ['eslint', 'unit'], - eslint: 'eslint-only', - unit: 'mocha', - assertionLibrary: 'chai', - packageManager: hasYarn ? 'yarn' : 'npm' + packageManager: hasYarn ? 'yarn' : 'npm', + plugins: { + '@vue/cli-plugin-babel': {}, + '@vue/cli-plugin-eslint': { config: 'eslint-only' }, + '@vue/cli-plugin-unit-mocha-webpack': { assertionLibrary: 'chai' } + } } module.exports = class Creator { - constructor (name, generators) { - this.name = name + constructor (modules) { const { modePrompt, featurePrompt } = this.resolveIntroPrompts() this.modePrompt = modePrompt this.featurePrompt = featurePrompt this.outroPrompts = this.resolveOutroPrompts() this.injectedPrompts = [] this.promptCompleteCbs = [] - this.fileMiddlewares = [] - this.options = {} - this.pkg = { - name, - version: '0.1.0', - private: true, - scripts: {}, - dependencies: {}, - devDependencies: {} - } - // for conflict resolution - this.depSources = {} - // virtual file tree - this.files = {} - - generators.forEach(({ id, apply }) => { - apply(new GeneratorAPI(id, this)) - }) + const api = new PromptModuleAPI(this) + modules.forEach(m => m(api)) } - async create (targetDir) { + async create (name, targetDir) { // prompt clearConsole() - let options = await inquirer.prompt(this.resolveFinalPrompts()) - debug('rawOptions')(options) + const answers = await inquirer.prompt(this.resolveFinalPrompts()) + debug('answers')(answers) - if (options.mode === 'saved') { + let options + if (answers.mode === 'saved') { options = this.loadSavedOptions() - } else if (options.mode === 'default') { + } else if (answers.mode === 'default') { options = defaultOptions + } else { + options = { + packageManager: answers.packageManager, + plugins: {} + } } - options.projectName = this.name - // run cb registered by generators - this.promptCompleteCbs.forEach(cb => cb(options)) - this.options = options - debug('options')(options) + // run cb registered by prompt modules to finalize the options + this.promptCompleteCbs.forEach(cb => cb(answers, options)) + // save options - if (options.mode === 'manual' && options.save) { + if (answers.mode === 'manual' && answers.save) { this.saveOptions(options) } - // wait for file resolve - await this.resolveFiles() - // set package.json - this.resolvePkg() - this.files['package.json'] = JSON.stringify(this.pkg, null, 2) - // write file tree to disk - await writeFileTree(targetDir, this.files) - - success(`Project created in ${chalk.cyan(options.projectName)}.`) - - if (options.packageManager) { - info(`Installing dependencies with ${options.packageManager}. This may take a while...`) - await installDeps(options.packageManager, targetDir) + // inject core service + options.plugins['@vue/cli-service'] = { + projectName: name } + + debug('options')(options) + + // write base package.json to disk + info(`Creating project in ${chalk.cyan(targetDir)}.`) + writeFileTree(targetDir, { + 'package.json': JSON.stringify({ + name, + version: '0.1.0', + private: true + }, null, 2) + }) + + // install deps + info(`Installing dependencies with ${options.packageManager}. This may take a while...`) + const deps = Object.keys(options.plugins) + if (process.env.VUE_CLI_DEBUG) { + // in development, use linked packages + updatePackageForDev(targetDir, deps) + await installDeps(options.packageManager, targetDir) + } else { + await installDeps(options.packageManager, targetDir, deps) + } + + // run generator + const generator = new Generator(targetDir, options) + await generator.generate() + + // install deps again (new deps injected by generators) + await installDeps(options.packageManager, targetDir) + + // TODO run vue-cli-service init } resolveIntroPrompts () { const modePrompt = { name: 'mode', type: 'list', - message: `Pick a project creation mode:`, + message: `Hi there! Please pick a project creation mode:`, choices: [ { name: 'Zero-configuration with defaults', @@ -122,7 +131,7 @@ module.exports = class Creator { name: 'features', when: isMode('manual'), type: 'checkbox', - message: 'Please check the features needed for your project.', + message: 'Check the features needed for your project:', choices: [] } return { @@ -132,46 +141,33 @@ module.exports = class Creator { } resolveOutroPrompts () { - const outroPrompts = [ - { - name: 'save', - when: isMode('manual'), - type: 'confirm', - message: 'Save the preferences for future projects?' - } - ] + const outroPrompts = [] if (hasYarn) { - outroPrompts.unshift({ + outroPrompts.push({ name: 'packageManager', when: isMode('manual'), type: 'list', - message: 'Automatically install NPM dependencies after project creation?', + message: 'Pick the package manager to use when installing dependencies:', choices: [ - { - name: 'Use NPM', - value: 'npm', - short: 'NPM' - }, { name: 'Use Yarn', value: 'yarn', short: 'Yarn' }, { - name: `I'll handle that myself`, - value: false, - short: 'No' + name: 'Use NPM', + value: 'npm', + short: 'NPM' } ] }) - } else { - outroPrompts.unshift({ - name: 'packageManager', - when: isMode('manual'), - type: 'confirm', - message: 'Automatically install NPM dependencies after project creation?' - }) } + outroPrompts.push({ + name: 'save', + when: isMode('manual'), + type: 'confirm', + message: 'Save the preferences for future projects?' + }) return outroPrompts } @@ -208,6 +204,10 @@ module.exports = class Creator { } saveOptions (options) { + options = Object.assign({}, options) + delete options.projectName + delete options.mode + delete options.save try { fs.writeFileSync(rcPath, JSON.stringify(options, null, 2)) } catch (e) { @@ -218,21 +218,21 @@ module.exports = class Creator { ) } } - - resolvePkg () { - const sortDeps = deps => Object.keys(deps).sort().reduce((res, name) => { - res[name] = deps[name] - return res - }, {}) - this.pkg.dependencies = sortDeps(this.pkg.dependencies) - this.pkg.devDependencies = sortDeps(this.pkg.devDependencies) - debug('pkg')(this.pkg) - } - - async resolveFiles () { - for (const middleware of this.fileMiddlewares) { - await middleware(this.files, ejs.render) - } - debug('files')(this.files) - } +} + +function updatePackageForDev (targetDir, deps) { + const pkg = require(path.resolve(targetDir, 'package.json')) + pkg.devDependencies = {} + deps.forEach(dep => { + pkg.devDependencies[dep] = require(path.resolve( + __dirname, + '../../../', + dep, + 'package.json' + )).version + }) + fs.writeFileSync( + path.resolve(targetDir, 'package.json'), + JSON.stringify(pkg, null, 2) + ) } diff --git a/packages/@vue/cli/lib/Generator.js b/packages/@vue/cli/lib/Generator.js new file mode 100644 index 000000000..a3bb87f11 --- /dev/null +++ b/packages/@vue/cli/lib/Generator.js @@ -0,0 +1,56 @@ +const ejs = require('ejs') +const path = require('path') +const debug = require('debug') +const resolve = require('resolve') +const GeneratorAPI = require('./GeneratorAPI') +const { success } = require('@vue/cli-shared-utils') +const writeFileTree = require('./util/writeFileTree') + +module.exports = class Generator { + constructor (context, options) { + this.context = context + this.options = options + this.pkg = require(path.resolve(context, 'package.json')) + // for conflict resolution + this.depSources = {} + // virtual file tree + this.files = {} + this.fileMiddlewares = [] + + // apply generators from plugins + Object.keys(options.plugins).forEach(id => { + const generatorPath = resolve.sync(`${id}/generator`, { basedir: context }) + const generator = require(generatorPath) + const generatorOptions = options.plugins[id] + generator(new GeneratorAPI(id, this, generatorOptions), generatorOptions) + }) + } + + async generate () { + // wait for file resolve + await this.resolveFiles() + // set package.json + this.resolvePkg() + this.files['package.json'] = JSON.stringify(this.pkg, null, 2) + // write file tree to disk + await writeFileTree(this.context, this.files) + success(`Successfully generated project files.`) + } + + resolvePkg () { + const sortDeps = deps => Object.keys(deps).sort().reduce((res, name) => { + res[name] = deps[name] + return res + }, {}) + this.pkg.dependencies = sortDeps(this.pkg.dependencies) + this.pkg.devDependencies = sortDeps(this.pkg.devDependencies) + debug('pkg')(this.pkg) + } + + async resolveFiles () { + for (const middleware of this.fileMiddlewares) { + await middleware(this.files, ejs.render) + } + debug('files')(this.files) + } +} diff --git a/packages/@vue/cli/lib/GeneratorAPI.js b/packages/@vue/cli/lib/GeneratorAPI.js index 0ad976f64..606edb6db 100644 --- a/packages/@vue/cli/lib/GeneratorAPI.js +++ b/packages/@vue/cli/lib/GeneratorAPI.js @@ -5,54 +5,24 @@ const walk = require('klaw-sync') const isBinary = require('isbinaryfile') const mergeDeps = require('./util/mergeDeps') const errorParser = require('error-stack-parser') -const { error } = require('@vue/cli-shared-utils') const isString = val => typeof val === 'string' const isFunction = val => typeof val === 'function' const isObject = val => val && typeof val === 'object' module.exports = class GeneratorAPI { - constructor (id, creator) { + constructor (id, generator, options) { this.id = id - this.creator = creator - } - - injectFeature (feature) { - this.creator.featurePrompt.choices.push(feature) - } - - injectPrompt (prompt) { - this.creator.injectedPrompts.push(prompt) - } - - injectOptionForPrompt (name, option) { - const prompt = this.creator.injectedPrompts.find(f => { - return f.name === name - }) - if (!prompt) { - error( - `injectOptionForFeature error in generator "${ - this.id - }": prompt "${name}" does not exist.` - ) - } - prompt.choices.push(option) - } - - onPromptComplete (cb) { - this.creator.promptCompleteCbs.push(cb) - } - - onCreateComplete (cb) { - this.creator.onCreateCompleteCbs.push(cb) + this.generator = generator + this.options = options } injectFileMiddleware (middleware) { - this.creator.fileMiddlewares.push(middleware) + this.generator.fileMiddlewares.push(middleware) } extendPackage (fields, options = { merge: true }) { - const pkg = this.creator.pkg + const pkg = this.generator.pkg const toMerge = isFunction(fields) ? fields(pkg) : fields for (const key in toMerge) { if (!options.merge || !(key in pkg)) { @@ -69,7 +39,7 @@ module.exports = class GeneratorAPI { this.id, existing, value, - this.creator.depSources + this.generator.depSources ) } else { pkg[key] = Object.assign({}, existing, value) @@ -87,7 +57,7 @@ module.exports = class GeneratorAPI { fileDir = path.resolve(baseDir, fileDir) this.injectFileMiddleware(files => { const data = Object.assign({ - options: this.creator.options + options: this.options }, additionalData) const _files = walk(fileDir, { nodir: true, @@ -101,7 +71,7 @@ module.exports = class GeneratorAPI { } else if (isObject(fileDir)) { this.injectFileMiddleware(files => { const data = Object.assign({ - options: this.creator.options + options: this.options }, additionalData) for (const targetPath in fileDir) { const sourcePath = path.resolve(baseDir, fileDir[targetPath]) diff --git a/packages/@vue/cli/lib/PromptModuleAPI.js b/packages/@vue/cli/lib/PromptModuleAPI.js new file mode 100644 index 000000000..dc825583f --- /dev/null +++ b/packages/@vue/cli/lib/PromptModuleAPI.js @@ -0,0 +1,23 @@ +module.exports = class PromptModuleAPI { + constructor (creator) { + this.creator = creator + } + + injectFeature (feature) { + this.creator.featurePrompt.choices.push(feature) + } + + injectPrompt (prompt) { + this.creator.injectedPrompts.push(prompt) + } + + injectOptionForPrompt (name, option) { + this.creator.injectedPrompts.find(f => { + return f.name === name + }).choices.push(option) + } + + onPromptComplete (cb) { + this.creator.promptCompleteCbs.push(cb) + } +} diff --git a/packages/@vue/cli/lib/create.js b/packages/@vue/cli/lib/create.js index 70c7da9dc..442641cf5 100644 --- a/packages/@vue/cli/lib/create.js +++ b/packages/@vue/cli/lib/create.js @@ -5,9 +5,7 @@ const rimraf = require('rimraf') const inquirer = require('inquirer') const program = require('commander') const Creator = require('./Creator') -const debug = require('debug')('create') -const { warn, error } = require('@vue/cli-shared-utils') -const resolveInstalledGenerators = require('./util/resolveInstalledGenerators') +const { warn, error, clearConsole } = require('@vue/cli-shared-utils') async function run () { program @@ -23,39 +21,33 @@ async function run () { const targetDir = path.resolve(process.cwd(), projectName) if (fs.existsSync(targetDir)) { - const { overwrite } = await inquirer.prompt([ + clearConsole() + const { action } = await inquirer.prompt([ { - name: 'overwrite', - type: 'confirm', - message: `Target directory ${chalk.cyan(targetDir)} already exists.\n Overwrite?` + name: 'action', + type: 'list', + message: `Target directory ${chalk.cyan(targetDir)} already exists. Pick an action:`, + choices: [ + { name: 'Overwrite', value: 'overwrite' }, + { name: 'Merge', value: 'merge' }, + { name: 'Cancel', value: false } + ] } ]) - if (overwrite) { - rimraf.sync(targetDir) - } else { + if (!action) { return + } else if (action === 'overwrite') { + rimraf.sync(targetDir) } } - const createGenerator = (id, requirePath = id) => ({ - id, - apply: require(requirePath) - }) + const promptModules = fs + .readdirSync(path.resolve(__dirname, './promptModules')) + .filter(file => file.charAt(0) !== '.') + .map(file => require(`./promptModules/${file}`)) - const builtInGenerators = fs - .readdirSync(path.resolve(__dirname, './generators')) - .filter(dir => dir.charAt(0) !== '.') - .map(id => createGenerator(id, `./generators/${id}`)) - - debug(builtInGenerators) - - const installedGenerators = resolveInstalledGenerators().map(id => { - return createGenerator(id) - }) - - const creator = new Creator(projectName, builtInGenerators.concat(installedGenerators)) - - await creator.create(targetDir) + const creator = new Creator(promptModules) + await creator.create(projectName, targetDir) } run().catch(error) diff --git a/packages/@vue/cli/lib/generators/babel/index.js b/packages/@vue/cli/lib/generators/babel/index.js deleted file mode 100644 index 2c5d5172a..000000000 --- a/packages/@vue/cli/lib/generators/babel/index.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = api => { - api.onPromptComplete(options => { - if (!options.features.includes('ts') && !options.features.includes('-babel')) { - api.extendPackage({ - devDependencies: { - '@vue/cli-plugin-babel': '^0.1.0', - 'babel-preset-vue-app': '^2.0.0' - }, - babel: { - presets: ['vue-app'] // TODO update babel-preset-vue-app - } - }) - } - }) -} diff --git a/packages/@vue/cli/lib/generators/core/index.js b/packages/@vue/cli/lib/generators/core/index.js deleted file mode 100644 index 94383daef..000000000 --- a/packages/@vue/cli/lib/generators/core/index.js +++ /dev/null @@ -1,31 +0,0 @@ -module.exports = api => { - api.onPromptComplete(options => { - if (!options.features.includes('-core')) { - api.renderFiles('./files') - api.extendPackage({ - scripts: { - 'dev': 'vue-cli-service serve', - 'build': 'vue-cli-service build', - 'start': 'vue-cli-service serve --prod' - }, - dependencies: { - 'vue': '^2.5.13' - }, - devDependencies: { - '@vue/cli-service': '^0.1.0', - 'vue-template-compiler': '^2.5.13' - }, - 'postcss': { - 'plugins': { - 'autoprefixer': {} - } - }, - browserslist: [ - '> 1%', - 'last 2 versions', - 'not ie <= 8' - ] - }) - } - }) -} diff --git a/packages/@vue/cli/lib/generators/e2e/index.js b/packages/@vue/cli/lib/generators/e2e/index.js deleted file mode 100644 index 61406aa61..000000000 --- a/packages/@vue/cli/lib/generators/e2e/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = api => { - -} diff --git a/packages/@vue/cli/lib/generators/eslint/index.js b/packages/@vue/cli/lib/generators/eslint/index.js deleted file mode 100644 index 61406aa61..000000000 --- a/packages/@vue/cli/lib/generators/eslint/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = api => { - -} diff --git a/packages/@vue/cli/lib/generators/pwa/index.js b/packages/@vue/cli/lib/generators/pwa/index.js deleted file mode 100644 index 61406aa61..000000000 --- a/packages/@vue/cli/lib/generators/pwa/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = api => { - -} diff --git a/packages/@vue/cli/lib/generators/router/index.js b/packages/@vue/cli/lib/generators/router/index.js deleted file mode 100644 index 61406aa61..000000000 --- a/packages/@vue/cli/lib/generators/router/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = api => { - -} diff --git a/packages/@vue/cli/lib/generators/typescript/index.js b/packages/@vue/cli/lib/generators/typescript/index.js deleted file mode 100644 index 61406aa61..000000000 --- a/packages/@vue/cli/lib/generators/typescript/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = api => { - -} diff --git a/packages/@vue/cli/lib/generators/vuex/index.js b/packages/@vue/cli/lib/generators/vuex/index.js deleted file mode 100644 index 61406aa61..000000000 --- a/packages/@vue/cli/lib/generators/vuex/index.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = api => { - -} diff --git a/packages/@vue/cli/lib/promptModules/e2e.js b/packages/@vue/cli/lib/promptModules/e2e.js new file mode 100644 index 000000000..aec191910 --- /dev/null +++ b/packages/@vue/cli/lib/promptModules/e2e.js @@ -0,0 +1,2 @@ +module.exports = cli => { +} diff --git a/packages/@vue/cli/lib/promptModules/eslint.js b/packages/@vue/cli/lib/promptModules/eslint.js new file mode 100644 index 000000000..aec191910 --- /dev/null +++ b/packages/@vue/cli/lib/promptModules/eslint.js @@ -0,0 +1,2 @@ +module.exports = cli => { +} diff --git a/packages/@vue/cli/lib/promptModules/pwa.js b/packages/@vue/cli/lib/promptModules/pwa.js new file mode 100644 index 000000000..aec191910 --- /dev/null +++ b/packages/@vue/cli/lib/promptModules/pwa.js @@ -0,0 +1,2 @@ +module.exports = cli => { +} diff --git a/packages/@vue/cli/lib/promptModules/router.js b/packages/@vue/cli/lib/promptModules/router.js new file mode 100644 index 000000000..aec191910 --- /dev/null +++ b/packages/@vue/cli/lib/promptModules/router.js @@ -0,0 +1,2 @@ +module.exports = cli => { +} diff --git a/packages/@vue/cli/lib/promptModules/typescript.js b/packages/@vue/cli/lib/promptModules/typescript.js new file mode 100644 index 000000000..aec191910 --- /dev/null +++ b/packages/@vue/cli/lib/promptModules/typescript.js @@ -0,0 +1,2 @@ +module.exports = cli => { +} diff --git a/packages/@vue/cli/lib/generators/unit/index.js b/packages/@vue/cli/lib/promptModules/unit.js similarity index 65% rename from packages/@vue/cli/lib/generators/unit/index.js rename to packages/@vue/cli/lib/promptModules/unit.js index baf25ece5..54bbf76ac 100644 --- a/packages/@vue/cli/lib/generators/unit/index.js +++ b/packages/@vue/cli/lib/promptModules/unit.js @@ -1,13 +1,13 @@ -module.exports = api => { - api.injectFeature({ +module.exports = cli => { + cli.injectFeature({ name: 'Unit Testing', value: 'unit', short: 'Unit' }) - api.injectPrompt({ + cli.injectPrompt({ name: 'unit', - when: options => options.features.includes('unit'), + when: answers => answers.features.includes('unit'), type: 'list', message: 'Pick a unit testing solution:', choices: [ @@ -24,10 +24,10 @@ module.exports = api => { ] }) - api.injectPrompt({ + cli.injectPrompt({ name: 'assertionLibrary', message: 'Pick an assertion library for unit tests:', - when: options => options.unit === 'mocha', + when: answers => answers.unit === 'mocha', type: 'list', choices: [ { @@ -48,11 +48,13 @@ module.exports = api => { ] }) - api.onPromptComplete(options => { - if (options.unit === 'mocha') { - require('./mocha-webpack')(api, options) - } else if (options.unit === 'jest') { - require('./jest')(api, options) + cli.onPromptComplete((answers, options) => { + if (answers.unit === 'mocha') { + options.plugins['@vue/cli-plugin-unit-mocha-webpack'] = { + assertionLibrary: answers.assertionLibrary + } + } else if (answers.unit === 'jest') { + options.plugins['@vue/cli-plugin-unit-jest'] = {} } }) } diff --git a/packages/@vue/cli/lib/promptModules/vuex.js b/packages/@vue/cli/lib/promptModules/vuex.js new file mode 100644 index 000000000..aec191910 --- /dev/null +++ b/packages/@vue/cli/lib/promptModules/vuex.js @@ -0,0 +1,2 @@ +module.exports = cli => { +} diff --git a/packages/@vue/cli/lib/util/installDeps.js b/packages/@vue/cli/lib/util/installDeps.js index 35684780a..668da2375 100644 --- a/packages/@vue/cli/lib/util/installDeps.js +++ b/packages/@vue/cli/lib/util/installDeps.js @@ -1,3 +1,36 @@ -module.exports = async function installDeps (command, targetDir) { - // TODO think about dep strategy +const { spawn } = require('child_process') + +module.exports = function installDeps (command, targetDir, deps) { + return new Promise((resolve, reject) => { + const args = [] + if (command === 'npm') { + args.push('install', '--loglevel', 'error') + if (deps) { + args.push('--save-dev') + } + } else if (command === 'yarn') { + if (deps) { + args.push('add', '--dev') + } + args.push('--silent') + } else { + throw new Error(`unknown package manager: ${command}`) + } + if (deps) { + args.push.apply(args, deps) + } + + const child = spawn(command, args, { + cwd: targetDir, + stdio: 'inherit' + }) + child.on('close', code => { + if (code !== 0) { + return reject( + `command failed: ${command} ${args.join(' ')}` + ) + } + resolve() + }) + }) } diff --git a/packages/@vue/cli/lib/util/resolveInstalledGenerators.js b/packages/@vue/cli/lib/util/resolveInstalledGenerators.js deleted file mode 100644 index f9bfe74ab..000000000 --- a/packages/@vue/cli/lib/util/resolveInstalledGenerators.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = function resolveInstalledGenerators () { - // TODO - return [] -} diff --git a/packages/@vue/cli/lib/util/writeFileTree.js b/packages/@vue/cli/lib/util/writeFileTree.js index 5a398c4e0..815c73bb9 100644 --- a/packages/@vue/cli/lib/util/writeFileTree.js +++ b/packages/@vue/cli/lib/util/writeFileTree.js @@ -3,9 +3,6 @@ const path = require('path') const mkdirp = require('mkdirp') module.exports = function writeFileTree (dir, files) { - if (process.env.DEBUG) { - return - } for (const name in files) { const filePath = path.join(dir, name) mkdirp.sync(path.dirname(filePath)) diff --git a/packages/@vue/cli/package.json b/packages/@vue/cli/package.json index 2655c302a..2a3fcaeb9 100644 --- a/packages/@vue/cli/package.json +++ b/packages/@vue/cli/package.json @@ -35,6 +35,7 @@ "isbinaryfile": "^3.0.2", "klaw-sync": "^3.0.2", "mkdirp": "^0.5.1", + "resolve": "^1.5.0", "rimraf": "^2.6.2", "semver": "^5.4.1" }, diff --git a/yarn.lock b/yarn.lock index 08033051f..9f8af9ab9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6061,7 +6061,7 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.4.0: +resolve@^1.4.0, resolve@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" dependencies: