diff --git a/docs/generated/manifests/nx-api.json b/docs/generated/manifests/nx-api.json index ed4fbb92843a0..8e9ee162ecc0c 100644 --- a/docs/generated/manifests/nx-api.json +++ b/docs/generated/manifests/nx-api.json @@ -2601,7 +2601,7 @@ "githubRoot": "https://github.com/nrwl/nx/blob/master", "name": "vue", "packageName": "@nx/vue", - "description": "The Vue plugin for Nx contains executors and generators for managing Vue applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Jest, Cypress, and Storybook.\n\n- Generators for applications, libraries, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.", + "description": "The Vue plugin for Nx contains executors and generators for managing Vue applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Vitest, Cypress, and Storybook.\n\n- Generators for applications, libraries, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.", "documents": { "/nx-api/vue/documents/overview": { "id": "overview", diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index 0bd0d06d0b716..c25f789beaae9 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -2573,7 +2573,7 @@ "source": "/packages/vite/src" }, { - "description": "The Vue plugin for Nx contains executors and generators for managing Vue applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Jest, Cypress, and Storybook.\n\n- Generators for applications, libraries, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.", + "description": "The Vue plugin for Nx contains executors and generators for managing Vue applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Vitest, Cypress, and Storybook.\n\n- Generators for applications, libraries, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.", "documents": [ { "id": "overview", diff --git a/docs/generated/packages/vue/generators/application.json b/docs/generated/packages/vue/generators/application.json index 5caddb43b0d65..31e539a2be847 100644 --- a/docs/generated/packages/vue/generators/application.json +++ b/docs/generated/packages/vue/generators/application.json @@ -130,7 +130,7 @@ } }, "required": ["name"], - "examplesFile": "## Examples\n\n{% tabs %}\n{% tab label=\"Simple Application\" %}\n\nCreate an application named `my-app`:\n\n```shell\nnx g @nx/vue:app my-app\n```\n\n{% /tab %}\n\n{% tab label=\"Specify directory and style extension\" %}\n\nCreate an application named `my-app` in the `my-dir` directory and use `scss` for styles:\n\n{% callout type=\"note\" title=\"Directory Flag Behavior Changes\" %}\nThe command below uses the `as-provided` directory flag behavior, which is the default in Nx 16.8.0. If you're on an earlier version of Nx or using the `derived` option, use `--directory=my-dir`. See the [as-provided vs. derived documentation](/deprecated/as-provided-vs-derived) for more details.\n{% /callout %}\n\n```shell\nnx g @nx/vue:app my-app --directory=apps/my-dir/my-app --style=scss\n```\n\n{% /tab %}\n\n{% tab label=\"Add tags\" %}\n\nAdd tags to the application (used for linting).\n\n```shell\nnx g @nx/vue:app my-app --tags=scope:admin,type:ui\n```\n\n{% /tab %}\n{% /tabs %}\n", + "examplesFile": "---\ntitle: Vue application generator examples\ndescription: This page contains examples for the @nx/vue:app generator.\n---\n\n## Examples\n\n{% tabs %}\n{% tab label=\"Simple Application\" %}\n\nCreate an application named `my-app`:\n\n```shell\nnx g @nx/vue:app my-app\n```\n\n{% /tab %}\n\n{% tab label=\"Specify directory and style extension\" %}\n\nCreate an application named `my-app` in the `my-dir` directory and use `scss` for styles:\n\n{% callout type=\"note\" title=\"Directory Flag Behavior Changes\" %}\nThe command below uses the `as-provided` directory flag behavior, which is the default in Nx 16.8.0. If you're on an earlier version of Nx or using the `derived` option, use `--directory=my-dir`. See the [as-provided vs. derived documentation](/deprecated/as-provided-vs-derived) for more details.\n{% /callout %}\n\n```shell\nnx g @nx/vue:app my-app --directory=apps/my-dir/my-app --style=scss\n```\n\n{% /tab %}\n\n{% tab label=\"Add tags\" %}\n\nAdd tags to the application (used for linting).\n\n```shell\nnx g @nx/vue:app my-app --tags=scope:admin,type:ui\n```\n\n{% /tab %}\n{% /tabs %}\n", "presets": [] }, "aliases": ["app"], diff --git a/docs/generated/packages/vue/generators/component.json b/docs/generated/packages/vue/generators/component.json index 33c2e91948989..9b8263005d302 100644 --- a/docs/generated/packages/vue/generators/component.json +++ b/docs/generated/packages/vue/generators/component.json @@ -10,12 +10,8 @@ "type": "object", "examples": [ { - "command": "nx g component my-component --project=mylib", - "description": "Generate a component in the `mylib` library" - }, - { - "command": "nx g component my-component --project=mylib --classComponent", - "description": "Generate a class component in the `mylib` library" + "command": "nx g @nx/vue:component --directory=my-app/src/app/one --name=one --nameAndDirectoryFormat=as-provided --unitTestRunner=vitest", + "description": "Generate a component in the `my-app` application" } ], "properties": { diff --git a/docs/generated/packages/vue/generators/stories.json b/docs/generated/packages/vue/generators/stories.json index 9f0eb59455b84..19dfea258bbff 100644 --- a/docs/generated/packages/vue/generators/stories.json +++ b/docs/generated/packages/vue/generators/stories.json @@ -60,7 +60,7 @@ } }, "required": ["project"], - "examplesFile": "This generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/).\n\n```bash\nnx g @nx/vue:stories project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Vue overview page](/recipes/storybook/overview-vue#auto-generate-stories).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests)..\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/vue:stories --name=ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*\n```\n\nThis will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\nBy default, Nx will ignore the following paths:\n\n```text\n*.stories.ts, *.stories.tsx, *.stories.js, *.stories.jsx, *.stories.mdx\n```\n\nbut you can change this behaviour easily, as explained above.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/vue:stories --name=ui --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n", + "examplesFile": "---\ntitle: Stories generator examples\ndescription: This page contains examples for the @nx/vue:stories generator.\n---\n\nThis generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/).\n\nYou can also use this generator to generate stories for your **Nuxt** project:\n\n```bash\nnx g @nx/vue:stories project-name\n```\n\nor\n\n```bash\nnx g @nx/nuxt:stories project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Vue overview page](/recipes/storybook/overview-vue#auto-generate-stories).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests)..\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/vue:stories --name=ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*\n```\n\nThis will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\nBy default, Nx will ignore the following paths:\n\n```text\n*.stories.ts, *.stories.tsx, *.stories.js, *.stories.jsx, *.stories.mdx\n```\n\nbut you can change this behaviour easily, as explained above.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/vue:stories --name=ui --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n", "presets": [] }, "description": "Create stories for all components declared in an app or library.", diff --git a/docs/generated/packages/vue/generators/storybook-configuration.json b/docs/generated/packages/vue/generators/storybook-configuration.json index f481bb4bb5ccf..1bad15d7b0b7c 100644 --- a/docs/generated/packages/vue/generators/storybook-configuration.json +++ b/docs/generated/packages/vue/generators/storybook-configuration.json @@ -73,7 +73,7 @@ } }, "required": ["name"], - "examplesFile": "This generator will set up Storybook for your **Vue** project. You can also use this generator to generate Storybook configuration for your **Next.js** project. By default, starting Nx 16, Storybook v7 is used.\n\n```bash\nnx g @nx/vue:storybook-configuration project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Vue overview page](/recipes/storybook/overview-vue#generate-storybook-configuration-for-a-vue-project).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/vue/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/vue/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests)..\n- Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project.\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/vue/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Generate Storybook configuration\n\n```bash\nnx g @nx/vue:storybook-configuration ui\n```\n\nThis will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`).\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/vue:storybook-configuration ui --generateStories=true --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts\n```\n\nThis will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\nBy default, Nx will ignore the following paths:\n\n```text\n*.stories.ts, *.stories.tsx, *.stories.js, *.stories.jsx, *.stories.mdx\n```\n\nbut you can change this behaviour easily, as explained above.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/vue:storybook-configuration ui --generateStories=true --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n\n### Generate Storybook configuration using JavaScript\n\n```bash\nnx g @nx/vue:storybook-configuration ui --tsConfiguration=false\n```\n\nBy default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`).\n", + "examplesFile": "---\ntitle: Storybook configuration generator examples\ndescription: This page contains examples for the @nx/vue:storybook-configuration generator.\n---\n\nThis generator will set up Storybook for your **Vue** project. You can also use this generator to generate Storybook configuration for your **Nuxt** project.\n\n```bash\nnx g @nx/vue:storybook-configuration project-name\n```\n\nor\n\n```bash\nnx g @nx/nuxt:storybook-configuration project-name\n```\n\nYou can read more about how this generator works, in the [Storybook for Vue overview page](/recipes/storybook/overview-vue#generate-storybook-configuration-for-a-vue-project).\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `name` of the project you want to generate the configuration for.\n- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/vue/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/vue/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests)..\n- Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project.\n\nYou must provide a `name` for the generator to work.\n\nBy default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/vue/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended.\n\nThere are a number of other options available. Let's take a look at some examples.\n\n## Examples\n\n### Generate Storybook configuration\n\n```bash\nnx g @nx/vue:storybook-configuration ui\n```\n\nThis will generate Storybook configuration for the `ui` project using TypeScript for the Storybook configuration files (the files inside the `.storybook` directory, eg. `.storybook/main.ts`).\n\n### Ignore certain paths when generating stories\n\n```bash\nnx g @nx/vue:storybook-configuration ui --generateStories=true --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts\n```\n\nThis will generate a Storybook configuration for the `ui` project and generate stories for all components in the `libs/ui/src/lib` directory, except for the ones in the `libs/ui/src/not-stories` directory, and the ones in the `apps/my-app` directory that end with `.something.ts`, and also for components that their file name is of the pattern `*.other.*`.\n\nThis is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component.\n\nBy default, Nx will ignore the following paths:\n\n```text\n*.stories.ts, *.stories.tsx, *.stories.js, *.stories.jsx, *.stories.mdx\n```\n\nbut you can change this behaviour easily, as explained above.\n\n### Generate stories using JavaScript instead of TypeScript\n\n```bash\nnx g @nx/vue:storybook-configuration ui --generateStories=true --js=true\n```\n\nThis will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components.\n\n### Generate Storybook configuration using JavaScript\n\n```bash\nnx g @nx/vue:storybook-configuration ui --tsConfiguration=false\n```\n\nBy default, our generator generates TypeScript Storybook configuration files. You can choose to use JavaScript for the Storybook configuration files of your project (the files inside the `.storybook` directory, eg. `.storybook/main.js`).\n", "presets": [] }, "description": "Set up storybook for a Vue app or library.", diff --git a/docs/map.json b/docs/map.json index 04b7176d5f2c3..c01b984aeacb4 100644 --- a/docs/map.json +++ b/docs/map.json @@ -2125,6 +2125,20 @@ } ] }, + { + "name": "nuxt", + "id": "nuxt", + "description": "Nuxt package.", + "itemList": [ + { + "id": "overview", + "path": "/nx-api/nuxt", + "name": "Overview of the Nx Nuxt Plugin", + "description": "The Nx Plugin for Nuxt contains generators for managing Nuxt applications within a Nx workspace. This page also explains how to configure Nuxt on your Nx workspace.", + "file": "shared/packages/nuxt/nuxt-plugin" + } + ] + }, { "name": "webpack", "id": "webpack", diff --git a/docs/packages.json b/docs/packages.json index 6eeaecc5630ab..9dcff92fd4ebe 100644 --- a/docs/packages.json +++ b/docs/packages.json @@ -362,7 +362,7 @@ { "name": "vue", "packageName": "vue", - "description": "The Vue plugin for Nx contains executors and generators for managing Vue applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Jest, Cypress, and Storybook.\n\n- Generators for applications, libraries, components, hooks, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.", + "description": "The Vue plugin for Nx contains executors and generators for managing Vue applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Vitest, Cypress, and Storybook.\n\n- Generators for applications, libraries, components, hooks, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.", "path": "generated/packages/vite.json", "schemas": { "executors": [], diff --git a/docs/shared/packages/nuxt/nuxt-plugin.md b/docs/shared/packages/nuxt/nuxt-plugin.md new file mode 100644 index 0000000000000..0284b6abdcb1f --- /dev/null +++ b/docs/shared/packages/nuxt/nuxt-plugin.md @@ -0,0 +1,52 @@ +--- +title: Overview of the Nx Nuxt Plugin +description: The Nx Plugin for Nuxt contains generators for managing Nuxt applications within a Nx workspace. This page also explains how to configure Nuxt on your Nx workspace. +--- + +The Nx plugin for [Nuxt](https://nuxt.com/). + +## Setting up a new Nx workspace with Nuxt + +You can create a new workspace that uses Nuxt with one of the following commands: + +- Generate a new monorepo with a Nuxt app + +```shell +npx create-nx-workspace@latest --preset=nuxt +``` + +## Add Nuxt to an existing workspace + +There are a number of ways to use Nuxt in your existing workspace. + +### Install the `@nx/nuxt` plugin + +{% tabs %} +{% tab label="npm" %} + +```shell +npm install -D @nx/nuxt +``` + +{% /tab %} +{% tab label="yarn" %} + +```shell +yarn add -D @nx/nuxt +``` + +{% /tab %} +{% tab label="pnpm" %} + +```shell +pnpm install -D @nx/nuxt +``` + +{% /tab %} +{% /tabs %} + +### Generate a new Nuxt app + +```shell +nx g @nx/nuxt:app my-app +``` diff --git a/docs/shared/recipes/storybook/plugin-vue.md b/docs/shared/recipes/storybook/plugin-vue.md index ba8d7521a1101..4fef7176dc3f9 100644 --- a/docs/shared/recipes/storybook/plugin-vue.md +++ b/docs/shared/recipes/storybook/plugin-vue.md @@ -1,27 +1,41 @@ --- -title: Set up Storybook for Vue Projects -description: This guide explains how to set up Storybook for Vue projects in your Nx workspace. +title: Set up Storybook for Vue and Nuxt Projects +description: This guide explains how to set up Storybook for Vue and Nuxt projects in your Nx workspace. --- -# Set up Storybook for Vue Projects +# Set up Storybook for Vue and Nuxt Projects -This guide will walk you through setting up [Storybook](https://storybook.js.org) for Vue projects in your Nx workspace. +This guide will walk you through setting up [Storybook](https://storybook.js.org) for Vue and Nuxt projects in your Nx workspace. {% callout type="warning" title="Set up Storybook in your workspace" %} You first need to set up Storybook for your Nx workspace, if you haven't already. You can read the [Storybook plugin overview guide](/nx-api/storybook) to get started. {% /callout %} -## Generate Storybook Configuration for a Vue project +## Generate Storybook Configuration for a Vue or Nuxt project -You can generate Storybook configuration for an individual Vue project by using the [`@nx/vue:storybook-configuration` generator](/nx-api/vue/generators/storybook-configuration), like this: +You can generate Storybook configuration for an individual Vue or Nuxt project by using the [`@nx/vue:storybook-configuration` generator](/nx-api/vue/generators/storybook-configuration), like this: + +{% tabs %} +{% tab label="Vue" %} ```shell nx g @nx/vue:storybook-configuration project-name ``` +{% /tab %} +{% tab label="Nuxt" %} + +```shell +nx g @nx/nuxt:storybook-configuration my-nuxt-app +``` + +{% /tab %} + +{% /tabs %} + ## Auto-generate Stories -The [`@nx/vue:storybook-configuration` generator](/nx-api/vue/generators/storybook-configuration) has the option to automatically generate `*.stories.ts` files for each component declared in the library. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/). +The [`@nx/vue:storybook-configuration` generator](/nx-api/vue/generators/storybook-configuration) has the option to automatically generate `*.stories.ts` files for each component declared in the library. ```text / @@ -31,10 +45,24 @@ The [`@nx/vue:storybook-configuration` generator](/nx-api/vue/generators/storybo If you add more components to your project, and want to generate stories for all your (new) components at any point, you can use the [`@nx/vue:stories` generator](/nx-api/vue/generators/stories): +{% tabs %} +{% tab label="Vue" %} + ```shell nx g @nx/vue:stories --project= ``` +{% /tab %} +{% tab label="Nuxt" %} + +```shell +nx g @nx/nuxt:stories --project= +``` + +{% /tab %} + +{% /tabs %} + {% callout type="note" title="Example" %} Let's take for a example a library in your workspace, under `libs/feature/ui`, called `feature-ui`. This library contains a component, called `my-button`. diff --git a/e2e/nuxt/src/nuxt.test.ts b/e2e/nuxt/src/nuxt.test.ts index 4944e5b610ac9..051517de0282f 100644 --- a/e2e/nuxt/src/nuxt.test.ts +++ b/e2e/nuxt/src/nuxt.test.ts @@ -15,7 +15,10 @@ describe('Nuxt Plugin', () => { proj = newProject({ unsetProjectNameAndRootFormat: false, }); - runCLI(`generate @nx/nuxt:app ${app} --unitTestRunner=none`); + runCLI(`generate @nx/nuxt:app ${app} --unitTestRunner=vitest`); + runCLI( + `generate @nx/nuxt:component --directory=${app}/src/components/one --name=one --nameAndDirectoryFormat=as-provided --unitTestRunner=vitest` + ); }); afterAll(() => { @@ -30,9 +33,20 @@ describe('Nuxt Plugin', () => { ); }); + it('should test application', async () => { + const result = runCLI(`test ${app}`); + expect(result).toContain(`Successfully ran target test for project ${app}`); + }); + + // TODO(katerina): Enable when TypeScript version is 5.2.2 - when Angular 17 PR is merged + xit('should lint application', async () => { + const result = runCLI(`lint ${app}`); + expect(result).toContain(`Successfully ran target lint for project ${app}`); + }); + it('should build storybook for app', () => { runCLI( - `generate @nx/vue:storybook-configuration ${app} --generateStories --no-interactive` + `generate @nx/nuxt:storybook-configuration ${app} --generateStories --no-interactive` ); runCLI(`run ${app}:build-storybook --verbose`); checkFilesExist(`dist/storybook/${app}/index.html`); diff --git a/nx-dev/nx-dev/public/images/icons/nuxtdotjs.svg b/nx-dev/nx-dev/public/images/icons/nuxtdotjs.svg new file mode 100644 index 0000000000000..6b39e8faab629 --- /dev/null +++ b/nx-dev/nx-dev/public/images/icons/nuxtdotjs.svg @@ -0,0 +1 @@ +Nuxt.js \ No newline at end of file diff --git a/nx-dev/ui-references/src/lib/icons-map.ts b/nx-dev/ui-references/src/lib/icons-map.ts index a28fb5d2ae053..feef0bf4cf5d6 100644 --- a/nx-dev/ui-references/src/lib/icons-map.ts +++ b/nx-dev/ui-references/src/lib/icons-map.ts @@ -16,6 +16,7 @@ export const iconsMap: Record = { nest: '/images/icons/nestjs.svg', next: '/images/icons/nextdotjs.svg', node: '/images/icons/nodedotjs.svg', + nuxt: '/images/icons/nuxtdotjs.svg', nx: '/images/icons/nx.svg', playwright: '/images/icons/playwright.svg', plugin: '/images/icons/nx.svg', diff --git a/package.json b/package.json index 00e52eec79d93..a4f5060e3dfd7 100644 --- a/package.json +++ b/package.json @@ -64,8 +64,6 @@ "@ngrx/router-store": "~16.0.0", "@ngrx/store": "~16.0.0", "@nguniversal/builders": "~16.2.0", - "@nuxt/kit": "^3.7.4", - "@nuxt/schema": "^3.7.4", "@nx/angular": "17.0.0-rc.2", "@nx/cypress": "17.0.0-rc.2", "@nx/devkit": "17.0.0-rc.2", @@ -158,7 +156,6 @@ "cytoscape-popper": "^2.0.0", "cz-git": "^1.4.0", "czg": "^1.4.0", - "defu": "^6.1.2", "detect-port": "^1.5.1", "dotenv": "~16.3.1", "dotenv-expand": "^10.0.0", @@ -230,6 +227,7 @@ "ng-packagr": "~16.2.0", "node-fetch": "^2.6.7", "npm-package-arg": "11.0.1", + "nuxi": "npm:nuxi-nightly@3.9.2-1699007958.251cab5", "nx": "17.0.0-rc.2", "octokit": "^2.0.14", "open": "^8.4.0", diff --git a/packages/create-nx-workspace/bin/create-nx-workspace.ts b/packages/create-nx-workspace/bin/create-nx-workspace.ts index 70a59248deadd..2f5546f9cdb8d 100644 --- a/packages/create-nx-workspace/bin/create-nx-workspace.ts +++ b/packages/create-nx-workspace/bin/create-nx-workspace.ts @@ -66,7 +66,14 @@ interface VueArguments extends BaseArguments { stack: 'vue'; workspaceType: 'standalone' | 'integrated'; appName: string; - // framework: 'none' | 'nuxt'; + style: string; + e2eTestRunner: 'none' | 'cypress' | 'playwright'; +} + +interface NuxtArguments extends BaseArguments { + stack: 'nuxt'; + workspaceType: 'standalone' | 'integrated'; + appName: string; style: string; e2eTestRunner: 'none' | 'cypress' | 'playwright'; } @@ -88,6 +95,7 @@ type Arguments = | ReactArguments | AngularArguments | VueArguments + | NuxtArguments | NodeArguments | UnknownStackArguments; @@ -112,6 +120,8 @@ 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( ', ' @@ -357,7 +367,7 @@ async function determineFolder( async function determineStack( parsedArgs: yargs.Arguments -): Promise<'none' | 'react' | 'angular' | 'vue' | 'node' | 'unknown'> { +): Promise<'none' | 'react' | 'angular' | 'vue' | 'node' | 'nuxt' | 'unknown'> { if (parsedArgs.preset) { switch (parsedArgs.preset) { case Preset.Angular: @@ -373,6 +383,9 @@ async function determineStack( case Preset.VueStandalone: case Preset.VueMonorepo: return 'vue'; + case Preset.NuxtStandalone: + case Preset.Nuxt: + return 'nuxt'; case Preset.Nest: case Preset.NodeStandalone: case Preset.Express: @@ -437,6 +450,8 @@ async function determinePresetOptions( return determineAngularOptions(parsedArgs); case 'vue': return determineVueOptions(parsedArgs); + case 'nuxt': + return determineNuxtOptions(parsedArgs); case 'node': return determineNodeOptions(parsedArgs); default: @@ -670,6 +685,69 @@ async function determineVueOptions( 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; + } else { + preset = Preset.Nuxt; + } + } + + if (preset === Preset.NuxtStandalone) { + 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 determineAngularOptions( parsedArgs: yargs.Arguments ): Promise> { @@ -929,7 +1007,11 @@ async function determineStandaloneOrMonorepo(): Promise< async function determineAppName( parsedArgs: yargs.Arguments< - ReactArguments | AngularArguments | NodeArguments | VueArguments + | ReactArguments + | AngularArguments + | NodeArguments + | VueArguments + | NuxtArguments > ): Promise { if (parsedArgs.appName) return parsedArgs.appName; diff --git a/packages/create-nx-workspace/src/utils/preset/preset-options.ts b/packages/create-nx-workspace/src/utils/preset/preset-options.ts index b79c5020db927..29282480b11c1 100644 --- a/packages/create-nx-workspace/src/utils/preset/preset-options.ts +++ b/packages/create-nx-workspace/src/utils/preset/preset-options.ts @@ -23,6 +23,10 @@ export const presetOptions: { name: Preset; message: string }[] = [ name: Preset.VueMonorepo, message: 'vue [a monorepo with a single Vue application]', }, + { + name: Preset.Nuxt, + message: 'nuxt [a monorepo with a single Nuxt application]', + }, { name: Preset.NextJs, message: 'next.js [a monorepo with a single Next.js application]', diff --git a/packages/create-nx-workspace/src/utils/preset/preset.ts b/packages/create-nx-workspace/src/utils/preset/preset.ts index 198e58fb7702d..d9ee05393a120 100644 --- a/packages/create-nx-workspace/src/utils/preset/preset.ts +++ b/packages/create-nx-workspace/src/utils/preset/preset.ts @@ -11,6 +11,8 @@ export enum Preset { ReactStandalone = 'react-standalone', VueMonorepo = 'vue-monorepo', VueStandalone = 'vue-standalone', + Nuxt = 'nuxt', + NuxtStandalone = 'nuxt-standalone', NextJs = 'next', NextJsStandalone = 'nextjs-standalone', ReactNative = 'react-native', diff --git a/packages/nuxt/.eslintrc.json b/packages/nuxt/.eslintrc.json index 379043e4b42a9..0afb3c4c2a589 100644 --- a/packages/nuxt/.eslintrc.json +++ b/packages/nuxt/.eslintrc.json @@ -29,7 +29,13 @@ "error", { "buildTargets": ["build-base"], - "ignoredDependencies": ["nx", "typescript"] + "ignoredDependencies": [ + "nx", + "typescript", + "@nx/cypress", + "@nx/playwright", + "nuxi" + ] } ] } diff --git a/packages/nuxt/docs/.gitkeep b/packages/nuxt/docs/.gitkeep deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/packages/nuxt/docs/application-examples.md b/packages/nuxt/docs/application-examples.md index 530a91e0f6357..7a6c3f18714a8 100644 --- a/packages/nuxt/docs/application-examples.md +++ b/packages/nuxt/docs/application-examples.md @@ -3,6 +3,42 @@ title: Nuxt application generator examples description: This page contains examples for the @nx/nuxt:app generator. --- +Your new Nuxt application will be generated with the following directory structure, following the suggested [directory structure](https://nuxt.com/docs/guide/directory-structure) for Nuxt applications: + +```text +my-nuxt-app +├── nuxt.config.ts +├── project.json +├── src +│   ├── app.vue +│   ├── assets +│   │   └── css +│   │   └── styles.css +│   ├── components +│   │   └── NxWelcome.vue +│   ├── pages +│   │   ├── about.vue +│   │   └── index.vue +│   ├── public +│   │   └── favicon.ico +│   └── server +│   ├── api +│   │   └── greet.ts +│   └── tsconfig.json +├── tsconfig.app.json +├── tsconfig.json +├── tsconfig.spec.json +└── vitest.config.ts +``` + +Your new app will contain the following: + +- Two pages (home and about) under `pages` +- A component (`NxWelcome`) under `components` +- A `greet` API endpoint that returns a JSON response under `/api/greet` +- Configuration for `vitest` +- Your app's entrypoint (`app.vue`) will contain the navigation links to the home and about pages, and the `nuxt-page` component to display the contents of your pages. + ## Examples {% tabs %} @@ -13,21 +49,45 @@ The command below uses the `as-provided` directory flag behavior, which is the d {% /callout %} ```shell -nx g app myapp --directory=apps/nested/myapp +nx g @nx/nuxt:app myapp --directory=apps/nested/myapp ``` {% /tab %} -{% tab label="Use a custom Express server" %} + +{% tab label="Create app with vitest configured" %} ```shell -nx g app myapp --custom-server +nx g @nx/nuxt:app myapp --directory=apps/nested/myapp --unitTestRunner=vitest ``` {% /tab %} + {% tab label="Use plain JavaScript (not TypeScript)" %} ```shell -nx g app myapp --js +nx g @nx/nuxt:app myapp --js +``` + +{% /tab %} +{% /tabs %} + +## Generate pages and components + +You can use the the [`@nx/vue:component` generator](/nx-api/vue/generators/component) to generate new pages and components for your application. You can read more on the [`@nx/vue:component` generator documentation page](/nx-api/vue/generators/component), but here are some examples: + +{% tabs %} +{% tab label="New page" %} + +```shell +nx g @nx/nuxt:component --directory=my-app/src/pages --name=my-page +``` + +{% /tab %} + +{% tab label="New component" %} + +```shell +nx g @nx/nuxt:component --directory=my-app/src/components/my-cmp --name=my-cmp ``` {% /tab %} diff --git a/packages/nuxt/docs/stories-examples.md b/packages/nuxt/docs/stories-examples.md deleted file mode 100644 index df4cf3cf722be..0000000000000 --- a/packages/nuxt/docs/stories-examples.md +++ /dev/null @@ -1,46 +0,0 @@ -This generator will generate stories for all your components in your project. The stories will be generated using [Component Story Format 3 (CSF3)](https://storybook.js.org/blog/storybook-csf3-is-here/). - -```bash -nx g @nx/nuxt:stories project-name -``` - -You can read more about how this generator works, in the [Storybook for Nuxt overview page](/recipes/storybook/overview-nuxt#auto-generate-stories). - -When running this generator, you will be prompted to provide the following: - -- The `name` of the project you want to generate the configuration for. -- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).. - -You must provide a `name` for the generator to work. - -By default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/angular/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended. - -There are a number of other options available. Let's take a look at some examples. - -## Examples - -### Ignore certain paths when generating stories - -```bash -nx g @nx/nuxt:stories --name=ui --ignorePaths=libs/ui/src/not-stories/**,**/**/src/**/*.other.* -``` - -This will generate stories for all the components in the `ui` project, except for the ones in the `libs/ui/src/not-stories` directory, and also for components that their file name is of the pattern `*.other.*`. - -This is useful if you have a project that contains components that are not meant to be used in isolation, but rather as part of a larger component. - -By default, Nx will ignore the following paths: - -```text -*.stories.ts, *.stories.tsx, *.stories.js, *.stories.jsx, *.stories.mdx -``` - -but you can change this behaviour easily, as explained above. - -### Generate stories using JavaScript instead of TypeScript - -```bash -nx g @nx/nuxt:stories --name=ui --js=true -``` - -This will generate stories for all the components in the `ui` project using JavaScript instead of TypeScript. So, you will have `.stories.js` files next to your components. diff --git a/packages/nuxt/docs/storybook-configuration-examples.md b/packages/nuxt/docs/storybook-configuration-examples.md index c2dcdfd249183..a3639e85b1ce1 100644 --- a/packages/nuxt/docs/storybook-configuration-examples.md +++ b/packages/nuxt/docs/storybook-configuration-examples.md @@ -1,20 +1,25 @@ -This generator will set up Storybook for your **Nuxt** project. You can also use this generator to generate Storybook configuration for your **Next.js** project. By default, starting Nx 16, Storybook v7 is used. +--- +title: Storybook configuration generator examples +description: This page contains examples for the @nx/nuxt:storybook-configuration generator. +--- + +This generator calls the `@nx/vue:storybook-configuration` generator under the hood. It will set up Storybook for your **Nuxt** project. ```bash nx g @nx/nuxt:storybook-configuration project-name ``` -You can read more about how this generator works, in the [Storybook for Nuxt overview page](/recipes/storybook/overview-nuxt#generate-storybook-configuration-for-a-nuxt-project). +You can read more about how this generator works, in the [Storybook for Vue overview page](/recipes/storybook/overview-vue#generate-storybook-configuration-for-a-vue-project). When running this generator, you will be prompted to provide the following: - The `name` of the project you want to generate the configuration for. -- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/nuxt/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/nuxt/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).. +- Whether you want to set up [Storybook interaction tests](https://storybook.js.org/docs/vue/writing-tests/interaction-testing) (`interactionTests`). If you choose `yes`, a `play` function will be added to your stories, and all the necessary dependencies will be installed. Also, a `test-storybook` target will be generated in your project's `project.json`, with a command to invoke the [Storybook `test-runner`](https://storybook.js.org/docs/vue/writing-tests/test-runner). You can read more about this in the [Nx Storybook interaction tests documentation page](/packages/storybook/documents/interaction-tests).. - Whether you want to `generateStories` for the components in your project. If you choose `yes`, a `.stories.ts` file will be generated next to each of your components in your project. You must provide a `name` for the generator to work. -By default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/nuxt/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended. +By default, this generator will also set up [Storybook interaction tests](https://storybook.js.org/docs/vue/writing-tests/interaction-testing). If you don't want to set up Storybook interaction tests, you can pass the `--interactionTests=false` option, but it's not recommended. There are a number of other options available. Let's take a look at some examples. diff --git a/packages/nuxt/executors.json b/packages/nuxt/executors.json index 3a64718e93cb0..c58e015e23800 100644 --- a/packages/nuxt/executors.json +++ b/packages/nuxt/executors.json @@ -1,3 +1,14 @@ { - "executors": {} + "executors": { + "build": { + "implementation": "./src/executors/build/build.impl", + "schema": "./src/executors/build/schema.json", + "description": "Build with Nuxt." + }, + "serve": { + "implementation": "./src/executors/serve/serve.impl", + "schema": "./src/executors/serve/schema.json", + "description": "Serve with Nuxt." + } + } } diff --git a/packages/nuxt/generators.json b/packages/nuxt/generators.json index dfc623797ed45..75915054f3890 100644 --- a/packages/nuxt/generators.json +++ b/packages/nuxt/generators.json @@ -1,6 +1,7 @@ { "name": "Nx Nuxt", "version": "0.1", + "extends": ["@nx/vue"], "generators": { "init": { "factory": "./src/generators/init/init", @@ -15,30 +16,11 @@ "aliases": ["app"], "description": "Create a Nuxt application." }, - "component": { - "factory": "./src/generators/component/component", - "schema": "./src/generators/component/schema.json", - "aliases": ["c"], - "x-type": "component", - "description": "Create a Vue component for your Nuxt application." - }, - "page": { - "factory": "./src/generators/page/page", - "schema": "./src/generators/page/schema.json", - "x-type": "page", - "description": "Create a new page for your Nuxt application." - }, "storybook-configuration": { "factory": "./src/generators/storybook-configuration/configuration", "schema": "./src/generators/storybook-configuration/schema.json", "description": "Set up storybook for a Nuxt app.", "hidden": false - }, - "stories": { - "factory": "./src/generators/stories/stories", - "schema": "./src/generators/stories/schema.json", - "description": "Create stories for all components declared in an app or library.", - "hidden": false } } } diff --git a/packages/nuxt/index.ts b/packages/nuxt/index.ts index 832621779a608..acd7ab941d36f 100644 --- a/packages/nuxt/index.ts +++ b/packages/nuxt/index.ts @@ -2,4 +2,3 @@ export * from './src/utils/versions'; export { applicationGenerator } from './src/generators/application/application'; export { type InitSchema } from './src/generators/init/schema'; export { nuxtInitGenerator } from './src/generators/init/init'; -export * from './plugins/with-nuxt'; diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index e53639262b7e2..11b0734d5a57a 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -2,7 +2,7 @@ "name": "@nx/nuxt", "version": "0.0.1", "private": true, - "description": "The Nuxt plugin for Nx contains executors and generators for managing Nuxt applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Jest, Cypress, and Storybook.\n\n- Generators for applications, libraries, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.", + "description": "The Nuxt plugin for Nx contains executors and generators for managing Nuxt applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Vitest, Cypress, and Storybook.\n\n- Generators for applications, libraries, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.", "repository": { "type": "git", "url": "https://github.com/nrwl/nx.git", @@ -28,17 +28,12 @@ "migrations": "./migrations.json" }, "dependencies": { - "defu": "^6.1.2", - "fs-extra": "^11.1.0", + "nuxi": "npm:nuxi-nightly@3.9.2-1699007958.251cab5", "tslib": "^2.3.0", "@nx/devkit": "file:../devkit", "@nx/js": "file:../js", "@nx/eslint": "file:../eslint", - "@nx/vue": "file:../vue", - "@nx/cypress": "file:../cypress", - "@nx/playwright": "file:../playwright", - "@nuxt/kit": "^3.7.4", - "@nuxt/schema": "^3.7.4" + "@nx/vue": "file:../vue" }, "publishConfig": { "access": "public" diff --git a/packages/nuxt/plugins/with-nuxt.ts b/packages/nuxt/plugins/with-nuxt.ts deleted file mode 100644 index 798e31ad7c8f8..0000000000000 --- a/packages/nuxt/plugins/with-nuxt.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { join, resolve } from 'path'; -import { workspaceRoot } from '@nx/devkit'; -import { existsSync } from 'fs-extra'; -import { defineNuxtModule } from '@nuxt/kit'; -import { defu } from 'defu'; -import { NuxtModule } from '@nuxt/schema'; - -export const NxNuxtModule: NuxtModule = defineNuxtModule({ - meta: { name: '@nx/nuxt/module', configKey: 'nx' }, - setup(_options, nuxt) { - nuxt.options.alias = defu(nuxt.options.alias, nxTsPaths()); - }, -}); - -/** - * read the compilerOptions.paths option from a tsconfig and return as aliases for Nuxt - **/ -function nxTsPaths() { - const tsConfigPath = getTsConfig(join(workspaceRoot, 'tsconfig.base.json')); - const tsPaths = require(tsConfigPath)?.compilerOptions?.paths as Record< - string, - string[] - >; - - const alias: Record = {}; - if (tsPaths) { - for (const p in tsPaths) { - // '@org/something/*': ['libs/something/src/*'] => '@org/something': '{pathToWorkspaceRoot}/libs/something/src' - alias[p.replace(/\/\*$/, '')] = join( - workspaceRoot, - tsPaths[p][0].replace(/\/\*$/, '') - ); - } - } - - return alias; -} - -function getTsConfig(preferredTsConfigPath: string): string { - return [ - resolve(preferredTsConfigPath), - resolve(join(workspaceRoot, 'tsconfig.base.json')), - resolve(join(workspaceRoot, 'tsconfig.json')), - ].find((tsPath) => { - if (existsSync(tsPath)) { - return tsPath; - } - }); -} diff --git a/packages/nuxt/src/executors/.gitkeep b/packages/nuxt/src/executors/.gitkeep deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/packages/nuxt/src/executors/build/build.impl.ts b/packages/nuxt/src/executors/build/build.impl.ts new file mode 100644 index 0000000000000..9d2739766149e --- /dev/null +++ b/packages/nuxt/src/executors/build/build.impl.ts @@ -0,0 +1,59 @@ +import { ExecutorContext, joinPathFragments } from '@nx/devkit'; +import { NuxtBuildExecutorOptions } from './schema'; + +// Required because nuxi is ESM package. +export function loadNuxiDynamicImport() { + return Function('return import("nuxi")')() as Promise; +} + +export async function* nuxtBuildExecutor( + options: NuxtBuildExecutorOptions, + context: ExecutorContext +) { + const projectRoot = + context.projectsConfigurations.projects[context.projectName].root; + const { runCommand } = await loadNuxiDynamicImport(); + try { + await runCommand('build', [projectRoot], { + overrides: { + ...options, + workspaceDir: context.root, + buildDir: joinPathFragments(context.root, options.outputPath, '.nuxt'), + typescript: { + typeCheck: true, + tsConfig: { + extends: joinPathFragments( + context.root, + projectRoot, + 'tsconfig.app.json' + ), + }, + }, + imports: { + autoImport: false, + }, + nitro: { + output: { + dir: joinPathFragments(context.root, options.outputPath, '.output'), + serverDir: joinPathFragments( + context.root, + options.outputPath, + '.output/server' + ), + publicDir: joinPathFragments( + context.root, + options.outputPath, + '.output/public' + ), + }, + }, + }, + }); + return { success: true }; + } catch (e) { + console.error(e); + return { success: false, error: e }; + } +} + +export default nuxtBuildExecutor; diff --git a/packages/nuxt/src/executors/build/compat.ts b/packages/nuxt/src/executors/build/compat.ts new file mode 100644 index 0000000000000..d493d198bef9b --- /dev/null +++ b/packages/nuxt/src/executors/build/compat.ts @@ -0,0 +1,4 @@ +import { convertNxExecutor } from '@nx/devkit'; +import nuxtBuildExecutor from './build.impl'; + +export default convertNxExecutor(nuxtBuildExecutor); diff --git a/packages/nuxt/src/executors/build/schema.d.ts b/packages/nuxt/src/executors/build/schema.d.ts new file mode 100644 index 0000000000000..3a6964edc5acd --- /dev/null +++ b/packages/nuxt/src/executors/build/schema.d.ts @@ -0,0 +1,6 @@ +export interface NuxtBuildExecutorOptions { + debug?: boolean; + dev?: boolean; + ssr?: boolean; + outputPath: string; +} diff --git a/packages/nuxt/src/executors/build/schema.json b/packages/nuxt/src/executors/build/schema.json new file mode 100644 index 0000000000000..410adcc6316ce --- /dev/null +++ b/packages/nuxt/src/executors/build/schema.json @@ -0,0 +1,36 @@ +{ + "version": 2, + "outputCapture": "direct-nodejs", + "title": "Nuxt Prod Builder", + "cli": "nx", + "description": "Builds a Nuxt application for production.", + "type": "object", + "presets": [ + { + "name": "Default minimum setup", + "keys": [] + } + ], + "properties": { + "debug": { + "type": "boolean", + "description": "Set to true to enable debug mode." + }, + "dev": { + "type": "boolean", + "description": "Whether Nuxt is running in development mode." + }, + "ssr": { + "type": "boolean", + "description": "Whether to enable rendering of HTML - either dynamically (in server mode) or at generate time. If set to false generated pages will have no content." + }, + "outputPath": { + "type": "string", + "description": "The output path of the generated files.", + "x-completion-type": "directory", + "x-priority": "important" + } + }, + "definitions": {}, + "required": [] +} diff --git a/packages/nuxt/src/executors/serve/compat.ts b/packages/nuxt/src/executors/serve/compat.ts new file mode 100644 index 0000000000000..faadb34d372a5 --- /dev/null +++ b/packages/nuxt/src/executors/serve/compat.ts @@ -0,0 +1,4 @@ +import { convertNxExecutor } from '@nx/devkit'; +import nuxtServeExecutor from './serve.impl'; + +export default convertNxExecutor(nuxtServeExecutor); diff --git a/packages/nuxt/src/executors/serve/schema.d.ts b/packages/nuxt/src/executors/serve/schema.d.ts new file mode 100644 index 0000000000000..1e141be8b1a4b --- /dev/null +++ b/packages/nuxt/src/executors/serve/schema.d.ts @@ -0,0 +1,8 @@ +export interface NuxtServeExecutorOptions { + debug?: boolean; + dev?: boolean; + ssr?: boolean; + port?: number; + host?: string; + https?: boolean | Json; +} diff --git a/packages/nuxt/src/executors/serve/schema.json b/packages/nuxt/src/executors/serve/schema.json new file mode 100644 index 0000000000000..19b38bf39b6a2 --- /dev/null +++ b/packages/nuxt/src/executors/serve/schema.json @@ -0,0 +1,50 @@ +{ + "version": 2, + "outputCapture": "direct-nodejs", + "title": "Nuxt Server", + "cli": "nx", + "description": "Serves a Nuxt application for development.", + "type": "object", + "presets": [ + { + "name": "Default minimum setup", + "keys": [] + } + ], + "properties": { + "debug": { + "type": "boolean", + "description": "Set to true to enable debug mode." + }, + "dev": { + "type": "boolean", + "description": "Whether Nuxt is running in development mode." + }, + "ssr": { + "type": "boolean", + "description": "Whether to enable rendering of HTML - either dynamically (in server mode) or at generate time. If set to false generated pages will have no content." + }, + "port": { + "type": "number", + "description": "Port to listen on.", + "x-priority": "important" + }, + "host": { + "description": "Hostname of the server.", + "type": "string" + }, + "https": { + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "object" + } + ], + "description": "Listen with https protocol with a self-signed certificate by default." + } + }, + "definitions": {}, + "required": [] +} diff --git a/packages/nuxt/src/executors/serve/serve.impl.ts b/packages/nuxt/src/executors/serve/serve.impl.ts new file mode 100644 index 0000000000000..3ca8ab3392197 --- /dev/null +++ b/packages/nuxt/src/executors/serve/serve.impl.ts @@ -0,0 +1,90 @@ +import { ExecutorContext, joinPathFragments } from '@nx/devkit'; +import { NuxtServeExecutorOptions } from './schema'; +import { createAsyncIterable } from '@nx/devkit/src/utils/async-iterable'; + +// Required because nuxi is ESM package. +export function loadNuxiDynamicImport() { + return Function('return import("nuxi")')() as Promise; +} + +export async function* nuxtServeExecutor( + options: NuxtServeExecutorOptions, + context: ExecutorContext +) { + const projectRoot = + context.projectsConfigurations.projects[context.projectName].root; + yield* createAsyncIterable<{ success: boolean; baseUrl: string }>( + async ({ next, error }) => { + try { + const { runCommand } = await loadNuxiDynamicImport(); + await runCommand('dev', [projectRoot], { + overrides: getConfigOverrides(options, context.root, projectRoot), + }); + next({ + success: true, + baseUrl: `${options.https ? 'https' : 'http'}://${ + options.host ?? 'localhost' + }:${options.port ?? '4200'}`, + }); + } catch (err) { + console.error(err); + error(new Error(`Nuxt app exited with message ${err.message}`)); + } + } + ); +} + +function getConfigOverrides( + options: NuxtServeExecutorOptions, + workspaceRoot: string, + projectRoot: string +): { [key: string]: any } { + const json: { [key: string]: any } = { + workspaceDir: workspaceRoot, + typescript: { + typeCheck: true, + tsConfig: { + extends: joinPathFragments( + workspaceRoot, + projectRoot, + 'tsconfig.app.json' + ), + }, + }, + }; + + if (options.debug !== undefined) { + json.debug = options.debug; + } + + if (options.dev !== undefined) { + json.dev = options.dev; + } + + if (options.ssr !== undefined) { + json.ssr = options.ssr; + } + + if (options.https !== undefined) { + if (!json.devServer) { + json.devServer = {}; + } + json.devServer.https = options.https; + } + if (options.port) { + if (!json.devServer) { + json.devServer = {}; + } + json.devServer.port = options.port; + } + if (options.host) { + if (!json.devServer) { + json.devServer = {}; + } + json.devServer.host = options.host; + } + + return json; +} + +export default nuxtServeExecutor; diff --git a/packages/nuxt/src/generators/.gitkeep b/packages/nuxt/src/generators/.gitkeep deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/packages/nuxt/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/nuxt/src/generators/application/__snapshots__/application.spec.ts.snap index 41463a5277152..6a136acb0a880 100644 --- a/packages/nuxt/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/nuxt/src/generators/application/__snapshots__/application.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`app generated files content - as-provided should add nuxt entries in .gitignore 1`] = ` +exports[`app generated files content - as-provided general application should add nuxt entries in .gitignore 1`] = ` " # Nuxt dev/build outputs .output @@ -10,7 +10,7 @@ exports[`app generated files content - as-provided should add nuxt entries in .g .cache" `; -exports[`app generated files content - as-provided should configure eslint correctly 1`] = ` +exports[`app generated files content - as-provided general application should configure eslint correctly 1`] = ` "{ "extends": ["@nuxt/eslint-config", "../.eslintrc.json"], "ignorePatterns": ["!**/*"], @@ -26,20 +26,26 @@ exports[`app generated files content - as-provided should configure eslint corre " `; -exports[`app generated files content - as-provided should configure nuxt correctly 1`] = ` -"import { NxNuxtModule } from '@nx/nuxt'; +exports[`app generated files content - as-provided general application should configure nuxt correctly 1`] = ` +"import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; // https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ - modules: [NxNuxtModule], srcDir: 'src', devtools: { enabled: true }, - css: ['~/assets/css/styles.css'], + devServer: { + host: 'localhost', + port: 4200, + }, + + vite: { + plugins: [nxViteTsPaths()], + }, }); " `; -exports[`app generated files content - as-provided should configure tsconfig and project.json correctly 1`] = ` +exports[`app generated files content - as-provided general application should configure tsconfig and project.json correctly 1`] = ` "{ "name": "my-app", "$schema": "../node_modules/nx/schemas/project-schema.json", @@ -47,25 +53,15 @@ exports[`app generated files content - as-provided should configure tsconfig and "sourceRoot": "my-app/src", "targets": { "serve": { - "executor": "nx:run-commands", - "outputs": [ - "{workspaceRoot}/{projectRoot}/.output", - "{workspaceRoot}/{projectRoot}/.nuxt" - ], - "options": { - "command": "npx nuxi dev --port=4200", - "cwd": "my-app" - } + "executor": "@nx/nuxt:serve", + "outputs": ["{options.outputFile}"], + "options": {} }, "build": { - "executor": "nx:run-commands", - "outputs": [ - "{workspaceRoot}/{projectRoot}/.output", - "{workspaceRoot}/{projectRoot}/.nuxt" - ], + "executor": "@nx/nuxt:build", + "outputs": ["{options.outputFile}"], "options": { - "command": "npx nuxi build", - "cwd": "my-app" + "outputPath": "dist/my-app" } }, "lint": { @@ -80,7 +76,8 @@ exports[`app generated files content - as-provided should configure tsconfig and "outputs": ["{options.reportsDirectory}"], "options": { "passWithNoTests": true, - "reportsDirectory": "../coverage/my-app" + "reportsDirectory": "../coverage/my-app", + "config": "my-app/vitest.config.ts" } } } @@ -88,14 +85,14 @@ exports[`app generated files content - as-provided should configure tsconfig and " `; -exports[`app generated files content - as-provided should configure tsconfig and project.json correctly 2`] = ` +exports[`app generated files content - as-provided general application should configure tsconfig and project.json correctly 2`] = ` "{ "compilerOptions": {}, "files": [], "include": [], "references": [ { - "path": "./.nuxt/tsconfig.json" + "path": "./tsconfig.app.json" }, { "path": "./tsconfig.spec.json" @@ -106,7 +103,67 @@ exports[`app generated files content - as-provided should configure tsconfig and " `; -exports[`app generated files content - as-provided should create all new files in the correct location 1`] = ` +exports[`app generated files content - as-provided general application should configure vitest correctly 1`] = ` +"import { defineVitestConfig } from 'nuxt-vitest/config'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +export default defineVitestConfig({ + plugins: [nxViteTsPaths()], + test: { + globals: true, + cache: { + dir: '../node_modules/.vitest', + }, + include: ['my-app/src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + environment: 'nuxt', + }, +}); +" +`; + +exports[`app generated files content - as-provided general application should configure vitest correctly 2`] = ` +"{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../dist/out-tsc", + "types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"], + "composite": true + }, + "include": [ + "vitest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.test.tsx", + "src/**/*.spec.tsx", + "src/**/*.test.js", + "src/**/*.spec.js", + "src/**/*.test.jsx", + "src/**/*.spec.jsx", + "src/**/*.d.ts" + ] +} +" +`; + +exports[`app generated files content - as-provided general application should configure vitest correctly 3`] = ` +"{ + "compilerOptions": {}, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../tsconfig.base.json" +} +" +`; + +exports[`app generated files content - as-provided general application should create all new files in the correct location 1`] = ` [ ".prettierrc", "package.json", @@ -117,7 +174,6 @@ exports[`app generated files content - as-provided should create all new files i "my-app/.npmrc", "my-app/nuxt.config.ts", "my-app/src/app.vue", - "my-app/src/assets/css/styles.css", "my-app/src/components/NxWelcome.vue", "my-app/src/pages/about.vue", "my-app/src/pages/index.vue", @@ -125,12 +181,13 @@ exports[`app generated files content - as-provided should create all new files i "my-app/src/public/favicon.ico", "my-app/src/server/api/greet.ts", "my-app/src/server/tsconfig.json", + "my-app/tsconfig.app.json", "my-app/tsconfig.json", ".gitignore", ".eslintrc.json", ".eslintignore", "my-app/.eslintrc.json", - "my-app/vite.config.ts", + "my-app/vitest.config.ts", "my-app/tsconfig.spec.json", "my-app-e2e/project.json", "my-app-e2e/src/e2e/app.cy.ts", @@ -143,3 +200,85 @@ exports[`app generated files content - as-provided should create all new files i "my-app-e2e/.eslintrc.json", ] `; + +exports[`app generated files content - as-provided styles setup should configure css 1`] = ` +"import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + srcDir: 'src', + devtools: { enabled: true }, + devServer: { + host: 'localhost', + port: 4200, + }, + + css: ['~/assets/css/styles.css'], + + vite: { + plugins: [nxViteTsPaths()], + }, +}); +" +`; + +exports[`app generated files content - as-provided styles setup should configure less 1`] = ` +"import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + srcDir: 'src', + devtools: { enabled: true }, + devServer: { + host: 'localhost', + port: 4200, + }, + + css: ['~/assets/css/styles.less'], + + vite: { + plugins: [nxViteTsPaths()], + }, +}); +" +`; + +exports[`app generated files content - as-provided styles setup should configure scss 1`] = ` +"import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + srcDir: 'src', + devtools: { enabled: true }, + devServer: { + host: 'localhost', + port: 4200, + }, + + css: ['~/assets/css/styles.scss'], + + vite: { + plugins: [nxViteTsPaths()], + }, +}); +" +`; + +exports[`app generated files content - as-provided styles setup should not configure styles 1`] = ` +"import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + srcDir: 'src', + devtools: { enabled: true }, + devServer: { + host: 'localhost', + port: 4200, + }, + + vite: { + plugins: [nxViteTsPaths()], + }, +}); +" +`; diff --git a/packages/nuxt/src/generators/application/application.spec.ts b/packages/nuxt/src/generators/application/application.spec.ts index 3ee69ad6a2df8..02ff1857c0307 100644 --- a/packages/nuxt/src/generators/application/application.spec.ts +++ b/packages/nuxt/src/generators/application/application.spec.ts @@ -1,5 +1,5 @@ import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import { Tree } from '@nx/devkit'; +import { Tree, readJson } from '@nx/devkit'; import { applicationGenerator } from './application'; describe('app', () => { @@ -7,33 +7,96 @@ describe('app', () => { const name = 'my-app'; describe('generated files content - as-provided', () => { - beforeAll(async () => { - tree = createTreeWithEmptyWorkspace(); - await applicationGenerator(tree, { - name, - projectNameAndRootFormat: 'as-provided', + describe('general application', () => { + beforeAll(async () => { + tree = createTreeWithEmptyWorkspace(); + await applicationGenerator(tree, { + name, + projectNameAndRootFormat: 'as-provided', + unitTestRunner: 'vitest', + }); + }); + it('should create all new files in the correct location', async () => { + const newFiles = tree.listChanges().map((change) => change.path); + expect(newFiles).toMatchSnapshot(); }); - }); - it('should create all new files in the correct location', async () => { - const newFiles = tree.listChanges().map((change) => change.path); - expect(newFiles).toMatchSnapshot(); - }); - it('should add nuxt entries in .gitignore', () => { - expect(tree.read('.gitignore', 'utf-8')).toMatchSnapshot(); - }); + it('should add nuxt entries in .gitignore', () => { + expect(tree.read('.gitignore', 'utf-8')).toMatchSnapshot(); + }); - it('should configure nuxt correctly', () => { - expect(tree.read('my-app/nuxt.config.ts', 'utf-8')).toMatchSnapshot(); - }); + it('should configure nuxt correctly', () => { + expect(tree.read('my-app/nuxt.config.ts', 'utf-8')).toMatchSnapshot(); + }); + + it('should configure eslint correctly', () => { + expect(tree.read('my-app/.eslintrc.json', 'utf-8')).toMatchSnapshot(); + }); + + it('should configure vitest correctly', () => { + expect(tree.read('my-app/vitest.config.ts', 'utf-8')).toMatchSnapshot(); + expect( + tree.read('my-app/tsconfig.spec.json', 'utf-8') + ).toMatchSnapshot(); + expect(tree.read('my-app/tsconfig.json', 'utf-8')).toMatchSnapshot(); + const packageJson = readJson(tree, 'package.json'); + expect(packageJson.devDependencies['vitest']).toEqual('0.31.4'); + expect(packageJson.devDependencies['nuxt-vitest']).toEqual('^0.11.0'); + }); - it('should configure eslint correctly', () => { - expect(tree.read('my-app/.eslintrc.json', 'utf-8')).toMatchSnapshot(); + it('should configure tsconfig and project.json correctly', () => { + expect(tree.read('my-app/project.json', 'utf-8')).toMatchSnapshot(); + expect(tree.read('my-app/tsconfig.json', 'utf-8')).toMatchSnapshot(); + }); }); - it('should configure tsconfig and project.json correctly', () => { - expect(tree.read('my-app/project.json', 'utf-8')).toMatchSnapshot(); - expect(tree.read('my-app/tsconfig.json', 'utf-8')).toMatchSnapshot(); + describe('styles setup', () => { + beforeAll(async () => { + tree = createTreeWithEmptyWorkspace(); + }); + it('should configure css', async () => { + await applicationGenerator(tree, { + name: 'myapp1', + projectNameAndRootFormat: 'as-provided', + unitTestRunner: 'none', + style: 'css', + }); + expect(tree.exists('myapp1/src/assets/css/styles.css')).toBeTruthy(); + expect(tree.read('myapp1/nuxt.config.ts', 'utf-8')).toMatchSnapshot(); + }); + + it('should configure scss', async () => { + await applicationGenerator(tree, { + name: 'myapp2', + projectNameAndRootFormat: 'as-provided', + unitTestRunner: 'none', + style: 'scss', + }); + expect(tree.exists('myapp2/src/assets/css/styles.scss')).toBeTruthy(); + expect(tree.read('myapp2/nuxt.config.ts', 'utf-8')).toMatchSnapshot(); + }); + + it('should configure less', async () => { + await applicationGenerator(tree, { + name: 'myapp3', + projectNameAndRootFormat: 'as-provided', + unitTestRunner: 'none', + style: 'less', + }); + expect(tree.exists('myapp3/src/assets/css/styles.less')).toBeTruthy(); + expect(tree.read('myapp3/nuxt.config.ts', 'utf-8')).toMatchSnapshot(); + }); + + it('should not configure styles', async () => { + await applicationGenerator(tree, { + name: 'myapp4', + projectNameAndRootFormat: 'as-provided', + unitTestRunner: 'none', + style: 'none', + }); + expect(tree.exists('myapp4/src/assets/css/styles.css')).toBeFalsy(); + expect(tree.read('myapp4/nuxt.config.ts', 'utf-8')).toMatchSnapshot(); + }); }); }); }); diff --git a/packages/nuxt/src/generators/application/application.ts b/packages/nuxt/src/generators/application/application.ts index db19cf95e6df5..576190300454a 100644 --- a/packages/nuxt/src/generators/application/application.ts +++ b/packages/nuxt/src/generators/application/application.ts @@ -1,10 +1,9 @@ -import * as path from 'path'; import { addProjectConfiguration, - ensurePackage, formatFiles, generateFiles, GeneratorCallback, + joinPathFragments, offsetFromRoot, runTasksInSerial, toJS, @@ -19,14 +18,18 @@ import { updateGitIgnore } from '../../utils/update-gitignore'; import { addBuildTarget, addServeTarget } from './lib/add-targets'; import { Linter } from '@nx/eslint'; import { addE2e } from './lib/add-e2e'; -import { nxVersion } from '../../utils/versions'; import { addLinting } from '../../utils/add-linting'; +import { addVitest } from './lib/add-vitest'; export async function applicationGenerator(tree: Tree, schema: Schema) { const tasks: GeneratorCallback[] = []; const options = await normalizeOptions(tree, schema); + const outputPath = joinPathFragments('dist', options.appProjectRoot); + + const projectOffsetFromRoot = offsetFromRoot(options.appProjectRoot); + const nuxtInitTask = await nuxtInitGenerator(tree, { ...options, skipFormat: true, @@ -40,13 +43,25 @@ export async function applicationGenerator(tree: Tree, schema: Schema) { targets: {}, }); - generateFiles(tree, path.join(__dirname, './files'), options.appProjectRoot, { - ...options, - offsetFromRoot: offsetFromRoot(options.appProjectRoot), - title: options.projectName, - dot: '.', - tmpl: '', - }); + generateFiles( + tree, + joinPathFragments(__dirname, './files'), + options.appProjectRoot, + { + ...options, + offsetFromRoot: projectOffsetFromRoot, + title: options.projectName, + dot: '.', + tmpl: '', + style: options.style, + } + ); + + if (options.style === 'none') { + tree.delete( + joinPathFragments(options.appProjectRoot, `src/assets/css/styles.none`) + ); + } createTsConfig( tree, @@ -54,12 +69,13 @@ export async function applicationGenerator(tree: Tree, schema: Schema) { projectRoot: options.appProjectRoot, rootProject: options.rootProject, unitTestRunner: options.unitTestRunner, + outputPath, }, getRelativePathToRootTsConfig(tree, options.appProjectRoot) ); - addServeTarget(tree, options.name, options.appProjectRoot); - addBuildTarget(tree, options.name, options.appProjectRoot); + addServeTarget(tree, options.name); + addBuildTarget(tree, options.name, outputPath); updateGitIgnore(tree); @@ -74,15 +90,7 @@ export async function applicationGenerator(tree: Tree, schema: Schema) { ); if (options.unitTestRunner === 'vitest') { - const { vitestGenerator } = ensurePackage('@nx/vite', nxVersion); - tasks.push( - await vitestGenerator(tree, { - uiFramework: 'none', - project: options.projectName, - coverageProvider: 'c8', - skipFormat: true, - }) - ); + addVitest(tree, options, options.appProjectRoot, projectOffsetFromRoot); } tasks.push(await addE2e(tree, options)); diff --git a/packages/nuxt/src/generators/application/files/nuxt.config.ts__tmpl__ b/packages/nuxt/src/generators/application/files/nuxt.config.ts__tmpl__ index 455c9b4f74a43..7ddade069f194 100644 --- a/packages/nuxt/src/generators/application/files/nuxt.config.ts__tmpl__ +++ b/packages/nuxt/src/generators/application/files/nuxt.config.ts__tmpl__ @@ -1,9 +1,19 @@ -import { NxNuxtModule } from '@nx/nuxt'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; // https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ - modules: [NxNuxtModule], srcDir: 'src', devtools: { enabled: true }, - css: ['~/assets/css/styles.css'], + devServer: { + host: 'localhost', + port: 4200, + }, + <% if (style !== 'none') { %> + css: ['~/assets/css/styles.<%= style %>'], + <% } %> + vite: { + plugins: [ + nxViteTsPaths() + ], + } }); diff --git a/packages/nuxt/src/generators/application/files/src/app.vue__tmpl__ b/packages/nuxt/src/generators/application/files/src/app.vue__tmpl__ index b1d63eea6e559..0613086dbcc08 100644 --- a/packages/nuxt/src/generators/application/files/src/app.vue__tmpl__ +++ b/packages/nuxt/src/generators/application/files/src/app.vue__tmpl__ @@ -1,16 +1,18 @@ - + diff --git a/packages/nuxt/src/generators/application/files/src/assets/css/styles.css__tmpl__ b/packages/nuxt/src/generators/application/files/src/assets/css/styles.__style__ similarity index 100% rename from packages/nuxt/src/generators/application/files/src/assets/css/styles.css__tmpl__ rename to packages/nuxt/src/generators/application/files/src/assets/css/styles.__style__ diff --git a/packages/nuxt/src/generators/application/lib/add-e2e.ts b/packages/nuxt/src/generators/application/lib/add-e2e.ts index d9e53e853c72d..cb43d6fb62a14 100644 --- a/packages/nuxt/src/generators/application/lib/add-e2e.ts +++ b/packages/nuxt/src/generators/application/lib/add-e2e.ts @@ -50,7 +50,7 @@ export async function addE2e(host: Tree, options: NormalizedSchema) { js: false, linter: options.linter, setParserOptionsProject: options.setParserOptionsProject, - webServerAddress: 'http://127.0.0.1:4200', + webServerAddress: 'http://localhost:4200', webServerCommand: `${getPackageManagerCommand().exec} nx serve ${ options.projectName }`, diff --git a/packages/nuxt/src/generators/application/lib/add-targets.ts b/packages/nuxt/src/generators/application/lib/add-targets.ts index 220ab4c19cedc..b095e16f34de8 100644 --- a/packages/nuxt/src/generators/application/lib/add-targets.ts +++ b/packages/nuxt/src/generators/application/lib/add-targets.ts @@ -1,26 +1,15 @@ import { Tree, - joinPathFragments, readProjectConfiguration, updateProjectConfiguration, } from '@nx/devkit'; -export function addServeTarget( - tree: Tree, - projectName: string, - projectRoot: string -) { +export function addServeTarget(tree: Tree, projectName: string) { const projectConfig = readProjectConfiguration(tree, projectName); projectConfig.targets['serve'] = { - executor: 'nx:run-commands', - outputs: [ - '{workspaceRoot}/{projectRoot}/.output', - '{workspaceRoot}/{projectRoot}/.nuxt', - ], - options: { - command: 'npx nuxi dev --port=4200', - cwd: joinPathFragments(projectRoot), - }, + executor: '@nx/nuxt:serve', + outputs: ['{options.outputFile}'], + options: {}, }; updateProjectConfiguration(tree, projectName, projectConfig); } @@ -28,18 +17,14 @@ export function addServeTarget( export function addBuildTarget( tree: Tree, projectName: string, - projectRoot: string + outputPath: string ) { const projectConfig = readProjectConfiguration(tree, projectName); projectConfig.targets['build'] = { - executor: 'nx:run-commands', - outputs: [ - '{workspaceRoot}/{projectRoot}/.output', - '{workspaceRoot}/{projectRoot}/.nuxt', - ], + executor: '@nx/nuxt:build', + outputs: ['{options.outputFile}'], options: { - command: 'npx nuxi build', - cwd: joinPathFragments(projectRoot), + outputPath: outputPath, }, }; updateProjectConfiguration(tree, projectName, projectConfig); diff --git a/packages/nuxt/src/generators/application/lib/add-vitest.ts b/packages/nuxt/src/generators/application/lib/add-vitest.ts new file mode 100644 index 0000000000000..9eea140959062 --- /dev/null +++ b/packages/nuxt/src/generators/application/lib/add-vitest.ts @@ -0,0 +1,88 @@ +import { + Tree, + addDependenciesToPackageJson, + joinPathFragments, + readProjectConfiguration, + updateProjectConfiguration, + writeJson, +} from '@nx/devkit'; +import { NormalizedSchema } from '../schema'; +import { + happyDomVersion, + nuxtVitestVersion, + nxVersion, + vitestVersion, +} from '../../../utils/versions'; + +export function addVitest( + tree: Tree, + options: NormalizedSchema, + projectRoot: string, + projectOffsetFromRoot: string +) { + addDependenciesToPackageJson( + tree, + {}, + { + '@nx/vite': nxVersion, + '@vitest/coverage-c8': vitestVersion, + '@vitest/ui': vitestVersion, + vitest: vitestVersion, + 'nuxt-vitest': nuxtVitestVersion, + 'happy-dom': happyDomVersion, + } + ); + + const projectConfig = readProjectConfiguration(tree, options.name); + projectConfig.targets['test'] = { + executor: '@nx/vite:test', + outputs: ['{options.reportsDirectory}'], + options: { + passWithNoTests: true, + reportsDirectory: `${projectOffsetFromRoot}coverage/${projectRoot}`, + config: `${projectRoot}/vitest.config.ts`, + }, + }; + updateProjectConfiguration(tree, options.name, projectConfig); + + tree.write( + joinPathFragments(projectRoot, 'vitest.config.ts'), + ` + import { defineVitestConfig } from 'nuxt-vitest/config'; + import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + + export default defineVitestConfig({ + plugins: [nxViteTsPaths()], + test: { + globals: true, + cache: { + dir: '${projectOffsetFromRoot}node_modules/.vitest', + }, + include: ['${projectRoot}/src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + environment: 'nuxt', + }, + }); + ` + ); + + writeJson(tree, joinPathFragments(projectRoot, 'tsconfig.spec.json'), { + extends: './tsconfig.json', + compilerOptions: { + outDir: `${projectOffsetFromRoot}dist/out-tsc`, + types: ['vitest/globals', 'vitest/importMeta', 'vite/client', 'node'], + composite: true, + }, + include: [ + 'vitest.config.ts', + 'src/**/*.test.ts', + 'src/**/*.spec.ts', + 'src/**/*.test.tsx', + 'src/**/*.spec.tsx', + 'src/**/*.test.js', + 'src/**/*.spec.js', + 'src/**/*.test.jsx', + 'src/**/*.spec.jsx', + 'src/**/*.d.ts', + ], + }); +} diff --git a/packages/nuxt/src/generators/application/lib/normalize-options.ts b/packages/nuxt/src/generators/application/lib/normalize-options.ts index 8eca8fff5482e..a214e1f036712 100644 --- a/packages/nuxt/src/generators/application/lib/normalize-options.ts +++ b/packages/nuxt/src/generators/application/lib/normalize-options.ts @@ -45,6 +45,7 @@ export async function normalizeOptions( e2eProjectName, e2eProjectRoot, parsedTags, + style: options.style ?? 'none', } as NormalizedSchema; normalized.unitTestRunner ??= 'vitest'; diff --git a/packages/nuxt/src/generators/application/schema.json b/packages/nuxt/src/generators/application/schema.json index f8233d4787f68..c3a9c2b5e6c81 100644 --- a/packages/nuxt/src/generators/application/schema.json +++ b/packages/nuxt/src/generators/application/schema.json @@ -80,7 +80,24 @@ "style": { "description": "The file extension to be used for style files.", "type": "string", - "default": "css" + "alias": "s", + "default": "css", + "x-prompt": { + "message": "Which stylesheet format would you like to use?", + "type": "list", + "items": [ + { "value": "css", "label": "CSS" }, + { + "value": "scss", + "label": "SASS(.scss) [ http://sass-lang.com ]" + }, + { + "value": "less", + "label": "LESS [ http://lesscss.org ]" + }, + { "value": "none", "label": "None" } + ] + } }, "setParserOptionsProject": { "type": "boolean", diff --git a/packages/nuxt/src/generators/component/component.spec.ts b/packages/nuxt/src/generators/component/component.spec.ts deleted file mode 100644 index 731c8e1cd6ebe..0000000000000 --- a/packages/nuxt/src/generators/component/component.spec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import { Tree } from '@nx/devkit'; -import { applicationGenerator } from '../application/application'; -import { componentGenerator } from './component'; - -describe('component', () => { - let tree: Tree; - const name = 'my-app'; - - describe('generated files content - as-provided', () => { - beforeAll(async () => { - tree = createTreeWithEmptyWorkspace(); - await applicationGenerator(tree, { - name, - projectNameAndRootFormat: 'as-provided', - }); - }); - it('should create a new vue component in the correct location', async () => { - await componentGenerator(tree, { - name: 'hello', - project: name, - }); - - expect(tree.exists('my-app/src/components/hello/hello.vue')).toBeTruthy(); - }); - }); -}); diff --git a/packages/nuxt/src/generators/component/component.ts b/packages/nuxt/src/generators/component/component.ts deleted file mode 100644 index cbfe22c37433b..0000000000000 --- a/packages/nuxt/src/generators/component/component.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { formatFiles, Tree } from '@nx/devkit'; -import { componentGenerator as vueComponentGenerator } from '@nx/vue'; -import { Schema } from './schema'; - -/* - * This generator is basically the Vue one, but for Nuxt we - * are just adjusting some options - */ -export async function componentGenerator(host: Tree, options: Schema) { - await vueComponentGenerator(host, { - ...options, - routing: false, - skipFormat: true, - directory: options.directory ?? 'components', - }); - - if (!options.skipFormat) { - await formatFiles(host); - } -} - -export default componentGenerator; diff --git a/packages/nuxt/src/generators/component/schema.d.ts b/packages/nuxt/src/generators/component/schema.d.ts deleted file mode 100644 index 567885995e4d8..0000000000000 --- a/packages/nuxt/src/generators/component/schema.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface Schema { - project: string; - name: string; - skipTests?: boolean; - flat?: boolean; - pascalCaseFiles?: boolean; - pascalCaseDirectory?: boolean; - fileName?: string; - inSourceTests?: boolean; - skipFormat?: boolean; - directory?: string; -} diff --git a/packages/nuxt/src/generators/component/schema.json b/packages/nuxt/src/generators/component/schema.json deleted file mode 100644 index 51fb677a5f2f3..0000000000000 --- a/packages/nuxt/src/generators/component/schema.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "$schema": "http://json-schema.org/schema", - "cli": "nx", - "$id": "NxNuxtComponent", - "title": "Create a Nuxt Component", - "description": "Create a Nuxt Component for Nx.", - "type": "object", - "examples": [ - { - "command": "nx g component my-component --project=myapp", - "description": "Generate a component in the `myapp` application" - }, - { - "command": "nx g component my-component --project=myapp --classComponent", - "description": "Generate a class component in the `myapp` application" - } - ], - "properties": { - "project": { - "type": "string", - "description": "The name of the project.", - "alias": "p", - "$default": { - "$source": "projectName" - }, - "x-prompt": "What is the name of the project for this component?", - "x-priority": "important" - }, - "name": { - "type": "string", - "description": "The name of the component.", - "$default": { - "$source": "argv", - "index": 0 - }, - "x-prompt": "What name would you like to use for the component?", - "x-priority": "important" - }, - "skipTests": { - "type": "boolean", - "description": "When true, does not create `spec.ts` test files for the new component.", - "default": false, - "x-priority": "internal" - }, - "flat": { - "type": "boolean", - "description": "Create component at the source root rather than its own directory.", - "default": false - }, - "directory": { - "type": "string", - "description": "Create the component under this directory (can be nested).", - "alias": "dir", - "x-priority": "important" - }, - "pascalCaseFiles": { - "type": "boolean", - "description": "Use pascal case component file name (e.g. `App.vue`).", - "alias": "P", - "default": false - }, - "pascalCaseDirectory": { - "type": "boolean", - "description": "Use pascal case directory name (e.g. `App/App.vue`).", - "alias": "R", - "default": false - }, - "fileName": { - "type": "string", - "description": "Create a component with this file name." - }, - "inSourceTests": { - "type": "boolean", - "default": false, - "description": "When using Vitest, separate spec files will not be generated and instead will be included within the source files. Read more on the Vitest docs site: https://vitest.dev/guide/in-source.html" - }, - "skipFormat": { - "description": "Skip formatting files.", - "type": "boolean", - "default": false, - "x-priority": "internal" - } - }, - "required": ["name", "project"] -} diff --git a/packages/nuxt/src/generators/init/__snapshots__/init.spec.ts.snap b/packages/nuxt/src/generators/init/__snapshots__/init.spec.ts.snap index 4c421e02ed6b1..c0b882c92ba43 100644 --- a/packages/nuxt/src/generators/init/__snapshots__/init.spec.ts.snap +++ b/packages/nuxt/src/generators/init/__snapshots__/init.spec.ts.snap @@ -4,17 +4,20 @@ exports[`init should add nuxt dependencies 1`] = ` { "dependencies": {}, "devDependencies": { - "@nuxt/devtools": "1.0.0-beta.0", + "@nuxt/devtools": "1.0.0", + "@nuxt/ui-templates": "^1.3.1", "@nx/js": "0.0.1", "@nx/nuxt": "0.0.1", + "@nx/vite": "0.0.1", "@swc-node/register": "~1.6.7", "@swc/core": "~1.3.85", "h3": "^1.8.2", - "nuxt": "^3.7.4", + "nuxt": "^3.8.0", "prettier": "^2.6.2", "typescript": "~5.1.3", "vue": "^3.3.4", "vue-router": "^4.2.4", + "vue-tsc": "^1.8.8", }, "name": "@proj/source", } diff --git a/packages/nuxt/src/generators/init/init.ts b/packages/nuxt/src/generators/init/init.ts index 081500907eaf7..23026428bda96 100644 --- a/packages/nuxt/src/generators/init/init.ts +++ b/packages/nuxt/src/generators/init/init.ts @@ -10,27 +10,28 @@ import { nuxtDevtoolsVersion, nuxtVersion, h3Version, + nuxtUiTemplatesVersion, } from '../../utils/versions'; import { lessVersion, sassVersion, vueRouterVersion, vueVersion, + vueTscVersion, } from '@nx/vue'; import { InitSchema } from './schema'; function updateDependencies(host: Tree, schema: InitSchema) { - let dependencies: { [key: string]: string } = { - vue: vueVersion, - }; - let devDependencies: { [key: string]: string } = { '@nx/nuxt': nxVersion, + '@nx/vite': nxVersion, // needed for the nxViteTsPaths plugin '@nuxt/devtools': nuxtDevtoolsVersion, + '@nuxt/ui-templates': nuxtUiTemplatesVersion, nuxt: nuxtVersion, h3: h3Version, vue: vueVersion, 'vue-router': vueRouterVersion, + 'vue-tsc': vueTscVersion, }; if (schema.style === 'scss') { diff --git a/packages/nuxt/src/generators/page/page.spec.ts b/packages/nuxt/src/generators/page/page.spec.ts deleted file mode 100644 index 7f36e64acce03..0000000000000 --- a/packages/nuxt/src/generators/page/page.spec.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import { Tree } from '@nx/devkit'; -import { applicationGenerator } from '../application/application'; -import { getDirectory, pageGenerator } from './page'; - -describe('page', () => { - let tree: Tree; - const name = 'my-app'; - - describe('getDirectory', () => { - it('should return "pages" if no directory is provided', () => { - expect(getDirectory(undefined)).toEqual('pages'); - }); - - it('should return the directory unchanged if it already starts with "pages/"', () => { - expect(getDirectory('pages/someDir')).toEqual('pages/someDir'); - }); - - it('should prepend "pages/" to the directory if it does not start with "pages/"', () => { - expect(getDirectory('someDir')).toEqual('pages/someDir'); - }); - - it('should work with an empty string', () => { - expect(getDirectory('')).toEqual('pages'); - }); - }); - describe('generated files content - as-provided', () => { - beforeAll(async () => { - tree = createTreeWithEmptyWorkspace(); - await applicationGenerator(tree, { - name, - projectNameAndRootFormat: 'as-provided', - }); - }); - it('should create a new page in the correct location', async () => { - await pageGenerator(tree, { - name: 'about', - project: name, - }); - - expect(tree.exists('my-app/src/pages/about.vue')).toBeTruthy(); - }); - - it('should create a new page in the correct location for nested directory', async () => { - await pageGenerator(tree, { - name: 'about', - project: name, - }); - - expect(tree.exists('my-app/src/pages/about.vue')).toBeTruthy(); - }); - }); -}); diff --git a/packages/nuxt/src/generators/page/page.ts b/packages/nuxt/src/generators/page/page.ts deleted file mode 100644 index d005920f002a7..0000000000000 --- a/packages/nuxt/src/generators/page/page.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { formatFiles, joinPathFragments, Tree } from '@nx/devkit'; -import { componentGenerator } from '../component/component'; -import { Schema } from './schema'; - -export async function pageGenerator(host: Tree, options: Schema) { - await componentGenerator(host, { - ...options, - directory: getDirectory(options.directory), - skipTests: true, - flat: true, - pascalCaseFiles: false, // it's good to keep route names lowercase - pascalCaseDirectory: false, - skipFormat: true, - }); - - if (!options.skipFormat) { - await formatFiles(host); - } -} - -export function getDirectory(directory: string) { - return directory?.length > 0 - ? directory.startsWith('pages/') - ? directory - : joinPathFragments('pages', directory) - : 'pages'; -} - -export default pageGenerator; diff --git a/packages/nuxt/src/generators/page/schema.d.ts b/packages/nuxt/src/generators/page/schema.d.ts deleted file mode 100644 index c3c8815adcc69..0000000000000 --- a/packages/nuxt/src/generators/page/schema.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface Schema { - project: string; - name: string; - directory?: string; - fileName?: string; - skipFormat?: boolean; -} diff --git a/packages/nuxt/src/generators/page/schema.json b/packages/nuxt/src/generators/page/schema.json deleted file mode 100644 index 481722b5fc6c2..0000000000000 --- a/packages/nuxt/src/generators/page/schema.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "$schema": "http://json-schema.org/schema", - "cli": "nx", - "$id": "NxNuxtPage", - "title": "Create a Nuxt page", - "description": "Create a Nuxt page for Nx.", - "type": "object", - "examples": [ - { - "command": "nx g page new-page --project=myapp", - "description": "Generate a page in the `myapp` application" - } - ], - "properties": { - "project": { - "type": "string", - "description": "The name of the project.", - "alias": "p", - "$default": { - "$source": "projectName" - }, - "x-prompt": "What is the name of the project for this page?", - "x-priority": "important" - }, - "name": { - "type": "string", - "description": "The name of the page.", - "$default": { - "$source": "argv", - "index": 0 - }, - "x-prompt": "What name would you like to use for the page?", - "x-priority": "important" - }, - "directory": { - "type": "string", - "description": "Create the page under this directory - all nested directories will be created under the pages directory.", - "alias": "dir" - }, - "fileName": { - "type": "string", - "description": "Create a component with this file name." - }, - "skipFormat": { - "description": "Skip formatting files.", - "type": "boolean", - "default": false, - "x-priority": "internal" - } - }, - "required": ["name", "project"] -} diff --git a/packages/nuxt/src/generators/stories/schema.json b/packages/nuxt/src/generators/stories/schema.json deleted file mode 100644 index 361ef58d269b5..0000000000000 --- a/packages/nuxt/src/generators/stories/schema.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "$schema": "http://json-schema.org/schema", - "cli": "nx", - "$id": "NxNuxtStorybookStories", - "title": "Generate Nuxt Storybook stories", - "description": "Generate stories/specs for all components declared in a project.", - "type": "object", - "properties": { - "project": { - "type": "string", - "aliases": ["name", "projectName"], - "description": "Project for which to generate stories.", - "$default": { - "$source": "projectName", - "index": 0 - }, - "x-prompt": "For which project do you want to generate stories?", - "x-priority": "important" - }, - "generateCypressSpecs": { - "type": "boolean", - "description": "Automatically generate `*.spec.ts` files in the cypress e2e app generated by the cypress-configure generator." - }, - "cypressProject": { - "type": "string", - "description": "The Cypress project to generate the stories under. This is inferred from `project` by default." - }, - "interactionTests": { - "type": "boolean", - "description": "Set up Storybook interaction tests.", - "x-prompt": "Do you want to set up Storybook interaction tests?", - "x-priority": "important", - "default": true - }, - "js": { - "type": "boolean", - "description": "Generate JavaScript files rather than TypeScript files.", - "default": false - }, - "ignorePaths": { - "type": "array", - "description": "Paths to ignore when looking for components.", - "items": { - "type": "string", - "description": "Path to ignore." - }, - "default": [ - "*.stories.ts,*.stories.tsx,*.stories.js,*.stories.jsx,*.stories.mdx" - ], - "examples": [ - "apps/my-app/src/not-stories/**", - "**/**/src/**/not-stories/**", - "libs/my-lib/**/*.something.ts", - "**/**/src/**/*.other.*", - "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" - ] - }, - "skipFormat": { - "description": "Skip formatting files.", - "type": "boolean", - "default": false, - "x-priority": "internal" - } - }, - "required": ["project"], - "examplesFile": "../../../docs/stories-examples.md" -} diff --git a/packages/nuxt/src/generators/stories/stories.ts b/packages/nuxt/src/generators/stories/stories.ts deleted file mode 100644 index bbe3458c18cbd..0000000000000 --- a/packages/nuxt/src/generators/stories/stories.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { runTasksInSerial, Tree } from '@nx/devkit'; -import { - storiesGenerator as vueStoriesGenerator, - StorybookStoriesSchema, -} from '@nx/vue'; - -/* - * This generator is basically the Vue one - */ -export async function storiesGenerator( - host: Tree, - options: StorybookStoriesSchema -) { - const storiesGenerator = await vueStoriesGenerator(host, { - ...options, - }); - - return runTasksInSerial(storiesGenerator); -} - -export default storiesGenerator; diff --git a/packages/nuxt/src/generators/storybook-configuration/__snapshots__/configuration.spec.ts.snap b/packages/nuxt/src/generators/storybook-configuration/__snapshots__/configuration.spec.ts.snap index e293df068a7d7..9ed86adc62228 100644 --- a/packages/nuxt/src/generators/storybook-configuration/__snapshots__/configuration.spec.ts.snap +++ b/packages/nuxt/src/generators/storybook-configuration/__snapshots__/configuration.spec.ts.snap @@ -29,3 +29,24 @@ export default config; `; exports[`nuxt:storybook-configuration should configure with vue3 framework and styles import 2`] = `""`; + +exports[`nuxt:storybook-configuration should configure with vue3 framework and styles import 3`] = ` +"{ + "extends": "./tsconfig.json", + "compilerOptions": { + "emitDecoratorMetadata": true, + "composite": true + }, + "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"], + "include": [ + "src/**/*.stories.ts", + "src/**/*.stories.js", + "src/**/*.stories.jsx", + "src/**/*.stories.tsx", + "src/**/*.stories.mdx", + ".storybook/*.js", + ".storybook/*.ts" + ] +} +" +`; diff --git a/packages/nuxt/src/generators/storybook-configuration/configuration.spec.ts b/packages/nuxt/src/generators/storybook-configuration/configuration.spec.ts index 2c18fc206ac6e..c819c7e14b268 100644 --- a/packages/nuxt/src/generators/storybook-configuration/configuration.spec.ts +++ b/packages/nuxt/src/generators/storybook-configuration/configuration.spec.ts @@ -2,8 +2,8 @@ import { logger, Tree } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { Linter } from '@nx/eslint'; import applicationGenerator from '../application/application'; -import componentGenerator from '../component/component'; import storybookConfigurationGenerator from './configuration'; +import { componentGenerator } from '@nx/vue'; const componentContent = `