diff --git a/docs/generated/packages/vite.json b/docs/generated/packages/vite.json index 66b524012889cf..e65fb0ae88666d 100644 --- a/docs/generated/packages/vite.json +++ b/docs/generated/packages/vite.json @@ -82,6 +82,18 @@ "description": "Is this a new project?", "default": false, "hidden": true + }, + "buildTarget": { + "type": "string", + "description": "The build target of the project to be transformed to use the @nrwl/vite:build executor." + }, + "serveTarget": { + "type": "string", + "description": "The serve target of the project to be transformed to use the @nrwl/vite:dev-server executor." + }, + "testTarget": { + "type": "string", + "description": "The test target of the project to be transformed to use the @nrwl/vite:test executor." } }, "examplesFile": "This is a generator for setting up Vite configuration for an existing React or Web application. It will change the build and serve targets to use the `@nrwl/vite` executors for serving and building the application. This generator will modify your code, so make sure to commit your changes before running it.\n\n```bash\nnx g @nrwl/vite:configuration\n```\n\nWhen running this generator, you will be prompted to provide the following:\n\n- The `project`, as the name of the project you want to generate the configuration for.\n- The `uiFramework` you want to use. Supported values are: `react` and `none`.\n\nYou must provide a `project` and a `uiFramework` for the generator to work.\n\nYou can read more about how this generator works, in the [Vite package overview page](/packages/vite).\n\n## Examples\n\n### Change a React app to use Vite\n\n```bash\nnx g @nrwl/vite:configuration --project=my-app --uiFramework=react\n```\n\nThis will change the `my-app` project to use Vite instead of the default Webpack configuration. The changes this generator will do are described in the [Vite package overview page](/packages/vite).\n\n### Change a Web app to use Vite\n\n```bash\nnx g @nrwl/vite:configuration --project=my-app --uiFramework=none\n```\n\nThis will change the `my-app` project to use Vite instead of the existing bundler configuration.\n", diff --git a/packages/vite/src/generators/configuration/configuration.ts b/packages/vite/src/generators/configuration/configuration.ts index abbf8b98992bd1..658454c183bba9 100644 --- a/packages/vite/src/generators/configuration/configuration.ts +++ b/packages/vite/src/generators/configuration/configuration.ts @@ -13,6 +13,7 @@ import { editTsConfig, moveAndEditIndexHtml, writeViteConfig, + handleUnsupportedCustomTargets, } from '../../utils/generator-utils'; import initGenerator from '../init/init'; @@ -28,27 +29,52 @@ export async function viteConfigurationGenerator(tree: Tree, schema: Schema) { ); let buildTargetName = 'build'; let serveTargetName = 'serve'; + let testTargetName = 'test'; schema.includeLib ??= projectType === 'library'; if (!schema.newProject) { - const { buildTarget, serveTarget, unsuppored } = - findExistingTargets(targets); + const { + buildTarget, + serveTarget, + testTarget, + unsupported, + unsupportedCustomTarget, + } = findExistingTargets(targets, { + build: schema.buildTarget, + serve: schema.serveTarget, + test: schema.testTarget, + }); /** - * Here, we make sure that the project has a build target - * and it is unsupported, before throwing the error. + * Here, we make sure that the project has only + * unsupported build targets before throwing the error. * The reason is that the project could not have a build * target at all, in which case we don't want to throw. - * Or the project can have multiple build targets, one of which unsupported. + * Or the project can have multiple build targets, + * one of which unsupported. * In that case, we convert the supported one. */ - if (!buildTarget && unsuppored) { + if (!buildTarget && unsupported) { throw new Error( `The project ${schema.project} cannot be converted to use the @nrwl/vite executors.` ); } + await handleUnsupportedCustomTargets( + unsupportedCustomTarget, + { + build: schema.buildTarget, + serve: schema.serveTarget, + test: schema.testTarget, + }, + { + build: buildTargetName, + serve: serveTargetName, + test: testTarget, + } + ); + buildTargetName = buildTarget ?? buildTargetName; serveTargetName = serveTarget ?? serveTargetName; diff --git a/packages/vite/src/generators/configuration/schema.d.ts b/packages/vite/src/generators/configuration/schema.d.ts index 9533d025cff33e..a18e5bf3da0e0b 100644 --- a/packages/vite/src/generators/configuration/schema.d.ts +++ b/packages/vite/src/generators/configuration/schema.d.ts @@ -5,4 +5,7 @@ export interface Schema { includeVitest?: boolean; inSourceTests?: boolean; includeLib?: boolean; + buildTarget?: string; + serveTarget?: string; + testTarget?: string; } diff --git a/packages/vite/src/generators/configuration/schema.json b/packages/vite/src/generators/configuration/schema.json index c506bd76916294..759cf4f30e0948 100644 --- a/packages/vite/src/generators/configuration/schema.json +++ b/packages/vite/src/generators/configuration/schema.json @@ -33,6 +33,18 @@ "description": "Is this a new project?", "default": false, "hidden": true + }, + "buildTarget": { + "type": "string", + "description": "The build target of the project to be transformed to use the @nrwl/vite:build executor." + }, + "serveTarget": { + "type": "string", + "description": "The serve target of the project to be transformed to use the @nrwl/vite:dev-server executor." + }, + "testTarget": { + "type": "string", + "description": "The test target of the project to be transformed to use the @nrwl/vite:test executor." } }, "examplesFile": "../../../docs/configuration-examples.md" diff --git a/packages/vite/src/utils/generator-utils.ts b/packages/vite/src/utils/generator-utils.ts index c6a7c67871b580..5933f81eb500cc 100644 --- a/packages/vite/src/utils/generator-utils.ts +++ b/packages/vite/src/utils/generator-utils.ts @@ -14,15 +14,33 @@ import { ViteDevServerExecutorOptions } from '../executors/dev-server/schema'; import { VitestExecutorOptions } from '../executors/test/schema'; import { Schema } from '../generators/configuration/schema'; -export function findExistingTargets(targets: { - [targetName: string]: TargetConfiguration; -}): { +export function findExistingTargets( + targets: { + [targetName: string]: TargetConfiguration; + }, + customTargets?: { + build?: string; + serve?: string; + test?: string; + } +): { buildTarget?: string; serveTarget?: string; testTarget?: string; - unsuppored?: boolean; + unsupported?: boolean; + unsupportedCustomTarget?: { + build?: boolean; + serve?: boolean; + test?: boolean; + }; } { - let buildTarget, serveTarget, testTarget, unsuppored; + let buildTarget, + serveTarget, + testTarget, + unsupported, + unsupportedCustomTargetBuild, + unsupportedCustomTargetServe, + unsupportedCustomTargetTest; const arrayOfBuilders = [ '@nxext/vite:build', @@ -52,6 +70,30 @@ export function findExistingTargets(targets: { '@nrwl/js:tsc', ]; + if (customTargets.build) { + if (arrayOfBuilders.includes(targets[customTargets.build].executor)) { + buildTarget = customTargets.build; + } else { + unsupportedCustomTargetBuild = true; + } + } + + if (customTargets.serve) { + if (arrayOfServers.includes(targets[customTargets.serve].executor)) { + buildTarget = customTargets.serve; + } else { + unsupportedCustomTargetServe = true; + } + } + + if (customTargets.test) { + if (arrayOfServers.includes(targets[customTargets.test].executor)) { + buildTarget = customTargets.test; + } else { + unsupportedCustomTargetTest = true; + } + } + for (const target in targets) { if (buildTarget && serveTarget && testTarget) { break; @@ -66,7 +108,7 @@ export function findExistingTargets(targets: { testTarget = target; } if (arrayofUnsupported.includes(targets[target].executor)) { - unsuppored = true; + unsupported = true; } } @@ -74,7 +116,12 @@ export function findExistingTargets(targets: { buildTarget, serveTarget, testTarget, - unsuppored, + unsupported, + unsupportedCustomTarget: { + build: unsupportedCustomTargetBuild, + serve: unsupportedCustomTargetServe, + test: unsupportedCustomTargetTest, + }, }; } @@ -497,3 +544,76 @@ export function getViteConfigPathForProject( return normalizeViteConfigFilePathWithTree(tree, root, viteConfigPath); } + +export async function handleUnsupportedCustomTargets( + unsupportedCustomTarget?: { + build?: boolean; + serve?: boolean; + test?: boolean; + }, + customTargets?: { + build: string; + serve: string; + test: string; + }, + targets?: { + build: string; + serve: string; + test: string; + } +) { + if (unsupportedCustomTarget.build && targets.build) { + await handleUnsupportedCustomTargetsErrors( + customTargets.build, + targets.build, + 'build', + 'build' + ); + } + + if (unsupportedCustomTarget.serve && targets.serve) { + await handleUnsupportedCustomTargetsErrors( + customTargets.serve, + targets.serve, + 'serve', + 'dev-server' + ); + } + + if (unsupportedCustomTarget.test && targets.test) { + await handleUnsupportedCustomTargetsErrors( + customTargets.test, + targets.test, + 'test', + 'test' + ); + } +} + +export async function handleUnsupportedCustomTargetsErrors( + customTarget: string, + foundTarget: string, + action: 'build' | 'serve' | 'test', + executor: 'build' | 'dev-server' | 'test' +) { + logger.warn( + `The custom ${action} target you provided (${customTarget}) cannot be converted to use the @nrwl/vite:${executor} executor. + However, we found the following ${action} target in your project that can be converted: ${foundTarget} + ` + ); + const { Confirm } = require('enquirer'); + const prompt = new Confirm({ + name: 'question', + message: `Should we convert this target to use the @nrwl/vite:${executor} executor?`, + initial: true, + }); + const shouldConvert = await prompt.run(); + if (!shouldConvert) { + throw new Error( + `The ${action} target ${customTarget} cannot be converted to use the @nrwl/vite:${executor} executor. + Please try again, either by providing a different ${action} target or by not providing a target at all (Nx will + convert the first one it finds, most probably this one: ${foundTarget}) + ` + ); + } +}