Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 90 additions & 57 deletions packages/nuxi/src/commands/init.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type { SelectPromptOptions } from 'consola'
import type { DownloadTemplateResult } from 'giget'
import type { PackageManagerName } from 'nypm'

import { existsSync } from 'node:fs'
import process from 'node:process'

import * as clack from '@clack/prompts'
import { box, cancel, confirm, isCancel, multiselect, outro, select, text } from '@clack/prompts'
import { defineCommand } from 'citty'
import { colors } from 'consola/utils'
import { downloadTemplate, startShell } from 'giget'
Expand Down Expand Up @@ -171,12 +170,18 @@ export default defineCommand({
logger.info(colors.bold(`Welcome to Nuxt!`.split('').map(m => `${themeColor}${m}`).join('')))

if (ctx.args.dir === '') {
ctx.args.dir = await logger.prompt('Where would you like to create your project?', {
const result = await text({
message: 'Where would you like to create your project?',
placeholder: './nuxt-app',
type: 'text',
default: 'nuxt-app',
cancel: 'reject',
}).catch(() => process.exit(1))
defaultValue: 'nuxt-app',
})

if (isCancel(result)) {
cancel('Operation cancelled.')
process.exit(1)
}

ctx.args.dir = result
}

const cwd = resolve(ctx.args.cwd)
Expand All @@ -197,28 +202,41 @@ export default defineCommand({
// when no `--force` flag is provided
const shouldVerify = !shouldForce && existsSync(templateDownloadPath)
if (shouldVerify) {
const selectedAction = await logger.prompt(
`The directory ${colors.cyan(templateDownloadPath)} already exists. What would you like to do?`,
{
type: 'select',
options: ['Override its contents', 'Select different directory', 'Abort'],
},
)
const selectedAction = await select({
message: `The directory ${colors.cyan(templateDownloadPath)} already exists. What would you like to do?`,
options: [
{ value: 'override', label: 'Override its contents' },
{ value: 'different', label: 'Select different directory' },
{ value: 'abort', label: 'Abort' },
],
})

if (isCancel(selectedAction)) {
cancel('Operation cancelled.')
process.exit(1)
}

switch (selectedAction) {
case 'Override its contents':
case 'override':
shouldForce = true
break

case 'Select different directory': {
templateDownloadPath = resolve(cwd, await logger.prompt('Please specify a different directory:', {
type: 'text',
cancel: 'reject',
}).catch(() => process.exit(1)))
case 'different': {
const result = await text({
message: 'Please specify a different directory:',
})

if (isCancel(result)) {
cancel('Operation cancelled.')
process.exit(1)
}

templateDownloadPath = resolve(cwd, result)
break
}

// 'Abort' or Ctrl+C
// 'Abort'
case 'abort':
default:
process.exit(1)
}
Expand Down Expand Up @@ -318,15 +336,26 @@ export default defineCommand({
label: pm,
value: pm,
hint: currentPackageManager === pm ? 'current' : undefined,
} satisfies SelectPromptOptions['options'][number]))
const selectedPackageManager = packageManagerOptions.includes(packageManagerArg)
? packageManagerArg
: await logger.prompt('Which package manager would you like to use?', {
type: 'select',
options: packageManagerSelectOptions,
initial: currentPackageManager,
cancel: 'reject',
}).catch(() => process.exit(1))
}))

let selectedPackageManager: PackageManagerName
if (packageManagerOptions.includes(packageManagerArg)) {
selectedPackageManager = packageManagerArg
}
else {
const result = await select({
message: 'Which package manager would you like to use?',
options: packageManagerSelectOptions,
initialValue: currentPackageManager,
})

if (isCancel(result)) {
cancel('Operation cancelled.')
process.exit(1)
}

selectedPackageManager = result
}

// Install project dependencies
// or skip installation based on the '--no-install' flag
Expand Down Expand Up @@ -357,10 +386,16 @@ export default defineCommand({
}

if (ctx.args.gitInit === undefined) {
ctx.args.gitInit = await logger.prompt('Initialize git repository?', {
type: 'confirm',
cancel: 'reject',
}).catch(() => process.exit(1))
const result = await confirm({
message: 'Initialize git repository?',
})

if (isCancel(result)) {
cancel('Operation cancelled.')
process.exit(1)
}

ctx.args.gitInit = result
}
if (ctx.args.gitInit) {
logger.info('Initializing git repository...\n')
Expand Down Expand Up @@ -396,14 +431,15 @@ export default defineCommand({
}[]
}>('https://api.nuxt.com/modules')

const wantsUserModules = await logger.prompt(
`Would you like to install any of the official modules?`,
{
initial: false,
type: 'confirm',
cancel: 'reject',
},
).catch(() => process.exit(1))
const wantsUserModules = await confirm({
message: `Would you like to install any of the official modules?`,
initialValue: false,
})

if (isCancel(wantsUserModules)) {
cancel('Operation cancelled.')
process.exit(1)
}

if (wantsUserModules) {
const [response, templateDeps] = await Promise.all([
Expand All @@ -419,19 +455,16 @@ export default defineCommand({
logger.info('All official modules are already included in this template.')
}
else {
const selectedOfficialModules = await logger.prompt(
'Pick the modules to install:',
{
type: 'multiselect',
options: officialModules.map(module => ({
label: `${colors.bold(colors.greenBright(module.npm))} – ${module.description.replace(/\.$/, '')}`,
value: module.npm,
})),
required: false,
},
)

if (selectedOfficialModules === undefined) {
const selectedOfficialModules = await multiselect({
message: 'Pick the modules to install:',
options: officialModules.map(module => ({
label: `${colors.bold(colors.greenBright(module.npm))} – ${module.description.replace(/\.$/, '')}`,
value: module.npm,
})),
required: false,
})

if (isCancel(selectedOfficialModules)) {
process.exit(1)
}

Expand Down Expand Up @@ -467,7 +500,7 @@ export default defineCommand({
await runCommand(addModuleCommand, args)
}

logger.log(`\n✨ Nuxt project has been created with the \`${template.name}\` template.\n`)
outro(`✨ Nuxt project has been created with the \`${template.name}\` template.`)

// Display next steps
const relativeTemplateDir = relative(process.cwd(), template.dir) || '.'
Expand All @@ -479,7 +512,7 @@ export default defineCommand({
colors.cyan(`${selectedPackageManager} ${runCmd} dev`),
].filter(Boolean)

clack.box(`\n${nextSteps.map(step => ` β€Ί ${step}`).join('\n')}\n`, ` πŸ‘‰ Next steps `, {
box(`\n${nextSteps.map(step => ` β€Ί ${step}`).join('\n')}\n`, ` πŸ‘‰ Next steps `, {
contentAlign: 'left',
titleAlign: 'left',
width: 'auto',
Expand Down
71 changes: 34 additions & 37 deletions packages/nuxi/src/commands/module/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { homedir } from 'node:os'
import { join } from 'node:path'

import process from 'node:process'
import { confirm, isCancel, select } from '@clack/prompts'
import { updateConfig } from 'c12/update'
import { defineCommand } from 'citty'
import { colors } from 'consola/utils'
Expand Down Expand Up @@ -72,16 +73,12 @@ export default defineCommand({
if (!projectPkg.dependencies?.nuxt && !projectPkg.devDependencies?.nuxt) {
logger.warn(`No \`nuxt\` dependency detected in \`${cwd}\`.`)

const shouldContinue = await logger.prompt(
`Do you want to continue anyway?`,
{
type: 'confirm',
initial: false,
cancel: 'default',
},
)
const shouldContinue = await confirm({
message: `Do you want to continue anyway?`,
initialValue: false,
})

if (shouldContinue !== true) {
if (isCancel(shouldContinue) || shouldContinue !== true) {
process.exit(1)
}
}
Expand Down Expand Up @@ -146,16 +143,21 @@ async function addModules(modules: ResolvedModule[], { skipInstall, skipConfig,
packageManager,
workspace: packageManager?.name === 'pnpm' && existsSync(resolve(cwd, 'pnpm-workspace.yaml')),
}).then(() => true).catch(
(error) => {
async (error) => {
logger.error(error)

const failedModulesList = notInstalledModules.map(module => colors.cyan(module.pkg)).join('\`, \`')
const s = notInstalledModules.length > 1 ? 's' : ''
return logger.prompt(`Install failed for \`${failedModulesList}\`. Do you want to continue adding the module${s} to ${colors.cyan('nuxt.config')}?`, {
type: 'confirm',
initial: false,
cancel: 'default',
const result = await confirm({
message: `Install failed for \`${failedModulesList}\`. Do you want to continue adding the module${s} to ${colors.cyan('nuxt.config')}?`,
initialValue: false,
})

if (isCancel(result)) {
return false
}

return result
},
)

Expand Down Expand Up @@ -255,15 +257,11 @@ async function resolveModule(moduleName: string, cwd: string): Promise<ModuleRes
logger.warn(
`The module \`${pkgName}\` is not compatible with Nuxt \`${nuxtVersion}\` (requires \`${matchedModule.compatibility.nuxt}\`)`,
)
const shouldContinue = await logger.prompt(
'Do you want to continue installing incompatible version?',
{
type: 'confirm',
initial: false,
cancel: 'default',
},
)
if (!shouldContinue) {
const shouldContinue = await confirm({
message: 'Do you want to continue installing incompatible version?',
initialValue: false,
})
if (isCancel(shouldContinue) || !shouldContinue) {
return false
}
}
Expand All @@ -280,14 +278,17 @@ async function resolveModule(moduleName: string, cwd: string): Promise<ModuleRes
logger.warn(
`Recommended version of \`${pkgName}\` for Nuxt \`${nuxtVersion}\` is \`${_moduleVersion}\` but you have requested \`${pkgVersion}\``,
)
pkgVersion = await logger.prompt('Choose a version:', {
type: 'select',
options: [_moduleVersion, pkgVersion],
cancel: 'undefined',
const result = await select({
message: 'Choose a version:',
options: [
{ value: _moduleVersion, label: _moduleVersion },
{ value: pkgVersion, label: pkgVersion },
],
})
if (!pkgVersion) {
if (isCancel(result)) {
return false
}
pkgVersion = result
}
break
}
Expand Down Expand Up @@ -327,15 +328,11 @@ async function resolveModule(moduleName: string, cwd: string): Promise<ModuleRes
&& !pkgDependencies['@nuxt/kit']
) {
logger.warn(`It seems that \`${pkgName}\` is not a Nuxt module.`)
const shouldContinue = await logger.prompt(
`Do you want to continue installing ${colors.cyan(pkgName)} anyway?`,
{
type: 'confirm',
initial: false,
cancel: 'default',
},
)
if (!shouldContinue) {
const shouldContinue = await confirm({
message: `Do you want to continue installing ${colors.cyan(pkgName)} anyway?`,
initialValue: false,
})
if (isCancel(shouldContinue) || !shouldContinue) {
return false
}
}
Expand Down
Loading
Loading