refactor: create config writer package (#9306)

* refactor: create config writer package

* test: fix

* test: fix

* docs: add changeset

* refactor: update config-writer
This commit is contained in:
Zoltan Kochan
2025-03-19 15:56:34 +01:00
committed by GitHub
parent 64f6b4f62b
commit 5a9e34f2bc
11 changed files with 191 additions and 47 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/config.config-writer": major
---
Initial release.

View File

@@ -0,0 +1,17 @@
# @pnpm/config.config-writer
> Functions for updating the configuration settings
<!--@shields('npm')-->
[![npm version](https://img.shields.io/npm/v/@pnpm/config.svg)](https://www.npmjs.com/package/@pnpm/config)
<!--/@-->
## Installation
```sh
pnpm add @pnpm/config.config-writer
```
## License
MIT

View File

@@ -0,0 +1,49 @@
{
"name": "@pnpm/config.config-writer",
"version": "1000.0.0-0",
"description": "Functions for updating the configuration settings",
"keywords": [
"pnpm",
"pnpm10",
"config"
],
"license": "MIT",
"funding": "https://opencollective.com/pnpm",
"repository": "https://github.com/pnpm/pnpm/blob/main/config/config-writer",
"homepage": "https://github.com/pnpm/pnpm/blob/main/config/config-writer#readme",
"bugs": {
"url": "https://github.com/pnpm/pnpm/issues"
},
"main": "lib/index.js",
"types": "lib/index.d.ts",
"exports": {
".": "./lib/index.js"
},
"files": [
"lib",
"!*.map"
],
"scripts": {
"prepublishOnly": "pnpm run compile",
"lint": "eslint \"src/**/*.ts\"",
"test": "pnpm run compile",
"start": "tsc --watch",
"compile": "tsc --build && pnpm run lint --fix"
},
"dependencies": {
"@pnpm/read-project-manifest": "workspace:*",
"@pnpm/types": "workspace:*",
"@pnpm/workspace.manifest-writer": "workspace:*",
"ramda": "catalog:"
},
"devDependencies": {
"@pnpm/config.config-writer": "workspace:*",
"@types/ramda": "catalog:"
},
"engines": {
"node": ">=18.12"
},
"jest": {
"preset": "@pnpm/jest-config"
}
}

View File

@@ -0,0 +1,37 @@
import { type ProjectManifest, type PnpmSettings } from '@pnpm/types'
import { tryReadProjectManifest } from '@pnpm/read-project-manifest'
import { updateWorkspaceManifest } from '@pnpm/workspace.manifest-writer'
import equals from 'ramda/src/equals'
export async function writeSettings (opts: {
updatedSettings: PnpmSettings
rootProjectManifest?: ProjectManifest
rootProjectManifestDir: string
workspaceDir: string
}): Promise<void> {
if (opts.rootProjectManifest?.pnpm != null) {
const { manifest, writeProjectManifest } = await tryReadProjectManifest(opts.rootProjectManifestDir)
if (manifest) {
manifest.pnpm ??= {}
let shouldBeUpdated = false
for (const [key, value] of Object.entries(opts.updatedSettings)) {
if (!equals(manifest.pnpm[key as keyof PnpmSettings], value)) {
shouldBeUpdated = true
if (value == null) {
delete manifest.pnpm[key as keyof PnpmSettings]
} else {
manifest.pnpm[key as keyof PnpmSettings] = value
}
}
}
if (Object.keys(manifest.pnpm).length === 0) {
delete manifest.pnpm
}
if (shouldBeUpdated) {
await writeProjectManifest(manifest)
}
return
}
}
await updateWorkspaceManifest(opts.workspaceDir, opts.updatedSettings)
}

View File

@@ -0,0 +1,22 @@
{
"extends": "@pnpm/tsconfig",
"compilerOptions": {
"outDir": "lib",
"rootDir": "src"
},
"include": [
"src/**/*.ts",
"../../__typings__/**/*.d.ts"
],
"references": [
{
"path": "../../packages/types"
},
{
"path": "../../pkg-manifest/read-project-manifest"
},
{
"path": "../../workspace/manifest-writer"
}
]
}

View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"include": [
"src/**/*.ts",
"test/**/*.ts",
"../../__typings__/**/*.d.ts"
]
}

View File

@@ -32,12 +32,11 @@
},
"dependencies": {
"@pnpm/config": "workspace:*",
"@pnpm/config.config-writer": "workspace:*",
"@pnpm/modules-yaml": "workspace:*",
"@pnpm/plugin-commands-rebuild": "workspace:*",
"@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:"

View File

@@ -1,13 +1,13 @@
import { type Config } from '@pnpm/config'
import { globalInfo } from '@pnpm/logger'
import { type StrictModules, writeModulesManifest } from '@pnpm/modules-yaml'
import { tryReadProjectManifest } from '@pnpm/read-project-manifest'
import { lexCompare } from '@pnpm/util.lex-comparator'
import { type PnpmSettings } from '@pnpm/types'
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 { writeSettings } from '@pnpm/config.config-writer'
import { getAutomaticallyIgnoredBuilds } from './getAutomaticallyIgnoredBuilds'
export type ApproveBuildsCommandOpts = Pick<Config, 'modulesDir' | 'dir' | 'rootProjectManifest' | 'rootProjectManifestDir' | 'onlyBuiltDependencies' | 'ignoredBuiltDependencies'>
@@ -92,23 +92,22 @@ 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
const updatedSettings: PnpmSettings = {}
if (ignoredPackages.length) {
if (opts.ignoredBuiltDependencies == null) {
updatedIgnoredBuiltDependencies = sortUniqueStrings(ignoredPackages)
updatedSettings.ignoredBuiltDependencies = sortUniqueStrings(ignoredPackages)
} else {
updatedIgnoredBuiltDependencies = sortUniqueStrings([
updatedSettings.ignoredBuiltDependencies = sortUniqueStrings([
...opts.ignoredBuiltDependencies,
...ignoredPackages,
])
}
}
let updatedOnlyBuiltDependencies: string[] | undefined
if (buildPackages.length) {
if (opts.onlyBuiltDependencies == null) {
updatedOnlyBuiltDependencies = sortUniqueStrings(buildPackages)
updatedSettings.onlyBuiltDependencies = sortUniqueStrings(buildPackages)
} else {
updatedOnlyBuiltDependencies = sortUniqueStrings([
updatedSettings.onlyBuiltDependencies = sortUniqueStrings([
...opts.onlyBuiltDependencies,
...buildPackages,
])
@@ -126,27 +125,15 @@ Do you approve?`,
return
}
}
let { manifest, writeProjectManifest } = await tryReadProjectManifest(opts.rootProjectManifestDir)
manifest ??= {}
if (opts.workspaceDir == null || manifest.pnpm?.onlyBuiltDependencies != null || manifest.pnpm?.ignoredBuiltDependencies != null) {
manifest.pnpm ??= {}
if (updatedOnlyBuiltDependencies) {
manifest.pnpm.onlyBuiltDependencies = updatedOnlyBuiltDependencies
}
if (updatedIgnoredBuiltDependencies) {
manifest.pnpm.ignoredBuiltDependencies = updatedIgnoredBuiltDependencies
}
await writeProjectManifest(manifest)
} else {
await updateWorkspaceManifest(opts.workspaceDir, {
onlyBuiltDependencies: updatedOnlyBuiltDependencies,
ignoredBuiltDependencies: updatedIgnoredBuiltDependencies,
})
}
await writeSettings({
...opts,
workspaceDir: opts.workspaceDir ?? opts.rootProjectManifestDir,
updatedSettings,
})
if (buildPackages.length) {
return rebuild.handler({
...opts,
onlyBuiltDependencies: updatedOnlyBuiltDependencies,
onlyBuiltDependencies: updatedSettings.onlyBuiltDependencies,
}, buildPackages)
} else if (modulesManifest) {
delete modulesManifest.ignoredBuilds

View File

@@ -82,6 +82,9 @@ test('approve selected build', async () => {
'@pnpm.e2e/pre-and-postinstall-scripts-example': '1.0.0',
'@pnpm.e2e/install-script-example': '*',
},
pnpm: {
overrides: {},
},
})
await approveSomeBuilds()
@@ -105,9 +108,9 @@ test('approve no builds', async () => {
await approveNoBuilds()
const manifest = loadJsonFile<ProjectManifest>(path.resolve('package.json'))
expect(manifest.pnpm?.onlyBuiltDependencies).toBeUndefined()
expect(manifest.pnpm?.ignoredBuiltDependencies?.sort()).toStrictEqual([
const manifest = readYamlFile<any>(path.resolve('pnpm-workspace.yaml')) // eslint-disable-line
expect(manifest.onlyBuiltDependencies).toBeUndefined()
expect(manifest.ignoredBuiltDependencies?.sort()).toStrictEqual([
'@pnpm.e2e/install-script-example',
'@pnpm.e2e/pre-and-postinstall-scripts-example',
])
@@ -145,8 +148,7 @@ test("works when root project manifest doesn't exist in a workspace", async () =
test('should update onlyBuiltDependencies when package.json exists with ignoredBuiltDependencies defined', async () => {
const temp = tempDir()
prepare({
const rootProjectManifest = {
dependencies: {
'@pnpm.e2e/pre-and-postinstall-scripts-example': '1.0.0',
'@pnpm.e2e/install-script-example': '*',
@@ -154,13 +156,15 @@ test('should update onlyBuiltDependencies when package.json exists with ignoredB
pnpm: {
ignoredBuiltDependencies: ['@pnpm.e2e/install-script-example'],
},
}, {
}
prepare(rootProjectManifest, {
tempDir: temp,
})
const workspaceManifestFile = path.join(temp, 'pnpm-workspace.yaml')
writeYamlFile(workspaceManifestFile, { packages: ['packages/*'] })
await approveSomeBuilds({ workspaceDir: temp, rootProjectManifestDir: temp })
await approveSomeBuilds({ workspaceDir: temp, rootProjectManifestDir: temp, rootProjectManifest })
expect(readYamlFile(workspaceManifestFile)).toStrictEqual({
packages: ['packages/*'],

View File

@@ -18,6 +18,9 @@
{
"path": "../../config/config"
},
{
"path": "../../config/config-writer"
},
{
"path": "../../packages/types"
},
@@ -27,12 +30,6 @@
{
"path": "../../pkg-manager/plugin-commands-installation"
},
{
"path": "../../pkg-manifest/read-project-manifest"
},
{
"path": "../../workspace/manifest-writer"
},
{
"path": "../plugin-commands-rebuild"
}

31
pnpm-lock.yaml generated
View File

@@ -1543,6 +1543,28 @@ importers:
specifier: 'catalog:'
version: 6.0.5
config/config-writer:
dependencies:
'@pnpm/read-project-manifest':
specifier: workspace:*
version: link:../../pkg-manifest/read-project-manifest
'@pnpm/types':
specifier: workspace:*
version: link:../../packages/types
'@pnpm/workspace.manifest-writer':
specifier: workspace:*
version: link:../../workspace/manifest-writer
ramda:
specifier: 'catalog:'
version: '@pnpm/ramda@0.28.1'
devDependencies:
'@pnpm/config.config-writer':
specifier: workspace:*
version: 'link:'
'@types/ramda':
specifier: 'catalog:'
version: 0.29.12
config/matcher:
dependencies:
escape-string-regexp:
@@ -2114,6 +2136,9 @@ importers:
'@pnpm/config':
specifier: workspace:*
version: link:../../config/config
'@pnpm/config.config-writer':
specifier: workspace:*
version: link:../../config/config-writer
'@pnpm/logger':
specifier: '>=5.1.0 <1001.0.0'
version: 1000.0.0
@@ -2126,15 +2151,9 @@ importers:
'@pnpm/prepare-temp-dir':
specifier: workspace:*
version: link:../../__utils__/prepare-temp-dir
'@pnpm/read-project-manifest':
specifier: workspace:*
version: link:../../pkg-manifest/read-project-manifest
'@pnpm/util.lex-comparator':
specifier: 'catalog:'
version: 3.0.1
'@pnpm/workspace.manifest-writer':
specifier: workspace:*
version: link:../../workspace/manifest-writer
chalk:
specifier: 'catalog:'
version: 4.1.2