mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-24 07:38:12 -05: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/global-bin-dir": "workspace:3.0.0",
|
||||
"@pnpm/pnpmfile": "workspace:1.2.0",
|
||||
"@pnpm/read-project-manifest": "workspace:2.0.7",
|
||||
"@pnpm/types": "workspace:7.6.0",
|
||||
"@zkochan/npm-conf": "2.0.2",
|
||||
"camelcase": "^6.2.0",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
Project,
|
||||
ProjectManifest,
|
||||
ProjectsGraph,
|
||||
Registries,
|
||||
} from '@pnpm/types'
|
||||
@@ -140,6 +141,7 @@ export interface Config {
|
||||
testPattern?: string[]
|
||||
changedFilesIgnorePattern?: string[]
|
||||
extendNodePath?: boolean
|
||||
rootProjectManifest?: ProjectManifest
|
||||
}
|
||||
|
||||
export interface ConfigWithDeprecatedSettings extends Config {
|
||||
|
||||
@@ -5,6 +5,7 @@ import { LAYOUT_VERSION } from '@pnpm/constants'
|
||||
import PnpmError from '@pnpm/error'
|
||||
import globalBinDir from '@pnpm/global-bin-dir'
|
||||
import { requireHooks } from '@pnpm/pnpmfile'
|
||||
import { safeReadProjectManifestOnly } from '@pnpm/read-project-manifest'
|
||||
import camelcase from 'camelcase'
|
||||
import loadNpmConf from '@zkochan/npm-conf'
|
||||
import npmTypes from '@zkochan/npm-conf/lib/types'
|
||||
@@ -483,6 +484,7 @@ export default async (
|
||||
if (!pnpmConfig.ignorePnpmfile) {
|
||||
pnpmConfig.hooks = requireHooks(pnpmConfig.lockfileDir ?? pnpmConfig.dir, pnpmConfig)
|
||||
}
|
||||
pnpmConfig.rootProjectManifest = await safeReadProjectManifestOnly(pnpmConfig.lockfileDir ?? pnpmConfig.dir) ?? undefined
|
||||
|
||||
return { config: pnpmConfig, warnings }
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
{
|
||||
"path": "../pnpmfile"
|
||||
},
|
||||
{
|
||||
"path": "../read-project-manifest"
|
||||
},
|
||||
{
|
||||
"path": "../types"
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import normalizeRegistries, { DEFAULT_REGISTRIES } from '@pnpm/normalize-registr
|
||||
import { WorkspacePackages } from '@pnpm/resolver-base'
|
||||
import { StoreController } from '@pnpm/store-controller-types'
|
||||
import {
|
||||
PackageExtension,
|
||||
ReadPackageHook,
|
||||
Registries,
|
||||
} from '@pnpm/types'
|
||||
@@ -44,8 +45,10 @@ export interface StrictInstallOptions {
|
||||
rawConfig: object
|
||||
verifyStoreIntegrity: boolean
|
||||
engineStrict: boolean
|
||||
neverBuiltDependencies: string[]
|
||||
nodeExecPath?: string
|
||||
nodeVersion: string
|
||||
packageExtensions: Record<string, PackageExtension>
|
||||
packageManager: {
|
||||
name: string
|
||||
version: string
|
||||
@@ -67,6 +70,7 @@ export interface StrictInstallOptions {
|
||||
unsafePerm: boolean
|
||||
registries: Registries
|
||||
tag: string
|
||||
overrides: Record<string, string>
|
||||
ownLifecycleHooksStdio: 'inherit' | 'pipe'
|
||||
workspacePackages: WorkspacePackages
|
||||
pruneStore: boolean
|
||||
@@ -120,9 +124,12 @@ const defaults = async (opts: InstallOptions) => {
|
||||
},
|
||||
lockfileDir: opts.lockfileDir ?? opts.dir ?? process.cwd(),
|
||||
lockfileOnly: false,
|
||||
neverBuiltDependencies: [] as string[],
|
||||
nodeVersion: process.version,
|
||||
overrides: {},
|
||||
ownLifecycleHooksStdio: 'inherit',
|
||||
ignorePackageManifest: false,
|
||||
packageExtensions: {},
|
||||
packageManager,
|
||||
preferFrozenLockfile: true,
|
||||
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,
|
||||
// so reading its manifest explicitly here.
|
||||
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({
|
||||
readPackageHook: opts.hooks.readPackage,
|
||||
overrides,
|
||||
overrides: opts.overrides,
|
||||
lockfileDir: opts.lockfileDir,
|
||||
packageExtensions,
|
||||
packageExtensions: opts.packageExtensions,
|
||||
})
|
||||
const ctx = await getContext(projects, opts)
|
||||
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 && (
|
||||
!equals(ctx.wantedLockfile.overrides ?? {}, overrides ?? {}) ||
|
||||
!equals((ctx.wantedLockfile.neverBuiltDependencies ?? []).sort(), (neverBuiltDependencies ?? []).sort()) ||
|
||||
!equals(ctx.wantedLockfile.overrides ?? {}, opts.overrides ?? {}) ||
|
||||
!equals((ctx.wantedLockfile.neverBuiltDependencies ?? []).sort(), (opts.neverBuiltDependencies ?? []).sort()) ||
|
||||
ctx.wantedLockfile.packageExtensionsChecksum !== packageExtensionsChecksum) ||
|
||||
opts.fixLockfile
|
||||
if (needsFullResolution) {
|
||||
ctx.wantedLockfile.overrides = overrides
|
||||
ctx.wantedLockfile.neverBuiltDependencies = neverBuiltDependencies
|
||||
ctx.wantedLockfile.overrides = opts.overrides
|
||||
ctx.wantedLockfile.neverBuiltDependencies = opts.neverBuiltDependencies
|
||||
ctx.wantedLockfile.packageExtensionsChecksum = packageExtensionsChecksum
|
||||
}
|
||||
const frozenLockfile = opts.frozenLockfile ||
|
||||
@@ -496,8 +488,6 @@ export async function mutateModules (
|
||||
currentLockfileIsUpToDate: !ctx.existsWantedLockfile || ctx.currentLockfileIsUpToDate,
|
||||
makePartialCurrentLockfile,
|
||||
needsFullResolution,
|
||||
neverBuiltDependencies,
|
||||
overrides,
|
||||
pruneVirtualStore,
|
||||
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 () => {
|
||||
const project = prepareEmpty()
|
||||
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'],
|
||||
await testDefaults({ fastUnpack: false })
|
||||
await testDefaults({ fastUnpack: false, neverBuiltDependencies })
|
||||
)
|
||||
|
||||
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 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-postinstall.js')).toBeFalsy()
|
||||
@@ -484,7 +484,6 @@ test('lockfile is updated if neverBuiltDependencies is changed', async () => {
|
||||
}
|
||||
|
||||
const neverBuiltDependencies = ['pre-and-postinstall-scripts-example']
|
||||
manifest.pnpm = { neverBuiltDependencies }
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
@@ -492,7 +491,7 @@ test('lockfile is updated if neverBuiltDependencies is changed', async () => {
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
], await testDefaults({ neverBuiltDependencies }))
|
||||
|
||||
{
|
||||
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 () => {
|
||||
preparePackages([
|
||||
{
|
||||
location: '.',
|
||||
package: {
|
||||
pnpm: {
|
||||
overrides: {
|
||||
'dep-of-pkg-with-1-dep': 'workspace:*',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
location: '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())
|
||||
|
||||
@@ -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
|
||||
await mutateModules(importers, await testDefaults({
|
||||
frozenLockfile: true,
|
||||
overrides,
|
||||
workspacePackages,
|
||||
}))
|
||||
})
|
||||
|
||||
@@ -6,21 +6,21 @@ import {
|
||||
testDefaults,
|
||||
} 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()
|
||||
|
||||
await addDistTag({ package: 'bar', version: '100.0.0', distTag: 'latest' })
|
||||
await addDistTag({ package: 'foo', version: '100.0.0', distTag: 'latest' })
|
||||
|
||||
const manifest = await addDependenciesToPackage({
|
||||
pnpm: {
|
||||
overrides: {
|
||||
'foobarqar>foo': 'npm:qar@100.0.0',
|
||||
'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', 'foobarqar@1.0.0'], await testDefaults())
|
||||
const overrides = {
|
||||
'foobarqar>foo': 'npm:qar@100.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 })
|
||||
)
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -44,12 +44,12 @@ test('versions are replaced with versions specified through pnpm.overrides field
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], { ...await testDefaults(), ignorePackageManifest: true })
|
||||
], { ...await testDefaults(), ignorePackageManifest: true, overrides })
|
||||
|
||||
// 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
|
||||
manifest.pnpm!.overrides!['foobarqar'] = '1.0.1'
|
||||
overrides['foobarqar'] = '1.0.1'
|
||||
await mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
@@ -57,7 +57,7 @@ test('versions are replaced with versions specified through pnpm.overrides field
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
], await testDefaults({ overrides }))
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -81,7 +81,7 @@ test('versions are replaced with versions specified through pnpm.overrides field
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ frozenLockfile: true }))
|
||||
], await testDefaults({ frozenLockfile: true, overrides }))
|
||||
|
||||
{
|
||||
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)
|
||||
}
|
||||
|
||||
manifest.pnpm!.overrides!['bar@^100.0.0'] = '100.0.1'
|
||||
overrides['bar@^100.0.0'] = '100.0.1'
|
||||
await expect(
|
||||
mutateModules([
|
||||
{
|
||||
@@ -104,54 +104,10 @@ test('versions are replaced with versions specified through pnpm.overrides field
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ frozenLockfile: true }))
|
||||
], await testDefaults({ frozenLockfile: true, overrides }))
|
||||
).rejects.toThrow(
|
||||
new PnpmError('FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE',
|
||||
'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,
|
||||
} 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 manifest = await addDependenciesToPackage({
|
||||
pnpm: {
|
||||
packageExtensions: {
|
||||
'is-positive': {
|
||||
dependencies: {
|
||||
bar: '100.1.0',
|
||||
},
|
||||
},
|
||||
const packageExtensions = {
|
||||
'is-positive': {
|
||||
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()
|
||||
@@ -36,7 +37,7 @@ test('manifests are extended with fields specified by pnpm.packageExtensions', a
|
||||
}
|
||||
|
||||
// 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([
|
||||
{
|
||||
buildIndex: 0,
|
||||
@@ -44,7 +45,7 @@ test('manifests are extended with fields specified by pnpm.packageExtensions', a
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults())
|
||||
], await testDefaults({ packageExtensions }))
|
||||
|
||||
{
|
||||
const lockfile = await project.readLockfile()
|
||||
@@ -68,7 +69,7 @@ test('manifests are extended with fields specified by pnpm.packageExtensions', a
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ frozenLockfile: true }))
|
||||
], await testDefaults({ frozenLockfile: true, packageExtensions }))
|
||||
|
||||
{
|
||||
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)
|
||||
}
|
||||
|
||||
manifest.pnpm!.packageExtensions!['is-positive'].dependencies!['bar'] = '100.0.1'
|
||||
packageExtensions['is-positive'].dependencies!['bar'] = '100.0.1'
|
||||
await expect(
|
||||
mutateModules([
|
||||
{
|
||||
@@ -93,7 +94,7 @@ test('manifests are extended with fields specified by pnpm.packageExtensions', a
|
||||
mutation: 'install',
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], await testDefaults({ frozenLockfile: true }))
|
||||
], await testDefaults({ frozenLockfile: true, packageExtensions }))
|
||||
).rejects.toThrow(
|
||||
new PnpmError('FROZEN_LOCKFILE_WITH_OUTDATED_LOCKFILE',
|
||||
'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 { parseSyml } from '@yarnpkg/parsers'
|
||||
import exists from 'path-exists'
|
||||
import getOptionsFromRootManifest from '../getOptionsFromRootManifest'
|
||||
import recursive from '../recursive'
|
||||
import { yarnLockFileKeyNormalizer } from './yarnUtil'
|
||||
|
||||
@@ -143,14 +144,16 @@ export async function handler (
|
||||
}
|
||||
|
||||
const store = await createOrConnectStoreController(opts)
|
||||
const manifest = await readProjectManifestOnly(opts.dir)
|
||||
const installOpts = {
|
||||
...opts,
|
||||
...getOptionsFromRootManifest(manifest),
|
||||
lockfileOnly: true,
|
||||
preferredVersions,
|
||||
storeController: store.ctrl,
|
||||
storeDir: store.dir,
|
||||
}
|
||||
await install(await readProjectManifestOnly(opts.dir), installOpts)
|
||||
await install(manifest, installOpts)
|
||||
}
|
||||
|
||||
async function readYarnLockFile (dir: string) {
|
||||
@@ -279,4 +282,4 @@ function getYarnLockfileType (
|
||||
return lockFileContents.includes('__metadata')
|
||||
? YarnLockType.yarn2
|
||||
: YarnLockType.yarn
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
import logger from '@pnpm/logger'
|
||||
import { sequenceGraph } from '@pnpm/sort-packages'
|
||||
import isSubdir from 'is-subdir'
|
||||
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||
import getPinnedVersion from './getPinnedVersion'
|
||||
import getSaveType from './getSaveType'
|
||||
import getNodeExecPath from './nodeExecPath'
|
||||
@@ -161,9 +162,18 @@ when running add/update with the --workspace option')
|
||||
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 installOpts = {
|
||||
...opts,
|
||||
...getOptionsFromRootManifest(manifest),
|
||||
forceHoistPattern,
|
||||
forcePublicHoistPattern,
|
||||
// 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
|
||||
if (updateMatch != null) {
|
||||
params = matchDependencies(updateMatch, manifest, includeDirect)
|
||||
|
||||
@@ -27,6 +27,7 @@ import pick from 'ramda/src/pick'
|
||||
import partition from 'ramda/src/partition'
|
||||
import renderHelp from 'render-help'
|
||||
import * as installCommand from './install'
|
||||
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||
import getSaveType from './getSaveType'
|
||||
|
||||
const isWindows = process.platform === 'win32' || global['FAKE_WINDOWS']
|
||||
@@ -140,6 +141,7 @@ export async function handler (
|
||||
await install(
|
||||
await readProjectManifestOnly(dir, opts), {
|
||||
...config,
|
||||
...getOptionsFromRootManifest(config.rootProjectManifest ?? {}),
|
||||
include: {
|
||||
dependencies: config.production !== false,
|
||||
devDependencies: config.dev !== false,
|
||||
|
||||
@@ -5,6 +5,7 @@ import { createOrConnectStoreController, CreateStoreControllerOptions } from '@p
|
||||
import { InstallOptions, mutateModules } from '@pnpm/core'
|
||||
import pick from 'ramda/src/pick'
|
||||
import renderHelp from 'render-help'
|
||||
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||
|
||||
export const rcOptionsTypes = cliOptionsTypes
|
||||
|
||||
@@ -44,19 +45,21 @@ export function help () {
|
||||
}
|
||||
|
||||
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 manifest = await readProjectManifestOnly(process.cwd(), opts)
|
||||
return mutateModules([
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: await readProjectManifestOnly(process.cwd(), opts),
|
||||
manifest,
|
||||
mutation: 'install',
|
||||
pruneDirectDependencies: true,
|
||||
rootDir: process.cwd(),
|
||||
},
|
||||
], {
|
||||
...opts,
|
||||
...getOptionsFromRootManifest(opts.rootProjectManifest ?? {}),
|
||||
include: {
|
||||
dependencies: opts.production !== false,
|
||||
devDependencies: opts.dev !== false,
|
||||
|
||||
@@ -34,6 +34,7 @@ import mem from 'mem'
|
||||
import pFilter from 'p-filter'
|
||||
import pLimit from 'p-limit'
|
||||
import readIniFile from 'read-ini-file'
|
||||
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||
import { createWorkspaceSpecs, updateToWorkspacePackagesFromManifest } from './updateWorkspaceDependencies'
|
||||
import updateToLatestSpecsFromManifest, { createLatestSpecs } from './updateToLatestSpecsFromManifest'
|
||||
import getSaveType from './getSaveType'
|
||||
@@ -122,6 +123,7 @@ export default async function recursive (
|
||||
: {}
|
||||
const targetDependenciesField = getSaveType(opts)
|
||||
const installOpts = Object.assign(opts, {
|
||||
...getOptionsFromRootManifest(manifestsByPath[opts.lockfileDir ?? opts.dir]?.manifest ?? {}),
|
||||
linkWorkspacePackagesDepth: opts.linkWorkspacePackages === 'deep' ? Infinity : opts.linkWorkspacePackages ? 0 : -1,
|
||||
ownLifecycleHooksStdio: 'pipe',
|
||||
peer: opts.savePeer,
|
||||
@@ -356,6 +358,7 @@ export default async function recursive (
|
||||
{
|
||||
...installOpts,
|
||||
...localConfig,
|
||||
...getOptionsFromRootManifest(manifest),
|
||||
bin: path.join(rootDir, 'node_modules', '.bin'),
|
||||
dir: rootDir,
|
||||
hooks,
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
import pick from 'ramda/src/pick'
|
||||
import without from 'ramda/src/without'
|
||||
import renderHelp from 'render-help'
|
||||
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||
import getSaveType from './getSaveType'
|
||||
import recursive from './recursive'
|
||||
|
||||
@@ -140,6 +141,7 @@ export async function handler (
|
||||
| 'production'
|
||||
| 'rawLocalConfig'
|
||||
| 'registries'
|
||||
| 'rootProjectManifest'
|
||||
| 'saveDev'
|
||||
| 'saveOptional'
|
||||
| 'saveProd'
|
||||
@@ -162,6 +164,7 @@ export async function handler (
|
||||
}
|
||||
const store = await createOrConnectStoreController(opts)
|
||||
const removeOpts = Object.assign(opts, {
|
||||
...getOptionsFromRootManifest(opts.rootProjectManifest ?? {}),
|
||||
storeController: store.ctrl,
|
||||
storeDir: store.dir,
|
||||
include,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Config } from '@pnpm/config'
|
||||
import { createOrConnectStoreController, CreateStoreControllerOptions } from '@pnpm/store-connection-manager'
|
||||
import { mutateModules } from '@pnpm/core'
|
||||
import renderHelp from 'render-help'
|
||||
import getOptionsFromRootManifest from './getOptionsFromRootManifest'
|
||||
import { cliOptionsTypes, rcOptionsTypes } from './install'
|
||||
import recursive from './recursive'
|
||||
|
||||
@@ -51,6 +52,7 @@ export async function handler (
|
||||
| 'selectedProjectsGraph'
|
||||
| 'rawLocalConfig'
|
||||
| 'registries'
|
||||
| 'rootProjectManifest'
|
||||
| 'pnpmfile'
|
||||
| 'workspaceDir'
|
||||
> & {
|
||||
@@ -64,6 +66,7 @@ export async function handler (
|
||||
}
|
||||
const store = await createOrConnectStoreController(opts)
|
||||
const unlinkOpts = Object.assign(opts, {
|
||||
...getOptionsFromRootManifest(opts.rootProjectManifest ?? {}),
|
||||
globalBin: opts.bin,
|
||||
storeController: store.ctrl,
|
||||
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/pnpmfile': workspace:1.2.0
|
||||
'@pnpm/prepare': workspace:0.0.28
|
||||
'@pnpm/read-project-manifest': workspace:2.0.7
|
||||
'@pnpm/types': workspace:7.6.0
|
||||
'@types/ramda': 0.27.39
|
||||
'@types/which': ^2.0.0
|
||||
@@ -347,6 +348,7 @@ importers:
|
||||
'@pnpm/error': link:../error
|
||||
'@pnpm/global-bin-dir': link:../global-bin-dir
|
||||
'@pnpm/pnpmfile': link:../pnpmfile
|
||||
'@pnpm/read-project-manifest': link:../read-project-manifest
|
||||
'@pnpm/types': link:../types
|
||||
'@zkochan/npm-conf': 2.0.2
|
||||
camelcase: 6.2.1
|
||||
|
||||
Reference in New Issue
Block a user