@pnpm/config.commands 1000.2.10

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015-2016 Rico Sta. Cruz and other contributors
4
+ Copyright (c) 2016-2026 Zoltan Kochan and other contributors
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # @pnpm/plugin-commands-config
2
+
3
+ > Commands for reading and writing settings to/from config files
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@pnpm/plugin-commands-config.svg)](https://www.npmjs.com/package/@pnpm/plugin-commands-config)
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ pnpm add @pnpm/plugin-commands-config
11
+ ```
12
+
13
+ ## License
14
+
15
+ MIT
@@ -0,0 +1,5 @@
1
+ import type { Config } from '@pnpm/config.reader';
2
+ export type ConfigCommandOptions = Pick<Config, 'configDir' | 'cliOptions' | 'dir' | 'global' | 'npmPath' | 'rawConfig' | 'workspaceDir'> & {
3
+ json?: boolean;
4
+ location?: 'global' | 'project';
5
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ConfigCommandOptions.js.map
@@ -0,0 +1,10 @@
1
+ import type { ConfigCommandOptions } from './ConfigCommandOptions.js';
2
+ export declare function rcOptionsTypes(): Record<string, unknown>;
3
+ export declare function cliOptionsTypes(): Record<string, unknown>;
4
+ export declare const commandNames: string[];
5
+ export declare function help(): string;
6
+ export type ConfigHandlerResult = string | undefined | {
7
+ output: string;
8
+ exitCode: number;
9
+ };
10
+ export declare function handler(opts: ConfigCommandOptions, params: string[]): Promise<ConfigHandlerResult>;
package/lib/config.js ADDED
@@ -0,0 +1,119 @@
1
+ import { docsUrl } from '@pnpm/cli.utils';
2
+ import { PnpmError } from '@pnpm/error';
3
+ import { renderHelp } from 'render-help';
4
+ import { configGet } from './configGet.js';
5
+ import { configList } from './configList.js';
6
+ import { configSet } from './configSet.js';
7
+ export function rcOptionsTypes() {
8
+ return {};
9
+ }
10
+ export function cliOptionsTypes() {
11
+ return {
12
+ global: Boolean,
13
+ location: ['global', 'project'],
14
+ json: Boolean,
15
+ };
16
+ }
17
+ export const commandNames = ['config', 'c'];
18
+ export function help() {
19
+ return renderHelp({
20
+ description: 'Manage the pnpm configuration files.',
21
+ descriptionLists: [
22
+ {
23
+ title: 'Commands',
24
+ list: [
25
+ {
26
+ description: 'Set the config key to the value provided',
27
+ name: 'set',
28
+ },
29
+ {
30
+ description: 'Print the config value for the provided key',
31
+ name: 'get',
32
+ },
33
+ {
34
+ description: 'Remove the config key from the config file',
35
+ name: 'delete',
36
+ },
37
+ {
38
+ description: 'Show all the config settings',
39
+ name: 'list',
40
+ },
41
+ ],
42
+ },
43
+ {
44
+ title: 'Options',
45
+ list: [
46
+ {
47
+ description: 'Sets the configuration in the global config file',
48
+ name: '--global',
49
+ shortAlias: '-g',
50
+ },
51
+ {
52
+ description: 'When set to "project", the pnpm-workspace.yaml file will be used if it exists. If only .npmrc exists, it will be used. If neither exists, a pnpm-workspace.yaml file will be created.',
53
+ name: '--location <project|global>',
54
+ },
55
+ {
56
+ description: 'Show all types of values in JSON format (not just objects and arrays)',
57
+ name: '--json',
58
+ },
59
+ ],
60
+ },
61
+ ],
62
+ url: docsUrl('config'),
63
+ usages: [
64
+ 'pnpm config set <key> <value>',
65
+ 'pnpm config get <key>',
66
+ 'pnpm config get --json <key>',
67
+ 'pnpm config delete <key>',
68
+ 'pnpm config list',
69
+ ],
70
+ });
71
+ }
72
+ export async function handler(opts, params) {
73
+ if (params.length === 0) {
74
+ throw new PnpmError('CONFIG_NO_SUBCOMMAND', 'Please specify the subcommand', {
75
+ hint: help(),
76
+ });
77
+ }
78
+ if (opts.location) {
79
+ opts.global = opts.location === 'global';
80
+ }
81
+ else if (opts.cliOptions['global'] == null) {
82
+ opts.global = true;
83
+ }
84
+ switch (params[0]) {
85
+ case 'set':
86
+ case 'delete': {
87
+ if (!params[1]) {
88
+ throw new PnpmError('CONFIG_NO_PARAMS', `\`pnpm config ${params[0]}\` requires the config key`);
89
+ }
90
+ if (params[0] === 'set') {
91
+ let [key, value] = params.slice(1);
92
+ if (value == null) {
93
+ const parts = key.split('=');
94
+ key = parts.shift();
95
+ value = parts.join('=');
96
+ }
97
+ return configSet(opts, key, value ?? '');
98
+ }
99
+ else {
100
+ return configSet(opts, params[1], null);
101
+ }
102
+ }
103
+ case 'get': {
104
+ if (params[1]) {
105
+ return configGet(opts, params[1]);
106
+ }
107
+ else {
108
+ return configList(opts);
109
+ }
110
+ }
111
+ case 'list': {
112
+ return configList(opts);
113
+ }
114
+ default: {
115
+ throw new PnpmError('CONFIG_UNKNOWN_SUBCOMMAND', 'This subcommand is not known');
116
+ }
117
+ }
118
+ }
119
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,5 @@
1
+ import type { ConfigCommandOptions } from './ConfigCommandOptions.js';
2
+ export declare function configGet(opts: ConfigCommandOptions, key: string): {
3
+ output: string;
4
+ exitCode: number;
5
+ };
@@ -0,0 +1,61 @@
1
+ import path from 'node:path';
2
+ import { types } from '@pnpm/config.reader';
3
+ import { runNpm } from '@pnpm/exec.run-npm';
4
+ import { getObjectValueByPropertyPath } from '@pnpm/object.property-path';
5
+ import { isCamelCase, isStrictlyKebabCase } from '@pnpm/text.naming-cases';
6
+ import kebabCase from 'lodash.kebabcase';
7
+ import { parseConfigPropertyPath } from './parseConfigPropertyPath.js';
8
+ import { processConfig } from './processConfig.js';
9
+ import { settingShouldFallBackToNpm } from './settingShouldFallBackToNpm.js';
10
+ export function configGet(opts, key) {
11
+ const isScopedKey = key.startsWith('@');
12
+ // Exclude scoped keys from npm fallback because they are pnpm-native config
13
+ // that can be read directly from rawConfig (e.g., '@scope:registry')
14
+ if (opts.global && settingShouldFallBackToNpm(key) && !isScopedKey) {
15
+ const { status: exitCode } = runNpm(opts.npmPath, ['config', 'get', key], {
16
+ location: 'user',
17
+ userConfigPath: path.join(opts.configDir, 'rc'),
18
+ });
19
+ return { output: '', exitCode: exitCode ?? 0 };
20
+ }
21
+ const configResult = getRcConfig(opts.rawConfig, key, isScopedKey) ?? getConfigByPropertyPath(opts.rawConfig, key);
22
+ const output = displayConfig(configResult?.value, opts);
23
+ return { output, exitCode: 0 };
24
+ }
25
+ function getRcConfig(rawConfig, key, isScopedKey) {
26
+ if (isScopedKey) {
27
+ const value = rawConfig[key];
28
+ return { value };
29
+ }
30
+ const rcKey = isCamelCase(key) ? kebabCase(key) : key;
31
+ if (Object.hasOwn(types, rcKey)) {
32
+ const value = rawConfig[rcKey];
33
+ return { value };
34
+ }
35
+ if (isStrictlyKebabCase(key)) {
36
+ const value = rawConfig[key];
37
+ return { value };
38
+ }
39
+ return undefined;
40
+ }
41
+ function getConfigByPropertyPath(rawConfig, propertyPath) {
42
+ const parsedPropertyPath = Array.from(parseConfigPropertyPath(propertyPath));
43
+ if (parsedPropertyPath.length === 0) {
44
+ return {
45
+ value: processConfig(rawConfig),
46
+ };
47
+ }
48
+ return {
49
+ value: getObjectValueByPropertyPath(rawConfig, parsedPropertyPath),
50
+ };
51
+ }
52
+ function displayConfig(config, opts) {
53
+ if (Boolean(opts.json) || Array.isArray(config)) {
54
+ return JSON.stringify(config, undefined, 2);
55
+ }
56
+ if (typeof config === 'object' && config != null) {
57
+ return JSON.stringify(config, undefined, 2);
58
+ }
59
+ return String(config);
60
+ }
61
+ //# sourceMappingURL=configGet.js.map
@@ -0,0 +1,3 @@
1
+ import type { ConfigCommandOptions } from './ConfigCommandOptions.js';
2
+ export type ConfigListOptions = Pick<ConfigCommandOptions, 'rawConfig'>;
3
+ export declare function configList(opts: ConfigListOptions): Promise<string>;
@@ -0,0 +1,6 @@
1
+ import { processConfig } from './processConfig.js';
2
+ export async function configList(opts) {
3
+ const processedConfig = processConfig(opts.rawConfig);
4
+ return JSON.stringify(processedConfig, undefined, 2);
5
+ }
6
+ //# sourceMappingURL=configList.js.map
@@ -0,0 +1,21 @@
1
+ import { PnpmError } from '@pnpm/error';
2
+ import type { ConfigCommandOptions } from './ConfigCommandOptions.js';
3
+ export declare function configSet(opts: ConfigCommandOptions, key: string, valueParam: string | null): Promise<void>;
4
+ export declare class ConfigSetKeyEmptyKeyError extends PnpmError {
5
+ constructor();
6
+ }
7
+ export declare class ConfigSetDeepKeyError extends PnpmError {
8
+ constructor();
9
+ }
10
+ export declare class ConfigSetUnsupportedIniConfigKeyError extends PnpmError {
11
+ readonly key: string;
12
+ constructor(key: string);
13
+ }
14
+ export declare class ConfigSetUnsupportedWorkspaceKeyError extends PnpmError {
15
+ readonly key: string;
16
+ constructor(key: string);
17
+ }
18
+ export declare class ConfigSetUnsupportedYamlConfigKeyError extends PnpmError {
19
+ readonly key: string;
20
+ constructor(key: string);
21
+ }
@@ -0,0 +1,231 @@
1
+ import path from 'node:path';
2
+ import util from 'node:util';
3
+ import { isConfigFileKey, types } from '@pnpm/config.reader';
4
+ import { GLOBAL_CONFIG_YAML_FILENAME, WORKSPACE_MANIFEST_FILENAME } from '@pnpm/constants';
5
+ import { PnpmError } from '@pnpm/error';
6
+ import { runNpm } from '@pnpm/exec.run-npm';
7
+ import { parsePropertyPath } from '@pnpm/object.property-path';
8
+ import { isCamelCase, isStrictlyKebabCase } from '@pnpm/text.naming-cases';
9
+ import { updateWorkspaceManifest } from '@pnpm/workspace.workspace-manifest-writer';
10
+ import camelCase from 'camelcase';
11
+ import kebabCase from 'lodash.kebabcase';
12
+ import { readIniFile } from 'read-ini-file';
13
+ import { writeIniFile } from 'write-ini-file';
14
+ import { getConfigFileInfo } from './getConfigFileInfo.js';
15
+ import { settingShouldFallBackToNpm } from './settingShouldFallBackToNpm.js';
16
+ export async function configSet(opts, key, valueParam) {
17
+ let shouldFallbackToNpm = settingShouldFallBackToNpm(key);
18
+ if (!shouldFallbackToNpm) {
19
+ key = validateSimpleKey(key);
20
+ shouldFallbackToNpm = settingShouldFallBackToNpm(key);
21
+ }
22
+ let value = valueParam;
23
+ if (valueParam != null && opts.json) {
24
+ value = JSON.parse(valueParam);
25
+ }
26
+ if (shouldFallbackToNpm) {
27
+ if (opts.global) {
28
+ const configPath = path.join(opts.configDir, 'rc');
29
+ const runNpmOpts = {
30
+ location: 'user',
31
+ userConfigPath: configPath,
32
+ };
33
+ const _runNpm = runNpm.bind(null, opts.npmPath);
34
+ if (value == null) {
35
+ _runNpm(['config', 'delete', key], runNpmOpts);
36
+ return;
37
+ }
38
+ if (typeof value === 'string') {
39
+ _runNpm(['config', 'set', `${key}=${value}`], runNpmOpts);
40
+ return;
41
+ }
42
+ throw new PnpmError('CONFIG_SET_AUTH_NON_STRING', `Cannot set ${key} to a non-string value (${JSON.stringify(value)})`);
43
+ }
44
+ else {
45
+ const configPath = path.join(opts.dir, '.npmrc');
46
+ const settings = await safeReadIniFile(configPath);
47
+ if (value == null) {
48
+ if (settings[key] == null)
49
+ return;
50
+ delete settings[key];
51
+ }
52
+ else {
53
+ settings[key] = value;
54
+ }
55
+ await writeIniFile(configPath, settings);
56
+ return;
57
+ }
58
+ }
59
+ const { configDir, configFileName } = getConfigFileInfo(key, opts);
60
+ const configPath = path.join(configDir, configFileName);
61
+ switch (configFileName) {
62
+ case GLOBAL_CONFIG_YAML_FILENAME:
63
+ case WORKSPACE_MANIFEST_FILENAME: {
64
+ if (configFileName === GLOBAL_CONFIG_YAML_FILENAME) {
65
+ key = validateYamlConfigKey(key);
66
+ }
67
+ key = validateWorkspaceKey(key);
68
+ await updateWorkspaceManifest(configDir, {
69
+ fileName: configFileName,
70
+ updatedFields: ({
71
+ [key]: castField(value, kebabCase(key)),
72
+ }),
73
+ });
74
+ break;
75
+ }
76
+ case 'rc':
77
+ case '.npmrc': {
78
+ const settings = await safeReadIniFile(configPath);
79
+ key = validateIniConfigKey(key);
80
+ if (value == null) {
81
+ if (settings[key] == null)
82
+ return;
83
+ delete settings[key];
84
+ }
85
+ else {
86
+ settings[key] = value;
87
+ }
88
+ await writeIniFile(configPath, settings);
89
+ break;
90
+ }
91
+ default: {
92
+ const _typeGuard = configFileName;
93
+ throw new Error(`Unhandled case: ${JSON.stringify(_typeGuard)}`);
94
+ }
95
+ }
96
+ }
97
+ function castField(value, key) {
98
+ if (typeof value !== 'string') {
99
+ return value;
100
+ }
101
+ const type = types[key];
102
+ const typeList = Array.isArray(type) ? type : [type];
103
+ const isNumber = typeList.includes(Number);
104
+ value = value.trim();
105
+ switch (value) {
106
+ case 'true': {
107
+ return true;
108
+ }
109
+ case 'false': {
110
+ return false;
111
+ }
112
+ case 'null': {
113
+ return null;
114
+ }
115
+ case 'undefined': {
116
+ return undefined;
117
+ }
118
+ }
119
+ if (isNumber && !isNaN(value)) {
120
+ value = Number(value);
121
+ }
122
+ return value;
123
+ }
124
+ export class ConfigSetKeyEmptyKeyError extends PnpmError {
125
+ constructor() {
126
+ super('CONFIG_SET_EMPTY_KEY', 'Cannot set config with an empty key');
127
+ }
128
+ }
129
+ export class ConfigSetDeepKeyError extends PnpmError {
130
+ constructor() {
131
+ // it shouldn't be supported until there is a mechanism to validate the config value
132
+ super('CONFIG_SET_DEEP_KEY', 'Setting deep property path is not supported');
133
+ }
134
+ }
135
+ /**
136
+ * Validate if {@link key} is a simple key or a property path.
137
+ *
138
+ * If it is an empty property path or a property path longer than 1, throw an error.
139
+ *
140
+ * If it is a simple key (or a property path with length of 1), return it.
141
+ */
142
+ function validateSimpleKey(key) {
143
+ if (isStrictlyKebabCase(key))
144
+ return key;
145
+ const iter = parsePropertyPath(key);
146
+ const first = iter.next();
147
+ if (first.done)
148
+ throw new ConfigSetKeyEmptyKeyError();
149
+ const second = iter.next();
150
+ if (!second.done)
151
+ throw new ConfigSetDeepKeyError();
152
+ return first.value.toString();
153
+ }
154
+ export class ConfigSetUnsupportedIniConfigKeyError extends PnpmError {
155
+ key;
156
+ constructor(key) {
157
+ super('CONFIG_SET_UNSUPPORTED_INI_CONFIG_KEY', `Key ${JSON.stringify(key)} isn't supported by INI config files`, {
158
+ hint: `Add ${JSON.stringify(camelCase(key))} to the project workspace manifest instead`,
159
+ });
160
+ this.key = key;
161
+ }
162
+ }
163
+ /**
164
+ * Validate whether the kebab-case of {@link key} is supported by INI config files.
165
+ *
166
+ * Return the kebab-case if it is, throw an error otherwise.
167
+ *
168
+ * "INI config files" includes:
169
+ * * The global INI config file named `rc`.
170
+ * * The local INI config file named `.npmrc`.
171
+ */
172
+ function validateIniConfigKey(key) {
173
+ const kebabKey = kebabCase(key);
174
+ if (Object.hasOwn(types, kebabKey)) {
175
+ return kebabKey;
176
+ }
177
+ throw new ConfigSetUnsupportedIniConfigKeyError(key);
178
+ }
179
+ export class ConfigSetUnsupportedWorkspaceKeyError extends PnpmError {
180
+ key;
181
+ constructor(key) {
182
+ super('CONFIG_SET_UNSUPPORTED_WORKSPACE_KEY', `The key ${JSON.stringify(key)} isn't supported by the workspace manifest`, {
183
+ hint: `Try ${JSON.stringify(camelCase(key))}`,
184
+ });
185
+ this.key = key;
186
+ }
187
+ }
188
+ /**
189
+ * Only an rc option key would be allowed to be kebab-case, otherwise, it must be camelCase.
190
+ *
191
+ * Return the camelCase of {@link key} if it's valid.
192
+ */
193
+ function validateWorkspaceKey(key) {
194
+ if (Object.hasOwn(types, key))
195
+ return camelCase(key);
196
+ if (!isCamelCase(key))
197
+ throw new ConfigSetUnsupportedWorkspaceKeyError(key);
198
+ return key;
199
+ }
200
+ async function safeReadIniFile(configPath) {
201
+ try {
202
+ return await readIniFile(configPath);
203
+ }
204
+ catch (err) {
205
+ if (util.types.isNativeError(err) && 'code' in err && err.code === 'ENOENT')
206
+ return {};
207
+ throw err;
208
+ }
209
+ }
210
+ export class ConfigSetUnsupportedYamlConfigKeyError extends PnpmError {
211
+ key;
212
+ constructor(key) {
213
+ super('CONFIG_SET_UNSUPPORTED_YAML_CONFIG_KEY', `The key ${JSON.stringify(key)} isn't supported by the global config.yaml file`, {
214
+ hint: 'Try setting them instead to the local pnpm-workspace.yaml file',
215
+ });
216
+ this.key = key;
217
+ }
218
+ }
219
+ /**
220
+ * Validate whether the {@link key} is allowed in the global config.yaml file.
221
+ *
222
+ * Return the kebab-case if it is, throw an error otherwise.
223
+ */
224
+ function validateYamlConfigKey(key) {
225
+ const kebabKey = kebabCase(key);
226
+ if (!isConfigFileKey(kebabKey)) {
227
+ throw new ConfigSetUnsupportedYamlConfigKeyError(key);
228
+ }
229
+ return kebabKey;
230
+ }
231
+ //# sourceMappingURL=configSet.js.map
package/lib/get.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import * as configCmd from './config.js';
2
+ import type { ConfigCommandOptions } from './ConfigCommandOptions.js';
3
+ export declare const rcOptionsTypes: typeof configCmd.rcOptionsTypes;
4
+ export declare const cliOptionsTypes: typeof configCmd.cliOptionsTypes;
5
+ export declare const help: typeof configCmd.help;
6
+ export declare const commandNames: string[];
7
+ export declare function handler(opts: ConfigCommandOptions, params: string[]): Promise<configCmd.ConfigHandlerResult>;
package/lib/get.js ADDED
@@ -0,0 +1,9 @@
1
+ import * as configCmd from './config.js';
2
+ export const rcOptionsTypes = configCmd.rcOptionsTypes;
3
+ export const cliOptionsTypes = configCmd.cliOptionsTypes;
4
+ export const help = configCmd.help;
5
+ export const commandNames = ['get'];
6
+ export async function handler(opts, params) {
7
+ return configCmd.handler(opts, ['get', ...params]);
8
+ }
9
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1,8 @@
1
+ import { GLOBAL_CONFIG_YAML_FILENAME, WORKSPACE_MANIFEST_FILENAME } from '@pnpm/constants';
2
+ import type { ConfigCommandOptions } from './ConfigCommandOptions.js';
3
+ export type ConfigFileName = 'rc' | '.npmrc' | typeof GLOBAL_CONFIG_YAML_FILENAME | typeof WORKSPACE_MANIFEST_FILENAME;
4
+ export interface ConfigFilePathInfo {
5
+ configDir: string;
6
+ configFileName: ConfigFileName;
7
+ }
8
+ export declare function getConfigFileInfo(key: string, opts: Pick<ConfigCommandOptions, 'global' | 'configDir' | 'dir'>): ConfigFilePathInfo;
@@ -0,0 +1,20 @@
1
+ import { isIniConfigKey } from '@pnpm/config.reader';
2
+ import { GLOBAL_CONFIG_YAML_FILENAME, WORKSPACE_MANIFEST_FILENAME } from '@pnpm/constants';
3
+ import kebabCase from 'lodash.kebabcase';
4
+ export function getConfigFileInfo(key, opts) {
5
+ key = kebabCase(key);
6
+ const configDir = opts.global ? opts.configDir : opts.dir;
7
+ if (isIniConfigKey(key)) {
8
+ // NOTE: The following code no longer does what the merged PR at <https://github.com/pnpm/pnpm/pull/10073> wants to do,
9
+ // but considering the settings are now clearly divided into 2 separate categories, it should no longer be relevant.
10
+ // TODO: Auth, network, and proxy settings should belong only to INI files.
11
+ // Add more settings to `isIniConfigKey` to make it complete.
12
+ const configFileName = opts.global ? 'rc' : '.npmrc';
13
+ return { configDir, configFileName };
14
+ }
15
+ else {
16
+ const configFileName = opts.global ? GLOBAL_CONFIG_YAML_FILENAME : WORKSPACE_MANIFEST_FILENAME;
17
+ return { configDir, configFileName };
18
+ }
19
+ }
20
+ //# sourceMappingURL=getConfigFileInfo.js.map
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import * as config from './config.js';
2
+ import * as getCommand from './get.js';
3
+ import * as setCommand from './set.js';
4
+ export { config, getCommand, setCommand };
package/lib/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import * as config from './config.js';
2
+ import * as getCommand from './get.js';
3
+ import * as setCommand from './set.js';
4
+ export { config, getCommand, setCommand };
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Just like {@link parsePropertyPath} but the first element may be converted into kebab-case
3
+ * if it's part of {@link types}.
4
+ */
5
+ export declare function parseConfigPropertyPath(propertyPath: string): Generator<string | number, void, void>;
@@ -0,0 +1,28 @@
1
+ import { types } from '@pnpm/config.reader';
2
+ import { parsePropertyPath } from '@pnpm/object.property-path';
3
+ import kebabCase from 'lodash.kebabcase';
4
+ /**
5
+ * Just like {@link parsePropertyPath} but the first element may be converted into kebab-case
6
+ * if it's part of {@link types}.
7
+ */
8
+ export function* parseConfigPropertyPath(propertyPath) {
9
+ const iter = parsePropertyPath(propertyPath);
10
+ const first = iter.next();
11
+ if (first.done)
12
+ return;
13
+ yield normalizeTopLevelConfigName(first.value);
14
+ yield* iter;
15
+ }
16
+ /**
17
+ * Turn a top-level config name into kebab-case if it's part of {@link types}.
18
+ * Otherwise, return the string as-is.
19
+ */
20
+ function normalizeTopLevelConfigName(configName) {
21
+ if (typeof configName === 'number')
22
+ return configName.toString();
23
+ const kebabKey = kebabCase(configName);
24
+ if (Object.hasOwn(types, kebabKey))
25
+ return kebabKey;
26
+ return configName;
27
+ }
28
+ //# sourceMappingURL=parseConfigPropertyPath.js.map
@@ -0,0 +1,4 @@
1
+ export interface ProcessConfigOptions {
2
+ json?: boolean;
3
+ }
4
+ export declare function processConfig(rawConfig: Record<string, unknown>): Record<string, unknown>;
@@ -0,0 +1,16 @@
1
+ import { sortDirectKeys } from '@pnpm/object.key-sorting';
2
+ import camelcase from 'camelcase';
3
+ import { censorProtectedSettings } from './protectedSettings.js';
4
+ const shouldChangeCase = (key) => key[0] !== '@' && !key.startsWith('//');
5
+ function camelCaseConfig(rawConfig) {
6
+ const result = {};
7
+ for (const key in rawConfig) {
8
+ const targetKey = shouldChangeCase(key) ? camelcase(key) : key;
9
+ result[targetKey] = rawConfig[key];
10
+ }
11
+ return result;
12
+ }
13
+ export function processConfig(rawConfig) {
14
+ return camelCaseConfig(censorProtectedSettings(sortDirectKeys(rawConfig)));
15
+ }
16
+ //# sourceMappingURL=processConfig.js.map
@@ -0,0 +1,4 @@
1
+ /** Protected settings are settings which `npm config get` refuses to print. */
2
+ export declare const isSettingProtected: (key: string) => boolean;
3
+ /** Hide all protected settings by setting them to `(protected)`. */
4
+ export declare function censorProtectedSettings(config: Record<string, unknown>): Record<string, unknown>;
@@ -0,0 +1,21 @@
1
+ const PROTECTED_SUFFICES = [
2
+ '_auth',
3
+ '_authToken',
4
+ 'username',
5
+ '_password',
6
+ ];
7
+ /** Protected settings are settings which `npm config get` refuses to print. */
8
+ export const isSettingProtected = (key) => key.startsWith('//')
9
+ ? PROTECTED_SUFFICES.some(suffix => key.endsWith(`:${suffix}`))
10
+ : PROTECTED_SUFFICES.includes(key);
11
+ /** Hide all protected settings by setting them to `(protected)`. */
12
+ export function censorProtectedSettings(config) {
13
+ config = { ...config };
14
+ for (const key in config) {
15
+ if (isSettingProtected(key)) {
16
+ config[key] = '(protected)';
17
+ }
18
+ }
19
+ return config;
20
+ }
21
+ //# sourceMappingURL=protectedSettings.js.map
package/lib/set.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import * as configCmd from './config.js';
2
+ import type { ConfigCommandOptions } from './ConfigCommandOptions.js';
3
+ export declare const rcOptionsTypes: typeof configCmd.rcOptionsTypes;
4
+ export declare const cliOptionsTypes: typeof configCmd.cliOptionsTypes;
5
+ export declare const help: typeof configCmd.help;
6
+ export declare const commandNames: string[];
7
+ export declare function handler(opts: ConfigCommandOptions, params: string[]): Promise<configCmd.ConfigHandlerResult>;
package/lib/set.js ADDED
@@ -0,0 +1,9 @@
1
+ import * as configCmd from './config.js';
2
+ export const rcOptionsTypes = configCmd.rcOptionsTypes;
3
+ export const cliOptionsTypes = configCmd.cliOptionsTypes;
4
+ export const help = configCmd.help;
5
+ export const commandNames = ['set'];
6
+ export async function handler(opts, params) {
7
+ return configCmd.handler(opts, ['set', ...params]);
8
+ }
9
+ //# sourceMappingURL=set.js.map
@@ -0,0 +1 @@
1
+ export declare function settingShouldFallBackToNpm(key: string): boolean;
@@ -0,0 +1,9 @@
1
+ // NOTE: The logic may be duplicated with `isIniConfigKey` from `@pnpm/config.reader`,
2
+ // but we have not the time to refactor it right now.
3
+ // TODO: Refactor it when we have the time.
4
+ export function settingShouldFallBackToNpm(key) {
5
+ return (['registry', '_auth', '_authToken', 'username', '_password'].includes(key) ||
6
+ key[0] === '@' ||
7
+ key.startsWith('//'));
8
+ }
9
+ //# sourceMappingURL=settingShouldFallBackToNpm.js.map
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@pnpm/config.commands",
3
+ "version": "1000.2.10",
4
+ "description": "Commands for reading and writing settings to/from config files",
5
+ "keywords": [
6
+ "pnpm",
7
+ "pnpm11",
8
+ "config"
9
+ ],
10
+ "license": "MIT",
11
+ "funding": "https://opencollective.com/pnpm",
12
+ "repository": "https://github.com/pnpm/pnpm/tree/main/config/commands",
13
+ "homepage": "https://github.com/pnpm/pnpm/tree/main/config/commands#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/pnpm/pnpm/issues"
16
+ },
17
+ "type": "module",
18
+ "main": "lib/index.js",
19
+ "types": "lib/index.d.ts",
20
+ "exports": {
21
+ ".": "./lib/index.js"
22
+ },
23
+ "files": [
24
+ "lib",
25
+ "!*.map"
26
+ ],
27
+ "dependencies": {
28
+ "camelcase": "^9.0.0",
29
+ "ini": "6.0.0",
30
+ "lodash.kebabcase": "^4.1.1",
31
+ "read-ini-file": "5.0.0",
32
+ "render-help": "^2.0.0",
33
+ "write-ini-file": "5.0.0",
34
+ "write-yaml-file": "^6.0.0",
35
+ "@pnpm/cli.utils": "1001.2.8",
36
+ "@pnpm/config.reader": "1004.4.2",
37
+ "@pnpm/error": "1000.0.5",
38
+ "@pnpm/constants": "1001.3.1",
39
+ "@pnpm/exec.run-npm": "1000.0.0",
40
+ "@pnpm/object.key-sorting": "1000.0.1",
41
+ "@pnpm/object.property-path": "1000.0.1",
42
+ "@pnpm/text.naming-cases": "1100.0.0-0",
43
+ "@pnpm/workspace.workspace-manifest-writer": "1001.0.3"
44
+ },
45
+ "peerDependencies": {
46
+ "@pnpm/logger": ">=1001.0.0 <1002.0.0"
47
+ },
48
+ "devDependencies": {
49
+ "@jest/globals": "30.0.5",
50
+ "@types/ini": "1.3.31",
51
+ "@types/lodash.kebabcase": "4.1.9",
52
+ "read-yaml-file": "^3.0.0",
53
+ "@pnpm/config.commands": "1000.2.10",
54
+ "@pnpm/logger": "1001.0.1",
55
+ "@pnpm/prepare": "1000.0.4"
56
+ },
57
+ "engines": {
58
+ "node": ">=22.13"
59
+ },
60
+ "jest": {
61
+ "preset": "@pnpm/jest-config"
62
+ },
63
+ "scripts": {
64
+ "lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
65
+ "_test": "cross-env NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules --disable-warning=ExperimentalWarning --disable-warning=DEP0169\" jest",
66
+ "test": "pnpm run compile && pnpm run _test",
67
+ "compile": "tsgo --build && pnpm run lint --fix"
68
+ }
69
+ }