rsnext/packages/next/bin/next.ts
Balázs Orbán 3ad2035ae6
feat(cli): introduce next info CLI command (#32972)
This PR adds a new command to the `next` CLI.

Running `next info` will print useful information to the terminal about how/where Next.js is run. This information can be added to the Bug report when opening an issue in the repository.

This makes reporting issues more accurate and doesn't require the user to guess certain details, the command will retrieve it on their behalf.

Example output:

```sh
$ npx --no-install next info

    Operating System:
      Platform: linux
      Version: #22-Ubuntu SMP Fri Nov 5 13:21:36 UTC 2021
    Binaries:
      Node: 16.13.0
      npm: 8.1.0
      Yarn: 1.22.17
      pnpm: 6.24.2
    Relevant packages:
      next: 12.0.8-canary.14
      react: 17.0.2
      react-dom: 17.0.2


```

The idea is based on #32858

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [x] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`


Co-authored-by: Steven <229881+styfle@users.noreply.github.com>
2022-01-04 15:35:32 +00:00

135 lines
4 KiB
JavaScript
Executable file

#!/usr/bin/env node
import * as log from '../build/output/log'
import arg from 'next/dist/compiled/arg/index.js'
import { NON_STANDARD_NODE_ENV } from '../lib/constants'
;['react', 'react-dom'].forEach((dependency) => {
try {
// When 'npm link' is used it checks the clone location. Not the project.
require.resolve(dependency)
} catch (err) {
console.warn(
`The module '${dependency}' was not found. Next.js requires that you include it in 'dependencies' of your 'package.json'. To add it, run 'npm install ${dependency}'`
)
}
})
const defaultCommand = 'dev'
export type cliCommand = (argv?: string[]) => void
const commands: { [command: string]: () => Promise<cliCommand> } = {
build: () => Promise.resolve(require('../cli/next-build').nextBuild),
start: () => Promise.resolve(require('../cli/next-start').nextStart),
export: () => Promise.resolve(require('../cli/next-export').nextExport),
dev: () => Promise.resolve(require('../cli/next-dev').nextDev),
lint: () => Promise.resolve(require('../cli/next-lint').nextLint),
telemetry: () =>
Promise.resolve(require('../cli/next-telemetry').nextTelemetry),
info: () => Promise.resolve(require('../cli/next-info').nextInfo),
}
const args = arg(
{
// Types
'--version': Boolean,
'--help': Boolean,
'--inspect': Boolean,
// Aliases
'-v': '--version',
'-h': '--help',
},
{
permissive: true,
}
)
// Version is inlined into the file using taskr build pipeline
if (args['--version']) {
console.log(`Next.js v${process.env.__NEXT_VERSION}`)
process.exit(0)
}
// Check if we are running `next <subcommand>` or `next`
const foundCommand = Boolean(commands[args._[0]])
// Makes sure the `next --help` case is covered
// This help message is only showed for `next --help`
// `next <subcommand> --help` falls through to be handled later
if (!foundCommand && args['--help']) {
console.log(`
Usage
$ next <command>
Available commands
${Object.keys(commands).join(', ')}
Options
--version, -v Version number
--help, -h Displays this message
For more information run a command with the --help flag
$ next build --help
`)
process.exit(0)
}
const command = foundCommand ? args._[0] : defaultCommand
const forwardedArgs = foundCommand ? args._.slice(1) : args._
if (args['--inspect'])
throw new Error(
`--inspect flag is deprecated. Use env variable NODE_OPTIONS instead: NODE_OPTIONS='--inspect' next ${command}`
)
// Make sure the `next <subcommand> --help` case is covered
if (args['--help']) {
forwardedArgs.push('--help')
}
const defaultEnv = command === 'dev' ? 'development' : 'production'
const standardEnv = ['production', 'development', 'test']
if (process.env.NODE_ENV) {
const isNotStandard = !standardEnv.includes(process.env.NODE_ENV)
const shouldWarnCommands =
process.env.NODE_ENV === 'development'
? ['start', 'build']
: process.env.NODE_ENV === 'production'
? ['dev']
: []
if (isNotStandard || shouldWarnCommands.includes(command)) {
log.warn(NON_STANDARD_NODE_ENV)
}
}
;(process.env as any).NODE_ENV = process.env.NODE_ENV || defaultEnv
// Make sure commands gracefully respect termination signals (e.g. from Docker)
process.on('SIGTERM', () => process.exit(0))
process.on('SIGINT', () => process.exit(0))
commands[command]()
.then((exec) => exec(forwardedArgs))
.then(() => {
if (command === 'build') {
// ensure process exits after build completes so open handles/connections
// don't cause process to hang
process.exit(0)
}
})
if (command === 'dev') {
const { CONFIG_FILES } = require('../shared/lib/constants')
const { watchFile } = require('fs')
for (const CONFIG_FILE of CONFIG_FILES) {
watchFile(`${process.cwd()}/${CONFIG_FILE}`, (cur: any, prev: any) => {
if (cur.size > 0 || prev.size > 0) {
console.log(
`\n> Found a change in ${CONFIG_FILE}. Restart the server to see the changes in effect.`
)
}
})
}
}