diff --git a/docs/generated/cli/create-nx-workspace.md b/docs/generated/cli/create-nx-workspace.md index 6b8696a24da7b0..e9b613c4322e1e 100644 --- a/docs/generated/cli/create-nx-workspace.md +++ b/docs/generated/cli/create-nx-workspace.md @@ -139,7 +139,7 @@ Package manager to use Type: `string` -Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "next", "nextjs-standalone", "react-native", "expo", "nest", "express", "react", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset +Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "nuxt", "nuxt-standalone", "next", "nextjs-standalone", "react-native", "expo", "nest", "express", "react", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset ### routing diff --git a/docs/generated/packages/nx/documents/create-nx-workspace.md b/docs/generated/packages/nx/documents/create-nx-workspace.md index 6b8696a24da7b0..e9b613c4322e1e 100644 --- a/docs/generated/packages/nx/documents/create-nx-workspace.md +++ b/docs/generated/packages/nx/documents/create-nx-workspace.md @@ -139,7 +139,7 @@ Package manager to use Type: `string` -Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "next", "nextjs-standalone", "react-native", "expo", "nest", "express", "react", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset +Customizes the initial content of your workspace. Default presets include: ["apps", "empty", "core", "npm", "ts", "web-components", "angular-monorepo", "angular-standalone", "react-monorepo", "react-standalone", "vue-monorepo", "vue-standalone", "nuxt", "nuxt-standalone", "next", "nextjs-standalone", "react-native", "expo", "nest", "express", "react", "angular", "node-standalone", "node-monorepo", "ts-standalone"]. To build your own see https://nx.dev/extending-nx/recipes/create-preset ### routing diff --git a/e2e/utils/create-project-utils.ts b/e2e/utils/create-project-utils.ts index ba434e9fbd8ba1..085acfa55f89d2 100644 --- a/e2e/utils/create-project-utils.ts +++ b/e2e/utils/create-project-utils.ts @@ -152,6 +152,7 @@ export function runCreateWorkspace( nextAppDir, e2eTestRunner, ssr, + framework, }: { preset: string; appName?: string; @@ -169,6 +170,7 @@ export function runCreateWorkspace( nextAppDir?: boolean; e2eTestRunner?: 'cypress' | 'playwright' | 'jest' | 'detox' | 'none'; ssr?: boolean; + framework?: string; } ) { projName = name; @@ -218,6 +220,10 @@ export function runCreateWorkspace( command += ` --e2eTestRunner=${e2eTestRunner}`; } + if (framework) { + command += ` --framework=${framework}`; + } + if (extraArgs) { command += ` ${extraArgs}`; } diff --git a/e2e/workspace-create/src/create-nx-workspace.test.ts b/e2e/workspace-create/src/create-nx-workspace.test.ts index c2f20436772c27..07f564a0aa772e 100644 --- a/e2e/workspace-create/src/create-nx-workspace.test.ts +++ b/e2e/workspace-create/src/create-nx-workspace.test.ts @@ -448,7 +448,7 @@ describe('create-nx-workspace', () => { expectCodeIsFormatted(); }); - it('should be able to create an vue monorepo', () => { + it('should be able to create a vue monorepo', () => { const wsName = uniq('vue'); const appName = uniq('app'); runCreateWorkspace(wsName, { @@ -460,6 +460,38 @@ describe('create-nx-workspace', () => { }); expectCodeIsFormatted(); }); + + it('should create a workspace with a single nuxt app at the root', () => { + const wsName = uniq('nuxt'); + + runCreateWorkspace(wsName, { + preset: 'nuxt-standalone', + appName: wsName, + style: 'css', + packageManager, + e2eTestRunner: 'none', + }); + + checkFilesExist('package.json'); + checkFilesExist('project.json'); + checkFilesExist('nuxt.config.ts'); + checkFilesExist('src/app.vue'); + checkFilesExist('src/pages/index.vue'); + expectCodeIsFormatted(); + }); + + it('should be able to create a nuxt monorepo', () => { + const wsName = uniq('nuxt'); + const appName = uniq('app'); + runCreateWorkspace(wsName, { + preset: 'nuxt', + appName, + style: 'css', + packageManager, + e2eTestRunner: 'none', + }); + expectCodeIsFormatted(); + }); }); describe('create-nx-workspace parent folder', () => { diff --git a/packages/create-nx-workspace/bin/create-nx-workspace.ts b/packages/create-nx-workspace/bin/create-nx-workspace.ts index d0640170245e42..6e990357f51571 100644 --- a/packages/create-nx-workspace/bin/create-nx-workspace.ts +++ b/packages/create-nx-workspace/bin/create-nx-workspace.ts @@ -68,14 +68,7 @@ interface VueArguments extends BaseArguments { stack: 'vue'; workspaceType: 'standalone' | 'integrated'; appName: string; - style: string; - e2eTestRunner: 'none' | 'cypress' | 'playwright'; -} - -interface NuxtArguments extends BaseArguments { - stack: 'nuxt'; - workspaceType: 'standalone' | 'integrated'; - appName: string; + framework: 'none' | 'nuxt'; style: string; e2eTestRunner: 'none' | 'cypress' | 'playwright'; } @@ -97,7 +90,6 @@ type Arguments = | ReactArguments | AngularArguments | VueArguments - | NuxtArguments | NodeArguments | UnknownStackArguments; @@ -122,8 +114,6 @@ export const commandsObject: yargs.Argv = yargs describe: chalk.dim`Customizes the initial content of your workspace. Default presets include: [${Object.values( Preset ) - // TODO(katerina): Remove this option when @nx/nuxt is released. - .filter((p) => p !== Preset.NuxtStandalone && p !== Preset.Nuxt) .map((p) => `"${p}"`) .join( ', ' @@ -375,7 +365,7 @@ async function determineFolder( async function determineStack( parsedArgs: yargs.Arguments -): Promise<'none' | 'react' | 'angular' | 'vue' | 'node' | 'nuxt' | 'unknown'> { +): Promise<'none' | 'react' | 'angular' | 'vue' | 'node' | 'unknown'> { if (parsedArgs.preset) { switch (parsedArgs.preset) { case Preset.Angular: @@ -390,10 +380,9 @@ async function determineStack( return 'react'; case Preset.VueStandalone: case Preset.VueMonorepo: - return 'vue'; - case Preset.NuxtStandalone: case Preset.Nuxt: - return 'nuxt'; + case Preset.NuxtStandalone: + return 'vue'; case Preset.Nest: case Preset.NodeStandalone: case Preset.Express: @@ -429,7 +418,7 @@ async function determineStack( }, { name: `vue`, - message: `Vue: Configures a Vue application with modern tooling.`, + message: `Vue: Configures a Vue application with your framework of choice.`, }, { name: `angular`, @@ -458,8 +447,6 @@ async function determinePresetOptions( return determineAngularOptions(parsedArgs); case 'vue': return determineVueOptions(parsedArgs); - case 'nuxt': - return determineNuxtOptions(parsedArgs); case 'node': return determineNodeOptions(parsedArgs); default: @@ -640,83 +627,33 @@ async function determineVueOptions( if (parsedArgs.preset) { preset = parsedArgs.preset; - } else { - const workspaceType = await determineStandaloneOrMonorepo(); - - if (workspaceType === 'standalone') { - preset = Preset.VueStandalone; + if (preset === Preset.VueStandalone || preset === Preset.NuxtStandalone) { + appName = parsedArgs.appName ?? parsedArgs.name; } else { - preset = Preset.VueMonorepo; + appName = await determineAppName(parsedArgs); } - } - - if (preset === Preset.VueStandalone) { - appName = parsedArgs.appName ?? parsedArgs.name; - } else { - appName = await determineAppName(parsedArgs); - } - - e2eTestRunner = await determineE2eTestRunner(parsedArgs); - - if (parsedArgs.style) { - style = parsedArgs.style; - } else { - const reply = await enquirer.prompt<{ style: string }>([ - { - name: 'style', - message: `Default stylesheet format`, - initial: 'css' as any, - type: 'autocomplete', - choices: [ - { - name: 'css', - message: 'CSS', - }, - { - name: 'scss', - message: 'SASS(.scss) [ http://sass-lang.com ]', - }, - { - name: 'less', - message: 'LESS [ http://lesscss.org ]', - }, - { - name: 'none', - message: 'None', - }, - ], - }, - ]); - style = reply.style; - } - - return { preset, style, appName, e2eTestRunner }; -} - -async function determineNuxtOptions( - parsedArgs: yargs.Arguments -): Promise> { - let preset: Preset; - let style: undefined | string = undefined; - let appName: string; - let e2eTestRunner: undefined | 'none' | 'cypress' | 'playwright' = undefined; - - if (parsedArgs.preset) { - preset = parsedArgs.preset; } else { const workspaceType = await determineStandaloneOrMonorepo(); - if (workspaceType === 'standalone') { - preset = Preset.NuxtStandalone; + appName = parsedArgs.appName ?? parsedArgs.name; } else { - preset = Preset.Nuxt; + appName = await determineAppName(parsedArgs); } - } + const framework = await determineVueFramework(parsedArgs); - if (preset === Preset.NuxtStandalone) { - appName = parsedArgs.appName ?? parsedArgs.name; - } else { - appName = await determineAppName(parsedArgs); + if (framework === 'nuxt') { + if (workspaceType === 'standalone') { + preset = Preset.NuxtStandalone; + } else { + preset = Preset.Nuxt; + } + } else { + if (workspaceType === 'standalone') { + preset = Preset.VueStandalone; + } else { + preset = Preset.VueMonorepo; + } + } } e2eTestRunner = await determineE2eTestRunner(parsedArgs); @@ -1021,11 +958,7 @@ async function determineStandaloneOrMonorepo(): Promise< async function determineAppName( parsedArgs: yargs.Arguments< - | ReactArguments - | AngularArguments - | NodeArguments - | VueArguments - | NuxtArguments + ReactArguments | AngularArguments | NodeArguments | VueArguments > ): Promise { if (parsedArgs.appName) return parsedArgs.appName; @@ -1133,6 +1066,34 @@ async function determineNextAppDir( return reply.nextAppDir === 'Yes'; } +async function determineVueFramework( + parsedArgs: yargs.Arguments +): Promise<'none' | 'nuxt'> { + if (!!parsedArgs.framework) return parsedArgs.framework; + const reply = await enquirer.prompt<{ + framework: 'none' | 'nuxt'; + }>([ + { + name: 'framework', + message: 'What framework would you like to use?', + type: 'autocomplete', + choices: [ + { + name: 'none', + message: 'None', + hint: ' I only want vue.', + }, + { + name: 'nuxt', + message: 'Nuxt [ https://nuxt.com/ ]', + }, + ], + initial: 'none' as any, + }, + ]); + return reply.framework; +} + async function determineNodeFramework( parsedArgs: yargs.Arguments ): Promise<'express' | 'fastify' | 'koa' | 'nest' | 'none'> {