diff --git a/packages/nuxt3/src/cli/command.ts b/packages/nuxt3/src/cli/command.ts deleted file mode 100644 index 5aaac69288..0000000000 --- a/packages/nuxt3/src/cli/command.ts +++ /dev/null @@ -1,250 +0,0 @@ - -import path from 'path' -import consola from 'consola' -import minimist, { Opts as MinimistOptions, ParsedArgs } from 'minimist' -import Hookable from 'hookable' - -import { Builder } from 'src/builder' -import { CliConfiguration } from 'src/config/options' -import { Nuxt } from 'src/core' - -import { name, version } from '../../package.json' - -import { forceExit } from './utils' -import { loadNuxtConfig } from './utils/config' -import { indent, foldLines, colorize } from './utils/formatting' -import { startSpaces, optionSpaces, forceExitTimeout } from './utils/constants' - -export interface Command { - name: string - usage: string - description: string - options?: Record - run?: (nuxt: NuxtCommand) => any | Promise -} - -type Hooks = Parameters[0] - -export default class NuxtCommand extends Hookable { - _argv: string[] - _parsedArgv: null | ParsedArgs - _lockRelease?: () => Promise - - cmd: Command & { options: Command['options'] } - - constructor (cmd: Command = { name: '', usage: '', description: '' }, argv = process.argv.slice(2), hooks: Hooks = {}) { - super(consola) - this.addHooks(hooks) - - if (!cmd.options) { - cmd.options = {} - } - this.cmd = cmd as Command & { options: Command['options'] } - - this._argv = Array.from(argv) - this._parsedArgv = null // Lazy evaluate - } - - static run (cmd: Command, argv: NodeJS.Process['argv'], hooks: Hooks) { - return NuxtCommand.from(cmd, argv, hooks).run() - } - - static from (cmd: Command, argv: NodeJS.Process['argv'], hooks: Hooks) { - if (cmd instanceof NuxtCommand) { - return cmd - } - return new NuxtCommand(cmd, argv, hooks) - } - - async run () { - await this.callHook('run:before', { - argv: this._argv, - cmd: this.cmd, - rootDir: path.resolve(this.argv._[0] || '.') - }) - - if (this.argv.help) { - this.showHelp() - return - } - - if (this.argv.version) { - this.showVersion() - return - } - - if (!(this.cmd.run instanceof Function)) { - throw new TypeError('Invalid command! Commands should at least implement run() function.') - } - - let cmdError: any - - try { - await this.cmd.run(this) - } catch (e) { - cmdError = e - } - - if (this.argv.lock) { - await this.releaseLock() - } - - if (this.argv['force-exit']) { - const forceExitByUser = this.isUserSuppliedArg('force-exit') - if (cmdError) { - consola.fatal(cmdError) - } - forceExit(this.cmd.name, forceExitByUser ? false : forceExitTimeout) - if (forceExitByUser) { - return - } - } - - if (cmdError) { - throw cmdError - } - } - - showVersion () { - process.stdout.write(`${name} v${version}\n`) - } - - showHelp () { - process.stdout.write(this._getHelp()) - } - - get argv () { - if (!this._parsedArgv) { - const minimistOptions = this._getMinimistOptions() - this._parsedArgv = minimist(this._argv, minimistOptions) - } - return this._parsedArgv - } - - async getNuxtConfig (extraOptions: Partial = {}) { - // Flag to indicate nuxt is running with CLI (not programmatic) - extraOptions._cli = true - - const context = { - command: this.cmd.name, - dev: !!extraOptions.dev - } - - const config = await loadNuxtConfig(this.argv, context) - const options = Object.assign(config, extraOptions) - - for (const name of Object.keys(this.cmd.options)) { - this.cmd.options[name].prepare && this.cmd.options[name].prepare(this, options, this.argv) - } - - await this.callHook('config', options) - - return options - } - - async getNuxt (options: CliConfiguration) { - const nuxt = new Nuxt(options) - await nuxt.ready() - - return nuxt - } - - getBuilder (nuxt: Nuxt) { - return new Builder(nuxt) - } - - async setLock (lockRelease?: () => Promise) { - if (lockRelease) { - if (this._lockRelease) { - consola.warn(`A previous unreleased lock was found, this shouldn't happen and is probably an error in 'nuxt ${this.cmd.name}' command. The lock will be removed but be aware of potential strange results`) - - await this.releaseLock() - this._lockRelease = lockRelease - } else { - this._lockRelease = lockRelease - } - } - } - - async releaseLock () { - if (this._lockRelease) { - await this._lockRelease() - this._lockRelease = undefined - } - } - - isUserSuppliedArg (option: string) { - return this._argv.includes(`--${option}`) || this._argv.includes(`--no-${option}`) - } - - _getDefaultOptionValue T) | T }>(option: Option) { - return option.default instanceof Function ? option.default(this.cmd) : option.default - } - - _getMinimistOptions () { - const minimistOptions: MinimistOptions = { - alias: {}, - boolean: [], - string: [], - default: {} - } - - for (const name of Object.keys(this.cmd.options)) { - const option = this.cmd.options[name] - - if (option.alias) { - minimistOptions.alias[option.alias] = name - } - if (option.type) { - minimistOptions[option.type].push(option.alias || name) - } - if (option.default) { - minimistOptions.default[option.alias || name] = this._getDefaultOptionValue(option) - } - } - - return minimistOptions - } - - _getHelp () { - const options: [string, string][] = [] - let maxOptionLength = 0 - - for (const name in this.cmd.options) { - const option = this.cmd.options[name] - - let optionHelp = '--' - optionHelp += option.type === 'boolean' && this._getDefaultOptionValue(option) ? 'no-' : '' - optionHelp += name - if (option.alias) { - optionHelp += `, -${option.alias}` - } - - maxOptionLength = Math.max(maxOptionLength, optionHelp.length) - options.push([optionHelp, option.description]) - } - - const _opts = options.map(([option, description]) => { - const i = indent(maxOptionLength + optionSpaces - option.length) - return foldLines( - option + i + description, - startSpaces + maxOptionLength + optionSpaces * 2, - startSpaces + optionSpaces - ) - }).join('\n') - - const usage = foldLines(`Usage: nuxt ${this.cmd.usage} [options]`, startSpaces) - const description = foldLines(this.cmd.description, startSpaces) - const opts = foldLines('Options:', startSpaces) + '\n\n' + _opts - - let helpText = colorize(`${usage}\n\n`) - if (this.cmd.description) { - helpText += colorize(`${description}\n\n`) - } - if (options.length) { - helpText += colorize(`${opts}\n\n`) - } - - return helpText - } -} diff --git a/packages/nuxt3/src/cli/commands/build.ts b/packages/nuxt3/src/cli/commands/build.ts deleted file mode 100644 index bf6abf2fb0..0000000000 --- a/packages/nuxt3/src/cli/commands/build.ts +++ /dev/null @@ -1,94 +0,0 @@ -import consola from 'consola' -import { MODES, TARGETS } from 'src/utils' -import type { ParsedArgs } from 'minimist' -import NuxtCommand from '../command' -import { common, locking } from '../options' -import { createLock } from '../utils' - -export default { - name: 'build', - description: 'Compiles the application for production deployment', - usage: 'build ', - options: { - ...common, - ...locking, - analyze: { - alias: 'a', - type: 'boolean', - description: 'Launch webpack-bundle-analyzer to optimize your bundles', - prepare (_cmd: NuxtCommand, options, argv: ParsedArgs) { - // Analyze option - options.build = options.build || {} - if (argv.analyze && typeof options.build.analyze !== 'object') { - options.build.analyze = true - } - } - }, - devtools: { - type: 'boolean', - default: false, - description: 'Enable Vue devtools', - prepare (_cmd: NuxtCommand, options, argv: ParsedArgs) { - options.vue = options.vue || {} - options.vue.config = options.vue.config || {} - if (argv.devtools) { - options.vue.config.devtools = true - } - } - }, - generate: { - type: 'boolean', - default: true, - description: 'Don\'t generate static version for SPA mode (useful for nuxt start)' - }, - quiet: { - alias: 'q', - type: 'boolean', - description: 'Disable output except for errors', - prepare (_cmd: NuxtCommand, options, argv: ParsedArgs) { - // Silence output when using --quiet - options.build = options.build || {} - if (argv.quiet) { - options.build.quiet = Boolean(argv.quiet) - } - } - }, - standalone: { - type: 'boolean', - default: false, - description: 'Bundle all server dependencies (useful for nuxt-start)', - prepare (_cmd: NuxtCommand, options, argv: ParsedArgs) { - if (argv.standalone) { - options.build.standalone = true - } - } - } - }, - async run (cmd: NuxtCommand) { - const config = await cmd.getNuxtConfig({ dev: false, server: false, _build: true }) - config.server = (config.mode === MODES.spa || config.ssr === false) && cmd.argv.generate !== false - const nuxt = await cmd.getNuxt(config) - - if (cmd.argv.lock) { - await cmd.setLock(await createLock({ - id: 'build', - dir: nuxt.options.buildDir, - root: config.rootDir - })) - } - - // TODO: remove if in Nuxt 3 - if (nuxt.options.mode === MODES.spa && nuxt.options.target === TARGETS.server && cmd.argv.generate !== false) { - // Build + Generate for static deployment - const generator = await cmd.getGenerator(nuxt) - await generator.generate({ build: true }) - } else { - // Build only - const builder = await cmd.getBuilder(nuxt) - await builder.build() - - const nextCommand = nuxt.options.target === TARGETS.static ? 'nuxt export' : 'nuxt start' - consola.info('Ready to run `' + (nextCommand) + '`') - } - } -} diff --git a/packages/nuxt3/src/cli/commands/dev.ts b/packages/nuxt3/src/cli/commands/dev.ts deleted file mode 100644 index faed7e68ea..0000000000 --- a/packages/nuxt3/src/cli/commands/dev.ts +++ /dev/null @@ -1,121 +0,0 @@ -import consola from 'consola' -import chalk from 'chalk' -import opener from 'opener' -import type { ParsedArgs } from 'minimist' - -import { Nuxt } from 'src/core' - -import type NuxtCommand from '../command' -import { common, server } from '../options' -import { eventsMapping, formatPath } from '../utils' -import { showBanner } from '../utils/banner' -import { showMemoryUsage } from '../utils/memory' - -export default { - name: 'dev', - description: 'Start the application in development mode (e.g. hot-code reloading, error reporting)', - usage: 'dev ', - options: { - ...common, - ...server, - open: { - alias: 'o', - type: 'boolean', - description: 'Opens the server listeners url in the default browser' - } - }, - - async run (cmd: NuxtCommand) { - const { argv } = cmd - - await this.startDev(cmd, argv, argv.open) - }, - - async startDev (cmd: NuxtCommand, argv) { - let nuxt - try { - nuxt = await this._listenDev(cmd, argv) - } catch (error) { - consola.fatal(error) - return - } - - try { - await this._buildDev(cmd, argv, nuxt) - } catch (error) { - await nuxt.callHook('cli:buildError', error) - consola.error(error) - } - - return nuxt - }, - - async _listenDev (cmd: NuxtCommand, argv: ParsedArgs) { - const config = await cmd.getNuxtConfig({ dev: true, _build: true }) - const nuxt = await cmd.getNuxt(config) - - // Setup hooks - nuxt.hook('watch:restart', payload => this.onWatchRestart(payload, { nuxt, cmd, argv })) - nuxt.hook('bundler:change', changedFileName => this.onBundlerChange(changedFileName)) - - // Wait for nuxt to be ready - await nuxt.ready() - - // Start listening - await nuxt.server.listen() - - // Show banner when listening - showBanner(nuxt, false) - - // Opens the server listeners url in the default browser (only once) - if (argv.open) { - argv.open = false - const openerPromises = nuxt.server.listeners.map(listener => opener(listener.url)) - await Promise.all(openerPromises) - } - - // Return instance - return nuxt - }, - - async _buildDev (cmd: NuxtCommand, _argv: ParsedArgs, nuxt: Nuxt) { - // Create builder instance - const builder = await cmd.getBuilder(nuxt) - - // Start Build - await builder.build() - - // Print memory usage - showMemoryUsage() - - // Display server urls after the build - for (const listener of nuxt.server.listeners) { - consola.info(chalk.bold('Listening on: ') + listener.url) - } - - // Return instance - return nuxt - }, - - logChanged ({ event, path }: { event: keyof typeof eventsMapping, path: string }) { - const { icon, color, action } = eventsMapping[event] || eventsMapping.change - - consola.log({ - type: event, - icon: chalk[color].bold(icon), - message: `${action} ${chalk.cyan(formatPath(path))}` - }) - }, - - async onWatchRestart ({ event, path }, { nuxt, cmd, argv }) { - this.logChanged({ event, path }) - - await nuxt.close() - - await this.startDev(cmd, argv) - }, - - onBundlerChange (path: string) { - this.logChanged({ event: 'change', path }) - } -} diff --git a/packages/nuxt3/src/cli/commands/export.ts b/packages/nuxt3/src/cli/commands/export.ts deleted file mode 100644 index f62083ceb9..0000000000 --- a/packages/nuxt3/src/cli/commands/export.ts +++ /dev/null @@ -1,51 +0,0 @@ -import path from 'path' -import consola from 'consola' -import { TARGETS } from 'src/utils' -import type NuxtCommand from '../command' -import { common, locking } from '../options' -import { createLock } from '../utils' - -export default { - name: 'export', - description: 'Export a static generated web application', - usage: 'export ', - options: { - ...common, - ...locking, - 'fail-on-error': { - type: 'boolean', - default: false, - description: 'Exit with non-zero status code if there are errors when exporting pages' - } - }, - async run (cmd: NuxtCommand) { - const config = await cmd.getNuxtConfig({ - dev: false, - target: TARGETS.static, - _export: true - }) - const nuxt = await cmd.getNuxt(config) - - if (cmd.argv.lock) { - await cmd.setLock(await createLock({ - id: 'export', - dir: nuxt.options.generate.dir, - root: config.rootDir - })) - } - - const generator = await cmd.getGenerator(nuxt) - await nuxt.server.listen(0) - - const { errors } = await generator.generate({ - init: true, - build: false - }) - - await nuxt.close() - if (cmd.argv['fail-on-error'] && errors.length > 0) { - throw new Error('Error exporting pages, exiting with non-zero code') - } - consola.info('Ready to run `nuxt serve` or deploy `' + path.basename(nuxt.options.generate.dir) + '/` directory') - } -} diff --git a/packages/nuxt3/src/cli/commands/generate.ts b/packages/nuxt3/src/cli/commands/generate.ts deleted file mode 100644 index 73ff8b8cd5..0000000000 --- a/packages/nuxt3/src/cli/commands/generate.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { TARGETS } from 'src/utils' -import type { ParsedArgs } from 'minimist' -import type NuxtCommand from '../command' -import { common, locking } from '../options' -import { normalizeArg, createLock } from '../utils' - -export default { - name: 'generate', - description: 'Generate a static web application (server-rendered)', - usage: 'generate ', - options: { - ...common, - ...locking, - build: { - type: 'boolean', - default: true, - description: 'Only generate pages for dynamic routes, used for incremental builds. Generate has to be run once without this option before using it' - }, - devtools: { - type: 'boolean', - default: false, - description: 'Enable Vue devtools', - prepare (_cmd: NuxtCommand, options, argv: ParsedArgs) { - options.vue = options.vue || {} - options.vue.config = options.vue.config || {} - if (argv.devtools) { - options.vue.config.devtools = true - } - } - }, - quiet: { - alias: 'q', - type: 'boolean', - description: 'Disable output except for errors', - prepare (_cmd: NuxtCommand, options, argv: ParsedArgs) { - // Silence output when using --quiet - options.build = options.build || {} - if (argv.quiet) { - options.build.quiet = true - } - } - }, - modern: { - ...common.modern, - description: 'Generate app in modern build (modern mode can be only client)', - prepare (_cmd: NuxtCommand, options, argv: ParsedArgs) { - if (normalizeArg(argv.modern)) { - options.modern = 'client' - } - } - }, - 'fail-on-error': { - type: 'boolean', - default: false, - description: 'Exit with non-zero status code if there are errors when generating pages' - } - }, - async run (cmd: NuxtCommand) { - const config = await cmd.getNuxtConfig({ - dev: false, - _build: cmd.argv.build, - _generate: true - }) - - if (config.target === TARGETS.static) { - throw new Error("Please use `nuxt export` when using `target: 'static'`") - } - - // Forcing static target anyway - config.target = TARGETS.static - - // Disable analyze if set by the nuxt config - config.build = config.build || {} - config.build.analyze = false - - // Set flag to keep the prerendering behaviour - config._legacyGenerate = true - - const nuxt = await cmd.getNuxt(config) - - if (cmd.argv.lock) { - await cmd.setLock(await createLock({ - id: 'build', - dir: nuxt.options.buildDir, - root: config.rootDir - })) - - nuxt.hook('build:done', async () => { - await cmd.releaseLock() - - await cmd.setLock(await createLock({ - id: 'generate', - dir: nuxt.options.generate.dir, - root: config.rootDir - })) - }) - } - - const generator = await cmd.getGenerator(nuxt) - await nuxt.server.listen(0) - - const { errors } = await generator.generate({ - init: true, - build: cmd.argv.build - }) - - await nuxt.close() - if (cmd.argv['fail-on-error'] && errors.length > 0) { - throw new Error('Error generating pages, exiting with non-zero code') - } - } -} diff --git a/packages/nuxt3/src/cli/commands/help.ts b/packages/nuxt3/src/cli/commands/help.ts deleted file mode 100644 index dc7b34bd9a..0000000000 --- a/packages/nuxt3/src/cli/commands/help.ts +++ /dev/null @@ -1,29 +0,0 @@ -import consola from 'consola' -import listCommands from '../list' -import { common } from '../options' -import NuxtCommand from '../command' -import getCommand from '.' - -export default { - name: 'help', - description: 'Shows help for ', - usage: 'help ', - options: { - help: common.help, - version: common.version - }, - async run (cmd: NuxtCommand) { - const [name] = cmd._argv - if (!name) { - return listCommands() - } - const command = await getCommand(name) - - if (!command) { - consola.info(`Unknown command: ${name}`) - return - } - - NuxtCommand.from(command).showHelp() - } -} diff --git a/packages/nuxt3/src/cli/commands/index.ts b/packages/nuxt3/src/cli/commands/index.ts deleted file mode 100644 index 52f282992b..0000000000 --- a/packages/nuxt3/src/cli/commands/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -const _commands = { - start: () => import('./start'), - serve: () => import('./serve'), - dev: () => import('./dev'), - build: () => import('./build'), - generate: () => import('./generate'), - export: () => import('./export'), - webpack: () => import('./webpack'), - help: () => import('./help') -} - -export default function getCommand (name: keyof typeof _commands) { - if (!_commands[name]) { - return Promise.resolve(null) - } - return _commands[name]().then(m => m.default) -} diff --git a/packages/nuxt3/src/cli/commands/serve.ts b/packages/nuxt3/src/cli/commands/serve.ts deleted file mode 100644 index 487b3d316c..0000000000 --- a/packages/nuxt3/src/cli/commands/serve.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { promises as fs } from 'fs' -import { join, extname, basename } from 'path' -import express from 'express' -import serveStatic from 'serve-static' -import compression from 'compression' -import { getNuxtConfig } from 'src/config' -import { TARGETS } from 'src/utils' -import { Listener } from 'src/server' -import { Nuxt } from 'src/core' -import { common, server } from '../options' -import { showBanner } from '../utils/banner' -import type NuxtCommand from '../command' - -export default { - name: 'serve', - description: 'Serve the exported static application (should be compiled with `nuxt build` and `nuxt export` first)', - usage: 'serve ', - options: { - 'config-file': common['config-file'], - version: common.version, - help: common.help, - ...server - }, - async run (cmd: NuxtCommand) { - let options = await cmd.getNuxtConfig({ dev: false }) - // add default options - options = getNuxtConfig(options) - try { - // overwrites with build config - const buildConfig = require(join(options.buildDir, 'nuxt/config.json')) - options.target = buildConfig.target - } catch (err) {} - - if (options.target === TARGETS.server) { - throw new Error('You cannot use `nuxt serve` with ' + TARGETS.server + ' target, please use `nuxt start`') - } - const distStat = await fs.stat(options.generate.dir).catch(_err => null) // eslint-disable-line handle-callback-err - if (!distStat || !distStat.isDirectory()) { - throw new Error('Output directory `' + basename(options.generate.dir) + '/` does not exists, please run `nuxt export` before `nuxt serve`.') - } - const app = express() - app.use(compression({ threshold: 0 })) - app.use( - options.router.base, - serveStatic(options.generate.dir, { - extensions: ['html'] - }) - ) - if (options.generate.fallback) { - const fallbackFile = await fs.readFile(join(options.generate.dir, options.generate.fallback), 'utf-8') - app.use((req, res, next) => { - const ext = extname(req.url) || '.html' - - if (ext !== '.html') { - return next() - } - res.writeHeader(200, { - 'Content-Type': 'text/html' - }) - res.write(fallbackFile) - res.end() - }) - } - - const { port, host, socket, https } = options.server - const listener = new Listener({ - port, - host, - socket, - https, - app, - dev: true, // try another port if taken - baseURL: options.router.base - }) - await listener.listen() - showBanner({ - constructor: Nuxt, - options, - server: { - listeners: [listener] - } - }, false) - } -} diff --git a/packages/nuxt3/src/cli/commands/start.ts b/packages/nuxt3/src/cli/commands/start.ts deleted file mode 100644 index 8ba810797a..0000000000 --- a/packages/nuxt3/src/cli/commands/start.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { TARGETS } from 'src/utils' - -import type NuxtCommand from '../command' -import { common, server } from '../options' -import { showBanner } from '../utils/banner' - -export default { - name: 'start', - description: 'Start the application in production mode (the application should be compiled with `nuxt build` first)', - usage: 'start ', - options: { - ...common, - ...server - }, - async run (cmd: NuxtCommand) { - const config = await cmd.getNuxtConfig({ dev: false, _start: true }) - if (config.target === TARGETS.static) { - throw new Error('You cannot use `nuxt start` with ' + TARGETS.static + ' target, please use `nuxt export` and `nuxt serve`') - } - const nuxt = await cmd.getNuxt(config) - - // Listen and show ready banner - await nuxt.server.listen() - showBanner(nuxt) - } -} diff --git a/packages/nuxt3/src/cli/commands/webpack.ts b/packages/nuxt3/src/cli/commands/webpack.ts deleted file mode 100644 index d57e4fefb6..0000000000 --- a/packages/nuxt3/src/cli/commands/webpack.ts +++ /dev/null @@ -1,118 +0,0 @@ -import util from 'util' -import consola from 'consola' -import get from 'lodash/get' - -import type NuxtCommand from '../command' -import { common } from '../options' - -export default { - name: 'webpack', - description: 'Inspect Nuxt webpack config', - usage: 'webpack [query...]', - options: { - ...common, - name: { - alias: 'n', - type: 'string', - default: 'client', - description: 'Webpack bundle name: server, client, modern' - }, - depth: { - alias: 'd', - type: 'string', - default: 2, - description: 'Inspection depth' - }, - colors: { - type: 'boolean', - default: process.stdout.isTTY, - description: 'Output with ANSI colors' - }, - dev: { - type: 'boolean', - default: false, - description: 'Inspect development mode webpack config' - } - }, - async run (cmd: NuxtCommand) { - const { name } = cmd.argv - const queries = [...cmd.argv._] - - const config = await cmd.getNuxtConfig({ dev: cmd.argv.dev, server: false }) - const nuxt = await cmd.getNuxt(config) - const builder = await cmd.getBuilder(nuxt) - const { bundleBuilder } = builder - const webpackConfig = bundleBuilder.getWebpackConfig(name) - - let queryError - const match = queries.reduce((result, query) => { - const m = advancedGet(result, query) - if (m === undefined) { - queryError = query - return result - } - return m - }, webpackConfig) - - const serialized = formatObj(match, { - depth: parseInt(cmd.argv.depth), - colors: cmd.argv.colors - }) - - consola.log(serialized + '\n') - - if (serialized.includes('[Object]' || serialized.includes('[Array'))) { - consola.info('You can use `--depth` or add more queries to inspect `[Object]` and `[Array]` fields.') - } - - if (queryError) { - consola.warn(`No match in webpack config for \`${queryError}\``) - } - } -} - -function advancedGet (obj = {}, query = '') { - let result = obj - - if (!query || !result) { - return result - } - - const [l, r] = query.split('=') - - if (!Array.isArray(result)) { - return typeof result === 'object' ? get(result, l) : result - } - - result = result.filter((i) => { - const v = get(i, l) - - if (!v) { - return false - } - - if ( - (v === r) || - (typeof v.test === 'function' && v.test(r)) || - (typeof v.match === 'function' && v.match(r)) || - (r && r.match(v)) - ) { - return true - } - - return false - }) - - if (result.length === 1) { - return result[0] - } - - return result.length ? result : undefined -} - -function formatObj (obj, formatOptions) { - if (!util.formatWithOptions) { - return util.format(obj) - } - return util.formatWithOptions(formatOptions, obj) -} diff --git a/packages/nuxt3/src/cli/index.ts b/packages/nuxt3/src/cli/index.ts deleted file mode 100644 index 7c8d3d81b1..0000000000 --- a/packages/nuxt3/src/cli/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as commands from './commands' -import * as options from './options' - -export { - commands, - options -} - -export { default as NuxtCommand } from './command' -export { default as setup } from './setup' -export { default as run } from './run' -export { loadNuxtConfig } from './utils/config' -export { getWebpackConfig } from './utils/webpack' diff --git a/packages/nuxt3/src/cli/list.ts b/packages/nuxt3/src/cli/list.ts deleted file mode 100644 index ca31a82df4..0000000000 --- a/packages/nuxt3/src/cli/list.ts +++ /dev/null @@ -1,35 +0,0 @@ -import chalk from 'chalk' -import { indent, foldLines, colorize } from './utils/formatting' -import { startSpaces, optionSpaces } from './utils/constants' -import getCommand from './commands' - -export default async function listCommands () { - const commandsOrder = ['dev', 'build', 'generate', 'start', 'help'] as const - - // Load all commands - const _commands = await Promise.all( - commandsOrder.map(cmd => getCommand(cmd)) - ) - - let maxLength = 0 - const commandsHelp = [] - - for (const command of _commands) { - commandsHelp.push([command.usage, command.description]) - maxLength = Math.max(maxLength, command.usage.length) - } - - const _cmds = commandsHelp.map(([cmd, description]) => { - const i = indent(maxLength + optionSpaces - cmd.length) - return foldLines( - chalk.green(cmd) + i + description, - startSpaces + maxLength + optionSpaces * 2, - startSpaces + optionSpaces - ) - }).join('\n') - - const usage = foldLines('Usage: nuxt [--help|-h]', startSpaces) - const cmds = foldLines('Commands:', startSpaces) + '\n\n' + _cmds - - process.stderr.write(colorize(`${usage}\n\n${cmds}\n\n`)) -} diff --git a/packages/nuxt3/src/cli/options/common.ts b/packages/nuxt3/src/cli/options/common.ts deleted file mode 100644 index 4a64ad8d0c..0000000000 --- a/packages/nuxt3/src/cli/options/common.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { defaultNuxtConfigFile } from 'src/config' -import { normalizeArg } from '../utils' - -export default { - spa: { - alias: 's', - type: 'boolean', - description: 'Launch in SPA mode' - }, - universal: { - alias: 'u', - type: 'boolean', - description: 'Launch in Universal mode (default)' - }, - 'config-file': { - alias: 'c', - type: 'string', - default: defaultNuxtConfigFile, - description: `Path to Nuxt.js config file (default: \`${defaultNuxtConfigFile}\`)` - }, - modern: { - alias: 'm', - type: 'string', - description: 'Build/Start app for modern browsers, e.g. server, client and false', - prepare (_cmd, options, argv) { - if (argv.modern !== undefined) { - options.modern = normalizeArg(argv.modern) - } - } - }, - target: { - alias: 't', - type: 'string', - description: 'Build/start app for a different target, e.g. server, serverless and static', - prepare (_cmd, options, argv) { - if (argv.target) { - options.target = argv.target - } - } - }, - 'force-exit': { - type: 'boolean', - default (cmd) { - return ['build', 'generate', 'export'].includes(cmd.name) - }, - description: 'Whether Nuxt.js should force exit after the command has finished' - }, - version: { - alias: 'v', - type: 'boolean', - description: 'Display the Nuxt version' - }, - help: { - alias: 'h', - type: 'boolean', - description: 'Display this message' - }, - processenv: { - type: 'boolean', - default: true, - description: 'Disable reading from `process.env` and updating it with dotenv' - }, - dotenv: { - type: 'string', - default: '.env', - description: 'Specify path to dotenv file (default: `.env`). Use `false` to disable' - } -} diff --git a/packages/nuxt3/src/cli/options/index.ts b/packages/nuxt3/src/cli/options/index.ts deleted file mode 100644 index 1d2420967e..0000000000 --- a/packages/nuxt3/src/cli/options/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import common from './common' -import server from './server' -import locking from './locking' - -export { - common, - server, - locking -} diff --git a/packages/nuxt3/src/cli/options/locking.ts b/packages/nuxt3/src/cli/options/locking.ts deleted file mode 100644 index 28035510ae..0000000000 --- a/packages/nuxt3/src/cli/options/locking.ts +++ /dev/null @@ -1,7 +0,0 @@ -export default { - lock: { - type: 'boolean', - default: true, - description: 'Do not set a lock on the project when building' - } -} diff --git a/packages/nuxt3/src/cli/options/server.ts b/packages/nuxt3/src/cli/options/server.ts deleted file mode 100644 index 9b5369afab..0000000000 --- a/packages/nuxt3/src/cli/options/server.ts +++ /dev/null @@ -1,34 +0,0 @@ -import consola from 'consola' -import type { ParsedArgs } from 'minimist' - -import { Configuration } from 'src/config/options' - -import NuxtCommand from '../command' - -export default { - port: { - alias: 'p', - type: 'string', - description: 'Port number on which to start the application', - prepare (_cmd: NuxtCommand, options: Configuration, argv: ParsedArgs) { - if (argv.port) { - options.server.port = +argv.port - } - } - }, - hostname: { - alias: 'H', - type: 'string', - description: 'Hostname on which to start the application', - prepare (_cmd: NuxtCommand, _options: any, argv: ParsedArgs) { - if (argv.hostname === '') { - consola.fatal('Provided hostname argument has no value') - } - } - }, - 'unix-socket': { - alias: 'n', - type: 'string', - description: 'Path to a UNIX socket' - } -} diff --git a/packages/nuxt3/src/cli/run.ts b/packages/nuxt3/src/cli/run.ts deleted file mode 100644 index 3d64fdd94e..0000000000 --- a/packages/nuxt3/src/cli/run.ts +++ /dev/null @@ -1,60 +0,0 @@ -import fs from 'fs' -import execa from 'execa' -import { name as pkgName } from '../../package.json' -import NuxtCommand from './command' -import setup from './setup' -import getCommand from './commands' - -function packageExists (name: string) { - try { - require.resolve(name) - return true - } catch (e) { - return false - } -} - -export default async function run (_argv: NodeJS.Process['argv'], hooks = {}) { - // Check for not installing both nuxt and nuxt-edge - const dupPkg = '@nuxt/' + (pkgName === '@nuxt/cli-edge' ? 'cli' : 'cli-edge') - if (packageExists(dupPkg)) { - throw new Error('Both `nuxt` and `nuxt-edge` dependencies are installed! This is unsupported, please choose one and remove the other one from dependencies.') - } - - // Read from process.argv - const argv = _argv ? Array.from(_argv) : process.argv.slice(2) - - // Check for internal command - let cmd = await getCommand(argv[0] as any) - - // Matching `nuxt` or `nuxt [dir]` or `nuxt -*` for `nuxt dev` shortcut - if (!cmd && (!argv[0] || argv[0][0] === '-' || (argv[0] !== 'static' && fs.existsSync(argv[0])))) { - argv.unshift('dev') - cmd = await getCommand('dev') - } - - // Check for dev - const dev = argv[0] === 'dev' - - // Setup env - setup({ dev }) - - // Try internal command - if (cmd) { - return NuxtCommand.run(cmd, argv.slice(1), hooks) - } - - // Try external command - try { - await execa(`nuxt-${argv[0]}`, argv.slice(1), { - stdout: process.stdout, - stderr: process.stderr, - stdin: process.stdin - }) - } catch (error) { - if (error.exitCode === 2) { - throw String(`Command not found: nuxt-${argv[0]}`) - } - throw String(`Failed to run command \`nuxt-${argv[0]}\`:\n${error}`) - } -} diff --git a/packages/nuxt3/src/cli/setup.ts b/packages/nuxt3/src/cli/setup.ts deleted file mode 100644 index e42ab55a61..0000000000 --- a/packages/nuxt3/src/cli/setup.ts +++ /dev/null @@ -1,38 +0,0 @@ -import consola from 'consola' -import exit from 'exit' -import { fatalBox } from './utils/formatting' - -let _setup = false - -export default function setup ({ dev }: { dev: boolean }) { - // Apply default NODE_ENV if not provided - if (!process.env.NODE_ENV) { - process.env.NODE_ENV = dev ? 'development' : 'production' - } - - if (_setup) { - return - } - _setup = true - - // Global error handler - /* istanbul ignore next */ - process.on('unhandledRejection', (err) => { - consola.error(err) - }) - - // Exit process on fatal errors - /* istanbul ignore next */ - consola.addReporter({ - log (logObj) { - if (logObj.type === 'fatal') { - const errorMessage = String(logObj.args[0]) - process.stderr.write(fatalBox(errorMessage)) - exit(1) - } - } - }) - - // Wrap all console logs with consola for better DX - consola.wrapConsole() -} diff --git a/packages/nuxt3/src/cli/utils/banner.ts b/packages/nuxt3/src/cli/utils/banner.ts deleted file mode 100644 index 1e96edb4cd..0000000000 --- a/packages/nuxt3/src/cli/utils/banner.ts +++ /dev/null @@ -1,62 +0,0 @@ -import consola from 'consola' -import env from 'std-env' -import chalk from 'chalk' - -import { Nuxt } from 'src/core' -import { successBox } from './formatting' -import { getFormattedMemoryUsage } from './memory' - -export function showBanner (nuxt: Nuxt, showMemoryUsage = true) { - if (env.test) { - return - } - - if (env.minimalCLI) { - for (const listener of nuxt.server.listeners) { - consola.info('Listening on: ' + listener.url) - } - return - } - - const titleLines = [] - const messageLines = [] - - // Name and version - const { bannerColor, badgeMessages } = nuxt.options.cli - titleLines.push(`${chalk[bannerColor].bold('Nuxt.js')} @ ${nuxt.constructor.version || 'exotic'}\n`) - - const label = (name: string) => chalk.bold.cyan(`▸ ${name}:`) - - // Environment - const isDev = nuxt.options.dev - let _env = isDev ? 'development' : 'production' - if (process.env.NODE_ENV !== _env) { - _env += ` (${chalk.cyan(process.env.NODE_ENV)})` - } - titleLines.push(`${label('Environment')} ${_env}`) - - // Rendering - const isSSR = nuxt.options.render.ssr - const rendering = isSSR ? 'server-side' : 'client-side' - titleLines.push(`${label('Rendering')} ${rendering}`) - - // Target - const target = nuxt.options.target || 'server' - titleLines.push(`${label('Target')} ${target}`) - - if (showMemoryUsage) { - titleLines.push('\n' + getFormattedMemoryUsage()) - } - - // Listeners - for (const listener of nuxt.server.listeners) { - messageLines.push(chalk.bold('Listening: ') + chalk.underline.blue(listener.url)) - } - - // Add custom badge messages - if (badgeMessages.length) { - messageLines.push('', ...badgeMessages) - } - - process.stdout.write(successBox(messageLines.join('\n'), titleLines.join('\n'))) -} diff --git a/packages/nuxt3/src/cli/utils/config.ts b/packages/nuxt3/src/cli/utils/config.ts deleted file mode 100644 index 04dccfa8fb..0000000000 --- a/packages/nuxt3/src/cli/utils/config.ts +++ /dev/null @@ -1,34 +0,0 @@ -import path from 'path' -import defaultsDeep from 'lodash/defaultsDeep' -import { loadNuxtConfig as _loadNuxtConfig, getDefaultNuxtConfig } from 'src/config' -import { MODES } from 'src/utils' -import type { ParsedArgs } from 'minimist' - -export async function loadNuxtConfig (argv: ParsedArgs, configContext) { - const rootDir = path.resolve(argv._[0] || '.') - const configFile = argv['config-file'] - - // Load config - const options = await _loadNuxtConfig({ - rootDir, - configFile, - configContext, - envConfig: { - dotenv: argv.dotenv === 'false' ? false : argv.dotenv, - env: argv.processenv ? process.env : {} - } - }) - - // Nuxt Mode - options.mode = - (argv.spa && MODES.spa) || (argv.universal && MODES.universal) || options.mode - - // Server options - options.server = defaultsDeep({ - port: argv.port || undefined, - host: argv.hostname || undefined, - socket: argv['unix-socket'] || undefined - }, options.server || {}, getDefaultNuxtConfig().server) - - return options -} diff --git a/packages/nuxt3/src/cli/utils/constants.ts b/packages/nuxt3/src/cli/utils/constants.ts deleted file mode 100644 index 4bd9089e8c..0000000000 --- a/packages/nuxt3/src/cli/utils/constants.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const forceExitTimeout = 5 - -export const startSpaces = 2 -export const optionSpaces = 2 - -// 80% of terminal column width -// this is a fn because console width can have changed since startup -export const maxCharsPerLine = () => (process.stdout.columns || 100) * 80 / 100 diff --git a/packages/nuxt3/src/cli/utils/formatting.ts b/packages/nuxt3/src/cli/utils/formatting.ts deleted file mode 100644 index d91cdf0c61..0000000000 --- a/packages/nuxt3/src/cli/utils/formatting.ts +++ /dev/null @@ -1,69 +0,0 @@ -import wrapAnsi from 'wrap-ansi' -import chalk from 'chalk' -import boxen from 'boxen' -import { maxCharsPerLine } from './constants' - -export function indent (count: number, chr = ' ') { - return chr.repeat(count) -} - -export function indentLines (string: string | string[], spaces: number, firstLineSpaces?: number) { - const lines = Array.isArray(string) ? string : string.split('\n') - let s = '' - if (lines.length) { - const i0 = indent(firstLineSpaces === undefined ? spaces : firstLineSpaces) - s = i0 + lines.shift() - } - if (lines.length) { - const i = indent(spaces) - s += '\n' + lines.map(l => i + l).join('\n') - } - return s -} - -export function foldLines (string: string, spaces: number, firstLineSpaces?: number, charsPerLine = maxCharsPerLine()) { - return indentLines(wrapAnsi(string, charsPerLine), spaces, firstLineSpaces) -} - -export function colorize (text: string) { - return text - .replace(/\[[^ ]+]/g, m => chalk.grey(m)) - .replace(/<[^ ]+>/g, m => chalk.green(m)) - .replace(/ (-[-\w,]+)/g, m => chalk.bold(m)) - .replace(/`([^`]+)`/g, (_, m) => chalk.bold.cyan(m)) -} - -export function box (message: string, title: string, options?: boxen.Options) { - return boxen([ - title || chalk.white('Nuxt Message'), - '', - chalk.white(foldLines(message, 0, 0, maxCharsPerLine())) - ].join('\n'), Object.assign({ - borderColor: 'white', - borderStyle: 'round', - padding: 1, - margin: 1 - }, options)) + '\n' -} - -export function successBox (message: string, title?: string) { - return box(message, title || chalk.green('✔ Nuxt Success'), { - borderColor: 'green' - }) -} - -export function warningBox (message: string, title?: string) { - return box(message, title || chalk.yellow('⚠ Nuxt Warning'), { - borderColor: 'yellow' - }) -} - -export function errorBox (message: string, title?: string) { - return box(message, title || chalk.red('✖ Nuxt Error'), { - borderColor: 'red' - }) -} - -export function fatalBox (message: string, title?: string) { - return errorBox(message, title || chalk.red('✖ Nuxt Fatal Error')) -} diff --git a/packages/nuxt3/src/cli/utils/index.ts b/packages/nuxt3/src/cli/utils/index.ts deleted file mode 100644 index 72d6a4de93..0000000000 --- a/packages/nuxt3/src/cli/utils/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -import path from 'path' -import exit from 'exit' - -import { lock } from 'src/utils' -import chalk from 'chalk' -import env from 'std-env' -import { warningBox } from './formatting' - -export const eventsMapping = { - add: { icon: '+', color: 'green', action: 'Created' }, - change: { icon: env.windows ? '»' : '↻', color: 'blue', action: 'Updated' }, - unlink: { icon: '-', color: 'red', action: 'Removed' } -} - -export function formatPath (filePath: string) { - if (!filePath) { - return - } - return filePath.replace(process.cwd() + path.sep, '') -} - -/** - * Normalize string argument in command - * - * @export - * @param {String} argument - * @param {*} defaultValue - * @returns formatted argument - */ -export function normalizeArg (arg: boolean | 'true' | '' | 'false', defaultValue?: boolean) { - switch (arg) { - case 'true': arg = true; break - case '': arg = true; break - case 'false': arg = false; break - case undefined: arg = defaultValue; break - } - return arg -} - -export function forceExit (cmdName: string, timeout: number | false) { - if (timeout !== false) { - const exitTimeout = setTimeout(() => { - const msg = `The command 'nuxt ${cmdName}' finished but did not exit after ${timeout}s -This is most likely not caused by a bug in Nuxt.js -Make sure to cleanup all timers and listeners you or your plugins/modules start. -Nuxt.js will now force exit - -${chalk.bold('DeprecationWarning: Starting with Nuxt version 3 this will be a fatal error')}` - - // TODO: Change this to a fatal error in v3 - process.stderr.write(warningBox(msg)) - exit(0) - }, timeout * 1000) - exitTimeout.unref() - } else { - exit(0) - } -} - -// An immediate export throws an error when mocking with jest -// TypeError: Cannot set property createLock of # which has only a getter -export function createLock (...args: Parameters) { - return lock(...args) -} diff --git a/packages/nuxt3/src/cli/utils/memory.ts b/packages/nuxt3/src/cli/utils/memory.ts deleted file mode 100644 index 3071e59f7a..0000000000 --- a/packages/nuxt3/src/cli/utils/memory.ts +++ /dev/null @@ -1,18 +0,0 @@ -import chalk from 'chalk' -import consola from 'consola' -import prettyBytes from 'pretty-bytes' - -export function getMemoryUsage () { - // https://nodejs.org/api/process.html#process_process_memoryusage - const { heapUsed, rss } = process.memoryUsage() - return { heap: heapUsed, rss } -} - -export function getFormattedMemoryUsage () { - const { heap, rss } = getMemoryUsage() - return `Memory usage: ${chalk.bold(prettyBytes(heap))} (RSS: ${prettyBytes(rss)})` -} - -export function showMemoryUsage () { - consola.info(getFormattedMemoryUsage()) -} diff --git a/packages/nuxt3/src/cli/utils/webpack.ts b/packages/nuxt3/src/cli/utils/webpack.ts deleted file mode 100644 index ae0f0eff08..0000000000 --- a/packages/nuxt3/src/cli/utils/webpack.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { loadNuxt } from 'src/core' -import { getBuilder } from 'src/builder' - -export async function getWebpackConfig (name = 'client', loadOptions = {}) { - const nuxt = await loadNuxt(loadOptions) - const builder = await getBuilder(nuxt) - const { bundleBuilder } = builder - return bundleBuilder.getWebpackConfig(name) -}