Skip to content

Commit

Permalink
fix(core): update ensurePackage util with workaround for bad module c…
Browse files Browse the repository at this point in the history
…ache (#14786)
  • Loading branch information
jaysoo committed Feb 7, 2023
1 parent 03e04e7 commit fc20e69
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 12 deletions.
10 changes: 10 additions & 0 deletions packages/devkit/src/utils/package-json.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,16 @@ describe('ensurePackage', () => {
tree = createTree();
});

it('should return successfully when package is present', async () => {
writeJson(tree, 'package.json', {});

await expect(
ensurePackage(tree, '@nrwl/devkit', '>=15.0.0', {
throwOnMissing: true,
})
).resolves.toBeUndefined(); // return void
});

it('should throw when dependencies are missing', async () => {
writeJson(tree, 'package.json', {});

Expand Down
49 changes: 37 additions & 12 deletions packages/devkit/src/utils/package-json.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { execSync } from 'child_process';
import { readJson, updateJson } from 'nx/src/generators/utils/json';
import { installPackagesTask } from '../tasks/install-packages-task';
import type { Tree } from 'nx/src/generators/tree';
import { GeneratorCallback } from 'nx/src/config/misc-interfaces';
import { clean, coerce, gt, satisfies } from 'semver';
import { getPackageManagerCommand } from 'nx/src/utils/package-manager';
import { execSync } from 'child_process';
import { readModulePackageJson } from 'nx/src/utils/package-json';
import { workspaceRoot } from 'nx/src/utils/workspace-root';

import { installPackagesTask } from '../tasks/install-packages-task';

const UNIDENTIFIED_VERSION = 'UNIDENTIFIED_VERSION';
const NON_SEMVER_TAGS = {
Expand Down Expand Up @@ -389,19 +390,12 @@ export async function ensurePackage(
throwOnMissing?: boolean;
} = {}
): Promise<void> {
let version: string;

// Read package and version from root package.json file.
const dev = options.dev ?? true;
const throwOnMissing = options.throwOnMissing ?? !!process.env.NX_DRY_RUN; // NX_DRY_RUN is set in `packages/nx/src/command-line/generate.ts`
const pmc = getPackageManagerCommand();

// Try to resolve the actual version from resolved module.
try {
version = readModulePackageJson(pkg).packageJson.version;
} catch {
// ignore
}
let version = getPackageVersion(pkg);

// Otherwise try to read in from package.json. This is needed for E2E tests to pass.
if (!version) {
Expand All @@ -410,7 +404,15 @@ export async function ensurePackage(
version = packageJson[field]?.[pkg];
}

if (!satisfies(version, requiredVersion)) {
if (
// Special case: When running Nx unit tests, the version read from package.json is "0.0.1".
!(
pkg.startsWith('@nrwl/') &&
(version === '0.0.1' || requiredVersion === '0.0.1')
) &&
// Normal case
!satisfies(version, requiredVersion, { includePrerelease: true })
) {
const installCmd = `${
dev ? pmc.addDev : pmc.add
} ${pkg}@${requiredVersion}`;
Expand All @@ -426,3 +428,26 @@ export async function ensurePackage(
}
}
}

/**
* Use another process to resolve the package.json path of the package (if it exists).
* Cannot use `require.resolve` here since there is an unclearable internal cache used by Node that can lead to issues
* when resolving the package after installation.
*
* See: https://github.com/nodejs/node/issues/31803
*/
function getPackageVersion(pkg: string): undefined | string {
try {
return execSync(
`node -e "console.log(require('${pkg}/package.json').version)"`,
{
cwd: workspaceRoot,
stdio: ['pipe', 'pipe', 'ignore'],
}
)
.toString()
.trim();
} catch (e) {
return undefined;
}
}

1 comment on commit fc20e69

@vercel
Copy link

@vercel vercel bot commented on fc20e69 Feb 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-git-master-nrwl.vercel.app
nx-dev-nrwl.vercel.app
nx-five.vercel.app
nx.dev

Please sign in to comment.