1
+ import { execSync } from 'child_process' ;
1
2
import { readJson , updateJson } from 'nx/src/generators/utils/json' ;
2
- import { installPackagesTask } from '../tasks/install-packages-task' ;
3
3
import type { Tree } from 'nx/src/generators/tree' ;
4
4
import { GeneratorCallback } from 'nx/src/config/misc-interfaces' ;
5
5
import { clean , coerce , gt , satisfies } from 'semver' ;
6
6
import { getPackageManagerCommand } from 'nx/src/utils/package-manager' ;
7
- import { execSync } from 'child_process' ;
8
- import { readModulePackageJson } from 'nx/src/utils/package-json' ;
7
+ import { workspaceRoot } from 'nx/src/utils/workspace-root' ;
8
+
9
+ import { installPackagesTask } from '../tasks/install-packages-task' ;
9
10
10
11
const UNIDENTIFIED_VERSION = 'UNIDENTIFIED_VERSION' ;
11
12
const NON_SEMVER_TAGS = {
@@ -389,19 +390,12 @@ export async function ensurePackage(
389
390
throwOnMissing ?: boolean ;
390
391
} = { }
391
392
) : Promise < void > {
392
- let version : string ;
393
-
394
393
// Read package and version from root package.json file.
395
394
const dev = options . dev ?? true ;
396
395
const throwOnMissing = options . throwOnMissing ?? ! ! process . env . NX_DRY_RUN ; // NX_DRY_RUN is set in `packages/nx/src/command-line/generate.ts`
397
396
const pmc = getPackageManagerCommand ( ) ;
398
397
399
- // Try to resolve the actual version from resolved module.
400
- try {
401
- version = readModulePackageJson ( pkg ) . packageJson . version ;
402
- } catch {
403
- // ignore
404
- }
398
+ let version = getPackageVersion ( pkg ) ;
405
399
406
400
// Otherwise try to read in from package.json. This is needed for E2E tests to pass.
407
401
if ( ! version ) {
@@ -410,7 +404,15 @@ export async function ensurePackage(
410
404
version = packageJson [ field ] ?. [ pkg ] ;
411
405
}
412
406
413
- if ( ! satisfies ( version , requiredVersion ) ) {
407
+ if (
408
+ // Special case: When running Nx unit tests, the version read from package.json is "0.0.1".
409
+ ! (
410
+ pkg . startsWith ( '@nrwl/' ) &&
411
+ ( version === '0.0.1' || requiredVersion === '0.0.1' )
412
+ ) &&
413
+ // Normal case
414
+ ! satisfies ( version , requiredVersion , { includePrerelease : true } )
415
+ ) {
414
416
const installCmd = `${
415
417
dev ? pmc . addDev : pmc . add
416
418
} ${ pkg } @${ requiredVersion } `;
@@ -426,3 +428,26 @@ export async function ensurePackage(
426
428
}
427
429
}
428
430
}
431
+
432
+ /**
433
+ * Use another process to resolve the package.json path of the package (if it exists).
434
+ * Cannot use `require.resolve` here since there is an unclearable internal cache used by Node that can lead to issues
435
+ * when resolving the package after installation.
436
+ *
437
+ * See: https://github.com/nodejs/node/issues/31803
438
+ */
439
+ function getPackageVersion ( pkg : string ) : undefined | string {
440
+ try {
441
+ return execSync (
442
+ `node -e "console.log(require('${ pkg } /package.json').version)"` ,
443
+ {
444
+ cwd : workspaceRoot ,
445
+ stdio : [ 'pipe' , 'pipe' , 'ignore' ] ,
446
+ }
447
+ )
448
+ . toString ( )
449
+ . trim ( ) ;
450
+ } catch ( e ) {
451
+ return undefined ;
452
+ }
453
+ }
0 commit comments