Skip to content

Commit

Permalink
Add --yes option to create-next-app
Browse files Browse the repository at this point in the history
This is a small improvement for power users that run `create-next-app`
frequently, using the same preferences. By specifying the `--yes` option
along with the project name, they won't be prompted for any preferences.
Instead, the previously used preferences are automatically chosen, using
the defaults as fallback.
  • Loading branch information
unstubbable committed Jul 25, 2024
1 parent eba4b31 commit 39e90ce
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 23 deletions.
17 changes: 11 additions & 6 deletions docs/02-app/02-api-reference/06-create-next-app.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -95,24 +95,24 @@ Options:

--use-npm

Explicitly tell the CLI to bootstrap the app using npm
Explicitly tell the CLI to bootstrap the application using npm

--use-pnpm

Explicitly tell the CLI to bootstrap the app using pnpm
Explicitly tell the CLI to bootstrap the application using pnpm

--use-yarn

Explicitly tell the CLI to bootstrap the app using Yarn
Explicitly tell the CLI to bootstrap the application using Yarn

--use-bun

Explicitly tell the CLI to bootstrap the app using Bun
Explicitly tell the CLI to bootstrap the application using Bun

-e, --example [name]|[github-url]

An example to bootstrap the app with. You can use an example name
from the official Next.js repo or a public GitHub URL. The URL can use
from the official Next.js repo or a GitHub URL. The URL can use
any branch and/or subdirectory

--example-path <path-to-example>
Expand All @@ -130,7 +130,12 @@ Options:

Explicitly tell the CLI to skip installing packages

-h, --help output usage information
--yes

Use previous preferences or defaults for all options that were not
explicitly specified, without prompting.

-h, --help display help for command
```

### Why use Create Next App?
Expand Down
27 changes: 20 additions & 7 deletions packages/create-next-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ You can also pass command line arguments to set up a new project
non-interactively. See `create-next-app --help`:

```bash
Usage: create-next-app <project-directory> [options]
Usage: create-next-app [project-directory] [options]

Options:
-V, --version output the version number
Expand Down Expand Up @@ -67,26 +67,30 @@ Options:

Specify import alias to use (default "@/*").

--empty

Initialize an empty project.

--use-npm

Explicitly tell the CLI to bootstrap the app using npm
Explicitly tell the CLI to bootstrap the application using npm

--use-pnpm

Explicitly tell the CLI to bootstrap the app using pnpm
Explicitly tell the CLI to bootstrap the application using pnpm

--use-yarn

Explicitly tell the CLI to bootstrap the app using Yarn
Explicitly tell the CLI to bootstrap the application using Yarn

--use-bun

Explicitly tell the CLI to bootstrap the app using Bun
Explicitly tell the CLI to bootstrap the application using Bun

-e, --example [name]|[github-url]

An example to bootstrap the app with. You can use an example name
from the official Next.js repo or a public GitHub URL. The URL can use
from the official Next.js repo or a GitHub URL. The URL can use
any branch and/or subdirectory

--example-path <path-to-example>
Expand All @@ -100,7 +104,16 @@ Options:

Explicitly tell the CLI to reset any stored preferences

-h, --help output usage information
--skip-install

Explicitly tell the CLI to skip installing packages

--yes

Use previous preferences or defaults for all options that were not
explicitly specified, without prompting.

-h, --help display help for command
```

### Why use Create Next App?
Expand Down
32 changes: 22 additions & 10 deletions packages/create-next-app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const program = new Command(packageJson.name)
'--eslint',
`
Initialize with eslint config.
Initialize with ESLint config.
`
)
.option(
Expand Down Expand Up @@ -170,6 +170,14 @@ const program = new Command(packageJson.name)
`
Explicitly tell the CLI to skip installing packages
`
)
.option(
'--yes',
`
Use previous preferences or defaults for all options that were not
explicitly specified, without prompting.
`
)
.allowUnknownOption()
Expand Down Expand Up @@ -271,10 +279,13 @@ async function run(): Promise<void> {
string,
boolean | string
>

/**
* If the user does not provide the necessary flags, prompt them for whether
* to use TS or JS.
* If the user does not provide the necessary flags, prompt them for their
* preferences, unless `--yes` option was specified, or when running in CI.
*/
const skipPrompt = ciInfo.isCI || program.yes

if (!example) {
const defaults: typeof preferences = {
typescript: true,
Expand All @@ -291,7 +302,7 @@ async function run(): Promise<void> {
preferences[field] ?? defaults[field]

if (!program.typescript && !program.javascript) {
if (ciInfo.isCI) {
if (skipPrompt) {
// default to TypeScript in CI as we can't prompt to
// prevent breaking setup flows
program.typescript = getPrefOrDefault('typescript')
Expand Down Expand Up @@ -330,7 +341,7 @@ async function run(): Promise<void> {
!process.argv.includes('--eslint') &&
!process.argv.includes('--no-eslint')
) {
if (ciInfo.isCI) {
if (skipPrompt) {
program.eslint = getPrefOrDefault('eslint')
} else {
const styledEslint = blue('ESLint')
Expand All @@ -352,7 +363,7 @@ async function run(): Promise<void> {
!process.argv.includes('--tailwind') &&
!process.argv.includes('--no-tailwind')
) {
if (ciInfo.isCI) {
if (skipPrompt) {
program.tailwind = getPrefOrDefault('tailwind')
} else {
const tw = blue('Tailwind CSS')
Expand All @@ -374,7 +385,7 @@ async function run(): Promise<void> {
!process.argv.includes('--src-dir') &&
!process.argv.includes('--no-src-dir')
) {
if (ciInfo.isCI) {
if (skipPrompt) {
program.srcDir = getPrefOrDefault('srcDir')
} else {
const styledSrcDir = blue('`src/` directory')
Expand All @@ -393,7 +404,7 @@ async function run(): Promise<void> {
}

if (!process.argv.includes('--app') && !process.argv.includes('--no-app')) {
if (ciInfo.isCI) {
if (skipPrompt) {
program.app = getPrefOrDefault('app')
} else {
const styledAppDir = blue('App Router')
Expand All @@ -407,11 +418,12 @@ async function run(): Promise<void> {
inactive: 'No',
})
program.app = Boolean(appRouter)
preferences.app = Boolean(appRouter)
}
}

if (!program.turbo && !process.argv.includes('--no-turbo')) {
if (ciInfo.isCI) {
if (skipPrompt) {
program.turbo = getPrefOrDefault('turbo')
} else {
const styledTurbo = blue('Turbopack')
Expand All @@ -434,7 +446,7 @@ async function run(): Promise<void> {
typeof program.importAlias !== 'string' ||
!importAliasPattern.test(program.importAlias)
) {
if (ciInfo.isCI) {
if (skipPrompt) {
// We don't use preferences here because the default value is @/* regardless of existing preferences
program.importAlias = defaults.importAlias
} else if (process.argv.includes('--no-import-alias')) {
Expand Down
42 changes: 42 additions & 0 deletions test/integration/create-next-app/prompts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,46 @@ describe('create-next-app prompts', () => {
`)
})
})

it('should not prompt user for choice and use defaults if --yes is defined', async () => {
await useTempDir(async (cwd) => {
const projectName = 'yes-we-can'
const childProcess = createNextApp(
[projectName, '--yes'],
{
cwd,
},
nextTgzFilename
)

await new Promise<void>((resolve) => {
childProcess.on('exit', async (exitCode) => {
expect(exitCode).toBe(0)
projectFilesShouldExist({
cwd,
projectName,
files: [
'app',
'.eslintrc.json',
'package.json',
'tailwind.config.ts',
'tsconfig.json',
],
})
resolve()
})
})

const pkg = require(join(cwd, projectName, 'package.json'))
expect(pkg.name).toBe(projectName)
const tsConfig = require(join(cwd, projectName, 'tsconfig.json'))
expect(tsConfig.compilerOptions.paths).toMatchInlineSnapshot(`
{
"@/*": [
"./*",
],
}
`)
})
})
})

0 comments on commit 39e90ce

Please sign in to comment.