diff --git a/packages/next/src/generators/convert-to-inferred/convert-to-inferred.spec.ts b/packages/next/src/generators/convert-to-inferred/convert-to-inferred.spec.ts index 58123956b9687..0cd4ccd8791d5 100644 --- a/packages/next/src/generators/convert-to-inferred/convert-to-inferred.spec.ts +++ b/packages/next/src/generators/convert-to-inferred/convert-to-inferred.spec.ts @@ -381,8 +381,10 @@ describe('convert-to-inferred', () => { {}, { build: { + debug: true, + profile: true, experimentalAppOnly: true, - experimentalBuildMode: true, + experimentalBuildMode: 'generate', }, } ); @@ -391,10 +393,33 @@ describe('convert-to-inferred', () => { await convertToInferred(tree, { project: project.name }); const projectConfig = readProjectConfiguration(tree, project.name); - expect(projectConfig.targets.build).toMatchObject({ - options: { - args: ['--experimental-app-only', '--experimental-build-mode'], - }, + expect(projectConfig.targets.build.options).toEqual({ + args: [ + '--debug', + '--profile', + '--experimental-app-only', + '--experimental-build-mode generate', + ], }); }); + + it('should not migrate options to CLI args if they are booleans and are false', async () => { + const project = createProject( + tree, + {}, + { + build: { + debug: false, + profile: false, + experimentalAppOnly: false, + }, + } + ); + writeNextConfig(tree, project.root); + + await convertToInferred(tree, { project: project.name }); + + const projectConfig = readProjectConfiguration(tree, project.name); + expect(projectConfig.targets.build.options).toBeUndefined(); + }); }); diff --git a/packages/next/src/generators/convert-to-inferred/lib/build-post-target-transformer.ts b/packages/next/src/generators/convert-to-inferred/lib/build-post-target-transformer.ts index 02fb153bfadcf..c209c4c3c17ff 100644 --- a/packages/next/src/generators/convert-to-inferred/lib/build-post-target-transformer.ts +++ b/packages/next/src/generators/convert-to-inferred/lib/build-post-target-transformer.ts @@ -157,17 +157,36 @@ function handlePropertiesFromTargetOptions( delete options.watch; } - if ('experimentalAppOnly' in options && options.experimentalAppOnly) { - options['args'] ??= []; - options['args'].push('--experimental-app-only'); + if ('debug' in options) { + if (options.debug) { + options['args'] ??= []; + options['args'].push('--debug'); + } + delete options.debug; + } + + if ('profile' in options) { + if (options.profile) { + options['args'] ??= []; + options['args'].push('--profile'); + } + delete options.profile; + } + + if ('experimentalAppOnly' in options) { + if (options.experimentalAppOnly) { + options['args'] ??= []; + options['args'].push('--experimental-app-only'); + } delete options.experimentalAppOnly; } - if ('experimentalBuildMode' in options && options.experimentalBuildMode) { + if ('experimentalBuildMode' in options) { options['args'] ??= []; - options['args'].push(`--experimental-build-mode`); + options['args'].push( + `--experimental-build-mode ${options.experimentalBuildMode}` + ); delete options.experimentalBuildMode; } - configValues[configuration] = configMap; } diff --git a/packages/next/src/generators/convert-to-inferred/lib/update-next-config.spec.ts b/packages/next/src/generators/convert-to-inferred/lib/update-next-config.spec.ts index c22b7ef21b67d..e44c0adfb1ca1 100644 --- a/packages/next/src/generators/convert-to-inferred/lib/update-next-config.spec.ts +++ b/packages/next/src/generators/convert-to-inferred/lib/update-next-config.spec.ts @@ -145,4 +145,80 @@ describe('UpdateNextConfig', () => { project: 'no-compose-plugins', }); }); + + describe('Reserved variables', () => { + it('should warn the user if the next config file contains reserved variables', () => { + const initConfig = ` + const options = {}; + const configValues = {}; + const configuration = {}; + `; + const projectDetails = { + projectName: 'reserved-variables', + root: 'reserved-variables', + }; + tree.write(`${projectDetails.root}/next.config.js`, initConfig); + + updateNextConfig(tree, '', projectDetails, mockLog); + + expect(mockLog.addLog).toHaveBeenCalledWith({ + executorName: '@nx/next:build', + log: "The project (reserved-variables) Next.js config contains reserved variables ('options', 'configValues' or 'configuration') which are generated during the migration. Leaving it as is.", + project: 'reserved-variables', + }); + }); + + it('should warn the user if the next config file contains a reserved variable (option)', () => { + const initConfig = `const options = {};`; + const projectDetails = { + projectName: 'reserved-options', + root: 'reserved-options', + }; + tree.write(`${projectDetails.root}/next.config.js`, initConfig); + + updateNextConfig(tree, '', projectDetails, mockLog); + + expect(mockLog.addLog).toHaveBeenCalledWith({ + executorName: '@nx/next:build', + log: "The project (reserved-options) Next.js config contains reserved variables ('options', 'configValues' or 'configuration') which are generated during the migration. Leaving it as is.", + project: 'reserved-options', + }); + }); + + it('should warn the user if the next config file contains a reserved variable (configValues)', () => { + const initConfig = `const configValues = {};`; + const projectDetails = { + projectName: 'reserved-config-values', + root: 'reserved-config-values', + }; + + tree.write(`${projectDetails.root}/next.config.js`, initConfig); + + updateNextConfig(tree, '', projectDetails, mockLog); + + expect(mockLog.addLog).toHaveBeenCalledWith({ + executorName: '@nx/next:build', + log: "The project (reserved-config-values) Next.js config contains reserved variables ('options', 'configValues' or 'configuration') which are generated during the migration. Leaving it as is.", + project: 'reserved-config-values', + }); + }); + + it('should warn the user if the next config file contains a reserved variable (configuration)', () => { + const initConfig = `const configuration = {};`; + const projectDetails = { + projectName: 'reserved-configuration-values', + root: 'reserved-configuration-values', + }; + + tree.write(`${projectDetails.root}/next.config.js`, initConfig); + + updateNextConfig(tree, '', projectDetails, mockLog); + + expect(mockLog.addLog).toHaveBeenCalledWith({ + executorName: '@nx/next:build', + log: "The project (reserved-configuration-values) Next.js config contains reserved variables ('options', 'configValues' or 'configuration') which are generated during the migration. Leaving it as is.", + project: 'reserved-configuration-values', + }); + }); + }); }); diff --git a/packages/next/src/generators/convert-to-inferred/lib/update-next-config.ts b/packages/next/src/generators/convert-to-inferred/lib/update-next-config.ts index a4dda729c4947..53c3903e08b4d 100644 --- a/packages/next/src/generators/convert-to-inferred/lib/update-next-config.ts +++ b/packages/next/src/generators/convert-to-inferred/lib/update-next-config.ts @@ -23,6 +23,22 @@ export function updateNextConfig( const nextConfigContents = tree.read(nextConfigPath, 'utf-8'); let ast = tsquery.ast(nextConfigContents); + const reservedVarQuery = ` + VariableStatement > VariableDeclarationList > VariableDeclaration:has(Identifier[name=configValues]), + VariableStatement > VariableDeclarationList > VariableDeclaration:has(Identifier[name=configuration]), + VariableStatement > VariableDeclarationList > VariableDeclaration:has(Identifier[name=options]) + `; + + const matches = tsquery(ast, reservedVarQuery); + if (matches.length > 0) { + migrationLogs.addLog({ + project: project.projectName, + executorName: '@nx/next:build', + log: `The project (${project.projectName}) Next.js config contains reserved variables ('options', 'configValues' or 'configuration') which are generated during the migration. Leaving it as is.`, + }); + return; + } + // Query to check for composePlugins in module.exports const composePluginsQuery = `ExpressionStatement > BinaryExpression > CallExpression > CallExpression:has(Identifier[name=composePlugins])`; const composePluginNode = tsquery(ast, composePluginsQuery)[0];