mirror of
https://github.com/pnpm/pnpm.git
synced 2026-05-18 13:51:38 -04:00
feat(core): overrides, packageExtensions, and neverBuiltDependencies are options (#4050)
This commit is contained in:
5
.changeset/angry-moles-give.md
Normal file
5
.changeset/angry-moles-give.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@pnpm/plugin-commands-installation": major
|
||||||
|
---
|
||||||
|
|
||||||
|
Pass `packageExtensions`, `overrides`, and `neverBuiltDependencies` to the core API. Take this information from `rootProjectManifest`, which should be passed in via the options.
|
||||||
5
.changeset/chatty-toys-talk.md
Normal file
5
.changeset/chatty-toys-talk.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@pnpm/core": major
|
||||||
|
---
|
||||||
|
|
||||||
|
`packageExtensions`, `overrides`, and `neverBuiltDependencies` are passed through as options to the core API. These settings are not read from the root manifest's `package.json`.
|
||||||
5
.changeset/six-suits-float.md
Normal file
5
.changeset/six-suits-float.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@pnpm/config": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Read the root project manifest and write it to the config object.
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
"@pnpm/error": "workspace:2.0.0",
|
"@pnpm/error": "workspace:2.0.0",
|
||||||
"@pnpm/global-bin-dir": "workspace:3.0.0",
|
"@pnpm/global-bin-dir": "workspace:3.0.0",
|
||||||
"@pnpm/pnpmfile": "workspace:1.2.0",
|
"@pnpm/pnpmfile": "workspace:1.2.0",
|
||||||
|
"@pnpm/read-project-manifest": "workspace:2.0.7",
|
||||||
"@pnpm/types": "workspace:7.6.0",
|
"@pnpm/types": "workspace:7.6.0",
|
||||||
"@zkochan/npm-conf": "2.0.2",
|
"@zkochan/npm-conf": "2.0.2",
|
||||||
"camelcase": "^6.2.0",
|
"camelcase": "^6.2.0",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
Project,
|
Project,
|
||||||
|
ProjectManifest,
|
||||||
ProjectsGraph,
|
ProjectsGraph,
|
||||||
Registries,
|
Registries,
|
||||||
} from '@pnpm/types'
|
} from '@pnpm/types'
|
||||||
@@ -140,6 +141,7 @@ export interface Config {
|
|||||||
testPattern?: string[]
|
testPattern?: string[]
|
||||||
changedFilesIgnorePattern?: string[]
|
changedFilesIgnorePattern?: string[]
|
||||||
extendNodePath?: boolean
|
extendNodePath?: boolean
|
||||||
|
rootProjectManifest?: ProjectManifest
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ConfigWithDeprecatedSettings extends Config {
|
export interface ConfigWithDeprecatedSettings extends Config {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { LAYOUT_VERSION } from '@pnpm/constants'
|
|||||||
import PnpmError from '@pnpm/error'
|
import PnpmError from '@pnpm/error'
|
||||||
import globalBinDir from '@pnpm/global-bin-dir'
|
import globalBinDir from '@pnpm/global-bin-dir'
|
||||||
import { requireHooks } from '@pnpm/pnpmfile'
|
import { requireHooks } from '@pnpm/pnpmfile'
|
||||||
|
import { safeReadProjectManifestOnly } from '@pnpm/read-project-manifest'
|
||||||
import camelcase from 'camelcase'
|
import camelcase from 'camelcase'
|
||||||
import loadNpmConf from '@zkochan/npm-conf'
|
import loadNpmConf from '@zkochan/npm-conf'
|
||||||
import npmTypes from '@zkochan/npm-conf/lib/types'
|
import npmTypes from '@zkochan/npm-conf/lib/types'
|
||||||
@@ -483,6 +484,7 @@ export default async (
|
|||||||
if (!pnpmConfig.ignorePnpmfile) {
|
if (!pnpmConfig.ignorePnpmfile) {
|
||||||
pnpmConfig.hooks = requireHooks(pnpmConfig.lockfileDir ?? pnpmConfig.dir, pnpmConfig)
|
pnpmConfig.hooks = requireHooks(pnpmConfig.lockfileDir ?? pnpmConfig.dir, pnpmConfig)
|
||||||
}
|
}
|
||||||
|
pnpmConfig.rootProjectManifest = await safeReadProjectManifestOnly(pnpmConfig.lockfileDir ?? pnpmConfig.dir) ?? undefined
|
||||||
|
|
||||||
return { config: pnpmConfig, warnings }
|
return { config: pnpmConfig, warnings }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,9 @@
|
|||||||
{
|
{
|
||||||
"path": "../pnpmfile"
|
"path": "../pnpmfile"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "../read-project-manifest"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "../types"
|
"path": "../types"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import normalizeRegistries, { DEFAULT_REGISTRIES } from '@pnpm/normalize-registr
|
|||||||
import { WorkspacePackages } from '@pnpm/resolver-base'
|
import { WorkspacePackages } from '@pnpm/resolver-base'
|
||||||
import { StoreController } from '@pnpm/store-controller-types'
|
import { StoreController } from '@pnpm/store-controller-types'
|
||||||
import {
|
import {
|
||||||
|
PackageExtension,
|
||||||
ReadPackageHook,
|
ReadPackageHook,
|
||||||
Registries,
|
Registries,
|
||||||
} from '@pnpm/types'
|
} from '@pnpm/types'
|
||||||
@@ -44,8 +45,10 @@ export interface StrictInstallOptions {
|
|||||||
rawConfig: object
|
rawConfig: object
|
||||||
verifyStoreIntegrity: boolean
|
verifyStoreIntegrity: boolean
|
||||||
engineStrict: boolean
|
engineStrict: boolean
|
||||||
|
neverBuiltDependencies: string[]
|
||||||
nodeExecPath?: string
|
nodeExecPath?: string
|
||||||
nodeVersion: string
|
nodeVersion: string
|
||||||
|
packageExtensions: Record<string, PackageExtension>
|
||||||
packageManager: {
|
packageManager: {
|
||||||
name: string
|
name: string
|
||||||
version: string
|
version: string
|
||||||
@@ -67,6 +70,7 @@ export interface StrictInstallOptions {
|
|||||||
unsafePerm: boolean
|
unsafePerm: boolean
|
||||||
registries: Registries
|
registries: Registries
|
||||||
tag: string
|
tag: string
|
||||||
|
overrides: Record<string, string>
|
||||||
ownLifecycleHooksStdio: 'inherit' | 'pipe'
|
ownLifecycleHooksStdio: 'inherit' | 'pipe'
|
||||||
workspacePackages: WorkspacePackages
|
workspacePackages: WorkspacePackages
|
||||||
pruneStore: boolean
|
pruneStore: boolean
|
||||||
@@ -120,9 +124,12 @@ const defaults = async (opts: InstallOptions) => {
|
|||||||
},
|
},
|
||||||
lockfileDir: opts.lockfileDir ?? opts.dir ?? process.cwd(),
|
lockfileDir: opts.lockfileDir ?? opts.dir ?? process.cwd(),
|
||||||
lockfileOnly: false,
|
lockfileOnly: false,
|
||||||
|
neverBuiltDependencies: [] as string[],
|
||||||
nodeVersion: process.version,
|
nodeVersion: process.version,
|
||||||
|
overrides: {},
|
||||||
ownLifecycleHooksStdio: 'inherit',
|
ownLifecycleHooksStdio: 'inherit',
|
||||||
ignorePackageManifest: false,
|
ignorePackageManifest: false,
|
||||||
|
packageExtensions: {},
|
||||||
packageManager,
|
packageManager,
|
||||||
preferFrozenLockfile: true,
|
preferFrozenLockfile: true,
|
||||||
preferWorkspacePackages: false,
|
preferWorkspacePackages: false,
|
||||||
|
|||||||
@@ -166,19 +166,11 @@ export async function mutateModules (
|
|||||||
// When running install/update on a subset of projects, the root project might not be included,
|
// When running install/update on a subset of projects, the root project might not be included,
|
||||||
// so reading its manifest explicitly here.
|
// so reading its manifest explicitly here.
|
||||||
await safeReadProjectManifestOnly(opts.lockfileDir)
|
await safeReadProjectManifestOnly(opts.lockfileDir)
|
||||||
// We read Yarn's resolutions field for compatibility
|
|
||||||
// but we really replace the version specs to any other version spec, not only to exact versions,
|
|
||||||
// so we cannot call it resolutions
|
|
||||||
const overrides = (rootProjectManifest != null)
|
|
||||||
? rootProjectManifest.pnpm?.overrides ?? rootProjectManifest.resolutions
|
|
||||||
: undefined
|
|
||||||
const neverBuiltDependencies = rootProjectManifest?.pnpm?.neverBuiltDependencies ?? []
|
|
||||||
const packageExtensions = rootProjectManifest?.pnpm?.packageExtensions
|
|
||||||
opts.hooks.readPackage = createReadPackageHook({
|
opts.hooks.readPackage = createReadPackageHook({
|
||||||
readPackageHook: opts.hooks.readPackage,
|
readPackageHook: opts.hooks.readPackage,
|
||||||
overrides,
|
overrides: opts.overrides,
|
||||||
lockfileDir: opts.lockfileDir,
|
lockfileDir: opts.lockfileDir,
|
||||||
packageExtensions,
|
packageExtensions: opts.packageExtensions,
|
||||||
})
|
})
|
||||||
const ctx = await getContext(projects, opts)
|
const ctx = await getContext(projects, opts)
|
||||||
const pruneVirtualStore = ctx.modulesFile?.prunedAt && opts.modulesCacheMaxAge > 0
|
const pruneVirtualStore = ctx.modulesFile?.prunedAt && opts.modulesCacheMaxAge > 0
|
||||||
@@ -225,15 +217,15 @@ export async function mutateModules (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const packageExtensionsChecksum = isEmpty(packageExtensions ?? {}) ? undefined : createObjectChecksum(packageExtensions!)
|
const packageExtensionsChecksum = isEmpty(opts.packageExtensions ?? {}) ? undefined : createObjectChecksum(opts.packageExtensions!)
|
||||||
let needsFullResolution = !maybeOpts.ignorePackageManifest && (
|
let needsFullResolution = !maybeOpts.ignorePackageManifest && (
|
||||||
!equals(ctx.wantedLockfile.overrides ?? {}, overrides ?? {}) ||
|
!equals(ctx.wantedLockfile.overrides ?? {}, opts.overrides ?? {}) ||
|
||||||
!equals((ctx.wantedLockfile.neverBuiltDependencies ?? []).sort(), (neverBuiltDependencies ?? []).sort()) ||
|
!equals((ctx.wantedLockfile.neverBuiltDependencies ?? []).sort(), (opts.neverBuiltDependencies ?? []).sort()) ||
|
||||||
ctx.wantedLockfile.packageExtensionsChecksum !== packageExtensionsChecksum) ||
|
ctx.wantedLockfile.packageExtensionsChecksum !== packageExtensionsChecksum) ||
|
||||||
opts.fixLockfile
|
opts.fixLockfile
|
||||||
if (needsFullResolution) {
|
if (needsFullResolution) {
|
||||||
ctx.wantedLockfile.overrides = overrides
|
ctx.wantedLockfile.overrides = opts.overrides
|
||||||
ctx.wantedLockfile.neverBuiltDependencies = neverBuiltDependencies
|
ctx.wantedLockfile.neverBuiltDependencies = opts.neverBuiltDependencies
|
||||||
ctx.wantedLockfile.packageExtensionsChecksum = packageExtensionsChecksum
|
ctx.wantedLockfile.packageExtensionsChecksum = packageExtensionsChecksum
|
||||||
}
|
}
|
||||||
const frozenLockfile = opts.frozenLockfile ||
|
const frozenLockfile = opts.frozenLockfile ||
|
||||||
@@ -496,8 +488,6 @@ export async function mutateModules (
|
|||||||
currentLockfileIsUpToDate: !ctx.existsWantedLockfile || ctx.currentLockfileIsUpToDate,
|
currentLockfileIsUpToDate: !ctx.existsWantedLockfile || ctx.currentLockfileIsUpToDate,
|
||||||
makePartialCurrentLockfile,
|
makePartialCurrentLockfile,
|
||||||
needsFullResolution,
|
needsFullResolution,
|
||||||
neverBuiltDependencies,
|
|
||||||
overrides,
|
|
||||||
pruneVirtualStore,
|
pruneVirtualStore,
|
||||||
updateLockfileMinorVersion: true,
|
updateLockfileMinorVersion: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -446,9 +446,9 @@ test('scripts have access to unlisted bins when hoisting is used', async () => {
|
|||||||
test('selectively ignore scripts in some dependencies', async () => {
|
test('selectively ignore scripts in some dependencies', async () => {
|
||||||
const project = prepareEmpty()
|
const project = prepareEmpty()
|
||||||
const neverBuiltDependencies = ['pre-and-postinstall-scripts-example']
|
const neverBuiltDependencies = ['pre-and-postinstall-scripts-example']
|
||||||
const manifest = await addDependenciesToPackage({ pnpm: { neverBuiltDependencies } },
|
const manifest = await addDependenciesToPackage({},
|
||||||
['pre-and-postinstall-scripts-example', 'install-script-example'],
|
['pre-and-postinstall-scripts-example', 'install-script-example'],
|
||||||
await testDefaults({ fastUnpack: false })
|
await testDefaults({ fastUnpack: false, neverBuiltDependencies })
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(await exists('node_modules/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy()
|
expect(await exists('node_modules/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy()
|
||||||
@@ -462,7 +462,7 @@ test('selectively ignore scripts in some dependencies', async () => {
|
|||||||
|
|
||||||
await rimraf('node_modules')
|
await rimraf('node_modules')
|
||||||
|
|
||||||
await install(manifest, await testDefaults({ fastUnpack: false, frozenLockfile: true }))
|
await install(manifest, await testDefaults({ fastUnpack: false, frozenLockfile: true, neverBuiltDependencies }))
|
||||||
|
|
||||||
expect(await exists('node_modules/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy()
|
expect(await exists('node_modules/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy()
|
||||||
expect(await exists('node_modules/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy()
|
expect(await exists('node_modules/pre-and-postinstall-scripts-example/generated-by-postinstall.js')).toBeFalsy()
|
||||||
@@ -484,7 +484,6 @@ test('lockfile is updated if neverBuiltDependencies is changed', async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const neverBuiltDependencies = ['pre-and-postinstall-scripts-example']
|
const neverBuiltDependencies = ['pre-and-postinstall-scripts-example']
|
||||||
manifest.pnpm = { neverBuiltDependencies }
|
|
||||||
await mutateModules([
|
await mutateModules([
|
||||||
{
|
{
|
||||||
buildIndex: 0,
|
buildIndex: 0,
|
||||||
@@ -492,7 +491,7 @@ test('lockfile is updated if neverBuiltDependencies is changed', async () => {
|
|||||||
mutation: 'install',
|
mutation: 'install',
|
||||||
rootDir: process.cwd(),
|
rootDir: process.cwd(),
|
||||||
},
|
},
|
||||||
], await testDefaults())
|
], await testDefaults({ neverBuiltDependencies }))
|
||||||
|
|
||||||
{
|
{
|
||||||
const lockfile = await project.readLockfile()
|
const lockfile = await project.readLockfile()
|
||||||
|
|||||||
@@ -1174,16 +1174,6 @@ test('resolve a subdependency from the workspace and use it as a peer', async ()
|
|||||||
|
|
||||||
test('resolve a subdependency from the workspace, when it uses the workspace protocol', async () => {
|
test('resolve a subdependency from the workspace, when it uses the workspace protocol', async () => {
|
||||||
preparePackages([
|
preparePackages([
|
||||||
{
|
|
||||||
location: '.',
|
|
||||||
package: {
|
|
||||||
pnpm: {
|
|
||||||
overrides: {
|
|
||||||
'dep-of-pkg-with-1-dep': 'workspace:*',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
location: 'project',
|
location: 'project',
|
||||||
package: { name: 'project' },
|
package: { name: 'project' },
|
||||||
@@ -1229,7 +1219,14 @@ test('resolve a subdependency from the workspace, when it uses the workspace pro
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
await mutateModules(importers, await testDefaults({ linkWorkspacePackagesDepth: -1, workspacePackages }))
|
const overrides = {
|
||||||
|
'dep-of-pkg-with-1-dep': 'workspace:*',
|
||||||
|
}
|
||||||
|
await mutateModules(importers, await testDefaults({
|
||||||
|
linkWorkspacePackagesDepth: -1,
|
||||||
|
overrides,
|
||||||
|
workspacePackages,
|
||||||
|
}))
|
||||||
|
|
||||||
const project = assertProject(process.cwd())
|
const project = assertProject(process.cwd())
|
||||||
|
|
||||||
@@ -1241,6 +1238,7 @@ test('resolve a subdependency from the workspace, when it uses the workspace pro
|
|||||||
// Testing that headless installation does not fail with links in subdeps
|
// Testing that headless installation does not fail with links in subdeps
|
||||||
await mutateModules(importers, await testDefaults({
|
await mutateModules(importers, await testDefaults({
|
||||||
frozenLockfile: true,
|
frozenLockfile: true,
|
||||||
|
overrides,
|
||||||
workspacePackages,
|
workspacePackages,
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,21 +6,21 @@ import {
|
|||||||
testDefaults,
|
testDefaults,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
test('versions are replaced with versions specified through pnpm.overrides field', async () => {
|
test('versions are replaced with versions specified through overrides option', async () => {
|
||||||
const project = prepareEmpty()
|
const project = prepareEmpty()
|
||||||
|
|
||||||
await addDistTag({ package: 'bar', version: '100.0.0', distTag: 'latest' })
|
await addDistTag({ package: 'bar', version: '100.0.0', distTag: 'latest' })
|
||||||
await addDistTag({ package: 'foo', version: '100.0.0', distTag: 'latest' })
|
await addDistTag({ package: 'foo', version: '100.0.0', distTag: 'latest' })
|
||||||
|
|
||||||
const manifest = await addDependenciesToPackage({
|
const overrides = {
|
||||||
pnpm: {
|
'foobarqar>foo': 'npm:qar@100.0.0',
|
||||||
overrides: {
|
'bar@^100.0.0': '100.1.0',
|
||||||
'foobarqar>foo': 'npm:qar@100.0.0',
|
'dep-of-pkg-with-1-dep': '101.0.0',
|
||||||
'bar@^100.0.0': '100.1.0',
|
}
|
||||||
'dep-of-pkg-with-1-dep': '101.0.0',
|
const manifest = await addDependenciesToPackage({},
|
||||||
},
|
['pkg-with-1-dep@100.0.0', 'foobar@100.0.0', 'foobarqar@1.0.0'],
|
||||||
},
|
await testDefaults({ overrides })
|
||||||
}, ['pkg-with-1-dep@100.0.0', 'foobar@100.0.0', 'foobarqar@1.0.0'], await testDefaults())
|
)
|
||||||
|
|
||||||
{
|
{
|
||||||
const lockfile = await project.readLockfile()
|
const lockfile = await project.readLockfile()
|
||||||
@@ -44,12 +44,12 @@ test('versions are replaced with versions specified through pnpm.overrides field
|
|||||||
mutation: 'install',
|
mutation: 'install',
|
||||||
rootDir: process.cwd(),
|
rootDir: process.cwd(),
|
||||||
},
|
},
|
||||||
], { ...await testDefaults(), ignorePackageManifest: true })
|
], { ...await testDefaults(), ignorePackageManifest: true, overrides })
|
||||||
|
|
||||||
// The lockfile is updated if the overrides are changed
|
// The lockfile is updated if the overrides are changed
|
||||||
manifest.pnpm!.overrides!['bar@^100.0.0'] = '100.0.0'
|
overrides['bar@^100.0.0'] = '100.0.0'
|
||||||
// A direct dependency may be overriden as well
|
// A direct dependency may be overriden as well
|
||||||
manifest.pnpm!.overrides!['foobarqar'] = '1.0.1'
|
overrides['foobarqar'] = '1.0.1'
|
||||||
await mutateModules([
|
await mutateModules([
|
||||||
{
|
{
|
||||||
buildIndex: 0,
|
buildIndex: 0,
|
||||||
@@ -57,7 +57,7 @@ test('versions are replaced with versions specified through pnpm.overrides field
|
|||||||
mutation: 'install',
|
mutation: 'install',
|
||||||
rootDir: process.cwd(),
|
rootDir: process.cwd(),
|
||||||
},
|
},
|
||||||
], await testDefaults())
|
], await testDefaults({ overrides }))
|
||||||
|
|
||||||
{
|
{
|
||||||
const lockfile = await project.readLockfile()
|
const lockfile = await project.readLockfile()
|
||||||
@@ -81,7 +81,7 @@ test('versions are replaced with versions specified through pnpm.overrides field
|
|||||||
mutation: 'install',
|
mutation: 'install',
|
||||||
rootDir: process.cwd(),
|
rootDir: process.cwd(),
|
||||||
},
|
},
|
||||||
], await testDefaults({ frozenLockfile: true }))
|
], await testDefaults({ frozenLockfile: true, overrides }))
|
||||||
|
|
||||||
{
|
{
|
||||||
const lockfile = await project.readLockfile()
|
const lockfile = await project.readLockfile()
|
||||||
@@ -95,7 +95,7 @@ test('versions are replaced with versions specified through pnpm.overrides field
|
|||||||
expect(lockfile.overrides).toStrictEqual(currentLockfile.overrides)
|
expect(lockfile.overrides).toStrictEqual(currentLockfile.overrides)
|
||||||
}
|
}
|
||||||
|
|
||||||
manifest.pnpm!.overrides!['bar@^100.0.0'] = '100.0.1'
|
overrides['bar@^100.0.0'] = '100.0.1'
|
||||||
await expect(
|
await expect(
|
||||||
mutateModules([
|
mutateModules([
|
||||||
{
|
{
|
||||||
@@ -104,54 +104,10 @@ test('versions are replaced with versions specified through pnpm.overrides field
|
|||||||
mutation: 'install',
|
mutation: 'install',
|
||||||
rootDir: process.cwd(),
|
rootDir: process.cwd(),
|
||||||
},
|
},
|
||||||
], await testDefaults({ frozenLockfile: true }))
|
], await testDefaults({ frozenLockfile: true, overrides }))
|
||||||
).rejects.toThrow(
|
).rejects.toThrow(
|
||||||
new PnpmError('FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE',
|
new PnpmError('FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE',
|
||||||
'Cannot perform a frozen installation because the lockfile needs updates'
|
'Cannot perform a frozen installation because the lockfile needs updates'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('versions are replaced with versions specified through "resolutions" field (for Yarn compatibility)', async () => {
|
|
||||||
const project = prepareEmpty()
|
|
||||||
|
|
||||||
await addDistTag({ package: 'bar', version: '100.0.0', distTag: 'latest' })
|
|
||||||
|
|
||||||
const manifest = await addDependenciesToPackage({
|
|
||||||
resolutions: {
|
|
||||||
'bar@^100.0.0': '100.1.0',
|
|
||||||
'dep-of-pkg-with-1-dep': '101.0.0',
|
|
||||||
},
|
|
||||||
}, ['pkg-with-1-dep@100.0.0', 'foobar@100.0.0'], await testDefaults())
|
|
||||||
|
|
||||||
{
|
|
||||||
const lockfile = await project.readLockfile()
|
|
||||||
expect(lockfile.packages).toHaveProperty(['/dep-of-pkg-with-1-dep/101.0.0'])
|
|
||||||
expect(lockfile.packages).toHaveProperty(['/bar/100.1.0'])
|
|
||||||
expect(lockfile.overrides).toStrictEqual({
|
|
||||||
'bar@^100.0.0': '100.1.0',
|
|
||||||
'dep-of-pkg-with-1-dep': '101.0.0',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// The lockfile is updated if the resolutions are changed
|
|
||||||
manifest.resolutions!['bar@^100.0.0'] = '100.0.0'
|
|
||||||
await mutateModules([
|
|
||||||
{
|
|
||||||
buildIndex: 0,
|
|
||||||
manifest,
|
|
||||||
mutation: 'install',
|
|
||||||
rootDir: process.cwd(),
|
|
||||||
},
|
|
||||||
], await testDefaults())
|
|
||||||
|
|
||||||
{
|
|
||||||
const lockfile = await project.readLockfile()
|
|
||||||
expect(lockfile.packages).toHaveProperty(['/dep-of-pkg-with-1-dep/101.0.0'])
|
|
||||||
expect(lockfile.packages).toHaveProperty(['/bar/100.0.0'])
|
|
||||||
expect(lockfile.overrides).toStrictEqual({
|
|
||||||
'bar@^100.0.0': '100.0.0',
|
|
||||||
'dep-of-pkg-with-1-dep': '101.0.0',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -6,20 +6,21 @@ import {
|
|||||||
testDefaults,
|
testDefaults,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
|
|
||||||
test('manifests are extended with fields specified by pnpm.packageExtensions', async () => {
|
test('manifests are extended with fields specified by packageExtensions', async () => {
|
||||||
const project = prepareEmpty()
|
const project = prepareEmpty()
|
||||||
|
|
||||||
const manifest = await addDependenciesToPackage({
|
const packageExtensions = {
|
||||||
pnpm: {
|
'is-positive': {
|
||||||
packageExtensions: {
|
dependencies: {
|
||||||
'is-positive': {
|
bar: '100.1.0',
|
||||||
dependencies: {
|
|
||||||
bar: '100.1.0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, ['is-positive@1.0.0'], await testDefaults())
|
}
|
||||||
|
const manifest = await addDependenciesToPackage(
|
||||||
|
{},
|
||||||
|
['is-positive@1.0.0'],
|
||||||
|
await testDefaults({ packageExtensions })
|
||||||
|
)
|
||||||
|
|
||||||
{
|
{
|
||||||
const lockfile = await project.readLockfile()
|
const lockfile = await project.readLockfile()
|
||||||
@@ -36,7 +37,7 @@ test('manifests are extended with fields specified by pnpm.packageExtensions', a
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The lockfile is updated if the overrides are changed
|
// The lockfile is updated if the overrides are changed
|
||||||
manifest.pnpm!.packageExtensions!['is-positive'].dependencies!['foobar'] = '100.0.0'
|
packageExtensions['is-positive'].dependencies!['foobar'] = '100.0.0'
|
||||||
await mutateModules([
|
await mutateModules([
|
||||||
{
|
{
|
||||||
buildIndex: 0,
|
buildIndex: 0,
|
||||||
@@ -44,7 +45,7 @@ test('manifests are extended with fields specified by pnpm.packageExtensions', a
|
|||||||
mutation: 'install',
|
mutation: 'install',
|
||||||
rootDir: process.cwd(),
|
rootDir: process.cwd(),
|
||||||
},
|
},
|
||||||
], await testDefaults())
|
], await testDefaults({ packageExtensions }))
|
||||||
|
|
||||||
{
|
{
|
||||||
const lockfile = await project.readLockfile()
|
const lockfile = await project.readLockfile()
|
||||||
@@ -68,7 +69,7 @@ test('manifests are extended with fields specified by pnpm.packageExtensions', a
|
|||||||
mutation: 'install',
|
mutation: 'install',
|
||||||
rootDir: process.cwd(),
|
rootDir: process.cwd(),
|
||||||
},
|
},
|
||||||
], await testDefaults({ frozenLockfile: true }))
|
], await testDefaults({ frozenLockfile: true, packageExtensions }))
|
||||||
|
|
||||||
{
|
{
|
||||||
const lockfile = await project.readLockfile()
|
const lockfile = await project.readLockfile()
|
||||||
@@ -84,7 +85,7 @@ test('manifests are extended with fields specified by pnpm.packageExtensions', a
|
|||||||
expect(lockfile.packageExtensionsChecksum).toStrictEqual(currentLockfile.packageExtensionsChecksum)
|
expect(lockfile.packageExtensionsChecksum).toStrictEqual(currentLockfile.packageExtensionsChecksum)
|
||||||
}
|
}
|
||||||
|
|
||||||
manifest.pnpm!.packageExtensions!['is-positive'].dependencies!['bar'] = '100.0.1'
|
packageExtensions['is-positive'].dependencies!['bar'] = '100.0.1'
|
||||||
await expect(
|
await expect(
|
||||||
mutateModules([
|
mutateModules([
|
||||||
{
|
{
|
||||||
@@ -93,7 +94,7 @@ test('manifests are extended with fields specified by pnpm.packageExtensions', a
|
|||||||
mutation: 'install',
|
mutation: 'install',
|
||||||
rootDir: process.cwd(),
|
rootDir: process.cwd(),
|
||||||
},
|
},
|
||||||
], await testDefaults({ frozenLockfile: true }))
|
], await testDefaults({ frozenLockfile: true, packageExtensions }))
|
||||||
).rejects.toThrow(
|
).rejects.toThrow(
|
||||||
new PnpmError('FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE',
|
new PnpmError('FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE',
|
||||||
'Cannot perform a frozen installation because the lockfile needs updates'
|
'Cannot perform a frozen installation because the lockfile needs updates'
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { ProjectManifest } from '@pnpm/types'
|
||||||
|
|
||||||
|
export default function getOptionsFromRootManifest (manifest: ProjectManifest) {
|
||||||
|
// We read Yarn's resolutions field for compatibility
|
||||||
|
// but we really replace the version specs to any other version spec, not only to exact versions,
|
||||||
|
// so we cannot call it resolutions
|
||||||
|
const overrides = manifest.pnpm?.overrides ?? manifest.resolutions
|
||||||
|
const neverBuiltDependencies = manifest.pnpm?.neverBuiltDependencies ?? []
|
||||||
|
const packageExtensions = manifest.pnpm?.packageExtensions
|
||||||
|
return {
|
||||||
|
overrides,
|
||||||
|
neverBuiltDependencies,
|
||||||
|
packageExtensions,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import { parse as parseYarnLock } from '@yarnpkg/lockfile'
|
|||||||
import * as yarnCore from '@yarnpkg/core'
|
import * as yarnCore from '@yarnpkg/core'
|
||||||
import { parseSyml } from '@yarnpkg/parsers'
|
import { parseSyml } from '@yarnpkg/parsers'
|
||||||
import exists from 'path-exists'
|
import exists from 'path-exists'
|
||||||
|
import getOptionsFromRootManifest from '../getOptionsFromRootManifest'
|
||||||
import recursive from '../recursive'
|
import recursive from '../recursive'
|
||||||
import { yarnLockFileKeyNormalizer } from './yarnUtil'
|
import { yarnLockFileKeyNormalizer } from './yarnUtil'
|
||||||
|
|
||||||
@@ -143,14 +144,16 @@ export async function handler (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const store = await createOrConnectStoreController(opts)
|
const store = await createOrConnectStoreController(opts)
|
||||||
|
const manifest = await readProjectManifestOnly(opts.dir)
|
||||||
const installOpts = {
|
const installOpts = {
|
||||||
...opts,
|
...opts,
|
||||||
|
...getOptionsFromRootManifest(manifest),
|
||||||
lockfileOnly: true,
|
lockfileOnly: true,
|
||||||
preferredVersions,
|
preferredVersions,
|
||||||
storeController: store.ctrl,
|
storeController: store.ctrl,
|
||||||
storeDir: store.dir,
|
storeDir: store.dir,
|
||||||
}
|
}
|
||||||
await install(await readProjectManifestOnly(opts.dir), installOpts)
|
await install(manifest, installOpts)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readYarnLockFile (dir: string) {
|
async function readYarnLockFile (dir: string) {
|
||||||
@@ -279,4 +282,4 @@ function getYarnLockfileType (
|
|||||||
return lockFileContents.includes('__metadata')
|
return lockFileContents.includes('__metadata')
|
||||||
? YarnLockType.yarn2
|
? YarnLockType.yarn2
|
||||||
: YarnLockType.yarn
|
: YarnLockType.yarn
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
import logger from '@pnpm/logger'
|
import logger from '@pnpm/logger'
|
||||||
import { sequenceGraph } from '@pnpm/sort-packages'
|
import { sequenceGraph } from '@pnpm/sort-packages'
|
||||||
import isSubdir from 'is-subdir'
|
import isSubdir from 'is-subdir'
|
||||||
|
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||||
import getPinnedVersion from './getPinnedVersion'
|
import getPinnedVersion from './getPinnedVersion'
|
||||||
import getSaveType from './getSaveType'
|
import getSaveType from './getSaveType'
|
||||||
import getNodeExecPath from './nodeExecPath'
|
import getNodeExecPath from './nodeExecPath'
|
||||||
@@ -161,9 +162,18 @@ when running add/update with the --workspace option')
|
|||||||
workspacePackages = arrayOfWorkspacePackagesToMap(allProjects)
|
workspacePackages = arrayOfWorkspacePackagesToMap(allProjects)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let { manifest, writeProjectManifest } = await tryReadProjectManifest(opts.dir, opts)
|
||||||
|
if (manifest === null) {
|
||||||
|
if (opts.update) {
|
||||||
|
throw new PnpmError('NO_IMPORTER_MANIFEST', 'No package.json found')
|
||||||
|
}
|
||||||
|
manifest = {}
|
||||||
|
}
|
||||||
|
|
||||||
const store = await createOrConnectStoreController(opts)
|
const store = await createOrConnectStoreController(opts)
|
||||||
const installOpts = {
|
const installOpts = {
|
||||||
...opts,
|
...opts,
|
||||||
|
...getOptionsFromRootManifest(manifest),
|
||||||
forceHoistPattern,
|
forceHoistPattern,
|
||||||
forcePublicHoistPattern,
|
forcePublicHoistPattern,
|
||||||
// In case installation is done in a multi-package repository
|
// In case installation is done in a multi-package repository
|
||||||
@@ -184,14 +194,6 @@ when running add/update with the --workspace option')
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let { manifest, writeProjectManifest } = await tryReadProjectManifest(opts.dir, opts)
|
|
||||||
if (manifest === null) {
|
|
||||||
if (opts.update) {
|
|
||||||
throw new PnpmError('NO_IMPORTER_MANIFEST', 'No package.json found')
|
|
||||||
}
|
|
||||||
manifest = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateMatch = opts.update && (params.length > 0) ? createMatcher(params) : null
|
const updateMatch = opts.update && (params.length > 0) ? createMatcher(params) : null
|
||||||
if (updateMatch != null) {
|
if (updateMatch != null) {
|
||||||
params = matchDependencies(updateMatch, manifest, includeDirect)
|
params = matchDependencies(updateMatch, manifest, includeDirect)
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import pick from 'ramda/src/pick'
|
|||||||
import partition from 'ramda/src/partition'
|
import partition from 'ramda/src/partition'
|
||||||
import renderHelp from 'render-help'
|
import renderHelp from 'render-help'
|
||||||
import * as installCommand from './install'
|
import * as installCommand from './install'
|
||||||
|
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||||
import getSaveType from './getSaveType'
|
import getSaveType from './getSaveType'
|
||||||
|
|
||||||
const isWindows = process.platform === 'win32' || global['FAKE_WINDOWS']
|
const isWindows = process.platform === 'win32' || global['FAKE_WINDOWS']
|
||||||
@@ -140,6 +141,7 @@ export async function handler (
|
|||||||
await install(
|
await install(
|
||||||
await readProjectManifestOnly(dir, opts), {
|
await readProjectManifestOnly(dir, opts), {
|
||||||
...config,
|
...config,
|
||||||
|
...getOptionsFromRootManifest(config.rootProjectManifest ?? {}),
|
||||||
include: {
|
include: {
|
||||||
dependencies: config.production !== false,
|
dependencies: config.production !== false,
|
||||||
devDependencies: config.dev !== false,
|
devDependencies: config.dev !== false,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { createOrConnectStoreController, CreateStoreControllerOptions } from '@p
|
|||||||
import { InstallOptions, mutateModules } from '@pnpm/core'
|
import { InstallOptions, mutateModules } from '@pnpm/core'
|
||||||
import pick from 'ramda/src/pick'
|
import pick from 'ramda/src/pick'
|
||||||
import renderHelp from 'render-help'
|
import renderHelp from 'render-help'
|
||||||
|
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||||
|
|
||||||
export const rcOptionsTypes = cliOptionsTypes
|
export const rcOptionsTypes = cliOptionsTypes
|
||||||
|
|
||||||
@@ -44,19 +45,21 @@ export function help () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function handler (
|
export async function handler (
|
||||||
opts: Pick<Config, 'dev' | 'engineStrict' | 'optional' | 'production'> & CreateStoreControllerOptions
|
opts: Pick<Config, 'dev' | 'engineStrict' | 'optional' | 'production' | 'rootProjectManifest'> & CreateStoreControllerOptions
|
||||||
) {
|
) {
|
||||||
const store = await createOrConnectStoreController(opts)
|
const store = await createOrConnectStoreController(opts)
|
||||||
|
const manifest = await readProjectManifestOnly(process.cwd(), opts)
|
||||||
return mutateModules([
|
return mutateModules([
|
||||||
{
|
{
|
||||||
buildIndex: 0,
|
buildIndex: 0,
|
||||||
manifest: await readProjectManifestOnly(process.cwd(), opts),
|
manifest,
|
||||||
mutation: 'install',
|
mutation: 'install',
|
||||||
pruneDirectDependencies: true,
|
pruneDirectDependencies: true,
|
||||||
rootDir: process.cwd(),
|
rootDir: process.cwd(),
|
||||||
},
|
},
|
||||||
], {
|
], {
|
||||||
...opts,
|
...opts,
|
||||||
|
...getOptionsFromRootManifest(opts.rootProjectManifest ?? {}),
|
||||||
include: {
|
include: {
|
||||||
dependencies: opts.production !== false,
|
dependencies: opts.production !== false,
|
||||||
devDependencies: opts.dev !== false,
|
devDependencies: opts.dev !== false,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import mem from 'mem'
|
|||||||
import pFilter from 'p-filter'
|
import pFilter from 'p-filter'
|
||||||
import pLimit from 'p-limit'
|
import pLimit from 'p-limit'
|
||||||
import readIniFile from 'read-ini-file'
|
import readIniFile from 'read-ini-file'
|
||||||
|
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||||
import { createWorkspaceSpecs, updateToWorkspacePackagesFromManifest } from './updateWorkspaceDependencies'
|
import { createWorkspaceSpecs, updateToWorkspacePackagesFromManifest } from './updateWorkspaceDependencies'
|
||||||
import updateToLatestSpecsFromManifest, { createLatestSpecs } from './updateToLatestSpecsFromManifest'
|
import updateToLatestSpecsFromManifest, { createLatestSpecs } from './updateToLatestSpecsFromManifest'
|
||||||
import getSaveType from './getSaveType'
|
import getSaveType from './getSaveType'
|
||||||
@@ -122,6 +123,7 @@ export default async function recursive (
|
|||||||
: {}
|
: {}
|
||||||
const targetDependenciesField = getSaveType(opts)
|
const targetDependenciesField = getSaveType(opts)
|
||||||
const installOpts = Object.assign(opts, {
|
const installOpts = Object.assign(opts, {
|
||||||
|
...getOptionsFromRootManifest(manifestsByPath[opts.lockfileDir ?? opts.dir]?.manifest ?? {}),
|
||||||
linkWorkspacePackagesDepth: opts.linkWorkspacePackages === 'deep' ? Infinity : opts.linkWorkspacePackages ? 0 : -1,
|
linkWorkspacePackagesDepth: opts.linkWorkspacePackages === 'deep' ? Infinity : opts.linkWorkspacePackages ? 0 : -1,
|
||||||
ownLifecycleHooksStdio: 'pipe',
|
ownLifecycleHooksStdio: 'pipe',
|
||||||
peer: opts.savePeer,
|
peer: opts.savePeer,
|
||||||
@@ -356,6 +358,7 @@ export default async function recursive (
|
|||||||
{
|
{
|
||||||
...installOpts,
|
...installOpts,
|
||||||
...localConfig,
|
...localConfig,
|
||||||
|
...getOptionsFromRootManifest(manifest),
|
||||||
bin: path.join(rootDir, 'node_modules', '.bin'),
|
bin: path.join(rootDir, 'node_modules', '.bin'),
|
||||||
dir: rootDir,
|
dir: rootDir,
|
||||||
hooks,
|
hooks,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
import pick from 'ramda/src/pick'
|
import pick from 'ramda/src/pick'
|
||||||
import without from 'ramda/src/without'
|
import without from 'ramda/src/without'
|
||||||
import renderHelp from 'render-help'
|
import renderHelp from 'render-help'
|
||||||
|
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||||
import getSaveType from './getSaveType'
|
import getSaveType from './getSaveType'
|
||||||
import recursive from './recursive'
|
import recursive from './recursive'
|
||||||
|
|
||||||
@@ -140,6 +141,7 @@ export async function handler (
|
|||||||
| 'production'
|
| 'production'
|
||||||
| 'rawLocalConfig'
|
| 'rawLocalConfig'
|
||||||
| 'registries'
|
| 'registries'
|
||||||
|
| 'rootProjectManifest'
|
||||||
| 'saveDev'
|
| 'saveDev'
|
||||||
| 'saveOptional'
|
| 'saveOptional'
|
||||||
| 'saveProd'
|
| 'saveProd'
|
||||||
@@ -162,6 +164,7 @@ export async function handler (
|
|||||||
}
|
}
|
||||||
const store = await createOrConnectStoreController(opts)
|
const store = await createOrConnectStoreController(opts)
|
||||||
const removeOpts = Object.assign(opts, {
|
const removeOpts = Object.assign(opts, {
|
||||||
|
...getOptionsFromRootManifest(opts.rootProjectManifest ?? {}),
|
||||||
storeController: store.ctrl,
|
storeController: store.ctrl,
|
||||||
storeDir: store.dir,
|
storeDir: store.dir,
|
||||||
include,
|
include,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Config } from '@pnpm/config'
|
|||||||
import { createOrConnectStoreController, CreateStoreControllerOptions } from '@pnpm/store-connection-manager'
|
import { createOrConnectStoreController, CreateStoreControllerOptions } from '@pnpm/store-connection-manager'
|
||||||
import { mutateModules } from '@pnpm/core'
|
import { mutateModules } from '@pnpm/core'
|
||||||
import renderHelp from 'render-help'
|
import renderHelp from 'render-help'
|
||||||
|
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||||
import { cliOptionsTypes, rcOptionsTypes } from './install'
|
import { cliOptionsTypes, rcOptionsTypes } from './install'
|
||||||
import recursive from './recursive'
|
import recursive from './recursive'
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@ export async function handler (
|
|||||||
| 'selectedProjectsGraph'
|
| 'selectedProjectsGraph'
|
||||||
| 'rawLocalConfig'
|
| 'rawLocalConfig'
|
||||||
| 'registries'
|
| 'registries'
|
||||||
|
| 'rootProjectManifest'
|
||||||
| 'pnpmfile'
|
| 'pnpmfile'
|
||||||
| 'workspaceDir'
|
| 'workspaceDir'
|
||||||
> & {
|
> & {
|
||||||
@@ -64,6 +66,7 @@ export async function handler (
|
|||||||
}
|
}
|
||||||
const store = await createOrConnectStoreController(opts)
|
const store = await createOrConnectStoreController(opts)
|
||||||
const unlinkOpts = Object.assign(opts, {
|
const unlinkOpts = Object.assign(opts, {
|
||||||
|
...getOptionsFromRootManifest(opts.rootProjectManifest ?? {}),
|
||||||
globalBin: opts.bin,
|
globalBin: opts.bin,
|
||||||
storeController: store.ctrl,
|
storeController: store.ctrl,
|
||||||
storeDir: store.dir,
|
storeDir: store.dir,
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import getOptionsFromRootManifest from '@pnpm/plugin-commands-installation/lib/getOptionsFromRootManifest'
|
||||||
|
|
||||||
|
test('getOptionsFromRootManifest() should read "resolutions" field for compatibility with Yarn', () => {
|
||||||
|
const options = getOptionsFromRootManifest({
|
||||||
|
resolutions: {
|
||||||
|
foo: '1.0.0',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(options.overrides).toStrictEqual({ foo: '1.0.0' })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('getOptionsFromRootManifest() should read "overrides" field', () => {
|
||||||
|
const options = getOptionsFromRootManifest({
|
||||||
|
pnpm: {
|
||||||
|
overrides: {
|
||||||
|
foo: '1.0.0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(options.overrides).toStrictEqual({ foo: '1.0.0' })
|
||||||
|
})
|
||||||
2
pnpm-lock.yaml
generated
2
pnpm-lock.yaml
generated
@@ -330,6 +330,7 @@ importers:
|
|||||||
'@pnpm/global-bin-dir': workspace:3.0.0
|
'@pnpm/global-bin-dir': workspace:3.0.0
|
||||||
'@pnpm/pnpmfile': workspace:1.2.0
|
'@pnpm/pnpmfile': workspace:1.2.0
|
||||||
'@pnpm/prepare': workspace:0.0.28
|
'@pnpm/prepare': workspace:0.0.28
|
||||||
|
'@pnpm/read-project-manifest': workspace:2.0.7
|
||||||
'@pnpm/types': workspace:7.6.0
|
'@pnpm/types': workspace:7.6.0
|
||||||
'@types/ramda': 0.27.39
|
'@types/ramda': 0.27.39
|
||||||
'@types/which': ^2.0.0
|
'@types/which': ^2.0.0
|
||||||
@@ -347,6 +348,7 @@ importers:
|
|||||||
'@pnpm/error': link:../error
|
'@pnpm/error': link:../error
|
||||||
'@pnpm/global-bin-dir': link:../global-bin-dir
|
'@pnpm/global-bin-dir': link:../global-bin-dir
|
||||||
'@pnpm/pnpmfile': link:../pnpmfile
|
'@pnpm/pnpmfile': link:../pnpmfile
|
||||||
|
'@pnpm/read-project-manifest': link:../read-project-manifest
|
||||||
'@pnpm/types': link:../types
|
'@pnpm/types': link:../types
|
||||||
'@zkochan/npm-conf': 2.0.2
|
'@zkochan/npm-conf': 2.0.2
|
||||||
camelcase: 6.2.1
|
camelcase: 6.2.1
|
||||||
|
|||||||
Reference in New Issue
Block a user