Skip to content

Commit 065b898

Browse files
committed
fix: allPreferredVerions and allowedAlternativeVersions are not recorded in the subspace pnpmfileSettings.json
1 parent 485be33 commit 065b898

10 files changed

Lines changed: 170 additions & 3 deletions

File tree

libraries/rush-lib/src/logic/pnpm/IPnpmfile.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ export interface IWorkspaceProjectInfo
3232
* The `settings` parameter passed to {@link IPnpmfileShim.hooks.readPackage} and
3333
* {@link IPnpmfileShim.hooks.afterAllResolved}.
3434
*/
35-
export interface ISubspacePnpmfileShimSettings {
36-
semverPath: string;
35+
export interface ISubspacePnpmfileShimSettings extends Omit<IPnpmfileShimSettings, 'workspaceVersions'> {
3736
workspaceProjects: Record<string, IWorkspaceProjectInfo>;
3837
subspaceProjects: Record<string, IWorkspaceProjectInfo>;
3938
userPnpmfilePath?: string;

libraries/rush-lib/src/logic/pnpm/SubspacePnpmfileConfiguration.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,22 @@
33

44
import * as path from 'node:path';
55

6-
import { FileSystem, Import, JsonFile, type IDependenciesMetaTable } from '@rushstack/node-core-library';
6+
import * as semver from 'semver';
7+
8+
import {
9+
FileSystem,
10+
Import,
11+
JsonFile,
12+
MapExtensions,
13+
type IDependenciesMetaTable
14+
} from '@rushstack/node-core-library';
715

816
import { subspacePnpmfileShimFilename, scriptsFolderPath } from '../../utilities/PathConstants';
917
import type { ISubspacePnpmfileShimSettings, IWorkspaceProjectInfo } from './IPnpmfile';
1018
import type { RushConfiguration } from '../../api/RushConfiguration';
1119
import type { RushConfigurationProject } from '../../api/RushConfigurationProject';
1220
import type { PnpmPackageManager } from '../../api/packageManager/PnpmPackageManager';
21+
import type { CommonVersionsConfiguration } from '../../api/CommonVersionsConfiguration';
1322
import { RushConstants } from '../RushConstants';
1423
import type { Subspace } from '../../api/Subspace';
1524
import type { PnpmOptionsConfiguration } from './PnpmOptionsConfiguration';
@@ -80,9 +89,35 @@ export class SubspacePnpmfileConfiguration {
8089
(subspace.contains(project) ? subspaceProjects : workspaceProjects)[packageName] = workspaceProjectInfo;
8190
}
8291

92+
let allPreferredVersions: { [dependencyName: string]: string } = {};
93+
let allowedAlternativeVersions: { [dependencyName: string]: readonly string[] } = {};
94+
95+
// Populate preferred versions from subspace's common-versions.json (same as non-subspace pnpmfile shim)
96+
const pnpmOptions: PnpmOptionsConfiguration =
97+
rushConfiguration.packageManagerOptions as PnpmOptionsConfiguration;
98+
if (pnpmOptions?.useWorkspaces) {
99+
const commonVersionsConfiguration: CommonVersionsConfiguration = subspace.getCommonVersions(variant);
100+
const preferredVersions: Map<string, string> = new Map();
101+
MapExtensions.mergeFromMap(
102+
preferredVersions,
103+
rushConfiguration.getImplicitlyPreferredVersions(subspace, variant)
104+
);
105+
for (const [name, version] of commonVersionsConfiguration.getAllPreferredVersions()) {
106+
if (!preferredVersions.has(name) || semver.subset(version, preferredVersions.get(name)!)) {
107+
preferredVersions.set(name, version);
108+
}
109+
}
110+
allPreferredVersions = MapExtensions.toObject(preferredVersions);
111+
allowedAlternativeVersions = MapExtensions.toObject(
112+
commonVersionsConfiguration.allowedAlternativeVersions
113+
);
114+
}
115+
83116
const settings: ISubspacePnpmfileShimSettings = {
84117
workspaceProjects,
85118
subspaceProjects,
119+
allPreferredVersions,
120+
allowedAlternativeVersions,
86121
semverPath: Import.resolveModule({ modulePath: 'semver', baseFolderPath: __dirname })
87122
};
88123

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2+
// See LICENSE in the project root for license information.
3+
4+
import { RushConfiguration } from '../../../api/RushConfiguration';
5+
import { SubspacePnpmfileConfiguration } from '../SubspacePnpmfileConfiguration';
6+
import { JsonFile, type JsonObject } from '@rushstack/node-core-library';
7+
8+
describe(SubspacePnpmfileConfiguration.name, () => {
9+
const repoPath: string = `${__dirname}/repo-with-subspace`;
10+
const rushFilename: string = `${repoPath}/rush.json`;
11+
const rushConfiguration: RushConfiguration = RushConfiguration.loadFromConfigurationFile(rushFilename);
12+
const shimPath: string = `${rushConfiguration.defaultSubspace.getSubspaceTempFolderPath()}/pnpmfileSettings.json`;
13+
14+
beforeAll(async () => {
15+
const subspace = rushConfiguration.defaultSubspace;
16+
await SubspacePnpmfileConfiguration.writeCommonTempSubspaceGlobalPnpmfileAsync(
17+
rushConfiguration,
18+
subspace,
19+
undefined
20+
);
21+
});
22+
23+
it('should use the smallest-available SemVer range (preferredVersions)', async () => {
24+
const shimJson: JsonObject = await JsonFile.loadAsync(shimPath);
25+
expect(shimJson.allPreferredVersions).toHaveProperty('@rushstack/terminal', '0.19.2');
26+
});
27+
28+
it('should record allPreferredVersions in pnpmfileSettings.json', async () => {
29+
const shimJson: JsonObject = await JsonFile.loadAsync(shimPath);
30+
expect(shimJson.allPreferredVersions).toHaveProperty('@rushstack/terminal', '0.19.2');
31+
});
32+
33+
it('should record allowedAlternativeVersions in pnpmfileSettings.json', async () => {
34+
const shimJson: JsonObject = await JsonFile.loadAsync(shimPath);
35+
const allowedAlternativeVersions = shimJson.allowedAlternativeVersions as
36+
| Record<string, readonly string[]>
37+
| undefined;
38+
expect(allowedAlternativeVersions).toBeDefined();
39+
expect(allowedAlternativeVersions).toHaveProperty('foo', ['1.0.0']);
40+
});
41+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "a",
3+
"version": "1.0.0",
4+
"description": "Test package a to test subspace pnpmfile shim with preferred versions",
5+
"dependencies": {
6+
"@rushstack/terminal": "~0.19.0"
7+
}
8+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"useWorkspaces": true
3+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* This configuration file manages the experimental "subspaces" feature for Rush,
3+
* which allows multiple PNPM lockfiles to be used in a single Rush workspace.
4+
* For full documentation, please see https://rushjs.io
5+
*/
6+
{
7+
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/subspaces.schema.json",
8+
"subspacesEnabled": true,
9+
"subspaceNames": ["default"]
10+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
registry=https://registry.npmjs.org/
2+
always-auth=false
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
3+
/**
4+
* When using the PNPM package manager, you can use pnpmfile.js to workaround
5+
* dependencies that have mistakes in their package.json file. (This feature is
6+
* functionally similar to Yarn's "resolutions".)
7+
*
8+
* For details, see the PNPM documentation:
9+
* https://pnpm.io/pnpmfile#hooks
10+
*
11+
* IMPORTANT: SINCE THIS FILE CONTAINS EXECUTABLE CODE, MODIFYING IT IS LIKELY TO INVALIDATE
12+
* ANY CACHED DEPENDENCY ANALYSIS. After any modification to pnpmfile.js, it's recommended to run
13+
* "rush update --full" so that PNPM will recalculate all version selections.
14+
*/
15+
module.exports = {
16+
hooks: {
17+
readPackage
18+
}
19+
};
20+
21+
function readPackage(packageJson, _context) {
22+
return packageJson;
23+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* This configuration file specifies NPM dependency version selections that affect all projects
3+
* in a Rush repo. More documentation is available on the Rush website: https://rushjs.io
4+
*/
5+
{
6+
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/common-versions.schema.json",
7+
8+
/**
9+
* A table that specifies a "preferred version" for a given NPM package. This feature is typically used
10+
* to hold back an indirect dependency to a specific older version, or to reduce duplication of indirect dependencies.
11+
*
12+
* The "preferredVersions" value can be any SemVer range specifier (e.g. "~1.2.3"). Rush injects these values into
13+
* the "dependencies" field of the top-level common/temp/package.json, which influences how the package manager
14+
* will calculate versions. The specific effect depends on your package manager. Generally it will have no
15+
* effect on an incompatible or already constrained SemVer range. If you are using PNPM, similar effects can be
16+
* achieved using the pnpmfile.js hook. See the Rush documentation for more details.
17+
*
18+
* After modifying this field, it's recommended to run "rush update --full" so that the package manager
19+
* will recalculate all version selections.
20+
*/
21+
"preferredVersions": {
22+
"@rushstack/terminal": "0.19.2"
23+
},
24+
"ensureConsistentVersions": false,
25+
"allowedAlternativeVersions": {
26+
"foo": ["1.0.0"]
27+
}
28+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* This is the main configuration file for Rush.
3+
* For full documentation, please see https://rushjs.io
4+
*/
5+
{
6+
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json",
7+
"rushVersion": "5.166.0",
8+
"pnpmVersion": "10.27.0",
9+
"nodeSupportedVersionRange": "*",
10+
// "projectFolderMinDepth": 1,
11+
// "projectFolderMaxDepth": 2,
12+
"projects": [
13+
{
14+
"packageName": "a",
15+
"projectFolder": "a"
16+
}
17+
]
18+
}

0 commit comments

Comments
 (0)