UNPKG

@nx/next

Version:

The Next.js plugin for Nx contains executors and generators for managing Next.js applications and libraries within an Nx workspace. It provides: - Scaffolding for creating, building, serving, linting, and testing Next.js applications. - Integration wit

83 lines (82 loc) 4.19 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.updateNextConfig = updateNextConfig; const utils_1 = require("./utils"); const tsquery_1 = require("@phenomnomnominal/tsquery"); const ts = require("typescript"); function updateNextConfig(tree, updatedConfigFileContents, project, migrationLogs) { const nextConfigPath = (0, utils_1.findNextConfigPath)(tree, project.root); if (!nextConfigPath) { migrationLogs.addLog({ project: project.projectName, executorName: '@nx/next:build', log: `The project ${project.projectName} does not use a supported Next.js config file format. Only .js and .cjs files using "composePlugins" is supported. Leaving it as is.`, }); return; } const nextConfigContents = tree.read(nextConfigPath, 'utf-8'); let ast = tsquery_1.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 = (0, tsquery_1.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 = (0, tsquery_1.tsquery)(ast, composePluginsQuery)[0]; if (!composePluginNode) { migrationLogs.addLog({ project: project.projectName, executorName: '@nx/next:build', log: `The project ${project.projectName} does not use a supported Next.js config file format. Only .js and .cjs files using "composePlugins" is supported. Leaving it as is.`, }); return; } let lastRequireEndPosition = -1; const findLastRequire = (node) => { if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === 'require') { lastRequireEndPosition = node.end; } ts.forEachChild(node, findLastRequire); }; findLastRequire(ast); let updatedCode = ` ${nextConfigContents.slice(0, lastRequireEndPosition)}\n ${updatedConfigFileContents}\n\n ${nextConfigContents.slice(lastRequireEndPosition)} `; ast = tsquery_1.tsquery.ast(updatedCode); const nextConfigNode = (0, tsquery_1.tsquery)(ast, 'VariableDeclaration:has(Identifier[name=nextConfig]) ObjectLiteralExpression')[0]; if (nextConfigNode) { const nxNode = (0, tsquery_1.tsquery)(nextConfigNode, 'PropertyAssignment:has(Identifier[name=nx]) ObjectLiteralExpression')[0]; if (nxNode) { const spread = ts.factory.createSpreadAssignment(ts.factory.createIdentifier('options')); const updatedNxNode = ts.factory.updateObjectLiteralExpression(nxNode, ts.factory.createNodeArray([...nxNode['properties'], spread])); const transformer = (context) => (rootNode) => { function visit(node) { if (node === nxNode) { return updatedNxNode; } return ts.visitEachChild(node, visit, context); } return ts.visitNode(rootNode, visit); }; const result = ts.transform(ast, [transformer]); const transformedSourceFile = result.transformed[0]; const printer = ts.createPrinter(); updatedCode = printer.printFile(transformedSourceFile); } tree.write(nextConfigPath, updatedCode); } }