@pnpm/releasing.exportable-manifest 1100.3.1 → 1100.3.3

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,29 @@
1
1
  # @pnpm/exportable-manifest
2
2
 
3
+ ## 1100.3.3
4
+
5
+ ### Patch Changes
6
+
7
+ - The `publish` command now resolves `workspace:` dependencies from workspace manifests when `node_modules` is not installed. Previously, publishing without `node_modules` failed with `ERR_PNPM_CANNOT_RESOLVE_WORKSPACE_PROTOCOL`. pnpm/pnpm#6567
8
+
9
+ - `make-dedicated-lockfile` no longer removes fields such as `main` and `types` from the `publishConfig` of the project's `package.json`.
10
+
11
+ - `pnpm publish` and `pnpm pack` now report a missing `version` or `name` field on a workspace dependency. Previously, pnpm reported that the dependency was not installed [#4164](https://github.com/pnpm/pnpm/issues/4164).
12
+
13
+ - Updated dependencies:
14
+ - @pnpm/bins.resolver@1100.0.17
15
+ - @pnpm/error@1100.2.0
16
+ - @pnpm/resolving.jsr-specifier-parser@1100.0.8
17
+ - @pnpm/types@1102.1.1
18
+ - @pnpm/workspace.project-manifest-reader@1100.1.0
19
+
20
+ ## 1100.3.2
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies:
25
+ - @pnpm/workspace.project-manifest-reader@1100.0.29
26
+
3
27
  ## 1100.3.1
4
28
 
5
29
  ### Patch Changes
package/lib/index.d.ts CHANGED
@@ -3,12 +3,17 @@ import type { Hooks } from '@pnpm/hooks.pnpmfile';
3
3
  import type { ProjectManifest } from '@pnpm/types';
4
4
  import { type ExportedManifest } from './transform/index.js';
5
5
  export { type ExportedManifest };
6
+ export type WorkspacePackageLookup = Array<{
7
+ manifest: ProjectManifest;
8
+ rootDir?: string;
9
+ }> | Map<string, unknown> | Record<string, unknown> | ((depName: string) => ProjectManifest | undefined);
6
10
  export interface MakePublishManifestOptions {
7
11
  catalogs: Catalogs;
8
12
  hooks?: Hooks;
9
13
  modulesDir?: string;
10
14
  skipManifestObfuscation?: boolean;
11
15
  embedReadme?: boolean;
16
+ workspacePackages?: WorkspacePackageLookup;
12
17
  }
13
18
  export declare function createExportableManifest(dir: string, originalManifest: ProjectManifest, opts: MakePublishManifestOptions): Promise<ExportedManifest>;
14
19
  export declare function readReadmeFile(projectDir: string): Promise<string | undefined>;
@@ -16,8 +21,10 @@ export type PublishDependencyConverter = (depName: string, depSpec: string, cont
16
21
  export interface PublishDependencyConverterContext {
17
22
  dir: string;
18
23
  modulesDir?: string;
24
+ workspacePackages?: (depName: string) => ProjectManifest | undefined;
19
25
  }
20
26
  export interface MakePublishDependenciesOpts {
21
27
  readonly modulesDir?: string;
22
28
  readonly convertDependencyForPublish: PublishDependencyConverter;
29
+ readonly workspacePackages?: (depName: string) => ProjectManifest | undefined;
23
30
  }
package/lib/index.js CHANGED
@@ -31,11 +31,13 @@ export async function createExportableManifest(dir, originalManifest, opts) {
31
31
  }
32
32
  const catalogResolver = resolveFromCatalog.bind(null, opts.catalogs);
33
33
  const replaceCatalogProtocol = resolveCatalogProtocol.bind(null, catalogResolver);
34
+ const getWorkspaceManifest = buildWorkspaceManifestGetter(opts.workspacePackages);
34
35
  const convertDependencyForPublish = combineConverters(replaceCatalogProtocol, replaceWorkspaceProtocol, replaceJsrProtocol);
35
36
  await Promise.all(['dependencies', 'devDependencies', 'optionalDependencies'].map(async (depsField) => {
36
37
  const deps = await makePublishDependencies(dir, originalManifest[depsField], {
37
38
  modulesDir: opts?.modulesDir,
38
39
  convertDependencyForPublish,
40
+ workspacePackages: getWorkspaceManifest,
39
41
  });
40
42
  if (deps != null) {
41
43
  publishManifest[depsField] = deps;
@@ -47,6 +49,7 @@ export async function createExportableManifest(dir, originalManifest, opts) {
47
49
  publishManifest.peerDependencies = await makePublishDependencies(dir, peerDependencies, {
48
50
  modulesDir: opts?.modulesDir,
49
51
  convertDependencyForPublish: convertPeersForPublish,
52
+ workspacePackages: getWorkspaceManifest,
50
53
  });
51
54
  }
52
55
  overridePublishConfig(publishManifest);
@@ -99,19 +102,91 @@ function combineConverters(...converters) {
99
102
  return bareSpecifier;
100
103
  };
101
104
  }
102
- async function makePublishDependencies(dir, dependencies, { modulesDir, convertDependencyForPublish }) {
105
+ async function makePublishDependencies(dir, dependencies, { modulesDir, convertDependencyForPublish, workspacePackages }) {
103
106
  if (dependencies == null)
104
107
  return dependencies;
105
- const publishDependencies = await Promise.all(Object.entries(dependencies).map(async ([depName, depSpec]) => [depName, await convertDependencyForPublish(depName, depSpec, { dir, modulesDir })]));
108
+ const publishDependencies = await Promise.all(Object.entries(dependencies).map(async ([depName, depSpec]) => [depName, await convertDependencyForPublish(depName, depSpec, { dir, modulesDir, workspacePackages })]));
106
109
  return Object.fromEntries(publishDependencies);
107
110
  }
108
- async function readAndCheckManifest(depName, dependencyDir) {
109
- const { manifest } = await tryReadProjectManifest(dependencyDir);
110
- if (!manifest?.name || !manifest?.version) {
111
+ function extractManifest(val) {
112
+ if (!val || typeof val !== 'object')
113
+ return undefined;
114
+ if ('manifest' in val && val.manifest && typeof val.manifest === 'object') {
115
+ return val.manifest;
116
+ }
117
+ if ('package' in val && val.package && typeof val.package === 'object' && 'manifest' in val.package && val.package.manifest && typeof val.package.manifest === 'object') {
118
+ return val.package.manifest;
119
+ }
120
+ if ('name' in val && typeof val.name === 'string') {
121
+ return val;
122
+ }
123
+ return undefined;
124
+ }
125
+ function buildWorkspaceManifestGetter(workspacePackages) {
126
+ if (!workspacePackages)
127
+ return undefined;
128
+ if (typeof workspacePackages === 'function') {
129
+ return workspacePackages;
130
+ }
131
+ const byName = new Map();
132
+ const addManifest = (val) => {
133
+ const manifest = extractManifest(val);
134
+ if (!manifest?.name)
135
+ return;
136
+ const existing = byName.get(manifest.name);
137
+ if (!existing || (!existing.version && manifest.version)) {
138
+ byName.set(manifest.name, manifest);
139
+ }
140
+ };
141
+ if (Array.isArray(workspacePackages)) {
142
+ for (const pkg of workspacePackages) {
143
+ addManifest(pkg);
144
+ }
145
+ }
146
+ else if (workspacePackages instanceof Map) {
147
+ for (const val of workspacePackages.values()) {
148
+ if (val instanceof Map) {
149
+ for (const subVal of val.values()) {
150
+ addManifest(subVal);
151
+ }
152
+ }
153
+ else {
154
+ addManifest(val);
155
+ }
156
+ }
157
+ }
158
+ else if (typeof workspacePackages === 'object') {
159
+ for (const val of Object.values(workspacePackages)) {
160
+ addManifest(val);
161
+ }
162
+ }
163
+ return (depName) => byName.get(depName);
164
+ }
165
+ async function readAndCheckManifest(depName, dependencyDir, getWorkspaceManifest, targetPkgName) {
166
+ const { manifest: dirManifest } = await tryReadProjectManifest(dependencyDir);
167
+ if (dirManifest?.name && dirManifest?.version) {
168
+ return dirManifest;
169
+ }
170
+ const lookupName = targetPkgName ?? depName;
171
+ const workspaceManifest = getWorkspaceManifest?.(lookupName);
172
+ if (workspaceManifest?.name && workspaceManifest?.version) {
173
+ return workspaceManifest;
174
+ }
175
+ const found = dirManifest?.name || dirManifest?.version
176
+ ? dirManifest
177
+ : workspaceManifest?.name || workspaceManifest?.version
178
+ ? workspaceManifest
179
+ : dirManifest ?? workspaceManifest;
180
+ if (found?.name && !found.version) {
181
+ throw new PnpmError('CANNOT_RESOLVE_WORKSPACE_PROTOCOL', `Cannot resolve workspace protocol of dependency "${depName}" ` +
182
+ 'because its package.json has no "version" field.', { hint: `Add a "version" field to the package.json of "${found.name}".` });
183
+ }
184
+ if (found) {
111
185
  throw new PnpmError('CANNOT_RESOLVE_WORKSPACE_PROTOCOL', `Cannot resolve workspace protocol of dependency "${depName}" ` +
112
- 'because this dependency is not installed. Try running "pnpm install".');
186
+ 'because its package.json has no "name" field.');
113
187
  }
114
- return manifest;
188
+ throw new PnpmError('CANNOT_RESOLVE_WORKSPACE_PROTOCOL', `Cannot resolve workspace protocol of dependency "${depName}" ` +
189
+ 'because this dependency is not installed. Try running "pnpm install".');
115
190
  }
116
191
  function resolveCatalogProtocol(catalogResolver, alias, bareSpecifier) {
117
192
  const result = catalogResolver({ alias, bareSpecifier });
@@ -121,7 +196,7 @@ function resolveCatalogProtocol(catalogResolver, alias, bareSpecifier) {
121
196
  case 'misconfiguration': throw result.error;
122
197
  }
123
198
  }
124
- async function replaceWorkspaceProtocol(depName, depSpec, { dir, modulesDir }) {
199
+ async function replaceWorkspaceProtocol(depName, depSpec, { dir, modulesDir, workspacePackages }) {
125
200
  if (!depSpec.startsWith('workspace:')) {
126
201
  return depSpec;
127
202
  }
@@ -129,7 +204,8 @@ async function replaceWorkspaceProtocol(depName, depSpec, { dir, modulesDir }) {
129
204
  const versionAliasSpecParts = /^workspace:(?:(.+)@)?([\^~*])?$/.exec(depSpec);
130
205
  if (versionAliasSpecParts != null) {
131
206
  modulesDir = modulesDir ?? path.join(dir, 'node_modules');
132
- const manifest = await readAndCheckManifest(depName, path.join(modulesDir, depName));
207
+ const targetPkgName = versionAliasSpecParts[1];
208
+ const manifest = await readAndCheckManifest(depName, path.join(modulesDir, depName), workspacePackages, targetPkgName);
133
209
  const specifierSuffix = versionAliasSpecParts[2];
134
210
  const semverRangeToken = specifierSuffix === '^' || specifierSuffix === '~' ? specifierSuffix : '';
135
211
  if (depName !== manifest.name) {
@@ -138,7 +214,7 @@ async function replaceWorkspaceProtocol(depName, depSpec, { dir, modulesDir }) {
138
214
  return `${semverRangeToken}${manifest.version}`;
139
215
  }
140
216
  if (depSpec.startsWith('workspace:./') || depSpec.startsWith('workspace:../')) {
141
- const manifest = await readAndCheckManifest(depName, path.join(dir, depSpec.slice(10)));
217
+ const manifest = await readAndCheckManifest(depName, path.join(dir, depSpec.slice(10)), workspacePackages);
142
218
  if (manifest.name === depName)
143
219
  return `${manifest.version}`;
144
220
  return `npm:${manifest.name}@${manifest.version}`;
@@ -149,7 +225,7 @@ async function replaceWorkspaceProtocol(depName, depSpec, { dir, modulesDir }) {
149
225
  }
150
226
  return depSpec;
151
227
  }
152
- async function replaceWorkspaceProtocolPeerDependency(depName, depSpec, { dir, modulesDir }) {
228
+ async function replaceWorkspaceProtocolPeerDependency(depName, depSpec, { dir, modulesDir, workspacePackages }) {
153
229
  if (!depSpec.includes('workspace:')) {
154
230
  return depSpec;
155
231
  }
@@ -161,7 +237,7 @@ async function replaceWorkspaceProtocolPeerDependency(depName, depSpec, { dir, m
161
237
  return `npm:${workspaceSpec.alias}@${version}`;
162
238
  }
163
239
  if (workspaceSpec?.version.startsWith('./') || workspaceSpec?.version.startsWith('../')) {
164
- return replaceWorkspaceProtocol(depName, depSpec, { dir, modulesDir });
240
+ return replaceWorkspaceProtocol(depName, depSpec, { dir, modulesDir, workspacePackages });
165
241
  }
166
242
  // Dependencies with bare "*", "^", "~",">=",">","<=", "<", version
167
243
  const workspaceSemverRegex = /workspace:([\^~*]|>=|>|<=|<)?((\d+|[xX*])(\.(\d+|[xX*])){0,2})?/;
@@ -172,7 +248,7 @@ async function replaceWorkspaceProtocolPeerDependency(depName, depSpec, { dir, m
172
248
  return depSpec.replace('workspace:', '');
173
249
  }
174
250
  modulesDir = modulesDir ?? path.join(dir, 'node_modules');
175
- const manifest = await readAndCheckManifest(depName, path.join(modulesDir, depName));
251
+ const manifest = await readAndCheckManifest(depName, path.join(modulesDir, depName), workspacePackages);
176
252
  const semverRangeToken = semverRangGroup !== '*' ? semverRangGroup : '';
177
253
  return depSpec.replace(workspaceSemverRegex, `${semverRangeToken}${manifest.version}`);
178
254
  }
@@ -30,9 +30,9 @@ const PUBLISH_CONFIG_WHITELIST = new Set([
30
30
  'typesVersions',
31
31
  ]);
32
32
  export function overridePublishConfig(publishManifest) {
33
- const { publishConfig } = publishManifest;
34
- if (!publishConfig)
33
+ if (!publishManifest.publishConfig)
35
34
  return;
35
+ const publishConfig = { ...publishManifest.publishConfig };
36
36
  for (const key in publishConfig) {
37
37
  if (!PUBLISH_CONFIG_WHITELIST.has(key))
38
38
  continue;
@@ -43,5 +43,8 @@ export function overridePublishConfig(publishManifest) {
43
43
  if (isEmpty(publishConfig)) {
44
44
  delete publishManifest.publishConfig;
45
45
  }
46
+ else {
47
+ publishManifest.publishConfig = publishConfig;
48
+ }
46
49
  }
47
50
  //# sourceMappingURL=overridePublishConfig.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/releasing.exportable-manifest",
3
- "version": "1100.3.1",
3
+ "version": "1100.3.3",
4
4
  "description": "Creates an exportable manifest",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -28,22 +28,22 @@
28
28
  ],
29
29
  "dependencies": {
30
30
  "@npm/types": "^2.1.0",
31
- "@pnpm/bins.resolver": "1100.0.16",
31
+ "@pnpm/bins.resolver": "1100.0.17",
32
32
  "@pnpm/catalogs.resolver": "1100.1.0",
33
- "@pnpm/error": "1100.1.4",
34
- "@pnpm/resolving.jsr-specifier-parser": "1100.0.7",
35
- "@pnpm/types": "1102.1.0",
36
- "@pnpm/workspace.project-manifest-reader": "1100.0.28",
33
+ "@pnpm/error": "1100.2.0",
34
+ "@pnpm/resolving.jsr-specifier-parser": "1100.0.8",
35
+ "@pnpm/types": "1102.1.1",
36
+ "@pnpm/workspace.project-manifest-reader": "1100.1.0",
37
37
  "@pnpm/workspace.spec-parser": "1100.0.1",
38
38
  "ramda": "npm:@pnpm/ramda@0.28.1"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@jest/globals": "30.4.1",
42
- "@pnpm/catalogs.config": "1100.0.7",
42
+ "@pnpm/catalogs.config": "1100.0.8",
43
43
  "@pnpm/catalogs.types": "1100.0.1",
44
- "@pnpm/hooks.pnpmfile": "1100.0.31",
45
- "@pnpm/prepare": "1100.0.30",
46
- "@pnpm/releasing.exportable-manifest": "1100.3.1",
44
+ "@pnpm/hooks.pnpmfile": "1100.0.33",
45
+ "@pnpm/prepare": "1100.0.32",
46
+ "@pnpm/releasing.exportable-manifest": "1100.3.3",
47
47
  "@types/cross-spawn": "^6.0.6",
48
48
  "@types/ramda": "0.32.0",
49
49
  "cross-spawn": "^7.0.6",