mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-23 23:29:17 -05:00
feat: reading settings from pnpm-workspace.yaml (#9121)
Related discussion: https://github.com/orgs/pnpm/discussions/9037 close #9033
This commit is contained in:
5
.changeset/famous-sloths-wink.md
Normal file
5
.changeset/famous-sloths-wink.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/workspace.manifest-writer": major
|
||||
---
|
||||
|
||||
Initial release.
|
||||
5
.changeset/few-walls-argue.md
Normal file
5
.changeset/few-walls-argue.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-installation": major
|
||||
---
|
||||
|
||||
Read `onlyBuiltDependencies` and `ignoredBuiltDependencies` from options.
|
||||
6
.changeset/five-birds-enjoy.md
Normal file
6
.changeset/five-birds-enjoy.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/config": minor
|
||||
"pnpm": minor
|
||||
---
|
||||
|
||||
Allow to set the "pnpm" settings from `package.json` via the `pnpm-workspace.yaml` file.
|
||||
5
.changeset/friendly-hounds-notice.md
Normal file
5
.changeset/friendly-hounds-notice.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/plugin-commands-rebuild": major
|
||||
---
|
||||
|
||||
Don't rebuild packages that are not in the approved list.
|
||||
5
.changeset/gorgeous-eggs-appear.md
Normal file
5
.changeset/gorgeous-eggs-appear.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/exec.build-commands": major
|
||||
---
|
||||
|
||||
Read `onlyBuiltDependencies` and `ignoredBuiltDependencies` from `options`.
|
||||
5
.changeset/itchy-apricots-rest.md
Normal file
5
.changeset/itchy-apricots-rest.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/core": major
|
||||
---
|
||||
|
||||
By default, don't allow to run scripts of dependencies.
|
||||
5
.changeset/quick-monkeys-tie.md
Normal file
5
.changeset/quick-monkeys-tie.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/types": minor
|
||||
---
|
||||
|
||||
Export PnpmSettings.
|
||||
5
.changeset/rude-masks-train.md
Normal file
5
.changeset/rude-masks-train.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/deps.status": major
|
||||
---
|
||||
|
||||
Read `configDependencies` from `options`.
|
||||
5
.changeset/silver-goats-lick.md
Normal file
5
.changeset/silver-goats-lick.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/workspace.read-manifest": minor
|
||||
---
|
||||
|
||||
Extend WorkspaceManifest with PnpmSettings.
|
||||
6
.changeset/slimy-hounds-sniff.md
Normal file
6
.changeset/slimy-hounds-sniff.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/workspace.read-manifest": minor
|
||||
"pnpm": minor
|
||||
---
|
||||
|
||||
The `packages` field in `pnpm-workspace.yaml` became optional.
|
||||
5
.changeset/tender-swans-drive.md
Normal file
5
.changeset/tender-swans-drive.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/workspace.manifest-writer": major
|
||||
---
|
||||
|
||||
Initial release.
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- pkg
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- "*"
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
type SslConfig,
|
||||
} from '@pnpm/types'
|
||||
import type { Hooks } from '@pnpm/pnpmfile'
|
||||
import { type OptionsFromRootManifest } from './getOptionsFromRootManifest'
|
||||
|
||||
export type UniversalOptions = Pick<Config, 'color' | 'dir' | 'rawConfig' | 'rawLocalConfig'>
|
||||
|
||||
@@ -17,7 +18,7 @@ export interface WantedPackageManager {
|
||||
|
||||
export type VerifyDepsBeforeRun = 'install' | 'warn' | 'error' | 'prompt' | false
|
||||
|
||||
export interface Config {
|
||||
export interface Config extends OptionsFromRootManifest {
|
||||
allProjects?: Project[]
|
||||
selectedProjectsGraph?: ProjectsGraph
|
||||
allProjectsGraph?: ProjectsGraph
|
||||
|
||||
@@ -6,10 +6,12 @@ import {
|
||||
type PackageExtension,
|
||||
type PeerDependencyRules,
|
||||
type ProjectManifest,
|
||||
type PnpmSettings,
|
||||
} from '@pnpm/types'
|
||||
import mapValues from 'ramda/src/map'
|
||||
import pick from 'ramda/src/pick'
|
||||
|
||||
export interface OptionsFromRootManifest {
|
||||
export type OptionsFromRootManifest = {
|
||||
allowedDeprecatedVersions?: AllowedDeprecatedVersions
|
||||
allowNonAppliedPatches?: boolean
|
||||
overrides?: Record<string, string>
|
||||
@@ -22,63 +24,50 @@ export interface OptionsFromRootManifest {
|
||||
patchedDependencies?: Record<string, string>
|
||||
peerDependencyRules?: PeerDependencyRules
|
||||
supportedArchitectures?: SupportedArchitectures
|
||||
}
|
||||
} & Pick<PnpmSettings, 'configDependencies'>
|
||||
|
||||
export function getOptionsFromRootManifest (manifestDir: string, manifest: ProjectManifest): OptionsFromRootManifest {
|
||||
// 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 = mapValues(
|
||||
createVersionReferencesReplacer(manifest),
|
||||
{
|
||||
const settings: OptionsFromRootManifest = getOptionsFromPnpmSettings(manifestDir, {
|
||||
...manifest.pnpm,
|
||||
// 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
|
||||
overrides: {
|
||||
...manifest.resolutions,
|
||||
...manifest.pnpm?.overrides,
|
||||
}
|
||||
)
|
||||
const neverBuiltDependencies = manifest.pnpm?.neverBuiltDependencies
|
||||
let onlyBuiltDependencies = manifest.pnpm?.onlyBuiltDependencies
|
||||
const onlyBuiltDependenciesFile = manifest.pnpm?.onlyBuiltDependenciesFile
|
||||
if (onlyBuiltDependenciesFile == null && neverBuiltDependencies == null && onlyBuiltDependencies == null) {
|
||||
onlyBuiltDependencies = []
|
||||
},
|
||||
}, manifest)
|
||||
return settings
|
||||
}
|
||||
|
||||
export function getOptionsFromPnpmSettings (manifestDir: string, pnpmSettings: PnpmSettings, manifest?: ProjectManifest): OptionsFromRootManifest {
|
||||
const settings: OptionsFromRootManifest = pick([
|
||||
'allowNonAppliedPatches',
|
||||
'allowedDeprecatedVersions',
|
||||
'configDependencies',
|
||||
'ignoredBuiltDependencies',
|
||||
'ignoredOptionalDependencies',
|
||||
'neverBuiltDependencies',
|
||||
'onlyBuiltDependencies',
|
||||
'onlyBuiltDependenciesFile',
|
||||
'overrides',
|
||||
'packageExtensions',
|
||||
'peerDependencyRules',
|
||||
'supportedArchitectures',
|
||||
], pnpmSettings)
|
||||
if (settings.overrides && manifest) {
|
||||
settings.overrides = mapValues(createVersionReferencesReplacer(manifest), settings.overrides)
|
||||
}
|
||||
const packageExtensions = manifest.pnpm?.packageExtensions
|
||||
const ignoredOptionalDependencies = manifest.pnpm?.ignoredOptionalDependencies
|
||||
const peerDependencyRules = manifest.pnpm?.peerDependencyRules
|
||||
const allowedDeprecatedVersions = manifest.pnpm?.allowedDeprecatedVersions
|
||||
const allowNonAppliedPatches = manifest.pnpm?.allowNonAppliedPatches
|
||||
let patchedDependencies = manifest.pnpm?.patchedDependencies
|
||||
if (patchedDependencies) {
|
||||
patchedDependencies = { ...patchedDependencies }
|
||||
for (const [dep, patchFile] of Object.entries(patchedDependencies)) {
|
||||
if (pnpmSettings.onlyBuiltDependenciesFile) {
|
||||
settings.onlyBuiltDependenciesFile = path.join(manifestDir, pnpmSettings.onlyBuiltDependenciesFile)
|
||||
}
|
||||
if (pnpmSettings.patchedDependencies) {
|
||||
settings.patchedDependencies = { ...pnpmSettings.patchedDependencies }
|
||||
for (const [dep, patchFile] of Object.entries(pnpmSettings.patchedDependencies)) {
|
||||
if (path.isAbsolute(patchFile)) continue
|
||||
patchedDependencies[dep] = path.join(manifestDir, patchFile)
|
||||
settings.patchedDependencies[dep] = path.join(manifestDir, patchFile)
|
||||
}
|
||||
}
|
||||
|
||||
const supportedArchitectures = {
|
||||
os: manifest.pnpm?.supportedArchitectures?.os ?? ['current'],
|
||||
cpu: manifest.pnpm?.supportedArchitectures?.cpu ?? ['current'],
|
||||
libc: manifest.pnpm?.supportedArchitectures?.libc ?? ['current'],
|
||||
}
|
||||
|
||||
const settings: OptionsFromRootManifest = {
|
||||
allowedDeprecatedVersions,
|
||||
allowNonAppliedPatches,
|
||||
overrides,
|
||||
neverBuiltDependencies,
|
||||
packageExtensions,
|
||||
ignoredOptionalDependencies,
|
||||
peerDependencyRules,
|
||||
patchedDependencies,
|
||||
supportedArchitectures,
|
||||
ignoredBuiltDependencies: manifest.pnpm?.ignoredBuiltDependencies,
|
||||
}
|
||||
if (onlyBuiltDependencies) {
|
||||
settings.onlyBuiltDependencies = onlyBuiltDependencies
|
||||
}
|
||||
if (onlyBuiltDependenciesFile) {
|
||||
settings.onlyBuiltDependenciesFile = path.join(manifestDir, onlyBuiltDependenciesFile)
|
||||
}
|
||||
return settings
|
||||
}
|
||||
|
||||
|
||||
@@ -31,9 +31,10 @@ import { getWorkspaceConcurrency } from './concurrency'
|
||||
import { readWorkspaceManifest } from '@pnpm/workspace.read-manifest'
|
||||
|
||||
import { types } from './types'
|
||||
import { getOptionsFromPnpmSettings, getOptionsFromRootManifest } from './getOptionsFromRootManifest'
|
||||
export { types }
|
||||
|
||||
export { getOptionsFromRootManifest, type OptionsFromRootManifest } from './getOptionsFromRootManifest'
|
||||
export { getOptionsFromRootManifest, getOptionsFromPnpmSettings, type OptionsFromRootManifest } from './getOptionsFromRootManifest'
|
||||
export * from './readLocalConfig'
|
||||
|
||||
export type { Config, UniversalOptions, WantedPackageManager, VerifyDepsBeforeRun }
|
||||
@@ -484,13 +485,19 @@ export async function getConfig (opts: {
|
||||
if (pnpmConfig.rootProjectManifest.packageManager) {
|
||||
pnpmConfig.wantedPackageManager = parsePackageManager(pnpmConfig.rootProjectManifest.packageManager)
|
||||
}
|
||||
if (pnpmConfig.rootProjectManifest) {
|
||||
Object.assign(pnpmConfig, getOptionsFromRootManifest(pnpmConfig.rootProjectManifestDir, pnpmConfig.rootProjectManifest))
|
||||
}
|
||||
}
|
||||
|
||||
if (pnpmConfig.workspaceDir != null) {
|
||||
const workspaceManifest = await readWorkspaceManifest(pnpmConfig.workspaceDir)
|
||||
|
||||
pnpmConfig.workspacePackagePatterns = cliOptions['workspace-packages'] as string[] ?? workspaceManifest?.packages
|
||||
pnpmConfig.workspacePackagePatterns = cliOptions['workspace-packages'] as string[] ?? workspaceManifest?.packages ?? ['.']
|
||||
pnpmConfig.catalogs = getCatalogsFromWorkspaceManifest(workspaceManifest)
|
||||
if (workspaceManifest) {
|
||||
Object.assign(pnpmConfig, getOptionsFromPnpmSettings(pnpmConfig.workspaceDir, workspaceManifest, pnpmConfig.rootProjectManifest))
|
||||
}
|
||||
}
|
||||
|
||||
pnpmConfig.failedToLoadBuiltInConfig = failedToLoadBuiltInConfig
|
||||
|
||||
4
config/config/test/fixtures/settings-in-workspace-yaml/pnpm-workspace.yaml
vendored
Normal file
4
config/config/test/fixtures/settings-in-workspace-yaml/pnpm-workspace.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
packages: []
|
||||
onlyBuiltDependencies:
|
||||
- foo
|
||||
|
||||
@@ -80,7 +80,7 @@ test('getOptionsFromRootManifest() throws an error if cannot resolve an override
|
||||
|
||||
test('getOptionsFromRootManifest() should return an empty onlyBuiltDependencies list by default', () => {
|
||||
const options = getOptionsFromRootManifest(process.cwd(), {})
|
||||
expect(options.onlyBuiltDependencies).toStrictEqual([])
|
||||
expect(options.onlyBuiltDependencies).toStrictEqual(undefined)
|
||||
})
|
||||
|
||||
test('getOptionsFromRootManifest() should return the list fromm onlyBuiltDependencies', () => {
|
||||
|
||||
@@ -1009,3 +1009,18 @@ test('xxx', async () => {
|
||||
|
||||
process.env = oldEnv
|
||||
})
|
||||
|
||||
test('settings from pnpm-workspace.yaml are read', async () => {
|
||||
const workspaceDir = f.find('settings-in-workspace-yaml')
|
||||
process.chdir(workspaceDir)
|
||||
const { config } = await getConfig({
|
||||
cliOptions: {},
|
||||
workspaceDir,
|
||||
packageManager: {
|
||||
name: 'pnpm',
|
||||
version: '1.0.0',
|
||||
},
|
||||
})
|
||||
|
||||
expect(config.onlyBuiltDependencies).toStrictEqual(['foo'])
|
||||
})
|
||||
|
||||
3
deps/status/src/checkDepsStatus.ts
vendored
3
deps/status/src/checkDepsStatus.ts
vendored
@@ -59,6 +59,7 @@ export type CheckDepsStatusOptions = Pick<Config,
|
||||
| 'workspaceDir'
|
||||
| 'patchesDir'
|
||||
| 'pnpmfile'
|
||||
| 'configDependencies'
|
||||
> & {
|
||||
ignoreFilteredInstallCache?: boolean
|
||||
ignoredWorkspaceStateSettings?: Array<keyof WorkspaceStateSettings>
|
||||
@@ -136,7 +137,7 @@ async function _checkDepsStatus (opts: CheckDepsStatusOptions, workspaceState: W
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((rootProjectManifest?.pnpm?.configDependencies != null || workspaceState.configDependencies != null) && !equals(rootProjectManifest?.pnpm?.configDependencies ?? {}, workspaceState.configDependencies ?? {})) {
|
||||
if ((opts.configDependencies != null || workspaceState.configDependencies != null) && !equals(opts.configDependencies ?? {}, workspaceState.configDependencies ?? {})) {
|
||||
return {
|
||||
upToDate: false,
|
||||
issue: 'Configuration dependencies are not up to date',
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/pnpm/pnpm/blob/main/exec/build-commands#readme",
|
||||
"devDependencies": {
|
||||
"@pnpm/config": "workspace:*",
|
||||
"@pnpm/exec.build-commands": "workspace:*",
|
||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
@@ -47,6 +46,7 @@
|
||||
"@pnpm/prepare-temp-dir": "workspace:*",
|
||||
"@pnpm/read-project-manifest": "workspace:*",
|
||||
"@pnpm/util.lex-comparator": "catalog:",
|
||||
"@pnpm/workspace.manifest-writer": "workspace:*",
|
||||
"chalk": "catalog:",
|
||||
"enquirer": "catalog:",
|
||||
"render-help": "catalog:"
|
||||
|
||||
@@ -6,9 +6,10 @@ import renderHelp from 'render-help'
|
||||
import { prompt } from 'enquirer'
|
||||
import chalk from 'chalk'
|
||||
import { rebuild, type RebuildCommandOpts } from '@pnpm/plugin-commands-rebuild'
|
||||
import { updateWorkspaceManifest } from '@pnpm/workspace.manifest-writer'
|
||||
import { getAutomaticallyIgnoredBuilds } from './getAutomaticallyIgnoredBuilds'
|
||||
|
||||
export type ApproveBuildsCommandOpts = Pick<Config, 'modulesDir' | 'dir' | 'rootProjectManifest' | 'rootProjectManifestDir'>
|
||||
export type ApproveBuildsCommandOpts = Pick<Config, 'modulesDir' | 'dir' | 'rootProjectManifest' | 'rootProjectManifestDir' | 'onlyBuiltDependencies' | 'ignoredBuiltDependencies'>
|
||||
|
||||
export const commandNames = ['approve-builds']
|
||||
|
||||
@@ -87,28 +88,24 @@ export async function handler (opts: ApproveBuildsCommandOpts & RebuildCommandOp
|
||||
} as any) as any // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
const buildPackages = result.map(({ value }: { value: string }) => value)
|
||||
const ignoredPackages = automaticallyIgnoredBuilds.filter((automaticallyIgnoredBuild) => !buildPackages.includes(automaticallyIgnoredBuild))
|
||||
let updatedIgnoredBuiltDependencies: string[] | undefined
|
||||
if (ignoredPackages.length) {
|
||||
if (opts.rootProjectManifest.pnpm?.ignoredBuiltDependencies == null) {
|
||||
opts.rootProjectManifest.pnpm = {
|
||||
...opts.rootProjectManifest.pnpm,
|
||||
ignoredBuiltDependencies: sortUniqueStrings(ignoredPackages),
|
||||
}
|
||||
if (opts.ignoredBuiltDependencies == null) {
|
||||
updatedIgnoredBuiltDependencies = sortUniqueStrings(ignoredPackages)
|
||||
} else {
|
||||
opts.rootProjectManifest.pnpm.ignoredBuiltDependencies = sortUniqueStrings([
|
||||
...opts.rootProjectManifest.pnpm.ignoredBuiltDependencies,
|
||||
updatedIgnoredBuiltDependencies = sortUniqueStrings([
|
||||
...opts.ignoredBuiltDependencies,
|
||||
...ignoredPackages,
|
||||
])
|
||||
}
|
||||
}
|
||||
let updatedOnlyBuiltDependencies: string[] | undefined
|
||||
if (buildPackages.length) {
|
||||
if (opts.rootProjectManifest.pnpm?.onlyBuiltDependencies == null) {
|
||||
opts.rootProjectManifest.pnpm = {
|
||||
...opts.rootProjectManifest.pnpm,
|
||||
onlyBuiltDependencies: sortUniqueStrings(buildPackages),
|
||||
}
|
||||
if (opts.onlyBuiltDependencies == null) {
|
||||
updatedOnlyBuiltDependencies = sortUniqueStrings(buildPackages)
|
||||
} else {
|
||||
opts.rootProjectManifest.pnpm.onlyBuiltDependencies = sortUniqueStrings([
|
||||
...opts.rootProjectManifest.pnpm.onlyBuiltDependencies,
|
||||
updatedOnlyBuiltDependencies = sortUniqueStrings([
|
||||
...opts.onlyBuiltDependencies,
|
||||
...buildPackages,
|
||||
])
|
||||
}
|
||||
@@ -126,9 +123,26 @@ Do you approve?`,
|
||||
}
|
||||
}
|
||||
const { writeProjectManifest } = await readProjectManifest(opts.rootProjectManifestDir)
|
||||
await writeProjectManifest(opts.rootProjectManifest)
|
||||
if (opts.rootProjectManifest.pnpm?.ignoredBuiltDependencies != null || opts.rootProjectManifest.pnpm?.onlyBuiltDependencies != null || opts.workspaceDir == null) {
|
||||
opts.rootProjectManifest.pnpm = opts.rootProjectManifest.pnpm ?? {}
|
||||
if (updatedOnlyBuiltDependencies) {
|
||||
opts.rootProjectManifest.pnpm.onlyBuiltDependencies = updatedOnlyBuiltDependencies
|
||||
}
|
||||
if (updatedIgnoredBuiltDependencies) {
|
||||
opts.rootProjectManifest.pnpm.ignoredBuiltDependencies = updatedIgnoredBuiltDependencies
|
||||
}
|
||||
await writeProjectManifest(opts.rootProjectManifest)
|
||||
} else {
|
||||
await updateWorkspaceManifest(opts.workspaceDir, {
|
||||
onlyBuiltDependencies: updatedOnlyBuiltDependencies,
|
||||
ignoredBuiltDependencies: updatedIgnoredBuiltDependencies,
|
||||
})
|
||||
}
|
||||
if (buildPackages.length) {
|
||||
return rebuild.handler(opts, buildPackages)
|
||||
return rebuild.handler({
|
||||
...opts,
|
||||
onlyBuiltDependencies: updatedOnlyBuiltDependencies,
|
||||
}, buildPackages)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
{
|
||||
"path": "../../pkg-manifest/read-project-manifest"
|
||||
},
|
||||
{
|
||||
"path": "../../workspace/manifest-writer"
|
||||
},
|
||||
{
|
||||
"path": "../plugin-commands-rebuild"
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ export type StrictRebuildOptions = {
|
||||
peersSuffixMaxLength: number
|
||||
strictStorePkgContentCheck: boolean
|
||||
fetchFullMetadata?: boolean
|
||||
} & Pick<Config, 'sslConfigs'>
|
||||
} & Pick<Config, 'sslConfigs' | 'onlyBuiltDependencies' | 'onlyBuiltDependenciesFile' | 'neverBuiltDependencies'>
|
||||
|
||||
export type RebuildOptions = Partial<StrictRebuildOptions> &
|
||||
Pick<StrictRebuildOptions, 'storeDir' | 'storeController'> & Pick<Config, 'rootProjectManifest' | 'rootProjectManifestDir'>
|
||||
@@ -106,5 +106,8 @@ export async function extendRebuildOptions (
|
||||
...(opts.rootProjectManifest ? getOptionsFromRootManifest(opts.rootProjectManifestDir, opts.rootProjectManifest) : {}),
|
||||
}
|
||||
extendedOpts.registries = normalizeRegistries(extendedOpts.registries)
|
||||
if (extendedOpts.neverBuiltDependencies == null && extendedOpts.onlyBuiltDependencies == null && extendedOpts.onlyBuiltDependenciesFile == null) {
|
||||
extendedOpts.onlyBuiltDependencies = []
|
||||
}
|
||||
return extendedOpts
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ export const DEFAULT_OPTS = {
|
||||
localAddress: undefined,
|
||||
lock: false,
|
||||
lockStaleDuration: 90,
|
||||
neverBuiltDependencies: [],
|
||||
networkConcurrency: 16,
|
||||
offline: false,
|
||||
pending: false,
|
||||
|
||||
@@ -726,7 +726,9 @@ test('`pnpm run -r` should avoid infinite recursion', async () => {
|
||||
},
|
||||
},
|
||||
])
|
||||
writeYamlFile('pnpm-workspace.yaml', {})
|
||||
writeYamlFile('pnpm-workspace.yaml', {
|
||||
packages: ['**'],
|
||||
})
|
||||
|
||||
await execa(pnpmBin, [
|
||||
'install',
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- packages/**
|
||||
|
||||
@@ -127,33 +127,35 @@ export interface PeerDependencyRules {
|
||||
|
||||
export type AllowedDeprecatedVersions = Record<string, string>
|
||||
|
||||
export interface PnpmSettings {
|
||||
configDependencies?: Record<string, string>
|
||||
neverBuiltDependencies?: string[]
|
||||
onlyBuiltDependencies?: string[]
|
||||
onlyBuiltDependenciesFile?: string
|
||||
ignoredBuiltDependencies?: string[]
|
||||
overrides?: Record<string, string>
|
||||
packageExtensions?: Record<string, PackageExtension>
|
||||
ignoredOptionalDependencies?: string[]
|
||||
peerDependencyRules?: PeerDependencyRules
|
||||
allowedDeprecatedVersions?: AllowedDeprecatedVersions
|
||||
allowNonAppliedPatches?: boolean
|
||||
patchedDependencies?: Record<string, string>
|
||||
updateConfig?: {
|
||||
ignoreDependencies?: string[]
|
||||
}
|
||||
auditConfig?: {
|
||||
ignoreCves?: string[]
|
||||
ignoreGhsas?: string[]
|
||||
}
|
||||
requiredScripts?: string[]
|
||||
supportedArchitectures?: SupportedArchitectures
|
||||
executionEnv?: ExecutionEnv
|
||||
}
|
||||
|
||||
export interface ProjectManifest extends BaseManifest {
|
||||
packageManager?: string
|
||||
workspaces?: string[]
|
||||
pnpm?: {
|
||||
configDependencies?: Record<string, string>
|
||||
neverBuiltDependencies?: string[]
|
||||
onlyBuiltDependencies?: string[]
|
||||
onlyBuiltDependenciesFile?: string
|
||||
ignoredBuiltDependencies?: string[]
|
||||
overrides?: Record<string, string>
|
||||
packageExtensions?: Record<string, PackageExtension>
|
||||
ignoredOptionalDependencies?: string[]
|
||||
peerDependencyRules?: PeerDependencyRules
|
||||
allowedDeprecatedVersions?: AllowedDeprecatedVersions
|
||||
allowNonAppliedPatches?: boolean
|
||||
patchedDependencies?: Record<string, string>
|
||||
updateConfig?: {
|
||||
ignoreDependencies?: string[]
|
||||
}
|
||||
auditConfig?: {
|
||||
ignoreCves?: string[]
|
||||
ignoreGhsas?: string[]
|
||||
}
|
||||
requiredScripts?: string[]
|
||||
supportedArchitectures?: SupportedArchitectures
|
||||
executionEnv?: ExecutionEnv
|
||||
}
|
||||
pnpm?: PnpmSettings
|
||||
private?: boolean
|
||||
resolutions?: Record<string, string>
|
||||
}
|
||||
|
||||
@@ -268,6 +268,9 @@ export function extendOptions (
|
||||
}
|
||||
}
|
||||
}
|
||||
if (opts.neverBuiltDependencies == null && opts.onlyBuiltDependencies == null && opts.onlyBuiltDependenciesFile == null) {
|
||||
opts.onlyBuiltDependencies = []
|
||||
}
|
||||
if (opts.onlyBuiltDependencies && opts.neverBuiltDependencies) {
|
||||
throw new PnpmError('CONFIG_CONFLICT_BUILT_DEPENDENCIES', 'Cannot have both neverBuiltDependencies and onlyBuiltDependencies')
|
||||
}
|
||||
|
||||
@@ -473,9 +473,10 @@ test('selectively allow scripts in some dependencies by onlyBuiltDependencies',
|
||||
prepareEmpty()
|
||||
const reporter = sinon.spy()
|
||||
const onlyBuiltDependencies = ['@pnpm.e2e/install-script-example']
|
||||
const neverBuiltDependencies: string[] | undefined = undefined
|
||||
const { updatedManifest: manifest } = await addDependenciesToPackage({},
|
||||
['@pnpm.e2e/pre-and-postinstall-scripts-example@1.0.0', '@pnpm.e2e/install-script-example'],
|
||||
testDefaults({ fastUnpack: false, onlyBuiltDependencies, reporter })
|
||||
testDefaults({ fastUnpack: false, onlyBuiltDependencies, neverBuiltDependencies, reporter })
|
||||
)
|
||||
|
||||
expect(fs.existsSync('node_modules/@pnpm.e2e/pre-and-postinstall-scripts-example/generated-by-preinstall.js')).toBeFalsy()
|
||||
@@ -494,6 +495,7 @@ test('selectively allow scripts in some dependencies by onlyBuiltDependencies',
|
||||
fastUnpack: false,
|
||||
frozenLockfile: true,
|
||||
ignoredBuiltDependencies: ['@pnpm.e2e/pre-and-postinstall-scripts-example'],
|
||||
neverBuiltDependencies,
|
||||
onlyBuiltDependencies,
|
||||
reporter,
|
||||
}))
|
||||
|
||||
@@ -23,6 +23,7 @@ test('patch package', async () => {
|
||||
'is-positive@1.0.0': patchPath,
|
||||
}
|
||||
const opts = testDefaults({
|
||||
neverBuiltDependencies: undefined,
|
||||
onlyBuiltDependencies: [],
|
||||
fastUnpack: false,
|
||||
sideEffectsCacheRead: true,
|
||||
@@ -288,6 +289,7 @@ test('patch package when the package is not in onlyBuiltDependencies list', asyn
|
||||
sideEffectsCacheRead: true,
|
||||
sideEffectsCacheWrite: true,
|
||||
patchedDependencies,
|
||||
neverBuiltDependencies: undefined,
|
||||
onlyBuiltDependencies: [],
|
||||
}, {}, {}, { packageImportMethod: 'hardlink' })
|
||||
await install({
|
||||
@@ -355,6 +357,7 @@ test('patch package when the package is not in onlyBuiltDependencies list', asyn
|
||||
fastUnpack: false,
|
||||
sideEffectsCacheRead: true,
|
||||
sideEffectsCacheWrite: true,
|
||||
neverBuiltDependencies: undefined,
|
||||
onlyBuiltDependencies: [],
|
||||
offline: true,
|
||||
}, {}, {}, { packageImportMethod: 'hardlink' }))
|
||||
|
||||
@@ -56,6 +56,7 @@ export function testDefaults<T> (
|
||||
)
|
||||
const result = {
|
||||
cacheDir,
|
||||
neverBuiltDependencies: [] as string[],
|
||||
registries: {
|
||||
default: registry,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- "*"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- "*"
|
||||
|
||||
@@ -191,7 +191,9 @@ export async function handler (
|
||||
!opts.recursive &&
|
||||
opts.workspaceDir === opts.dir &&
|
||||
!opts.ignoreWorkspaceRootCheck &&
|
||||
!opts.workspaceRoot
|
||||
!opts.workspaceRoot &&
|
||||
opts.workspacePackagePatterns &&
|
||||
opts.workspacePackagePatterns.length > 1
|
||||
) {
|
||||
throw new PnpmError('ADDING_TO_ROOT',
|
||||
'Running this command will add the dependency to the workspace root, ' +
|
||||
|
||||
@@ -259,6 +259,7 @@ export type InstallCommandOptions = Pick<Config,
|
||||
| 'bin'
|
||||
| 'catalogs'
|
||||
| 'cliOptions'
|
||||
| 'configDependencies'
|
||||
| 'dedupeInjectedDeps'
|
||||
| 'dedupeDirectDeps'
|
||||
| 'dedupePeerDependents'
|
||||
|
||||
@@ -102,6 +102,7 @@ export type InstallDepsOptions = Pick<Config,
|
||||
| 'extraEnv'
|
||||
| 'ignoreWorkspaceCycles'
|
||||
| 'disallowWorkspaceCycles'
|
||||
| 'configDependencies'
|
||||
> & CreateStoreControllerOptions & {
|
||||
argv: {
|
||||
original: string[]
|
||||
@@ -171,8 +172,8 @@ when running add/update with the --workspace option')
|
||||
opts['preserveWorkspaceProtocol'] = !opts.linkWorkspacePackages
|
||||
}
|
||||
let store = await createOrConnectStoreController(opts)
|
||||
if (opts.rootProjectManifest?.pnpm?.configDependencies) {
|
||||
await installConfigDeps(opts.rootProjectManifest.pnpm.configDependencies, {
|
||||
if (opts.configDependencies) {
|
||||
await installConfigDeps(opts.configDependencies, {
|
||||
registries: opts.registries,
|
||||
rootDir: opts.lockfileDir ?? opts.rootProjectManifestDir,
|
||||
store: store.ctrl,
|
||||
@@ -346,7 +347,7 @@ when running add/update with the --workspace option')
|
||||
workspaceDir: opts.workspaceDir ?? opts.lockfileDir ?? opts.dir,
|
||||
pnpmfileExists: opts.hooks?.calculatePnpmfileChecksum != null,
|
||||
filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
|
||||
configDependencies: opts.rootProjectManifest?.pnpm?.configDependencies,
|
||||
configDependencies: opts.configDependencies,
|
||||
})
|
||||
}
|
||||
if (opts.strictDepBuilds && ignoredBuilds?.length) {
|
||||
@@ -406,7 +407,7 @@ when running add/update with the --workspace option')
|
||||
workspaceDir: opts.workspaceDir ?? opts.lockfileDir ?? opts.dir,
|
||||
pnpmfileExists: opts.hooks?.calculatePnpmfileChecksum != null,
|
||||
filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
|
||||
configDependencies: opts.rootProjectManifest?.pnpm?.configDependencies,
|
||||
configDependencies: opts.configDependencies,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -432,7 +433,7 @@ async function recursiveInstallThenUpdateWorkspaceState (
|
||||
workspaceDir: opts.workspaceDir,
|
||||
pnpmfileExists: opts.hooks?.calculatePnpmfileChecksum != null,
|
||||
filteredInstall: allProjects.length !== Object.keys(opts.selectedProjectsGraph ?? {}).length,
|
||||
configDependencies: opts.rootProjectManifest?.pnpm?.configDependencies,
|
||||
configDependencies: opts.configDependencies,
|
||||
})
|
||||
}
|
||||
return recursiveResult
|
||||
|
||||
@@ -46,6 +46,7 @@ import { IgnoredBuildsError } from './errors'
|
||||
|
||||
export type RecursiveOptions = CreateStoreControllerOptions & Pick<Config,
|
||||
| 'bail'
|
||||
| 'configDependencies'
|
||||
| 'dedupePeerDependents'
|
||||
| 'depth'
|
||||
| 'globalPnpmfile'
|
||||
|
||||
@@ -131,6 +131,7 @@ export async function handler (
|
||||
| 'allProjectsGraph'
|
||||
| 'bail'
|
||||
| 'bin'
|
||||
| 'configDependencies'
|
||||
| 'dev'
|
||||
| 'engineStrict'
|
||||
| 'globalPnpmfile'
|
||||
@@ -164,8 +165,8 @@ export async function handler (
|
||||
optionalDependencies: opts.optional !== false,
|
||||
}
|
||||
let store = await createOrConnectStoreController(opts)
|
||||
if (opts.rootProjectManifest?.pnpm?.configDependencies) {
|
||||
await installConfigDeps(opts.rootProjectManifest.pnpm.configDependencies, {
|
||||
if (opts.configDependencies) {
|
||||
await installConfigDeps(opts.configDependencies, {
|
||||
registries: opts.registries,
|
||||
rootDir: opts.lockfileDir ?? opts.rootProjectManifestDir,
|
||||
store: store.ctrl,
|
||||
|
||||
@@ -19,6 +19,7 @@ test('configuration dependency is installed', async () => {
|
||||
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
configDependencies: rootProjectManifest.pnpm!.configDependencies,
|
||||
dir: process.cwd(),
|
||||
rootProjectManifest,
|
||||
rootProjectManifestDir: process.cwd(),
|
||||
@@ -35,6 +36,7 @@ test('configuration dependency is installed', async () => {
|
||||
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
configDependencies: rootProjectManifest.pnpm!.configDependencies,
|
||||
dir: process.cwd(),
|
||||
rootProjectManifest,
|
||||
rootProjectManifestDir: process.cwd(),
|
||||
@@ -51,6 +53,7 @@ test('configuration dependency is installed', async () => {
|
||||
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
configDependencies: rootProjectManifest.pnpm!.configDependencies,
|
||||
dir: process.cwd(),
|
||||
rootProjectManifest,
|
||||
rootProjectManifestDir: process.cwd(),
|
||||
@@ -74,6 +77,7 @@ test('patch from configuration dependency is applied', async () => {
|
||||
|
||||
await add.handler({
|
||||
...DEFAULT_OPTS,
|
||||
configDependencies: rootProjectManifest.pnpm!.configDependencies,
|
||||
dir: process.cwd(),
|
||||
rootProjectManifest,
|
||||
rootProjectManifestDir: process.cwd(),
|
||||
@@ -94,6 +98,7 @@ test('installation fails if the checksum of the config dependency is invalid', a
|
||||
|
||||
await expect(install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
configDependencies: rootProjectManifest.pnpm!.configDependencies,
|
||||
dir: process.cwd(),
|
||||
rootProjectManifest,
|
||||
rootProjectManifestDir: process.cwd(),
|
||||
@@ -112,6 +117,7 @@ test('installation fails if the config dependency does not have a checksum', asy
|
||||
|
||||
await expect(install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
configDependencies: rootProjectManifest.pnpm!.configDependencies,
|
||||
dir: process.cwd(),
|
||||
rootProjectManifest,
|
||||
rootProjectManifestDir: process.cwd(),
|
||||
@@ -131,6 +137,7 @@ test('selectively allow scripts in some dependencies by onlyBuiltDependenciesFil
|
||||
|
||||
await add.handler({
|
||||
...DEFAULT_OPTS,
|
||||
configDependencies: rootProjectManifest.pnpm!.configDependencies,
|
||||
dir: process.cwd(),
|
||||
rootProjectManifest,
|
||||
rootProjectManifestDir: process.cwd(),
|
||||
@@ -144,6 +151,7 @@ test('selectively allow scripts in some dependencies by onlyBuiltDependenciesFil
|
||||
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
configDependencies: rootProjectManifest.pnpm!.configDependencies,
|
||||
dir: process.cwd(),
|
||||
frozenLockfile: true,
|
||||
rootProjectManifest,
|
||||
@@ -169,6 +177,7 @@ test('selectively allow scripts in some dependencies by onlyBuiltDependenciesFil
|
||||
|
||||
await add.handler({
|
||||
...DEFAULT_OPTS,
|
||||
configDependencies: rootProjectManifest.pnpm!.configDependencies,
|
||||
dir: process.cwd(),
|
||||
rootProjectManifest,
|
||||
rootProjectManifestDir: process.cwd(),
|
||||
@@ -182,6 +191,7 @@ test('selectively allow scripts in some dependencies by onlyBuiltDependenciesFil
|
||||
|
||||
await install.handler({
|
||||
...DEFAULT_OPTS,
|
||||
configDependencies: rootProjectManifest.pnpm!.configDependencies,
|
||||
dir: process.cwd(),
|
||||
frozenLockfile: true,
|
||||
rootProjectManifest,
|
||||
|
||||
19
pnpm-lock.yaml
generated
19
pnpm-lock.yaml
generated
@@ -2099,6 +2099,9 @@ importers:
|
||||
'@pnpm/util.lex-comparator':
|
||||
specifier: 'catalog:'
|
||||
version: 3.0.0
|
||||
'@pnpm/workspace.manifest-writer':
|
||||
specifier: workspace:*
|
||||
version: link:../../workspace/manifest-writer
|
||||
chalk:
|
||||
specifier: 'catalog:'
|
||||
version: 4.1.2
|
||||
@@ -8006,6 +8009,19 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: 'link:'
|
||||
|
||||
workspace/manifest-writer:
|
||||
dependencies:
|
||||
'@pnpm/workspace.read-manifest':
|
||||
specifier: workspace:*
|
||||
version: link:../read-manifest
|
||||
write-yaml-file:
|
||||
specifier: 'catalog:'
|
||||
version: 5.0.0
|
||||
devDependencies:
|
||||
'@pnpm/workspace.manifest-writer':
|
||||
specifier: workspace:*
|
||||
version: 'link:'
|
||||
|
||||
workspace/pkgs-graph:
|
||||
dependencies:
|
||||
'@pnpm/npm-package-arg':
|
||||
@@ -8042,6 +8058,9 @@ importers:
|
||||
'@pnpm/error':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/error
|
||||
'@pnpm/types':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/types
|
||||
read-yaml-file:
|
||||
specifier: 'catalog:'
|
||||
version: 2.1.0
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- "**"
|
||||
|
||||
@@ -240,7 +240,8 @@ test('`pnpm -r add` should fail if no package name was provided', () => {
|
||||
},
|
||||
])
|
||||
|
||||
fs.writeFileSync('pnpm-workspace.yaml', '', 'utf8')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', `packages:
|
||||
- project`, 'utf8')
|
||||
|
||||
const { status, stdout } = execPnpmSync(['-r', 'add'])
|
||||
|
||||
@@ -303,7 +304,8 @@ test('recursive install should fail if the used pnpm version does not satisfy th
|
||||
},
|
||||
])
|
||||
|
||||
fs.writeFileSync('pnpm-workspace.yaml', '', 'utf8')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', `packages:
|
||||
- "*"`, 'utf8')
|
||||
|
||||
process.chdir('project-1')
|
||||
|
||||
@@ -336,7 +338,8 @@ test('engine-strict=true: recursive install should fail if the used Node version
|
||||
},
|
||||
])
|
||||
|
||||
fs.writeFileSync('pnpm-workspace.yaml', '', 'utf8')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', `packages:
|
||||
- "*"`, 'utf8')
|
||||
|
||||
process.chdir('project-1')
|
||||
|
||||
@@ -369,7 +372,8 @@ test('engine-strict=false: recursive install should not fail if the used Node ve
|
||||
},
|
||||
])
|
||||
|
||||
fs.writeFileSync('pnpm-workspace.yaml', '', 'utf8')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', `packages:
|
||||
- "*"`, 'utf8')
|
||||
|
||||
process.chdir('project-1')
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { STORE_VERSION } from '@pnpm/constants'
|
||||
import { prepare, preparePackages } from '@pnpm/prepare'
|
||||
import { preparePackages } from '@pnpm/prepare'
|
||||
import { type LockfileFile } from '@pnpm/lockfile.types'
|
||||
import { sync as readYamlFile } from 'read-yaml-file'
|
||||
import { isCI } from 'ci-info'
|
||||
@@ -77,7 +77,8 @@ test('workspace .npmrc is always read', async () => {
|
||||
])
|
||||
|
||||
const storeDir = path.resolve('../store')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', '', 'utf8')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', `packages:
|
||||
- workspace/*`, 'utf8')
|
||||
fs.writeFileSync('.npmrc', 'shamefully-flatten = true\nshared-workspace-lockfile=false', 'utf8')
|
||||
fs.writeFileSync('workspace/project-2/.npmrc', 'hoist=false', 'utf8')
|
||||
|
||||
@@ -359,9 +360,22 @@ test('non-recursive install ignores filter from config', async () => {
|
||||
})
|
||||
|
||||
test('adding new dependency in the root should fail if neither --workspace-root nor --ignore-workspace-root-check are used', async () => {
|
||||
const project = prepare()
|
||||
const project = preparePackages([
|
||||
{
|
||||
location: '.',
|
||||
package: {
|
||||
name: 'root',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'project',
|
||||
},
|
||||
])['root']
|
||||
|
||||
fs.writeFileSync('pnpm-workspace.yaml', '', 'utf8')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', `packages:
|
||||
- '.'
|
||||
- 'project'
|
||||
`, 'utf8')
|
||||
|
||||
{
|
||||
const { status, stdout } = execPnpmSync(['add', 'is-positive'])
|
||||
@@ -455,7 +469,8 @@ test('set recursive-install to false in .npmrc would disable recursive install i
|
||||
])
|
||||
|
||||
process.chdir('workspace')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', '', 'utf8')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', `packages:
|
||||
- "**"`, 'utf8')
|
||||
fs.writeFileSync('.npmrc', `recursive-install = false
|
||||
dedupe-peer-dependents = false`, 'utf8')
|
||||
|
||||
@@ -493,7 +508,8 @@ test('set recursive-install to false would install as --filter {.}...', async ()
|
||||
])
|
||||
|
||||
process.chdir('workspace')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', '', 'utf8')
|
||||
fs.writeFileSync('pnpm-workspace.yaml', `packages:
|
||||
- "**"`, 'utf8')
|
||||
fs.writeFileSync('.npmrc', 'recursive-install = false', 'utf8')
|
||||
|
||||
process.chdir('project-1')
|
||||
|
||||
@@ -3,6 +3,14 @@ import { execPnpm } from '../utils'
|
||||
|
||||
test('`pnpm recursive rebuild` specific dependencies', async () => {
|
||||
const projects = preparePackages([
|
||||
{
|
||||
location: '.',
|
||||
package: {
|
||||
pnpm: {
|
||||
neverBuiltDependencies: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'project-1',
|
||||
version: '1.0.0',
|
||||
|
||||
13
workspace/manifest-writer/README.md
Normal file
13
workspace/manifest-writer/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# @pnpm/workspace.manifest-writer
|
||||
|
||||
> Updates the workspace manifest file
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
pnpm add @pnpm/workspace.manifest-writer
|
||||
```
|
||||
|
||||
## LICENSE
|
||||
|
||||
MIT
|
||||
44
workspace/manifest-writer/package.json
Normal file
44
workspace/manifest-writer/package.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "@pnpm/workspace.manifest-writer",
|
||||
"version": "1000.0.0-0",
|
||||
"description": "Updates the workspace manifest file",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"files": [
|
||||
"lib",
|
||||
"!*.map"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18.12"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint \"src/**/*.ts\"",
|
||||
"test": "pnpm run compile",
|
||||
"prepublishOnly": "pnpm run compile",
|
||||
"compile": "tsc --build && pnpm run lint --fix"
|
||||
},
|
||||
"repository": "https://github.com/pnpm/pnpm/blob/main/workspace/manifest-writer",
|
||||
"keywords": [
|
||||
"pnpm10",
|
||||
"pnpm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/pnpm/pnpm/issues"
|
||||
},
|
||||
"homepage": "https://github.com/pnpm/pnpm/blob/main/workspace/manifest-writer#readme",
|
||||
"dependencies": {
|
||||
"@pnpm/workspace.read-manifest": "workspace:*",
|
||||
"write-yaml-file": "catalog:"
|
||||
},
|
||||
"funding": "https://opencollective.com/pnpm",
|
||||
"devDependencies": {
|
||||
"@pnpm/workspace.manifest-writer": "workspace:*"
|
||||
},
|
||||
"exports": {
|
||||
".": "./lib/index.js"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@pnpm/jest-config"
|
||||
}
|
||||
}
|
||||
10
workspace/manifest-writer/src/index.ts
Normal file
10
workspace/manifest-writer/src/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { readWorkspaceManifest, type WorkspaceManifest } from '@pnpm/workspace.read-manifest'
|
||||
import writeYamlFile from 'write-yaml-file'
|
||||
|
||||
export async function updateWorkspaceManifest (dir: string, updatedFields: Partial<WorkspaceManifest>): Promise<void> {
|
||||
const manifest = await readWorkspaceManifest(dir)
|
||||
await writeYamlFile(dir, {
|
||||
...manifest,
|
||||
updatedFields,
|
||||
})
|
||||
}
|
||||
16
workspace/manifest-writer/tsconfig.json
Normal file
16
workspace/manifest-writer/tsconfig.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"extends": "@pnpm/tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"../../__typings__/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../read-manifest"
|
||||
}
|
||||
]
|
||||
}
|
||||
8
workspace/manifest-writer/tsconfig.lint.json
Normal file
8
workspace/manifest-writer/tsconfig.lint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"test/**/*.ts",
|
||||
"../../__typings__/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
@@ -31,6 +31,7 @@
|
||||
"dependencies": {
|
||||
"@pnpm/constants": "workspace:*",
|
||||
"@pnpm/error": "workspace:*",
|
||||
"@pnpm/types": "workspace:*",
|
||||
"read-yaml-file": "catalog:"
|
||||
},
|
||||
"funding": "https://opencollective.com/pnpm",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import util from 'util'
|
||||
import { WORKSPACE_MANIFEST_FILENAME } from '@pnpm/constants'
|
||||
import { type PnpmSettings } from '@pnpm/types'
|
||||
import path from 'node:path'
|
||||
import readYamlFile from 'read-yaml-file'
|
||||
import {
|
||||
@@ -10,7 +11,7 @@ import {
|
||||
} from './catalogs'
|
||||
import { InvalidWorkspaceManifestError } from './errors/InvalidWorkspaceManifestError'
|
||||
|
||||
export interface WorkspaceManifest {
|
||||
export interface WorkspaceManifest extends PnpmSettings {
|
||||
packages: string[]
|
||||
|
||||
/**
|
||||
@@ -75,7 +76,7 @@ function validateWorkspaceManifest (manifest: unknown): asserts manifest is Work
|
||||
|
||||
function assertValidWorkspaceManifestPackages (manifest: { packages?: unknown }): asserts manifest is { packages: string[] } {
|
||||
if (!manifest.packages) {
|
||||
throw new InvalidWorkspaceManifestError('packages field missing or empty')
|
||||
return
|
||||
}
|
||||
|
||||
if (!Array.isArray(manifest.packages)) {
|
||||
|
||||
@@ -21,10 +21,10 @@ test('readWorkspaceManifest() throws on array content', async () => {
|
||||
).rejects.toThrow('Expected object but found - array')
|
||||
})
|
||||
|
||||
test('readWorkspaceManifest() throws on empty packages field', async () => {
|
||||
test('readWorkspaceManifest() does not throw on empty packages field', async () => {
|
||||
await expect(
|
||||
readWorkspaceManifest(path.join(__dirname, '__fixtures__/packages-empty'))
|
||||
).rejects.toThrow('packages field missing or empty')
|
||||
).resolves.toBeTruthy()
|
||||
})
|
||||
|
||||
test('readWorkspaceManifest() throws on string packages field', async () => {
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
},
|
||||
{
|
||||
"path": "../../packages/error"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/types"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user