Skip to content

Commit

Permalink
feat: use workspace spec alias by default in pnpm add
Browse files Browse the repository at this point in the history
  • Loading branch information
Javier committed Jul 2, 2022
1 parent cdb4622 commit 705f561
Show file tree
Hide file tree
Showing 11 changed files with 300 additions and 22 deletions.
7 changes: 7 additions & 0 deletions .changeset/perfect-cherries-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@pnpm/manifest-utils": minor
"@pnpm/resolve-dependencies": minor
"@pnpm/which-version-is-pinned": major
---

Add "rolling" as a possible value of option "save-workspace-protocol"
2 changes: 1 addition & 1 deletion packages/config/src/Config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface Config {
saveDev?: boolean
saveOptional?: boolean
savePeer?: boolean
saveWorkspaceProtocol?: boolean
saveWorkspaceProtocol?: boolean | 'rolling'
scriptShell?: string
stream?: boolean
pnpmExecPath: string
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/install/extendInstallOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface StrictInstallOptions {
fixLockfile: boolean
ignorePackageManifest: boolean
preferFrozenLockfile: boolean
saveWorkspaceProtocol: boolean
saveWorkspaceProtocol: boolean | 'rolling'
preferWorkspacePackages: boolean
preserveWorkspaceProtocol: boolean
scriptsPrependNodePath: boolean | 'warn-only'
Expand Down
145 changes: 145 additions & 0 deletions packages/core/test/install/multipleImporters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,38 @@ test('adding a new dependency with the workspace: protocol', async () => {
expect(manifest.dependencies).toStrictEqual({ foo: 'workspace:^1.0.0' })
})

test('adding a new dependency with the workspace: protocol and save-workspace-protocol is "rolling"', async () => {
await addDistTag({ package: 'foo', version: '1.0.0', distTag: 'latest' })
prepareEmpty()

const [{ manifest }] = await mutateModules([
{
dependencySelectors: ['foo'],
manifest: {
name: 'project-1',
version: '1.0.0',
},
mutation: 'installSome',
rootDir: path.resolve('project-1'),
},
], await testDefaults({
saveWorkspaceProtocol: 'rolling',
workspacePackages: {
foo: {
'1.0.0': {
dir: '',
manifest: {
name: 'foo',
version: '1.0.0',
},
},
},
},
}))

expect(manifest.dependencies).toStrictEqual({ foo: 'workspace:^' })
})

test('update workspace range', async () => {
prepareEmpty()

Expand Down Expand Up @@ -907,6 +939,119 @@ test('update workspace range', async () => {
dep3: 'workspace:^2.0.0',
dep4: 'workspace:^2.0.0',
dep5: 'workspace:~2.0.0',
dep6: 'workspace:2.0.0',
}
expect(updatedImporters[0].manifest.dependencies).toStrictEqual(expected)
expect(updatedImporters[1].manifest.dependencies).toStrictEqual(expected)
})

test('update workspace range when save-workspace-protocol is "rolling"', async () => {
prepareEmpty()

const updatedImporters = await mutateModules([
{
dependencySelectors: ['dep1', 'dep2', 'dep3', 'dep4', 'dep5', 'dep6'],
manifest: {
name: 'project-1',
version: '1.0.0',

dependencies: {
dep1: 'workspace:1.0.0',
dep2: 'workspace:~1.0.0',
dep3: 'workspace:^1.0.0',
dep4: 'workspace:1',
dep5: 'workspace:1.0',
dep6: 'workspace:*',
},
},
mutation: 'installSome',
rootDir: path.resolve('project-1'),
},
{
buildIndex: 0,
manifest: {
name: 'project-2',
version: '1.0.0',

dependencies: {
dep1: 'workspace:1.0.0',
dep2: 'workspace:~1.0.0',
dep3: 'workspace:^1.0.0',
dep4: 'workspace:1',
dep5: 'workspace:1.0',
dep6: 'workspace:*',
},
},
mutation: 'install',
rootDir: path.resolve('project-2'),
},
], await testDefaults({
saveWorkspaceProtocol: 'rolling',
update: true,
workspacePackages: {
dep1: {
'2.0.0': {
dir: '',
manifest: {
name: 'dep1',
version: '2.0.0',
},
},
},
dep2: {
'2.0.0': {
dir: '',
manifest: {
name: 'dep2',
version: '2.0.0',
},
},
},
dep3: {
'2.0.0': {
dir: '',
manifest: {
name: 'dep3',
version: '2.0.0',
},
},
},
dep4: {
'2.0.0': {
dir: '',
manifest: {
name: 'dep4',
version: '2.0.0',
},
},
},
dep5: {
'2.0.0': {
dir: '',
manifest: {
name: 'dep5',
version: '2.0.0',
},
},
},
dep6: {
'2.0.0': {
dir: '',
manifest: {
name: 'dep6',
version: '2.0.0',
},
},
},
},
}))

const expected = {
dep1: 'workspace:*',
dep2: 'workspace:~',
dep3: 'workspace:^',
dep4: 'workspace:^',
dep5: 'workspace:~',
dep6: 'workspace:*',
}
expect(updatedImporters[0].manifest.dependencies).toStrictEqual(expected)
Expand Down
18 changes: 10 additions & 8 deletions packages/manifest-utils/src/getPref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,23 @@ export function getPref (
}
) {
const prefix = getPrefix(alias, name)
return `${prefix}${createVersionSpec(version, opts.pinnedVersion)}`
return `${prefix}${createVersionSpec(version, { pinnedVersion: opts.pinnedVersion })}`
}

export function createVersionSpec (version: string | undefined, pinnedVersion?: PinnedVersion) {
if (!version) return '*'
switch (pinnedVersion ?? 'major') {
export function createVersionSpec (version: string | undefined, opts: { pinnedVersion?: PinnedVersion, rolling?: boolean }) {
switch (opts.pinnedVersion ?? 'major') {
case 'none':
return '*'
case 'major':
return `^${version}`
if (opts.rolling) return '^'
return !version ? '*' : `^${version}`
case 'minor':
return `~${version}`
if (opts.rolling) return '~'
return !version ? '*' : `~${version}`
case 'patch':
return `${version}`
if (opts.rolling) return '*'
return !version ? '*' : `${version}`
default:
throw new PnpmError('BAD_PINNED_VERSION', `Cannot pin '${pinnedVersion ?? 'undefined'}'`)
throw new PnpmError('BAD_PINNED_VERSION', `Cannot pin '${opts.pinnedVersion ?? 'undefined'}'`)
}
}
27 changes: 27 additions & 0 deletions packages/plugin-commands-installation/test/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,33 @@ test('installing with "workspace:" should work even if link-workspace-packages i
await projects['project-1'].has('project-2')
})

test('installing with "workspace:" should work even if link-workspace-packages is off and save-workspace-protocol is "rolling"', async () => {
const projects = preparePackages([
{
name: 'project-1',
version: '1.0.0',
},
{
name: 'project-2',
version: '2.0.0',
},
])

await add.handler({
...DEFAULT_OPTIONS,
dir: path.resolve('project-1'),
linkWorkspacePackages: false,
saveWorkspaceProtocol: 'rolling',
workspaceDir: process.cwd(),
}, ['project-2@workspace:*'])

const pkg = await import(path.resolve('project-1/package.json'))

expect(pkg?.dependencies).toStrictEqual({ 'project-2': 'workspace:^' })

await projects['project-1'].has('project-2')
})

test('installing with "workspace=true" should work even if link-workspace-packages is off and save-workspace-protocol is false', async () => {
const projects = preparePackages([
{
Expand Down
41 changes: 41 additions & 0 deletions packages/plugin-commands-installation/test/miscRecursive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,47 @@ test('installing with "workspace=true" should work even if link-workspace-packag
await projects['project-1'].has('project-2')
})

test('installing with "workspace=true" should work even if link-workspace-packages is off and save-workspace-protocol is "rolling"', async () => {
const projects = preparePackages([
{
name: 'project-1',
version: '1.0.0',

dependencies: {
'project-2': '0.0.0',
},
},
{
name: 'project-2',
version: '2.0.0',
},
])

await update.handler({
...DEFAULT_OPTS,
...await readProjects(process.cwd(), []),
dir: process.cwd(),
linkWorkspacePackages: false,
lockfileDir: process.cwd(),
recursive: true,
saveWorkspaceProtocol: 'rolling',
sharedWorkspaceLockfile: true,
workspace: true,
workspaceDir: process.cwd(),
}, ['project-2'])

{
const pkg = await import(path.resolve('project-1/package.json'))
expect(pkg?.dependencies).toStrictEqual({ 'project-2': 'workspace:*' })
}
{
const pkg = await import(path.resolve('project-2/package.json'))
expect(pkg.dependencies).toBeFalsy()
}

await projects['project-1'].has('project-2')
})

test('recursive install on workspace with custom lockfile-dir', async () => {
preparePackages([
{
Expand Down
48 changes: 48 additions & 0 deletions packages/pnpm/test/monorepo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,54 @@ test('linking a package inside a monorepo with --link-workspace-packages when in
await projects['project-1'].has('project-4')
})

test('linking a package inside a monorepo with --link-workspace-packages when installing new dependencies and save-workspace-protocol is "rolling"', async () => {
const projects = preparePackages([
{
name: 'project-1',
version: '1.0.0',
},
{
name: 'project-2',
version: '2.0.0',
},
{
name: 'project-3',
version: '3.0.0',
},
{
name: 'project-4',
version: '4.0.0',
},
])

await fs.writeFile(
'.npmrc',
[
'link-workspace-packages = true',
'save-workspace-protocol = "rolling"',
].join('\n'),
'utf8')
await writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'] })

process.chdir('project-1')

await execPnpm(['add', 'project-2'])

await execPnpm(['add', 'project-3', '--save-dev'])

await execPnpm(['add', 'project-4', '--save-optional', '--no-save-workspace-protocol'])

const { default: pkg } = await import(path.resolve('package.json'))

expect(pkg?.dependencies).toStrictEqual({ 'project-2': 'workspace:^' }) // spec of linked package added to dependencies
expect(pkg?.devDependencies).toStrictEqual({ 'project-3': 'workspace:^' }) // spec of linked package added to devDependencies
expect(pkg?.optionalDependencies).toStrictEqual({ 'project-4': '^4.0.0' }) // spec of linked package added to optionalDependencies

await projects['project-1'].has('project-2')
await projects['project-1'].has('project-3')
await projects['project-1'].has('project-4')
})

test('linking a package inside a monorepo with --link-workspace-packages', async () => {
const projects = preparePackages([
{
Expand Down
2 changes: 1 addition & 1 deletion packages/resolve-dependencies/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export default async function (
opts: ResolveDependenciesOptions & {
defaultUpdateDepth: number
preserveWorkspaceProtocol: boolean
saveWorkspaceProtocol: boolean
saveWorkspaceProtocol: 'rolling' | boolean
}
) {
const _toResolveImporter = toResolveImporter.bind(null, {
Expand Down

0 comments on commit 705f561

Please sign in to comment.