@pnpm/config.commands 1100.0.37 → 1100.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @pnpm/plugin-commands-config
2
2
 
3
+ ## 1100.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - `pnpm config set` refuses to write a setting to a project's `pnpm-workspace.yaml` that pnpm does not read from there, rather than leaving a key in the file that does nothing. Those settings are `configDir`, `pnpmHomeDir`, `stateDir` and the others that name machine-level state. The command fails with `ERR_PNPM_CONFIG_SET_NOT_A_PROJECT_SETTING`, naming where the setting does belong when it belongs somewhere. `pnpm config delete` still clears one that a file already carries, in whichever spelling it uses [#13629](https://github.com/pnpm/pnpm/issues/13629).
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies:
12
+ - @pnpm/cli.utils@1101.0.23
13
+ - @pnpm/config.reader@1101.17.0
14
+ - @pnpm/error@1100.1.2
15
+ - @pnpm/object.property-path@1100.1.4
16
+ - @pnpm/workspace.workspace-manifest-writer@1100.1.0
17
+
3
18
  ## 1100.0.37
4
19
 
5
20
  ### Patch Changes
@@ -15,6 +15,10 @@ export declare class ConfigSetUnsupportedWorkspaceKeyError extends PnpmError {
15
15
  readonly key: string;
16
16
  constructor(key: string);
17
17
  }
18
+ export declare class ConfigSetNotAProjectSettingError extends PnpmError {
19
+ readonly key: string;
20
+ constructor(key: string);
21
+ }
18
22
  export declare class ConfigSetUnsupportedYamlConfigKeyError extends PnpmError {
19
23
  readonly key: string;
20
24
  constructor(key: string);
package/lib/configSet.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import util from 'node:util';
3
- import { isConfigFileKey, isIniConfigKey, types } from '@pnpm/config.reader';
3
+ import { isConfigFileKey, isIniConfigKey, isProjectManifestSkippedKey, types, whereRefusedKeyBelongs } from '@pnpm/config.reader';
4
4
  import { GLOBAL_CONFIG_YAML_FILENAME, WORKSPACE_MANIFEST_FILENAME } from '@pnpm/constants';
5
5
  import { PnpmError } from '@pnpm/error';
6
6
  import { parsePropertyPath } from '@pnpm/object.property-path';
@@ -45,16 +45,28 @@ export async function configSet(opts, key, valueParam) {
45
45
  switch (configFileName) {
46
46
  case GLOBAL_CONFIG_YAML_FILENAME:
47
47
  case WORKSPACE_MANIFEST_FILENAME: {
48
- if (configFileName === GLOBAL_CONFIG_YAML_FILENAME) {
48
+ // `pnpm config set <key> null` casts to a removal too.
49
+ const castValue = castField(value, kebabCase(key));
50
+ const isRemoval = castValue == null;
51
+ // Validation stops a write landing in a file that will not read it back.
52
+ // Nothing reads back a key being deleted, so a removal skips both checks.
53
+ if (configFileName === GLOBAL_CONFIG_YAML_FILENAME && !isRemoval) {
49
54
  key = validateYamlConfigKey(key);
50
55
  }
51
- key = validateWorkspaceKey(key);
52
- await updateWorkspaceManifest(configDir, {
53
- fileName: configFileName,
54
- updatedFields: ({
55
- [key]: castField(value, kebabCase(key)),
56
- }),
57
- });
56
+ const writtenKey = isRemoval ? camelCase(key) : validateWorkspaceKey(key);
57
+ if (castValue != null && configFileName === WORKSPACE_MANIFEST_FILENAME && isProjectManifestSkippedKey(writtenKey)) {
58
+ throw new ConfigSetNotAProjectSettingError(writtenKey);
59
+ }
60
+ const updatedFields = {
61
+ [writtenKey]: castValue,
62
+ };
63
+ // A hand-edited file may carry a spelling pnpm did not write, and that
64
+ // is the one the reader's warning names, so a removal clears them all.
65
+ if (isRemoval) {
66
+ updatedFields[key] = null;
67
+ updatedFields[kebabCase(writtenKey)] = null;
68
+ }
69
+ await updateWorkspaceManifest(configDir, { fileName: configFileName, updatedFields });
58
70
  break;
59
71
  }
60
72
  case 'auth.ini':
@@ -169,6 +181,22 @@ export class ConfigSetUnsupportedWorkspaceKeyError extends PnpmError {
169
181
  this.key = key;
170
182
  }
171
183
  }
184
+ /** The suggestion for {@link key}, which falls back when the key is allowed in a project manifest. */
185
+ function hintForRefusedKey(key, fallback) {
186
+ const camelKey = camelCase(key);
187
+ if (!isProjectManifestSkippedKey(camelKey))
188
+ return fallback;
189
+ return whereRefusedKeyBelongs(camelKey);
190
+ }
191
+ export class ConfigSetNotAProjectSettingError extends PnpmError {
192
+ key;
193
+ constructor(key) {
194
+ super('CONFIG_SET_NOT_A_PROJECT_SETTING', `The key ${JSON.stringify(key)} cannot be set in a project's pnpm-workspace.yaml`, {
195
+ hint: whereRefusedKeyBelongs(key),
196
+ });
197
+ this.key = key;
198
+ }
199
+ }
172
200
  /**
173
201
  * Only an rc option key would be allowed to be kebab-case, otherwise, it must be camelCase.
174
202
  *
@@ -177,6 +205,8 @@ export class ConfigSetUnsupportedWorkspaceKeyError extends PnpmError {
177
205
  function validateWorkspaceKey(key) {
178
206
  if (Object.hasOwn(types, key) || isConfigFileKey(key))
179
207
  return camelCase(key);
208
+ if (isProjectManifestSkippedKey(camelCase(key)))
209
+ return camelCase(key);
180
210
  if (!isCamelCase(key))
181
211
  throw new ConfigSetUnsupportedWorkspaceKeyError(key);
182
212
  return key;
@@ -205,7 +235,7 @@ export class ConfigSetUnsupportedYamlConfigKeyError extends PnpmError {
205
235
  key;
206
236
  constructor(key) {
207
237
  super('CONFIG_SET_UNSUPPORTED_YAML_CONFIG_KEY', `The key ${JSON.stringify(key)} isn't supported by the global config.yaml file`, {
208
- hint: 'Try setting them instead to the local pnpm-workspace.yaml file',
238
+ hint: hintForRefusedKey(key, 'Try setting them instead to the local pnpm-workspace.yaml file'),
209
239
  });
210
240
  this.key = key;
211
241
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/config.commands",
3
- "version": "1100.0.37",
3
+ "version": "1100.1.0",
4
4
  "description": "Commands for reading and writing settings to/from config files",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -28,14 +28,14 @@
28
28
  "!*.map"
29
29
  ],
30
30
  "dependencies": {
31
- "@pnpm/cli.utils": "1101.0.22",
32
- "@pnpm/config.reader": "1101.16.1",
31
+ "@pnpm/cli.utils": "1101.0.23",
32
+ "@pnpm/config.reader": "1101.17.0",
33
33
  "@pnpm/constants": "1101.0.0",
34
- "@pnpm/error": "1100.1.1",
34
+ "@pnpm/error": "1100.1.2",
35
35
  "@pnpm/object.key-sorting": "1100.0.2",
36
- "@pnpm/object.property-path": "1100.1.3",
36
+ "@pnpm/object.property-path": "1100.1.4",
37
37
  "@pnpm/text.naming-cases": "1100.0.2",
38
- "@pnpm/workspace.workspace-manifest-writer": "1100.0.21",
38
+ "@pnpm/workspace.workspace-manifest-writer": "1100.1.0",
39
39
  "camelcase": "^9.0.0",
40
40
  "ini": "6.0.0",
41
41
  "lodash.kebabcase": "^4.1.1",
@@ -49,9 +49,9 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "@jest/globals": "30.4.1",
52
- "@pnpm/config.commands": "1100.0.37",
52
+ "@pnpm/config.commands": "1100.1.0",
53
53
  "@pnpm/logger": "1100.0.0",
54
- "@pnpm/prepare": "1100.0.25",
54
+ "@pnpm/prepare": "1100.0.26",
55
55
  "@types/ini": "4.1.1",
56
56
  "@types/lodash.kebabcase": "4.1.9",
57
57
  "read-yaml-file": "^3.0.0"