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
  • Loading branch information
jaysoo committed Feb 3, 2023
1 parent 0f5d2c3 commit 503f5e6
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 10 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 @@ -342,6 +342,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
33 changes: 23 additions & 10 deletions packages/devkit/src/utils/package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ 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';

const NON_SEMVER_TAGS = {
'*': 2,
Expand Down Expand Up @@ -344,19 +344,14 @@ 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
}
// Try to read the installed package version.
// NOTE: Avoid `require.resolve` or `require` here, because doing so may pollute module cache and the package cannot be imported later.
let version = getPackageVersion(pkg);

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

if (!satisfies(version, requiredVersion)) {
if (!satisfies(version, requiredVersion, { includePrerelease: true })) {
const installCmd = `${
dev ? pmc.addDev : pmc.add
} ${pkg}@${requiredVersion}`;
Expand All @@ -381,3 +376,21 @@ export async function ensurePackage(
}
}
}

// Try to require the package in another Node process.
// Using `require.resolve` or `require` in current process may pollute the module/file cache when importing the package later on.
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 null;
}
}

0 comments on commit 503f5e6

Please sign in to comment.