From 1a3cc515a411961e64d102470a3bcd88d6e69183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Thu, 1 Dec 2022 12:07:52 +0100 Subject: [PATCH] fix(core): prevent peer deps from ending up as dev deps in create package json (#13502) --- e2e/next/src/next.test.ts | 6 +- e2e/node/src/node.test.ts | 2 +- .../build/lib/create-package-json.ts | 1 + packages/nx/src/utils/create-package-json.ts | 68 ++++++++++++------- 4 files changed, 50 insertions(+), 27 deletions(-) diff --git a/e2e/next/src/next.test.ts b/e2e/next/src/next.test.ts index b840e004c17e3..7fc883be6e073 100644 --- a/e2e/next/src/next.test.ts +++ b/e2e/next/src/next.test.ts @@ -242,11 +242,11 @@ describe('Next.js Applications', () => { if (found) throw new Error('Found SVGR plugin'); console.log('NODE_ENV is', process.env.NODE_ENV); - + return config; } }; - + module.exports = withNx(nextConfig); ` ); @@ -265,7 +265,7 @@ describe('Next.js Applications', () => { const { withNx } = require('@nrwl/next/plugins/with-nx'); // Not including "nx" entry should still work. const nextConfig = {}; - + module.exports = withNx(nextConfig); ` ); diff --git a/e2e/node/src/node.test.ts b/e2e/node/src/node.test.ts index 305b2ff3a4c02..b556236053f59 100644 --- a/e2e/node/src/node.test.ts +++ b/e2e/node/src/node.test.ts @@ -229,7 +229,7 @@ describe('Build Node apps', () => { afterEach(() => cleanupProject()); - it('should generate a package.json with the `--generatePackageJson` flag MMM', async () => { + it('should generate a package.json with the `--generatePackageJson` flag', async () => { const scope = newProject(); const nestapp = uniq('nestapp'); runCLI(`generate @nrwl/nest:app ${nestapp} --linter=eslint`); diff --git a/packages/next/src/executors/build/lib/create-package-json.ts b/packages/next/src/executors/build/lib/create-package-json.ts index 9371898005ac4..c26e2805d6611 100644 --- a/packages/next/src/executors/build/lib/create-package-json.ts +++ b/packages/next/src/executors/build/lib/create-package-json.ts @@ -27,6 +27,7 @@ export async function createPackageJson( const typescriptNode = context.projectGraph.externalNodes['npm:typescript']; if (typescriptNode) { + packageJson.dependencies = packageJson.dependencies || {}; packageJson.dependencies['typescript'] = typescriptNode.data.version; } diff --git a/packages/nx/src/utils/create-package-json.ts b/packages/nx/src/utils/create-package-json.ts index 475f92211b650..c7f64745aaa8f 100644 --- a/packages/nx/src/utils/create-package-json.ts +++ b/packages/nx/src/utils/create-package-json.ts @@ -1,8 +1,9 @@ import { readJsonFile } from './fileutils'; -import { sortObjectByKeys } from 'nx/src/utils/object-sort'; +import { sortObjectByKeys } from './object-sort'; import { ProjectGraph } from '../config/project-graph'; import { PackageJson } from './package-json'; import { existsSync } from 'fs'; +import { workspaceRoot } from './workspace-root'; /** * Creates a package.json in the output directory for support to install dependencies within containers. @@ -18,40 +19,47 @@ export function createPackageJson( ): PackageJson { const npmDeps = findAllNpmDeps(projectName, graph); // default package.json if one does not exist - let packageJson = { + let packageJson: PackageJson = { name: projectName, version: '0.0.1', - dependencies: {}, - devDependencies: {}, }; if (existsSync(`${graph.nodes[projectName].data.root}/package.json`)) { try { packageJson = readJsonFile( `${graph.nodes[projectName].data.root}/package.json` ); - if (!packageJson.dependencies) { - packageJson.dependencies = {}; - } - if (!packageJson.devDependencies) { - packageJson.devDependencies = {}; - } } catch (e) {} } - const rootPackageJson = readJsonFile(`${options.root || '.'}/package.json`); - Object.entries(npmDeps).forEach(([packageName, version]) => { + const rootPackageJson = readJsonFile( + `${options.root || workspaceRoot}/package.json` + ); + Object.entries(npmDeps.dependencies).forEach(([packageName, version]) => { if ( rootPackageJson.devDependencies?.[packageName] && - !packageJson.dependencies[packageName] + !packageJson.dependencies?.[packageName] && + !packageJson.peerDependencies?.[packageName] ) { + packageJson.devDependencies = packageJson.devDependencies || {}; packageJson.devDependencies[packageName] = version; } else { + if (!packageJson.peerDependencies?.[packageName]) { + packageJson.dependencies = packageJson.dependencies || {}; + packageJson.dependencies[packageName] = version; + } + } + }); + Object.entries(npmDeps.peerDependencies).forEach(([packageName, version]) => { + if (!packageJson.peerDependencies?.[packageName]) { packageJson.dependencies[packageName] = version; } }); packageJson.devDependencies &&= sortObjectByKeys(packageJson.devDependencies); packageJson.dependencies &&= sortObjectByKeys(packageJson.dependencies); + packageJson.peerDependencies &&= sortObjectByKeys( + packageJson.peerDependencies + ); return packageJson; } @@ -59,20 +67,29 @@ export function createPackageJson( function findAllNpmDeps( projectName: string, graph: ProjectGraph, - list: { [packageName: string]: string } = {}, + list: { + dependencies: Record; + peerDependencies: Record; + } = { dependencies: {}, peerDependencies: {} }, seen = new Set() ) { + const node = graph.externalNodes[projectName]; + if (seen.has(projectName)) { + // if it's in peerDependencies, move it to regular dependencies + // since this is a direct dependency of the project + if (node && list.peerDependencies[node.data.packageName]) { + list.dependencies[node.data.packageName] = node.data.version; + delete list.peerDependencies[node.data.packageName]; + } return list; } seen.add(projectName); - const node = graph.externalNodes[projectName]; - if (node) { - list[node.data.packageName] = node.data.version; - recursivelyCollectPeerDependencies(node.name, graph, list); + list.dependencies[node.data.packageName] = node.data.version; + recursivelyCollectPeerDependencies(node.name, graph, list, seen); } else { // we are not interested in the dependencies of external projects graph.dependencies[projectName]?.forEach((dep) => { @@ -88,15 +105,17 @@ function findAllNpmDeps( function recursivelyCollectPeerDependencies( projectName: string, graph: ProjectGraph, - list: { [packageName: string]: string } = {}, + list: { + dependencies: Record; + peerDependencies: Record; + }, seen = new Set() ) { const npmPackage = graph.externalNodes[projectName]; - if (!npmPackage || seen.has(projectName)) { + if (!npmPackage) { return list; } - seen.add(projectName); const packageName = npmPackage.data.packageName; try { const packageJson = require(`${packageName}/package.json`); @@ -110,9 +129,12 @@ function recursivelyCollectPeerDependencies( .filter(Boolean) .forEach((node) => { if ( - !packageJson.peerDependenciesMeta?.[node.data.packageName]?.optional + !packageJson.peerDependenciesMeta?.[node.data.packageName] + ?.optional && + !seen.has(node.name) ) { - list[node.data.packageName] = node.data.version; + seen.add(node.name); + list.peerDependencies[node.data.packageName] = node.data.version; recursivelyCollectPeerDependencies(node.name, graph, list, seen); } });