mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-04 23:34:58 -04:00
feat: treat bare workspace: protocol as workspace:* (#10436)
* feat: treat bare `workspace:` protocol as `workspace:*` * chore: add chageset * test(exportable-manifest): add test for `workspace` with explicit versions * test: add tests and update changesets --------- Co-authored-by: Zoltan Kochan <z@kochan.io>
This commit is contained in:
committed by
Zoltan Kochan
parent
5c7ee66fd5
commit
ed87c99359
8
.changeset/nine-areas-glow.md
Normal file
8
.changeset/nine-areas-glow.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"@pnpm/resolve-workspace-range": minor
|
||||
"@pnpm/exportable-manifest": minor
|
||||
"@pnpm/npm-resolver": minor
|
||||
pnpm: minor
|
||||
---
|
||||
|
||||
Support bare `workspace:` protocol without version specifier. It is now treated as `workspace:*` and resolves to the concrete version during publish [#10436](https://github.com/pnpm/pnpm/pull/10436).
|
||||
@@ -36,6 +36,7 @@
|
||||
"copyfiles",
|
||||
"corejs",
|
||||
"corepack",
|
||||
"corge",
|
||||
"cowsay",
|
||||
"cves",
|
||||
"cwsay",
|
||||
@@ -83,6 +84,7 @@
|
||||
"forgejo",
|
||||
"fsevents",
|
||||
"gabor",
|
||||
"garply",
|
||||
"gcttmf",
|
||||
"getattr",
|
||||
"ghsa",
|
||||
@@ -90,6 +92,7 @@
|
||||
"gitea",
|
||||
"globalconfig",
|
||||
"globstar",
|
||||
"grault",
|
||||
"gruntfile",
|
||||
"gwhitney",
|
||||
"haptics",
|
||||
@@ -181,6 +184,7 @@
|
||||
"pkgname",
|
||||
"pkgs",
|
||||
"plotly",
|
||||
"plugh",
|
||||
"pnpmfile",
|
||||
"pnpmfiles",
|
||||
"pnpmjs",
|
||||
|
||||
@@ -136,13 +136,14 @@ async function replaceWorkspaceProtocol (depName: string, depSpec: string, dir:
|
||||
return depSpec
|
||||
}
|
||||
|
||||
// Dependencies with bare "*", "^" and "~" versions
|
||||
const versionAliasSpecParts = /^workspace:(.*?)@?([\^~*])$/.exec(depSpec)
|
||||
// Dependencies with bare "*", "^", "~" versions, or no version (workspace:)
|
||||
const versionAliasSpecParts = /^workspace:(?:(.+)@)?([\^~*])?$/.exec(depSpec)
|
||||
if (versionAliasSpecParts != null) {
|
||||
modulesDir = modulesDir ?? path.join(dir, 'node_modules')
|
||||
const manifest = await readAndCheckManifest(depName, path.join(modulesDir, depName))
|
||||
|
||||
const semverRangeToken = versionAliasSpecParts[2] !== '*' ? versionAliasSpecParts[2] : ''
|
||||
const specifierSuffix: string | undefined = versionAliasSpecParts[2]
|
||||
const semverRangeToken = specifierSuffix === '^' || specifierSuffix === '~' ? specifierSuffix : ''
|
||||
if (depName !== manifest.name) {
|
||||
return `npm:${manifest.name!}@${semverRangeToken}${manifest.version}`
|
||||
}
|
||||
|
||||
@@ -96,9 +96,13 @@ test('workspace deps are replaced', async () => {
|
||||
baz: 'workspace:baz@^',
|
||||
foo: 'workspace:*',
|
||||
qux: 'workspace:^',
|
||||
quux: 'workspace:',
|
||||
waldo: 'workspace:^',
|
||||
xerox: 'workspace:../xerox',
|
||||
xeroxAlias: 'workspace:../xerox',
|
||||
corge: 'workspace:1.0.0',
|
||||
grault: 'workspace:^1.0.0',
|
||||
garply: 'workspace:plugh@2.0.0',
|
||||
},
|
||||
peerDependencies: {
|
||||
foo: 'workspace:>= || ^3.9.0',
|
||||
@@ -127,6 +131,10 @@ test('workspace deps are replaced', async () => {
|
||||
name: 'qux',
|
||||
version: '1.0.0-alpha-a.b-c-something+build.1-aef.1-its-okay',
|
||||
},
|
||||
{
|
||||
name: 'quux',
|
||||
version: '7.8.9',
|
||||
},
|
||||
{
|
||||
name: 'waldo',
|
||||
version: '1.9.0',
|
||||
@@ -135,6 +143,18 @@ test('workspace deps are replaced', async () => {
|
||||
name: 'xerox',
|
||||
version: '4.5.6',
|
||||
},
|
||||
{
|
||||
name: 'corge',
|
||||
version: '1.0.0',
|
||||
},
|
||||
{
|
||||
name: 'grault',
|
||||
version: '1.0.0',
|
||||
},
|
||||
{
|
||||
name: 'plugh',
|
||||
version: '2.0.0',
|
||||
},
|
||||
])
|
||||
|
||||
writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'] })
|
||||
@@ -151,9 +171,13 @@ test('workspace deps are replaced', async () => {
|
||||
baz: '^1.2.3',
|
||||
foo: '4.5.6',
|
||||
qux: '^1.0.0-alpha-a.b-c-something+build.1-aef.1-its-okay',
|
||||
quux: '7.8.9',
|
||||
waldo: '^1.9.0',
|
||||
xerox: '4.5.6',
|
||||
xeroxAlias: 'npm:xerox@4.5.6',
|
||||
corge: '1.0.0',
|
||||
grault: '^1.0.0',
|
||||
garply: 'npm:plugh@2.0.0',
|
||||
},
|
||||
peerDependencies: {
|
||||
baz: '^1.0.0 || >1.2.3',
|
||||
|
||||
@@ -7,7 +7,7 @@ export function workspacePrefToNpm (workspaceBareSpecifier: string): string {
|
||||
}
|
||||
|
||||
const { alias, version } = parseResult
|
||||
const versionPart = version === '^' || version === '~' ? '*' : version
|
||||
const versionPart = version === '^' || version === '~' || version === '' ? '*' : version
|
||||
return alias
|
||||
? `npm:${alias}@${versionPart}`
|
||||
: versionPart
|
||||
|
||||
@@ -2,8 +2,10 @@ import { workspacePrefToNpm } from '../lib/workspacePrefToNpm.js'
|
||||
|
||||
describe('workspacePrefToNpm', () => {
|
||||
test('resolve workspace only version aliases', async () => {
|
||||
expect(workspacePrefToNpm('workspace:^')).toStrictEqual('*')
|
||||
expect(workspacePrefToNpm('workspace:~')).toStrictEqual('*')
|
||||
expect(workspacePrefToNpm('workspace:')).toBe('*')
|
||||
expect(workspacePrefToNpm('workspace:*')).toBe('*')
|
||||
expect(workspacePrefToNpm('workspace:^')).toBe('*')
|
||||
expect(workspacePrefToNpm('workspace:~')).toBe('*')
|
||||
})
|
||||
|
||||
test('resolve package name aliases', async () => {
|
||||
|
||||
@@ -25,8 +25,9 @@
|
||||
],
|
||||
"scripts": {
|
||||
"start": "tsc --watch",
|
||||
"test": "pnpm run compile",
|
||||
"lint": "eslint \"src/**/*.ts\"",
|
||||
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
"_test": "cross-env NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest",
|
||||
"test": "pnpm run compile && pnpm run _test",
|
||||
"prepublishOnly": "pnpm run compile",
|
||||
"compile": "tsc --build && pnpm run lint --fix"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import semver from 'semver'
|
||||
|
||||
export function resolveWorkspaceRange (range: string, versions: string[]): string | null {
|
||||
if (range === '*' || range === '^' || range === '~') {
|
||||
if (range === '*' || range === '^' || range === '~' || range === '') {
|
||||
return semver.maxSatisfying(versions, '*', {
|
||||
includePrerelease: true,
|
||||
})
|
||||
|
||||
31
workspace/resolve-workspace-range/test/index.test.ts
Normal file
31
workspace/resolve-workspace-range/test/index.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { resolveWorkspaceRange } from '@pnpm/resolve-workspace-range'
|
||||
|
||||
describe('resolveWorkspaceRange', () => {
|
||||
const versions = ['1.0.0', '2.0.0', '3.0.0-beta.1']
|
||||
|
||||
test('resolves * to max version including prereleases', () => {
|
||||
expect(resolveWorkspaceRange('*', versions)).toBe('3.0.0-beta.1')
|
||||
})
|
||||
|
||||
test('resolves ^ to max version including prereleases', () => {
|
||||
expect(resolveWorkspaceRange('^', versions)).toBe('3.0.0-beta.1')
|
||||
})
|
||||
|
||||
test('resolves ~ to max version including prereleases', () => {
|
||||
expect(resolveWorkspaceRange('~', versions)).toBe('3.0.0-beta.1')
|
||||
})
|
||||
|
||||
test('resolves empty string (bare workspace:) to max version including prereleases', () => {
|
||||
expect(resolveWorkspaceRange('', versions)).toBe('3.0.0-beta.1')
|
||||
})
|
||||
|
||||
test('resolves semver range', () => {
|
||||
expect(resolveWorkspaceRange('^1.0.0', versions)).toBe('1.0.0')
|
||||
expect(resolveWorkspaceRange('^2.0.0', versions)).toBe('2.0.0')
|
||||
expect(resolveWorkspaceRange('>=1.0.0', versions)).toBe('2.0.0')
|
||||
})
|
||||
|
||||
test('returns null when no version satisfies range', () => {
|
||||
expect(resolveWorkspaceRange('^4.0.0', versions)).toBeNull()
|
||||
})
|
||||
})
|
||||
18
workspace/resolve-workspace-range/test/tsconfig.json
Normal file
18
workspace/resolve-workspace-range/test/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": false,
|
||||
"outDir": "../node_modules/.test.lib",
|
||||
"rootDir": "..",
|
||||
"isolatedModules": true
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"../../../__typings__/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": ".."
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user