@pnpm/pkg-manifest.commands 1100.1.30 → 1100.1.32

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,22 @@
1
1
  # @pnpm/pkg-manifest.commands
2
2
 
3
+ ## 1100.1.32
4
+
5
+ ### Patch Changes
6
+
7
+ - `pnpm -r pkg get` now reports every selected project when several share a package name. Projects with the same name are keyed by their directory relative to the workspace root. Before, only one of them appeared in the output.
8
+
9
+ - Updated dependencies:
10
+ - @pnpm/cli.utils@1101.0.31
11
+ - @pnpm/config.reader@1102.3.3
12
+
13
+ ## 1100.1.31
14
+
15
+ ### Patch Changes
16
+
17
+ - Updated dependencies:
18
+ - @pnpm/config.reader@1102.3.2
19
+
3
20
  ## 1100.1.30
4
21
 
5
22
  ### Patch Changes
package/lib/pkg.js CHANGED
@@ -4,6 +4,7 @@ import { types as allTypes } from '@pnpm/config.reader';
4
4
  import { PnpmError } from '@pnpm/error';
5
5
  import { deleteObjectValueByPropertyPathString, getObjectValueByPropertyPathString, setObjectValueByPropertyPathString, } from '@pnpm/object.property-path';
6
6
  import { renderHelp } from 'render-help';
7
+ import { assignReportKeys } from './reportKeys.js';
7
8
  export const rcOptionsTypes = cliOptionsTypes;
8
9
  export function cliOptionsTypes() {
9
10
  const types = allTypes;
@@ -57,12 +58,18 @@ async function handleRecursiveCommand(opts, subcmd, args) {
57
58
  throw new PnpmError('PKG_RECURSIVE_NO_PACKAGES', 'No workspace packages were selected');
58
59
  }
59
60
  if (subcmd === 'get') {
60
- const entries = await Promise.all(selectedProjects.map(async ({ package: pkg }) => {
61
+ const projects = await Promise.all(selectedProjects.map(async ({ package: pkg }) => {
61
62
  const manifest = await readProjectManifestOnly(pkg.rootDir);
62
- const pkgName = String(manifest.name ?? path.relative(workspaceDir, pkg.rootDir));
63
- return [pkgName, selectFromManifest(manifest, args)];
63
+ return {
64
+ identity: {
65
+ name: manifest.name == null ? undefined : String(manifest.name),
66
+ dirKey: path.relative(workspaceDir, pkg.rootDir),
67
+ },
68
+ value: selectFromManifest(manifest, args),
69
+ };
64
70
  }));
65
- return JSON.stringify(Object.fromEntries(entries), undefined, 2);
71
+ const keys = assignReportKeys(projects.map(({ identity }) => identity));
72
+ return JSON.stringify(Object.fromEntries(projects.map(({ value }, index) => [keys[index], value])), undefined, 2);
66
73
  }
67
74
  await Promise.all(selectedProjects.map(({ package: pkg }) => runSubcommand({ ...opts, dir: pkg.rootDir }, subcmd, args)));
68
75
  }
@@ -129,77 +136,80 @@ async function pkgDelete(opts, args) {
129
136
  }
130
137
  async function pkgFix(opts) {
131
138
  const { manifest, writeProjectManifest } = await readProjectManifest(opts.dir);
132
- const m = manifest;
133
- if ('name' in m && typeof m.name !== 'string') {
134
- delete m.name;
139
+ const untypedManifest = manifest;
140
+ if ('name' in untypedManifest && typeof untypedManifest.name !== 'string') {
141
+ delete untypedManifest.name;
135
142
  }
136
- if ('version' in m && typeof m.version !== 'string') {
137
- delete m.version;
143
+ if ('version' in untypedManifest && typeof untypedManifest.version !== 'string') {
144
+ delete untypedManifest.version;
138
145
  }
139
146
  for (const field of ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies', 'scripts']) {
140
- if (field in m && !isPlainObject(m[field])) {
141
- delete m[field];
147
+ if (field in untypedManifest && !isPlainObject(untypedManifest[field])) {
148
+ delete untypedManifest[field];
142
149
  }
143
150
  }
144
- if ('bin' in m && typeof m.bin !== 'string' && !isPlainObject(m.bin)) {
145
- delete m.bin;
151
+ if ('bin' in untypedManifest && typeof untypedManifest.bin !== 'string' && !isPlainObject(untypedManifest.bin)) {
152
+ delete untypedManifest.bin;
146
153
  }
147
154
  await writeProjectManifest(manifest);
148
155
  }
149
156
  function isPlainObject(value) {
150
157
  return typeof value === 'object' && value !== null && !Array.isArray(value);
151
158
  }
159
+ const COMMANDS = {
160
+ title: 'Commands',
161
+ list: [
162
+ {
163
+ description: 'Retrieves a value from package.json',
164
+ name: 'get [<key> [<key> ...]]',
165
+ },
166
+ {
167
+ description: 'Sets a value in package.json',
168
+ name: 'set <key>=<value> [<key>=<value> ...]',
169
+ },
170
+ {
171
+ description: 'Deletes a key from package.json',
172
+ name: 'delete <key> [<key> ...]',
173
+ },
174
+ {
175
+ description: 'Auto corrects common errors in package.json',
176
+ name: 'fix',
177
+ },
178
+ ],
179
+ };
180
+ const OPTIONS = {
181
+ title: 'Options',
182
+ list: [
183
+ {
184
+ description: 'When setting, parse the value as JSON. When getting a single key, return its JSON-encoded form instead of the raw value',
185
+ name: '--json',
186
+ },
187
+ {
188
+ description: 'Run on every workspace project or every project selected by a filter',
189
+ name: '--recursive',
190
+ shortAlias: '-r',
191
+ },
192
+ ],
193
+ };
194
+ const USAGES = [
195
+ 'pnpm pkg get [<key> [<key> ...]]',
196
+ 'pnpm pkg set <key>=<value> [<key>=<value> ...]',
197
+ 'pnpm pkg delete <key> [<key> ...]',
198
+ 'pnpm pkg fix',
199
+ 'pnpm pkg set <key>=<value> --json',
200
+ 'pnpm -r pkg get name',
201
+ 'pnpm --filter <selector> pkg get name',
202
+ 'pnpm -r pkg set version=1.0.0',
203
+ ];
152
204
  export function help() {
153
205
  return renderHelp({
154
206
  description: 'Manages your package.json',
155
207
  descriptionLists: [
156
- {
157
- title: 'Commands',
158
- list: [
159
- {
160
- description: 'Retrieves a value from package.json',
161
- name: 'get [<key> [<key> ...]]',
162
- },
163
- {
164
- description: 'Sets a value in package.json',
165
- name: 'set <key>=<value> [<key>=<value> ...]',
166
- },
167
- {
168
- description: 'Deletes a key from package.json',
169
- name: 'delete <key> [<key> ...]',
170
- },
171
- {
172
- description: 'Auto corrects common errors in package.json',
173
- name: 'fix',
174
- },
175
- ],
176
- },
177
- {
178
- title: 'Options',
179
- list: [
180
- {
181
- description: 'When setting, parse the value as JSON. When getting a single key, return its JSON-encoded form instead of the raw value',
182
- name: '--json',
183
- },
184
- {
185
- description: 'Run on every workspace project or every project selected by a filter',
186
- name: '--recursive',
187
- shortAlias: '-r',
188
- },
189
- ],
190
- },
208
+ COMMANDS,
209
+ OPTIONS,
191
210
  ],
192
211
  url: docsUrl('pkg'),
193
- usages: [
194
- 'pnpm pkg get [<key> [<key> ...]]',
195
- 'pnpm pkg set <key>=<value> [<key>=<value> ...]',
196
- 'pnpm pkg delete <key> [<key> ...]',
197
- 'pnpm pkg fix',
198
- 'pnpm pkg set <key>=<value> --json',
199
- 'pnpm -r pkg get name',
200
- 'pnpm --filter <selector> pkg get name',
201
- 'pnpm -r pkg set version=1.0.0',
202
- ],
212
+ usages: USAGES,
203
213
  });
204
214
  }
205
215
  //# sourceMappingURL=pkg.js.map
@@ -0,0 +1,17 @@
1
+ export interface ReportIdentity {
2
+ /** The manifest's `name`, when it declares one. */
3
+ name?: string;
4
+ /** The project's directory, relative to the workspace root. */
5
+ dirKey: string;
6
+ }
7
+ /**
8
+ * Chooses a distinct `pnpm -r pkg get` report key for every project, in input order.
9
+ *
10
+ * A project is keyed by its name unless that would hide another project:
11
+ * a project without a name, every project that shares its name with
12
+ * another selected project, and a project whose name equals the directory
13
+ * key another project is reported under are keyed by their directory instead. Directories
14
+ * are distinct, so the keys are too, and a workspace whose names are unique
15
+ * keeps its name keys.
16
+ */
17
+ export declare function assignReportKeys(identities: ReportIdentity[]): string[];
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Chooses a distinct `pnpm -r pkg get` report key for every project, in input order.
3
+ *
4
+ * A project is keyed by its name unless that would hide another project:
5
+ * a project without a name, every project that shares its name with
6
+ * another selected project, and a project whose name equals the directory
7
+ * key another project is reported under are keyed by their directory instead. Directories
8
+ * are distinct, so the keys are too, and a workspace whose names are unique
9
+ * keeps its name keys.
10
+ */
11
+ export function assignReportKeys(identities) {
12
+ const keyedByDir = initiallyKeyedByDir(identities);
13
+ moveNamesShadowedByDirs(identities, keyedByDir);
14
+ return identities.map((identity, index) => identity.name == null || keyedByDir[index] ? identity.dirKey : identity.name);
15
+ }
16
+ function initiallyKeyedByDir(identities) {
17
+ const nameCounts = new Map();
18
+ for (const { name } of identities) {
19
+ if (name != null)
20
+ nameCounts.set(name, (nameCounts.get(name) ?? 0) + 1);
21
+ }
22
+ return identities.map(({ name }) => name == null || nameCounts.get(name) > 1);
23
+ }
24
+ /**
25
+ * Moves every name-keyed project whose name equals a directory key in use
26
+ * to its own directory key. A moved project's directory key can in turn
27
+ * shadow another name, so each move is followed up the same way.
28
+ */
29
+ function moveNamesShadowedByDirs(identities, keyedByDir) {
30
+ const nameKeyed = new Map();
31
+ for (const [index, { name }] of identities.entries()) {
32
+ if (name != null && !keyedByDir[index])
33
+ nameKeyed.set(name, index);
34
+ }
35
+ const pending = identities.flatMap((_, index) => keyedByDir[index] ? [index] : []);
36
+ for (let index = pending.pop(); index !== undefined; index = pending.pop()) {
37
+ const shadowed = nameKeyed.get(identities[index].dirKey);
38
+ if (shadowed !== undefined && !keyedByDir[shadowed]) {
39
+ keyedByDir[shadowed] = true;
40
+ pending.push(shadowed);
41
+ }
42
+ }
43
+ }
44
+ //# sourceMappingURL=reportKeys.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/pkg-manifest.commands",
3
- "version": "1100.1.30",
3
+ "version": "1100.1.32",
4
4
  "description": "Commands for managing package.json",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -28,8 +28,8 @@
28
28
  "!*.map"
29
29
  ],
30
30
  "dependencies": {
31
- "@pnpm/cli.utils": "1101.0.30",
32
- "@pnpm/config.reader": "1102.3.1",
31
+ "@pnpm/cli.utils": "1101.0.31",
32
+ "@pnpm/config.reader": "1102.3.3",
33
33
  "@pnpm/error": "1100.2.1",
34
34
  "@pnpm/object.property-path": "1100.1.8",
35
35
  "@pnpm/types": "1102.1.1",
@@ -37,8 +37,8 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@jest/globals": "30.4.1",
40
- "@pnpm/pkg-manifest.commands": "1100.1.30",
41
- "@pnpm/prepare": "1100.0.33"
40
+ "@pnpm/pkg-manifest.commands": "1100.1.32",
41
+ "@pnpm/prepare": "1100.0.35"
42
42
  },
43
43
  "engines": {
44
44
  "node": ">=22.13"