From 28a071f2432e34757581ad5713b2e9361bd95f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Jona=C5=A1?= Date: Wed, 5 Jul 2023 17:47:49 +0200 Subject: [PATCH 1/2] fix(js): ignore dependencies from non-index root files for create-package-json (#17930) --- .../src/rules/dependency-checks.ts | 13 +++++++--- .../src/utils/package-json-utils.ts | 22 ++++++++++------ .../package-json/update-package-json.spec.ts | 2 +- .../js/package-json/create-package-json.ts | 26 +++++++++++++++---- 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/packages/eslint-plugin/src/rules/dependency-checks.ts b/packages/eslint-plugin/src/rules/dependency-checks.ts index 9b047098fc978..25c4ae9c400e0 100644 --- a/packages/eslint-plugin/src/rules/dependency-checks.ts +++ b/packages/eslint-plugin/src/rules/dependency-checks.ts @@ -9,6 +9,7 @@ import { satisfies } from 'semver'; import { getHelperDependenciesFromProjectGraph } from '@nx/js'; import { getAllDependencies, + getPackageJson, removePackageJsonFromFileMap, } from '../utils/package-json-utils'; import { JSONLiteral } from 'jsonc-eslint-parser/lib/parser/ast'; @@ -126,13 +127,17 @@ export default createESLintRule({ projectGraph ); + const rootPackageJson = getPackageJson(join(workspaceRoot, 'package.json')); + // find all dependencies for the project const npmDeps = findProjectsNpmDependencies( sourceProject, projectGraph, buildTarget, + rootPackageJson, { helperDependencies: helperDependencies.map((dep) => dep.target), + isProduction: true, }, removePackageJsonFromFileMap(projectFileMap) ); @@ -148,12 +153,12 @@ export default createESLintRule({ 'package.json' ); - globalThis.projPackageJsonDeps ??= getAllDependencies(projPackageJsonPath); + globalThis.projPackageJsonDeps ??= getAllDependencies( + getPackageJson(projPackageJsonPath) + ); const projPackageJsonDeps: Record = globalThis.projPackageJsonDeps; - const rootPackageJsonDeps = getAllDependencies( - join(workspaceRoot, 'package.json') - ); + const rootPackageJsonDeps = getAllDependencies(rootPackageJson); function validateMissingDependencies(node: AST.JSONProperty) { if (!checkMissingDependencies) { diff --git a/packages/eslint-plugin/src/utils/package-json-utils.ts b/packages/eslint-plugin/src/utils/package-json-utils.ts index 4423ab7128d9d..bf1759d37f32e 100644 --- a/packages/eslint-plugin/src/utils/package-json-utils.ts +++ b/packages/eslint-plugin/src/utils/package-json-utils.ts @@ -1,16 +1,22 @@ import { ProjectFileMap, readJsonFile } from '@nx/devkit'; import { existsSync } from 'fs'; +import { PackageJson } from 'nx/src/utils/package-json'; -export function getAllDependencies(path: string): Record { +export function getAllDependencies( + packageJson: PackageJson +): Record { + return { + ...packageJson.dependencies, + ...packageJson.devDependencies, + ...packageJson.peerDependencies, + }; +} + +export function getPackageJson(path: string): PackageJson { if (existsSync(path)) { - const packageJson = readJsonFile(path); - return { - ...packageJson.dependencies, - ...packageJson.devDependencies, - ...packageJson.peerDependencies, - }; + return readJsonFile(path); } - return {}; + return {} as PackageJson; } export function removePackageJsonFromFileMap( diff --git a/packages/js/src/utils/package-json/update-package-json.spec.ts b/packages/js/src/utils/package-json/update-package-json.spec.ts index c627c25889fd9..0a8f44ca810dd 100644 --- a/packages/js/src/utils/package-json/update-package-json.spec.ts +++ b/packages/js/src/utils/package-json/update-package-json.spec.ts @@ -290,7 +290,7 @@ describe('updatePackageJson', () => { const fileMap = { '@org/lib1': [ { - file: 'test.ts', + file: 'libs/lib1/src/test.ts', hash: '', deps: ['npm:external1', 'npm:external2'], }, diff --git a/packages/nx/src/plugins/js/package-json/create-package-json.ts b/packages/nx/src/plugins/js/package-json/create-package-json.ts index c84ad7ea027a5..e67be3838eb79 100644 --- a/packages/nx/src/plugins/js/package-json/create-package-json.ts +++ b/packages/nx/src/plugins/js/package-json/create-package-json.ts @@ -43,11 +43,19 @@ export function createPackageJson( const projectNode = graph.nodes[projectName]; const isLibrary = projectNode.type === 'lib'; + const rootPackageJson = readJsonFile( + `${options.root || workspaceRoot}/package.json` + ); + const npmDeps = findProjectsNpmDependencies( projectNode, graph, options.target, - { helperDependencies: options.helperDependencies }, + rootPackageJson, + { + helperDependencies: options.helperDependencies, + isProduction: options.isProduction, + }, fileMap ); @@ -92,9 +100,6 @@ export function createPackageJson( ); }; - const rootPackageJson = readJsonFile( - `${options.root || workspaceRoot}/package.json` - ); Object.entries(npmDeps.dependencies).forEach(([packageName, version]) => { if ( rootPackageJson.devDependencies?.[packageName] && @@ -179,9 +184,11 @@ export function findProjectsNpmDependencies( projectNode: ProjectGraphProjectNode, graph: ProjectGraph, target: string, + rootPackageJson: PackageJson, options: { helperDependencies?: string[]; ignoredDependencies?: string[]; + isProduction?: boolean; }, fileMap?: ProjectFileMap ): NpmDeps { @@ -208,13 +215,22 @@ export function findProjectsNpmDependencies( recursivelyCollectPeerDependencies(dep, graph, npmDeps, seen); }); + // if it's production, we want to ignore all found devDependencies + const ignoredDependencies = + options.isProduction && rootPackageJson.devDependencies + ? [ + ...(options.ignoredDependencies || []), + ...Object.keys(rootPackageJson.devDependencies), + ] + : options.ignoredDependencies || []; + findAllNpmDeps( fileMap, projectNode, graph, npmDeps, seen, - options.ignoredDependencies || [], + ignoredDependencies, dependencyInputs, selfInputs ); From fc58ef45d6bff3e8d8ea9d6ce0b43b339cc0da4b Mon Sep 17 00:00:00 2001 From: Isaac Mann Date: Wed, 5 Jul 2023 11:51:42 -0400 Subject: [PATCH 2/2] docs(core): fix wording in update dependencies page (#17968) --- .../core-features/automate-updating-dependencies.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/shared/core-features/automate-updating-dependencies.md b/docs/shared/core-features/automate-updating-dependencies.md index b2b47e7d0483a..5edc4e1d6ce99 100644 --- a/docs/shared/core-features/automate-updating-dependencies.md +++ b/docs/shared/core-features/automate-updating-dependencies.md @@ -1,8 +1,8 @@ # Automate Updating Dependencies -Keeping a codebase updated with the latest changes in your framework of choice and tooling can be challenging. Not to mention that "tooling maintenance work" is usually hard to squeeze into your feature sprint. +Keeping a codebase updated with the latest changes in your framework of choice can be challenging. Not to mention that "tooling maintenance work" is usually hard to squeeze into your feature sprint. -The `nx migrate` helps by automating the process of updating: +The `nx migrate` command helps by automating the process of updating: - package versions in your `package.json` - configuration files (e.g. your Jest, ESLint or Nx config) @@ -10,15 +10,15 @@ The `nx migrate` helps by automating the process of updating: ## How does it work? -Nx knows where its configuration files are and can therefore make sure they match the expected format or can alternatively adjust them. This automated update process, commonly referred to as "migration," becomes even more powerful when you leverage [Nx plugins](/packages). Nx plugins, which are NPM packages with a range of capabilities (code generation, task automation...), offer targeted updates based on their specific areas of responsibility. +Nx knows where its configuration files are and can therefore make sure they match the expected format. This automated update process, commonly referred to as "migration," becomes even more powerful when you leverage [Nx plugins](/packages). Nx plugins, which are NPM packages with a range of capabilities (code generation, task automation...), offer targeted updates based on their specific areas of responsibility. For example, the [Nx ESLint plugin](/packages/linter) excels at configuring linting in your workspace. With its understanding of the configuration file locations, this plugin can provide precise migration scripts to update ESLint packages in your `package.json` and corresponding configuration files in your workspace when a new version is released. Updating happens in three steps: - The installed dependencies are updated including the `package.json` (and `node_modules`). -- The source code in the repo is updated to match the new versions of packages according to set of instructions specified in `migrations.json` file. -- Optionally remove the `migrations.json` file or keep it to re-run it in different Git branches +- The source code in the repo is updated to match the new versions of packages according to the set of instructions specified in `migrations.json` file. +- Optionally remove the `migrations.json` file or keep it to re-run the migration in different Git branches ### Step 1: Updating dependencies and generating migrations