Skip to content

Commit 599fbb7

Browse files
committed
feat: allow "npm:name@version" dependency redirections in manifest
1 parent 2f7a489 commit 599fbb7

File tree

4 files changed

+26
-5
lines changed

4 files changed

+26
-5
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"execa": "^8.0.1",
3333
"pony-cause": "^2.1.9",
3434
"semver": "^7.5.4",
35+
"validate-npm-package-name": "^5.0.0",
3536
"which": "^3.0.0",
3637
"yaml": "^2.2.2",
3738
"yargs": "^17.7.1"

src/package-manifest.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ describe('package-manifest', () => {
6767
b: '^2.0.0',
6868
c: '~4.3.0',
6969
d: 'workspace:^',
70+
e: 'npm:a@^2.0.0',
7071
},
7172
};
7273
const validated = {
@@ -79,6 +80,7 @@ describe('package-manifest', () => {
7980
b: '^2.0.0',
8081
c: '~4.3.0',
8182
d: 'workspace:^',
83+
e: 'npm:a@^2.0.0',
8284
},
8385
peerDependencies: {},
8486
};

src/package-manifest.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
ManifestDependencyFieldNames as PackageManifestDependenciesFieldNames,
55
} from '@metamask/action-utils';
66
import { isPlainObject } from '@metamask/utils';
7+
const validateNPMPackageName = require('validate-npm-package-name');
78
import { readJsonObjectFile } from './fs.js';
89
import { isTruthyString } from './misc-utils.js';
910
import { semver, SemVer } from './semver.js';
@@ -144,8 +145,10 @@ function isValidPackageManifestVersionField(
144145

145146
/**
146147
* Type guard to ensure that the provided version value is a valid dependency version
147-
* specifier for a package manifest. This function validates both semantic versioning
148-
* ranges and the special 'workspace:^' notation.
148+
* specifier for a package manifest. This function validates:
149+
* - semantic versioning ranges
150+
* - 'workspace:^' notation
151+
* - 'npm:{packageName}:{semverRange}' redirections
149152
*
150153
* @param version - The value to check.
151154
* @returns `true` if the version is a valid string that either
@@ -155,9 +158,23 @@ function isValidPackageManifestVersionField(
155158
function isValidPackageManifestDependencyValue(
156159
version: unknown,
157160
): version is string {
158-
return (
159-
isValidPackageManifestVersionField(version) || version === 'workspace:^'
160-
);
161+
if (typeof version !== 'string') {
162+
return false;
163+
}
164+
if (isValidPackageManifestVersionField(version) || version === 'workspace:^') {
165+
return true;
166+
}
167+
const redirectedDependencyRegexp = /^npm:(.*)@(.*?)$/u;
168+
try {
169+
const redirectedDependencyMatch = redirectedDependencyRegexp.exec(version);
170+
if (!redirectedDependencyMatch || redirectedDependencyMatch.length < 3) {
171+
return false;
172+
}
173+
const [redirectedName, redirectedVersion] = redirectedDependencyMatch;
174+
return validateNPMPackageName(redirectedName) && isValidPackageManifestVersionField(redirectedVersion);
175+
} catch (e) {
176+
return false;
177+
}
161178
}
162179

163180
/**

yarn.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2117,6 +2117,7 @@ __metadata:
21172117
stdio-mock: ^1.2.0
21182118
tsx: ^4.6.1
21192119
typescript: ~5.1.6
2120+
validate-npm-package-name: ^5.0.0
21202121
which: ^3.0.0
21212122
yaml: ^2.2.2
21222123
yargs: ^17.7.1

0 commit comments

Comments
 (0)