@pnpm/releasing.commands 1100.4.4 → 1100.5.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/lib/deploy/createDeployFiles.d.ts +1 -1
- package/lib/publish/batchPublish.d.ts +20 -0
- package/lib/publish/batchPublish.js +201 -0
- package/lib/publish/extractManifestFromPacked.d.ts +1 -1
- package/lib/publish/oidc/authToken.d.ts +1 -1
- package/lib/publish/oidc/idToken.d.ts +1 -1
- package/lib/publish/oidc/provenance.d.ts +1 -1
- package/lib/publish/otp.d.ts +1 -1
- package/lib/publish/publish.js +10 -0
- package/lib/publish/publishPackedPkg.d.ts +26 -3
- package/lib/publish/publishPackedPkg.js +35 -34
- package/lib/publish/recursivePublish.d.ts +1 -0
- package/lib/publish/recursivePublish.js +49 -39
- package/lib/stage/context.js +1 -1
- package/lib/stage/types.d.ts +1 -1
- package/lib/tarball/publishSummary.d.ts +8 -0
- package/lib/tarball/publishSummary.js +20 -0
- package/package.json +40 -39
|
@@ -20,4 +20,4 @@ export interface DeployFiles {
|
|
|
20
20
|
manifest: ProjectManifest;
|
|
21
21
|
workspaceManifest?: DeployWorkspaceManifest;
|
|
22
22
|
}
|
|
23
|
-
export declare function createDeployFiles({ allProjects, deployDir, lockfile, lockfileDir, patchedDependencies, selectedProjectManifest, projectId, rootProjectManifestDir, allowBuilds }: CreateDeployFilesOptions): DeployFiles;
|
|
23
|
+
export declare function createDeployFiles({ allProjects, deployDir, lockfile, lockfileDir, patchedDependencies, selectedProjectManifest, projectId, rootProjectManifestDir, allowBuilds, }: CreateDeployFilesOptions): DeployFiles;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Config, ConfigContext } from '@pnpm/config.reader';
|
|
2
|
+
import type { Project } from '@pnpm/types';
|
|
3
|
+
import { type PublishSummary } from '../tarball/publishSummary.js';
|
|
4
|
+
import type { PublishRecursiveOpts } from './recursivePublish.js';
|
|
5
|
+
export declare const BATCH_PUBLISH_ENDPOINT = "/-/pnpm/v1/publish";
|
|
6
|
+
export type BatchPublishOptions = PublishRecursiveOpts & Pick<Config, 'embedReadme' | 'ignoreScripts' | 'nodeLinker' | 'packGzipLevel' | 'skipManifestObfuscation'> & Partial<Pick<ConfigContext, 'hooks'>>;
|
|
7
|
+
/**
|
|
8
|
+
* Publish all {@link pkgs} by sending a single `PUT /-/pnpm/v1/publish` request per target
|
|
9
|
+
* registry, instead of one request per package. The endpoint is not part of the standard npm
|
|
10
|
+
* registry API — the registry has to implement it explicitly (pnpr does), so this whole code
|
|
11
|
+
* path is opt-in via the `--batch` flag.
|
|
12
|
+
*
|
|
13
|
+
* Every package is packed (and its `prepublishOnly`/`prepublish` scripts run) before anything
|
|
14
|
+
* is sent, so a package that fails to pack aborts the publish before any package reaches the
|
|
15
|
+
* registry. The `publish`/`postpublish` scripts run only after the requests succeeded.
|
|
16
|
+
*
|
|
17
|
+
* @param pkgs packages to publish, already filtered (no private packages, no already-published
|
|
18
|
+
* versions) and in dependency order.
|
|
19
|
+
*/
|
|
20
|
+
export declare function batchPublishPackages(pkgs: Project[], opts: BatchPublishOptions): Promise<PublishSummary[]>;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { PnpmError } from '@pnpm/error';
|
|
5
|
+
import { globalInfo, globalWarn } from '@pnpm/logger';
|
|
6
|
+
import { withOtpHandling } from '@pnpm/network.web-auth';
|
|
7
|
+
import { rimraf } from '@zkochan/rimraf';
|
|
8
|
+
import npmFetch from 'npm-registry-fetch';
|
|
9
|
+
import { realpathMissing } from 'realpath-missing';
|
|
10
|
+
import semver from 'semver';
|
|
11
|
+
import { temporaryDirectory } from 'tempy';
|
|
12
|
+
import { createPublishSummary } from '../tarball/publishSummary.js';
|
|
13
|
+
import * as pack from './pack.js';
|
|
14
|
+
import { runScriptsIfPresent } from './publish.js';
|
|
15
|
+
import { createPublishContext, createPublishOptions, findRegistryInfo, isPublishAccess, } from './publishPackedPkg.js';
|
|
16
|
+
export const BATCH_PUBLISH_ENDPOINT = '/-/pnpm/v1/publish';
|
|
17
|
+
/**
|
|
18
|
+
* Publish all {@link pkgs} by sending a single `PUT /-/pnpm/v1/publish` request per target
|
|
19
|
+
* registry, instead of one request per package. The endpoint is not part of the standard npm
|
|
20
|
+
* registry API — the registry has to implement it explicitly (pnpr does), so this whole code
|
|
21
|
+
* path is opt-in via the `--batch` flag.
|
|
22
|
+
*
|
|
23
|
+
* Every package is packed (and its `prepublishOnly`/`prepublish` scripts run) before anything
|
|
24
|
+
* is sent, so a package that fails to pack aborts the publish before any package reaches the
|
|
25
|
+
* registry. The `publish`/`postpublish` scripts run only after the requests succeeded.
|
|
26
|
+
*
|
|
27
|
+
* @param pkgs packages to publish, already filtered (no private packages, no already-published
|
|
28
|
+
* versions) and in dependency order.
|
|
29
|
+
*/
|
|
30
|
+
export async function batchPublishPackages(pkgs, opts) {
|
|
31
|
+
if (opts.stage) {
|
|
32
|
+
throw new PnpmError('BATCH_PUBLISH_NO_STAGE', 'Staged publishing cannot be combined with --batch');
|
|
33
|
+
}
|
|
34
|
+
if (opts.provenance) {
|
|
35
|
+
throw new PnpmError('BATCH_PUBLISH_NO_PROVENANCE', 'Provenance statements cannot be generated when publishing with --batch', {
|
|
36
|
+
hint: 'Provenance is bound to a single package, but --batch sends many packages in one request. Publish without --batch to attach provenance.',
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const packedByRegistry = new Map();
|
|
40
|
+
const packedPkgs = [];
|
|
41
|
+
for (const project of pkgs) {
|
|
42
|
+
// eslint-disable-next-line no-await-in-loop
|
|
43
|
+
const packedPkg = await packPkgForBatch(project, opts);
|
|
44
|
+
const publishConfigRegistry = typeof packedPkg.publishedManifest.publishConfig?.registry === 'string'
|
|
45
|
+
? packedPkg.publishedManifest.publishConfig.registry
|
|
46
|
+
: undefined;
|
|
47
|
+
const { registry } = findRegistryInfo(packedPkg.publishedManifest, opts, publishConfigRegistry);
|
|
48
|
+
let group = packedByRegistry.get(registry);
|
|
49
|
+
if (!group) {
|
|
50
|
+
group = [];
|
|
51
|
+
packedByRegistry.set(registry, group);
|
|
52
|
+
}
|
|
53
|
+
group.push(packedPkg);
|
|
54
|
+
packedPkgs.push(packedPkg);
|
|
55
|
+
}
|
|
56
|
+
for (const [registry, group] of packedByRegistry.entries()) {
|
|
57
|
+
for (const { summary } of group) {
|
|
58
|
+
globalInfo(`📦 ${summary.id} → ${registry}`);
|
|
59
|
+
}
|
|
60
|
+
if (opts.dryRun) {
|
|
61
|
+
globalWarn(`Skip publishing ${group.length} package(s) to ${registry} (dry run)`);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
// eslint-disable-next-line no-await-in-loop
|
|
65
|
+
await multiPublishToRegistry(registry, group, opts);
|
|
66
|
+
globalInfo(`✅ Published ${group.length} package(s) to ${registry} in a single request`);
|
|
67
|
+
}
|
|
68
|
+
if (!opts.ignoreScripts) {
|
|
69
|
+
for (const { project } of packedPkgs) {
|
|
70
|
+
// eslint-disable-next-line no-await-in-loop
|
|
71
|
+
await runScriptsIfPresent(await lifecycleOpts(project.rootDir, opts), ['publish', 'postpublish'], project.manifest);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return packedPkgs.map(({ summary }) => summary);
|
|
75
|
+
}
|
|
76
|
+
async function packPkgForBatch(project, opts) {
|
|
77
|
+
if (!opts.ignoreScripts) {
|
|
78
|
+
await runScriptsIfPresent(await lifecycleOpts(project.rootDir, opts), ['prepublishOnly', 'prepublish'], project.manifest);
|
|
79
|
+
}
|
|
80
|
+
// The tarball is packed into a temporary directory and read into memory right away — the
|
|
81
|
+
// request body carries it base64-encoded, so nothing needs to stay on disk.
|
|
82
|
+
const packDestination = temporaryDirectory();
|
|
83
|
+
try {
|
|
84
|
+
const packResult = await pack.api({
|
|
85
|
+
...opts,
|
|
86
|
+
dir: project.rootDir,
|
|
87
|
+
packDestination,
|
|
88
|
+
dryRun: false,
|
|
89
|
+
});
|
|
90
|
+
const tarballData = await fs.readFile(packResult.tarballPath);
|
|
91
|
+
return {
|
|
92
|
+
project,
|
|
93
|
+
publishedManifest: packResult.publishedManifest,
|
|
94
|
+
tarballData,
|
|
95
|
+
summary: createPublishSummary(packResult, tarballData),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
await rimraf(packDestination);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async function lifecycleOpts(pkgRoot, opts) {
|
|
103
|
+
return {
|
|
104
|
+
depPath: pkgRoot,
|
|
105
|
+
extraBinPaths: opts.extraBinPaths,
|
|
106
|
+
extraEnv: opts.extraEnv,
|
|
107
|
+
pkgRoot,
|
|
108
|
+
rootModulesDir: await realpathMissing(path.join(pkgRoot, 'node_modules')),
|
|
109
|
+
stdio: 'inherit',
|
|
110
|
+
unsafePerm: true, // when running scripts explicitly, assume that they're trusted.
|
|
111
|
+
userAgent: opts.userAgent,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
async function multiPublishToRegistry(registry, group, opts) {
|
|
115
|
+
// A package-scoped OIDC token cannot authorize a request that publishes many packages, so the
|
|
116
|
+
// OIDC exchange is skipped and only statically configured credentials are used.
|
|
117
|
+
const publishOptions = await createPublishOptions(group[0].publishedManifest, opts, { oidc: false });
|
|
118
|
+
const body = {
|
|
119
|
+
packages: group.map((packedPkg) => createPublishDocument(packedPkg, registry, opts)),
|
|
120
|
+
};
|
|
121
|
+
const fetchOptions = {
|
|
122
|
+
method: 'GET',
|
|
123
|
+
retry: {
|
|
124
|
+
factor: opts.fetchRetryFactor,
|
|
125
|
+
maxTimeout: opts.fetchRetryMaxtimeout,
|
|
126
|
+
minTimeout: opts.fetchRetryMintimeout,
|
|
127
|
+
retries: opts.fetchRetries,
|
|
128
|
+
},
|
|
129
|
+
timeout: opts.fetchTimeout,
|
|
130
|
+
};
|
|
131
|
+
try {
|
|
132
|
+
await withOtpHandling({
|
|
133
|
+
context: createPublishContext(opts),
|
|
134
|
+
fetchOptions,
|
|
135
|
+
operation: async (otp) => npmFetch(BATCH_PUBLISH_ENDPOINT, {
|
|
136
|
+
...publishOptions,
|
|
137
|
+
access: publishOptions.access ?? undefined,
|
|
138
|
+
otp,
|
|
139
|
+
method: 'PUT',
|
|
140
|
+
body,
|
|
141
|
+
ignoreBody: true,
|
|
142
|
+
}),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
const statusCode = err.statusCode;
|
|
147
|
+
if (statusCode === 404 || statusCode === 405) {
|
|
148
|
+
throw new PnpmError('BATCH_PUBLISH_UNSUPPORTED', `The registry at ${registry} does not support publishing multiple packages in a single request`, {
|
|
149
|
+
hint: `Retry without the --batch flag, or publish to a registry that implements "PUT ${BATCH_PUBLISH_ENDPOINT}" (for example, pnpr).`,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
throw err;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Build the npm publish document for one package — the same JSON body `libnpmpublish` would
|
|
157
|
+
* send as the whole `PUT /:pkg` request. The batch publish request body is an array of these,
|
|
158
|
+
* which lets the registry reuse its single-package publish pipeline per entry.
|
|
159
|
+
*/
|
|
160
|
+
function createPublishDocument({ publishedManifest, tarballData }, registry, opts) {
|
|
161
|
+
const name = publishedManifest.name;
|
|
162
|
+
const version = semver.clean(publishedManifest.version);
|
|
163
|
+
if (!version) {
|
|
164
|
+
throw new PnpmError('BAD_SEMVER', `Invalid semver: ${publishedManifest.version}`);
|
|
165
|
+
}
|
|
166
|
+
const publishConfigAccess = publishedManifest.publishConfig?.access;
|
|
167
|
+
const access = opts.access ?? (isPublishAccess(publishConfigAccess) ? publishConfigAccess : null);
|
|
168
|
+
if (!name.startsWith('@') && access === 'restricted') {
|
|
169
|
+
throw new PnpmError('UNSCOPED_RESTRICTED', `Can't restrict access to the unscoped package ${name}`);
|
|
170
|
+
}
|
|
171
|
+
const tarballName = `${name}-${version}.tgz`;
|
|
172
|
+
const manifest = {
|
|
173
|
+
...publishedManifest,
|
|
174
|
+
_id: `${name}@${version}`,
|
|
175
|
+
version,
|
|
176
|
+
_nodeVersion: process.versions.node,
|
|
177
|
+
dist: {
|
|
178
|
+
integrity: `sha512-${createHash('sha512').update(tarballData).digest('base64')}`,
|
|
179
|
+
shasum: createHash('sha1').update(tarballData).digest('hex'),
|
|
180
|
+
// libnpmpublish stores an http:// URL on purpose (clients fetch via HTTPS regardless when
|
|
181
|
+
// the registry is HTTPS); keep the wire format identical to a single-package publish.
|
|
182
|
+
tarball: new URL(`${name}/-/${tarballName}`, registry).href.replace(/^https:\/\//, 'http://'),
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
return {
|
|
186
|
+
_id: name,
|
|
187
|
+
name,
|
|
188
|
+
description: publishedManifest.description,
|
|
189
|
+
'dist-tags': { [opts.tag ?? 'latest']: version },
|
|
190
|
+
versions: { [version]: manifest },
|
|
191
|
+
access,
|
|
192
|
+
_attachments: {
|
|
193
|
+
[tarballName]: {
|
|
194
|
+
content_type: 'application/octet-stream',
|
|
195
|
+
data: tarballData.toString('base64'),
|
|
196
|
+
length: tarballData.length,
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=batchPublish.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PnpmError } from '@pnpm/error';
|
|
2
2
|
import type { ExportedManifest } from '@pnpm/releasing.exportable-manifest';
|
|
3
3
|
declare const TARBALL_SUFFIXES: readonly ['.tar.gz', '.tgz'];
|
|
4
|
-
export type TarballSuffix =
|
|
4
|
+
export type TarballSuffix = typeof TARBALL_SUFFIXES[number];
|
|
5
5
|
export type TarballPath = `${string}${TarballSuffix}`;
|
|
6
6
|
export declare const isTarballPath: (path: string) => path is TarballPath;
|
|
7
7
|
export declare function extractManifestFromPacked<Output = ExportedManifest>(tarballPath: TarballPath): Promise<Output>;
|
|
@@ -43,7 +43,7 @@ export interface AuthTokenParams {
|
|
|
43
43
|
* @see https://github.com/npm/cli/blob/7d900c46/lib/utils/oidc.js#L112-L142 for npm's implementation.
|
|
44
44
|
* @see https://github.com/yarnpkg/berry/blob/bafbef55/packages/plugin-npm/sources/npmHttpUtils.ts#L626-L641 for yarn's implementation.
|
|
45
45
|
*/
|
|
46
|
-
export declare function fetchAuthToken({ context: { fetch }, options, idToken, packageName, registry }: AuthTokenParams): Promise<string>;
|
|
46
|
+
export declare function fetchAuthToken({ context: { fetch, }, options, idToken, packageName, registry, }: AuthTokenParams): Promise<string>;
|
|
47
47
|
export declare abstract class AuthTokenError extends PnpmError {
|
|
48
48
|
}
|
|
49
49
|
export declare class AuthTokenFetchError extends AuthTokenError {
|
|
@@ -57,7 +57,7 @@ export interface IdTokenParams {
|
|
|
57
57
|
* @see https://github.com/npm/cli/blob/7d900c46/lib/utils/oidc.js#L37-L110 for npm's implementation
|
|
58
58
|
* @see https://github.com/yarnpkg/berry/blob/bafbef55/packages/plugin-npm/sources/npmHttpUtils.ts#L594-L624 for yarn's implementation
|
|
59
59
|
*/
|
|
60
|
-
export declare function getIdToken({ context: { Date, ciInfo: { GITHUB_ACTIONS }, fetch, globalInfo, process: { env } }, options, registry }: IdTokenParams): Promise<string | undefined>;
|
|
60
|
+
export declare function getIdToken({ context: { Date, ciInfo: { GITHUB_ACTIONS }, fetch, globalInfo, process: { env }, }, options, registry, }: IdTokenParams): Promise<string | undefined>;
|
|
61
61
|
export declare abstract class IdTokenError extends PnpmError {
|
|
62
62
|
}
|
|
63
63
|
export declare class IdTokenGitHubWorkflowIncorrectPermissionsError extends IdTokenError {
|
|
@@ -50,7 +50,7 @@ export interface ProvenanceParams {
|
|
|
50
50
|
*
|
|
51
51
|
* @see https://github.com/npm/cli/blob/7d900c46/lib/utils/oidc.js#L145-L164 for npm's implementation.
|
|
52
52
|
*/
|
|
53
|
-
export declare function determineProvenance({ authToken, idToken, options, packageName, registry, context: { ciInfo: { GITHUB_ACTIONS, GITLAB }, fetch, process: { env } } }: ProvenanceParams): Promise<boolean | undefined>;
|
|
53
|
+
export declare function determineProvenance({ authToken, idToken, options, packageName, registry, context: { ciInfo: { GITHUB_ACTIONS, GITLAB }, fetch, process: { env }, }, }: ProvenanceParams): Promise<boolean | undefined>;
|
|
54
54
|
export declare abstract class ProvenanceError extends PnpmError {
|
|
55
55
|
}
|
|
56
56
|
export declare class ProvenanceMalformedIdTokenError extends ProvenanceError {
|
package/lib/publish/otp.d.ts
CHANGED
|
@@ -35,4 +35,4 @@ export interface OtpParams {
|
|
|
35
35
|
* @see https://github.com/npm/cli/blob/7d900c46/lib/utils/otplease.js for npm's implementation.
|
|
36
36
|
* @see https://github.com/npm/npm-profile/blob/main/lib/index.js for the webauth polling flow.
|
|
37
37
|
*/
|
|
38
|
-
export declare function publishWithOtpHandling({ context, manifest, publishOptions, tarballData }: OtpParams): Promise<OtpPublishResponse>;
|
|
38
|
+
export declare function publishWithOtpHandling({ context, manifest, publishOptions, tarballData, }: OtpParams): Promise<OtpPublishResponse>;
|
package/lib/publish/publish.js
CHANGED
|
@@ -35,6 +35,7 @@ export function rcOptionsTypes() {
|
|
|
35
35
|
export function cliOptionsTypes() {
|
|
36
36
|
return {
|
|
37
37
|
...rcOptionsTypes(),
|
|
38
|
+
batch: Boolean,
|
|
38
39
|
'dry-run': Boolean,
|
|
39
40
|
force: Boolean,
|
|
40
41
|
json: Boolean,
|
|
@@ -100,6 +101,10 @@ export function help() {
|
|
|
100
101
|
name: '--recursive',
|
|
101
102
|
shortAlias: '-r',
|
|
102
103
|
},
|
|
104
|
+
{
|
|
105
|
+
description: 'Send all packages to the registry in a single request instead of one request per package. Requires --recursive and a registry that implements the "/-/pnpm/v1/publish" endpoint (for example, pnpr)',
|
|
106
|
+
name: '--batch',
|
|
107
|
+
},
|
|
103
108
|
],
|
|
104
109
|
},
|
|
105
110
|
FILTERING,
|
|
@@ -126,6 +131,11 @@ export async function handler(opts, params) {
|
|
|
126
131
|
return result;
|
|
127
132
|
}
|
|
128
133
|
export async function publish(opts, params) {
|
|
134
|
+
if (opts.batch && !opts.recursive) {
|
|
135
|
+
throw new PnpmError('BATCH_PUBLISH_REQUIRES_RECURSIVE', '--batch can only be used together with --recursive', {
|
|
136
|
+
hint: 'Run "pnpm publish -r --batch" to publish all workspace packages in a single request.',
|
|
137
|
+
});
|
|
138
|
+
}
|
|
129
139
|
if (opts.gitChecks !== false && await isGitRepo()) {
|
|
130
140
|
if (!(await isWorkingTreeClean())) {
|
|
131
141
|
throw new PnpmError('GIT_UNCLEAN', 'Unclean working tree. Commit or stash changes first.', {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { Config } from '@pnpm/config.reader';
|
|
2
2
|
import { PnpmError } from '@pnpm/error';
|
|
3
3
|
import type { ExportedManifest } from '@pnpm/releasing.exportable-manifest';
|
|
4
|
+
import { type RegistryConfig } from '@pnpm/types';
|
|
4
5
|
import { type PublishSummary } from '../tarball/publishSummary.js';
|
|
5
6
|
import { type OtpContext, type PublishOptionsWithDefaultAccess } from './otp.js';
|
|
6
7
|
import type { PackResult } from './pack.js';
|
|
8
|
+
import { type NormalizedRegistryUrl } from './registryConfigKeys.js';
|
|
7
9
|
export type { PublishSummary };
|
|
8
10
|
export type PublishPackedPkgOptions = Pick<Config, 'configByUri' | 'dryRun' | 'fetchRetries' | 'fetchRetryFactor' | 'fetchRetryMaxtimeout' | 'fetchRetryMintimeout' | 'fetchTimeout' | 'registries' | 'tag' | 'userAgent'> & Partial<Pick<Config, 'ca' | 'cert' | 'httpProxy' | 'httpsProxy' | 'key' | 'localAddress' | 'noProxy' | 'strictSsl'>> & {
|
|
9
11
|
access?: 'public' | 'restricted';
|
|
@@ -27,10 +29,31 @@ type StagePublishOptions = PublishOptionsWithDefaultAccess & {
|
|
|
27
29
|
stage?: boolean;
|
|
28
30
|
};
|
|
29
31
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
+
* Build the libnpmpublish / npm-registry-fetch options (registry, auth, headers) for publishing
|
|
33
|
+
* {@link manifest}. When `oidc` is `false`, the per-package OIDC token exchange is skipped and only
|
|
34
|
+
* statically configured credentials are used — batch publish sends many packages in one request,
|
|
35
|
+
* which a package-scoped OIDC token cannot authorize.
|
|
36
|
+
*
|
|
37
|
+
* @internal Exported for unit testing of the access / registry / auth fallback rules and for batch
|
|
38
|
+
* publish. Not part of the package's public API.
|
|
39
|
+
*/
|
|
40
|
+
export declare function createPublishOptions(manifest: ExportedManifest, options: PublishPackedPkgOptions, { oidc }?: {
|
|
41
|
+
oidc?: boolean;
|
|
42
|
+
}): Promise<StagePublishOptions>;
|
|
43
|
+
export declare function isPublishAccess(access: unknown): access is 'public' | 'restricted';
|
|
44
|
+
interface RegistryInfo {
|
|
45
|
+
registry: NormalizedRegistryUrl;
|
|
46
|
+
config: RegistryConfig;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Find credentials and SSL info for a package's registry.
|
|
50
|
+
* Follows {@link https://docs.npmjs.com/cli/v10/configuring-npm/npmrc#auth-related-configuration}.
|
|
51
|
+
*
|
|
52
|
+
* The manifest's `publishConfig.registry`, when set, takes precedence over `registries`.
|
|
53
|
+
*
|
|
54
|
+
* @internal Exported for batch publish, which groups packages by their target registry.
|
|
32
55
|
*/
|
|
33
|
-
export declare function
|
|
56
|
+
export declare function findRegistryInfo({ name }: ExportedManifest, { configByUri, registries }: Pick<Config, 'configByUri' | 'registries'>, publishConfigRegistry?: string): Partial<RegistryInfo>;
|
|
34
57
|
export declare class PublishUnsupportedRegistryProtocolError extends PnpmError {
|
|
35
58
|
readonly registryUrl: string;
|
|
36
59
|
constructor(registryUrl: string);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
1
|
import fs from 'node:fs/promises';
|
|
3
|
-
import path from 'node:path';
|
|
4
2
|
import { PnpmError } from '@pnpm/error';
|
|
5
3
|
import { globalInfo, globalWarn } from '@pnpm/logger';
|
|
6
4
|
import { createDispatchedFetch } from '@pnpm/network.fetch';
|
|
7
|
-
import {
|
|
5
|
+
import { DEFAULT_REGISTRY_SCOPE } from '@pnpm/types';
|
|
6
|
+
import { createPublishSummary } from '../tarball/publishSummary.js';
|
|
8
7
|
import { displayError } from './displayError.js';
|
|
9
8
|
import { executeTokenHelper } from './executeTokenHelper.js';
|
|
10
9
|
import { createFailedToPublishError } from './FailedToPublishError.js';
|
|
@@ -22,21 +21,7 @@ export async function publishPackedPkg(packResult, opts) {
|
|
|
22
21
|
const { registry } = publishOptions;
|
|
23
22
|
const isStage = opts.stage === true;
|
|
24
23
|
globalInfo(`📦 ${name}@${version} → ${registry ?? 'the default registry'}`);
|
|
25
|
-
const summary = {
|
|
26
|
-
id: `${name}@${version}`,
|
|
27
|
-
name: name,
|
|
28
|
-
version: version,
|
|
29
|
-
size: tarballData.byteLength,
|
|
30
|
-
unpackedSize,
|
|
31
|
-
// SHA-1 is what `npm publish --json` reports as `shasum` for back-compat with the registry's
|
|
32
|
-
// legacy dist.shasum field; `integrity` below is the modern SRI hash.
|
|
33
|
-
shasum: createHash('sha1').update(tarballData).digest('hex'),
|
|
34
|
-
integrity: `sha512-${createHash('sha512').update(tarballData).digest('base64')}`,
|
|
35
|
-
filename: path.basename(tarballPath),
|
|
36
|
-
files: contents.map((file) => ({ path: file })),
|
|
37
|
-
entryCount: contents.length,
|
|
38
|
-
bundled: extractBundledDependencies(publishedManifest),
|
|
39
|
-
};
|
|
24
|
+
const summary = createPublishSummary({ publishedManifest, tarballPath, contents, unpackedSize }, tarballData);
|
|
40
25
|
if (opts.dryRun) {
|
|
41
26
|
globalWarn(`Skip ${isStage ? 'staging' : 'publishing'} ${name}@${version} (dry run)`);
|
|
42
27
|
return summary;
|
|
@@ -71,15 +56,21 @@ export function createPublishContext(opts) {
|
|
|
71
56
|
};
|
|
72
57
|
}
|
|
73
58
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
59
|
+
* Build the libnpmpublish / npm-registry-fetch options (registry, auth, headers) for publishing
|
|
60
|
+
* {@link manifest}. When `oidc` is `false`, the per-package OIDC token exchange is skipped and only
|
|
61
|
+
* statically configured credentials are used — batch publish sends many packages in one request,
|
|
62
|
+
* which a package-scoped OIDC token cannot authorize.
|
|
63
|
+
*
|
|
64
|
+
* @internal Exported for unit testing of the access / registry / auth fallback rules and for batch
|
|
65
|
+
* publish. Not part of the package's public API.
|
|
76
66
|
*/
|
|
77
|
-
export async function createPublishOptions(manifest, options) {
|
|
67
|
+
export async function createPublishOptions(manifest, options, { oidc = true } = {}) {
|
|
78
68
|
const publishConfigRegistry = typeof manifest.publishConfig?.registry === 'string'
|
|
79
69
|
? manifest.publishConfig.registry
|
|
80
70
|
: undefined;
|
|
81
71
|
const { registry, config } = findRegistryInfo(manifest, options, publishConfigRegistry);
|
|
82
|
-
const
|
|
72
|
+
const tls = config?.tls;
|
|
73
|
+
const creds = config?.[DEFAULT_REGISTRY_SCOPE];
|
|
83
74
|
const publishConfigAccess = manifest.publishConfig?.access;
|
|
84
75
|
const access = options.access ?? (isPublishAccess(publishConfigAccess) ? publishConfigAccess : null);
|
|
85
76
|
const { ci: isFromCI, fetchRetries, fetchRetryFactor, fetchRetryMaxtimeout, fetchRetryMintimeout, fetchTimeout: timeout, otp, provenance, provenanceFile, tag: defaultTag, userAgent, } = options;
|
|
@@ -102,6 +93,7 @@ export async function createPublishOptions(manifest, options) {
|
|
|
102
93
|
provenance,
|
|
103
94
|
provenanceFile,
|
|
104
95
|
registry,
|
|
96
|
+
strictSSL: options.strictSsl, // npm-registry-fetch defaults to true; must be set explicitly to honour strictSsl: false
|
|
105
97
|
userAgent,
|
|
106
98
|
// Signal to the registry that the client supports web-based authentication.
|
|
107
99
|
// Without this, the registry would never offer the web auth flow and would
|
|
@@ -121,21 +113,23 @@ export async function createPublishOptions(manifest, options) {
|
|
|
121
113
|
publishOptions.stage = true;
|
|
122
114
|
}
|
|
123
115
|
if (registry) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
116
|
+
if (oidc) {
|
|
117
|
+
// OIDC takes precedence over a configured static `_authToken`, mirroring the npm CLI's
|
|
118
|
+
// behavior (see https://github.com/npm/cli/blob/7d900c46/lib/utils/oidc.js). Trusted
|
|
119
|
+
// publishing wins whenever the registry has it configured for the package; the static
|
|
120
|
+
// token is used only as a fallback when OIDC is not applicable.
|
|
121
|
+
const oidcTokenProvenance = await fetchTokenAndProvenanceByOidc(manifest.name, registry, options);
|
|
122
|
+
if (oidcTokenProvenance?.authToken) {
|
|
123
|
+
publishOptions.token = oidcTokenProvenance.authToken;
|
|
124
|
+
}
|
|
125
|
+
publishOptions.provenance ??= oidcTokenProvenance?.provenance;
|
|
131
126
|
}
|
|
132
|
-
publishOptions.provenance ??= oidcTokenProvenance?.provenance;
|
|
133
127
|
appendAuthOptionsForRegistry(publishOptions, registry);
|
|
134
128
|
}
|
|
135
129
|
pruneUndefined(publishOptions);
|
|
136
130
|
return publishOptions;
|
|
137
131
|
}
|
|
138
|
-
function isPublishAccess(access) {
|
|
132
|
+
export function isPublishAccess(access) {
|
|
139
133
|
return access === 'public' || access === 'restricted';
|
|
140
134
|
}
|
|
141
135
|
/**
|
|
@@ -143,8 +137,10 @@ function isPublishAccess(access) {
|
|
|
143
137
|
* Follows {@link https://docs.npmjs.com/cli/v10/configuring-npm/npmrc#auth-related-configuration}.
|
|
144
138
|
*
|
|
145
139
|
* The manifest's `publishConfig.registry`, when set, takes precedence over `registries`.
|
|
140
|
+
*
|
|
141
|
+
* @internal Exported for batch publish, which groups packages by their target registry.
|
|
146
142
|
*/
|
|
147
|
-
function findRegistryInfo({ name }, { configByUri, registries }, publishConfigRegistry) {
|
|
143
|
+
export function findRegistryInfo({ name }, { configByUri, registries }, publishConfigRegistry) {
|
|
148
144
|
// eslint-disable-next-line regexp/no-unused-capturing-group
|
|
149
145
|
const scopedMatches = /@(?<scope>[^/]+)\/(?<slug>[^/]+)/.exec(name);
|
|
150
146
|
const registryName = scopedMatches?.groups ? `@${scopedMatches.groups.scope}` : 'default';
|
|
@@ -154,6 +150,7 @@ function findRegistryInfo({ name }, { configByUri, registries }, publishConfigRe
|
|
|
154
150
|
throw new PublishUnsupportedRegistryProtocolError(nonNormalizedRegistry);
|
|
155
151
|
}
|
|
156
152
|
const { normalizedUrl: registry, longestConfigKey: initialRegistryConfigKey, } = supportedRegistryInfo;
|
|
153
|
+
const credsScope = registryName === 'default' ? DEFAULT_REGISTRY_SCOPE : registryName;
|
|
157
154
|
let creds;
|
|
158
155
|
let tls = {};
|
|
159
156
|
for (const registryConfigKey of allRegistryConfigKeys(initialRegistryConfigKey)) {
|
|
@@ -161,13 +158,17 @@ function findRegistryInfo({ name }, { configByUri, registries }, publishConfigRe
|
|
|
161
158
|
if (!entry)
|
|
162
159
|
continue;
|
|
163
160
|
// Auth from longer path collectively overrides shorter path
|
|
164
|
-
creds ??= entry
|
|
161
|
+
creds ??= entry[credsScope] ?? entry[DEFAULT_REGISTRY_SCOPE];
|
|
165
162
|
// TLS from longer path individually overrides shorter path
|
|
166
163
|
tls = { ...entry.tls, ...tls };
|
|
167
164
|
}
|
|
165
|
+
const config = { tls };
|
|
166
|
+
if (creds) {
|
|
167
|
+
config[DEFAULT_REGISTRY_SCOPE] = creds;
|
|
168
|
+
}
|
|
168
169
|
return {
|
|
169
170
|
registry,
|
|
170
|
-
config
|
|
171
|
+
config,
|
|
171
172
|
};
|
|
172
173
|
}
|
|
173
174
|
function extractToken({ authToken, tokenHelper, }) {
|
|
@@ -6,6 +6,7 @@ import { sortProjects } from '@pnpm/workspace.projects-sorter';
|
|
|
6
6
|
import pFilter from 'p-filter';
|
|
7
7
|
import { pick } from 'ramda';
|
|
8
8
|
import { writeJsonFile } from 'write-json-file';
|
|
9
|
+
import { batchPublishPackages } from './batchPublish.js';
|
|
9
10
|
import { publish } from './publish.js';
|
|
10
11
|
export async function recursivePublish(opts) {
|
|
11
12
|
const pkgs = Object.values(opts.selectedProjectsGraph).map((wsPkg) => wsPkg.package);
|
|
@@ -56,46 +57,55 @@ export async function recursivePublish(opts) {
|
|
|
56
57
|
}
|
|
57
58
|
const chunks = sortProjects(opts.selectedProjectsGraph);
|
|
58
59
|
const tag = opts.tag ?? 'latest';
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
60
|
+
if (opts.batch) {
|
|
61
|
+
const sortedPkgs = chunks
|
|
62
|
+
.flat()
|
|
63
|
+
.filter((pkgDir) => publishedPkgDirs.has(pkgDir))
|
|
64
|
+
.map((pkgDir) => opts.selectedProjectsGraph[pkgDir].package);
|
|
65
|
+
publishedPackages.push(...await batchPublishPackages(sortedPkgs, { ...opts, tag }));
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const commandArgs = opts.stage ? ['stage', 'publish'] : ['publish'];
|
|
69
|
+
for (const chunk of chunks) {
|
|
70
|
+
// We can't run publish concurrently due to the npm CLI asking for OTP.
|
|
71
|
+
// NOTE: If we solve the OTP issue, we still need to limit packages concurrency.
|
|
72
|
+
// Otherwise, publishing will consume too much resources.
|
|
73
|
+
// See related issue: https://github.com/pnpm/pnpm/issues/6968
|
|
74
|
+
for (const pkgDir of chunk) {
|
|
75
|
+
if (!publishedPkgDirs.has(pkgDir))
|
|
76
|
+
continue;
|
|
77
|
+
const pkg = opts.selectedProjectsGraph[pkgDir].package;
|
|
78
|
+
const registry = pkg.manifest.publishConfig?.registry ?? pickRegistryForPackage(opts.registries, pkg.manifest.name);
|
|
79
|
+
// eslint-disable-next-line no-await-in-loop
|
|
80
|
+
const publishResult = await publish({
|
|
81
|
+
...opts,
|
|
82
|
+
dir: pkg.rootDir,
|
|
83
|
+
argv: {
|
|
84
|
+
original: [
|
|
85
|
+
...commandArgs,
|
|
86
|
+
'--tag',
|
|
87
|
+
tag,
|
|
88
|
+
'--registry',
|
|
89
|
+
registry,
|
|
90
|
+
...appendedArgs,
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
gitChecks: false,
|
|
94
|
+
recursive: false,
|
|
95
|
+
}, [pkg.rootDir]);
|
|
96
|
+
if (publishResult?.publishSummary != null) {
|
|
97
|
+
publishedPackages.push(publishResult.publishSummary);
|
|
96
98
|
}
|
|
97
|
-
else
|
|
98
|
-
|
|
99
|
+
else {
|
|
100
|
+
// Fallback for paths that don't produce a full PublishSummary (e.g. dry run via the
|
|
101
|
+
// legacy npm-CLI bridge, or future call sites that bypass publishPackedPkg).
|
|
102
|
+
const publishedManifest = publishResult?.publishedManifest ?? publishResult?.manifest;
|
|
103
|
+
if (publishedManifest != null) {
|
|
104
|
+
publishedPackages.push(pick(['name', 'version'], publishedManifest));
|
|
105
|
+
}
|
|
106
|
+
else if (publishResult?.exitCode) {
|
|
107
|
+
return { exitCode: publishResult.exitCode, publishedPackages };
|
|
108
|
+
}
|
|
99
109
|
}
|
|
100
110
|
}
|
|
101
111
|
}
|
package/lib/stage/context.js
CHANGED
|
@@ -8,7 +8,7 @@ export function createStageContext(opts, packageName) {
|
|
|
8
8
|
return {
|
|
9
9
|
opts,
|
|
10
10
|
registry,
|
|
11
|
-
authHeaderValue: getAuthHeaderByUri(registry),
|
|
11
|
+
authHeaderValue: packageName ? getAuthHeaderByUri(registry, { pkgName: packageName }) : getAuthHeaderByUri(registry),
|
|
12
12
|
fetchFromRegistry: createFetchFromRegistry(opts),
|
|
13
13
|
};
|
|
14
14
|
}
|
package/lib/stage/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as publishCommand from '../publish/publish.js';
|
|
2
2
|
export declare const STAGE_SUBCOMMANDS: readonly ['publish', 'list', 'view', 'approve', 'reject', 'download'];
|
|
3
|
-
export type StageSubcommand =
|
|
3
|
+
export type StageSubcommand = typeof STAGE_SUBCOMMANDS[number];
|
|
4
4
|
/**
|
|
5
5
|
* Options accepted by every `pnpm stage` subcommand.
|
|
6
6
|
*
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ExportedManifest } from '@pnpm/releasing.exportable-manifest';
|
|
1
2
|
/**
|
|
2
3
|
* Per-package summary describing a successful publish, modeled after `npm publish --json`.
|
|
3
4
|
* Returned to callers and serialized to stdout when `pnpm publish --json` is used.
|
|
@@ -28,6 +29,13 @@ export interface PublishSummary {
|
|
|
28
29
|
/** Staged publish identifier returned by the registry. Only present for staged publishes. */
|
|
29
30
|
stageId?: string;
|
|
30
31
|
}
|
|
32
|
+
export interface PackedPkgInfo {
|
|
33
|
+
publishedManifest: ExportedManifest;
|
|
34
|
+
tarballPath: string;
|
|
35
|
+
contents: string[];
|
|
36
|
+
unpackedSize: number;
|
|
37
|
+
}
|
|
38
|
+
export declare function createPublishSummary({ publishedManifest, tarballPath, contents, unpackedSize }: PackedPkgInfo, tarballData: Buffer): PublishSummary;
|
|
31
39
|
/**
|
|
32
40
|
* Normalize the two equivalent manifest keys (`bundledDependencies` and `bundleDependencies`)
|
|
33
41
|
* into a flat list of dependency names, matching npm's interpretation.
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export function createPublishSummary({ publishedManifest, tarballPath, contents, unpackedSize }, tarballData) {
|
|
4
|
+
const { name, version } = publishedManifest;
|
|
5
|
+
return {
|
|
6
|
+
id: `${name}@${version}`,
|
|
7
|
+
name: name,
|
|
8
|
+
version: version,
|
|
9
|
+
size: tarballData.byteLength,
|
|
10
|
+
unpackedSize,
|
|
11
|
+
// SHA-1 is what `npm publish --json` reports as `shasum` for back-compat with the registry's
|
|
12
|
+
// legacy dist.shasum field; `integrity` below is the modern SRI hash.
|
|
13
|
+
shasum: createHash('sha1').update(tarballData).digest('hex'),
|
|
14
|
+
integrity: `sha512-${createHash('sha512').update(tarballData).digest('base64')}`,
|
|
15
|
+
filename: path.basename(tarballPath),
|
|
16
|
+
files: contents.map((file) => ({ path: file })),
|
|
17
|
+
entryCount: contents.length,
|
|
18
|
+
bundled: extractBundledDependencies(publishedManifest),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
1
21
|
/**
|
|
2
22
|
* Normalize the two equivalent manifest keys (`bundledDependencies` and `bundleDependencies`)
|
|
3
23
|
* into a flat list of dependency names, matching npm's interpretation.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/releasing.commands",
|
|
3
|
-
"version": "1100.
|
|
3
|
+
"version": "1100.5.0",
|
|
4
4
|
"description": "Commands for deploy, pack, and publish",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -38,61 +38,62 @@
|
|
|
38
38
|
"libnpmpublish": "^11.2.0",
|
|
39
39
|
"normalize-path": "^3.0.0",
|
|
40
40
|
"normalize-registry-url": "2.0.1",
|
|
41
|
+
"npm-registry-fetch": "^19.0.0",
|
|
41
42
|
"p-filter": "^4.1.0",
|
|
42
43
|
"p-limit": "^7.3.0",
|
|
43
44
|
"ramda": "npm:@pnpm/ramda@0.28.1",
|
|
44
45
|
"realpath-missing": "^2.0.0",
|
|
45
46
|
"render-help": "^2.0.0",
|
|
46
|
-
"semver": "^7.8.
|
|
47
|
+
"semver": "^7.8.4",
|
|
47
48
|
"tar-stream": "^3.2.0",
|
|
48
49
|
"tempy": "3.0.0",
|
|
49
50
|
"tinyglobby": "^0.2.16",
|
|
50
51
|
"validate-npm-package-name": "7.0.2",
|
|
51
52
|
"write-json-file": "^7.0.0",
|
|
52
53
|
"write-yaml-file": "^6.0.0",
|
|
53
|
-
"@pnpm/bins.resolver": "1100.0.
|
|
54
|
+
"@pnpm/bins.resolver": "1100.0.8",
|
|
54
55
|
"@pnpm/catalogs.types": "1100.0.0",
|
|
55
|
-
"@pnpm/
|
|
56
|
-
"@pnpm/
|
|
57
|
-
"@pnpm/
|
|
58
|
-
"@pnpm/
|
|
56
|
+
"@pnpm/config.pick-registry-for-package": "1100.0.9",
|
|
57
|
+
"@pnpm/config.reader": "1101.9.0",
|
|
58
|
+
"@pnpm/engine.runtime.commands": "1100.1.5",
|
|
59
|
+
"@pnpm/deps.path": "1100.0.8",
|
|
59
60
|
"@pnpm/constants": "1100.0.0",
|
|
60
|
-
"@pnpm/
|
|
61
|
-
"@pnpm/engine.runtime.commands": "1100.1.4",
|
|
62
|
-
"@pnpm/engine.runtime.node-resolver": "1101.1.6",
|
|
61
|
+
"@pnpm/engine.runtime.node-resolver": "1101.1.7",
|
|
63
62
|
"@pnpm/error": "1100.0.0",
|
|
64
|
-
"@pnpm/
|
|
65
|
-
"@pnpm/
|
|
66
|
-
"@pnpm/
|
|
67
|
-
"@pnpm/fs.indexed-pkg-importer": "1100.0.13",
|
|
63
|
+
"@pnpm/cli.utils": "1101.0.12",
|
|
64
|
+
"@pnpm/fs.indexed-pkg-importer": "1100.0.14",
|
|
65
|
+
"@pnpm/cli.common-cli-options-help": "1100.0.2",
|
|
68
66
|
"@pnpm/fs.is-empty-dir-or-nothing": "1100.0.0",
|
|
69
|
-
"@pnpm/
|
|
70
|
-
"@pnpm/
|
|
71
|
-
"@pnpm/
|
|
72
|
-
"@pnpm/
|
|
73
|
-
"@pnpm/installing.
|
|
74
|
-
"@pnpm/
|
|
75
|
-
"@pnpm/
|
|
67
|
+
"@pnpm/installing.commands": "1100.9.0",
|
|
68
|
+
"@pnpm/exec.lifecycle": "1100.0.18",
|
|
69
|
+
"@pnpm/exec.pnpm-cli-runner": "1100.0.1",
|
|
70
|
+
"@pnpm/fetching.directory-fetcher": "1100.0.17",
|
|
71
|
+
"@pnpm/installing.client": "1100.2.8",
|
|
72
|
+
"@pnpm/lockfile.types": "1100.0.11",
|
|
73
|
+
"@pnpm/lockfile.fs": "1100.1.5",
|
|
74
|
+
"@pnpm/network.web-auth": "1101.1.1",
|
|
75
|
+
"@pnpm/releasing.exportable-manifest": "1100.1.6",
|
|
76
|
+
"@pnpm/resolving.resolver-base": "1100.4.2",
|
|
77
|
+
"@pnpm/network.fetch": "1100.1.3",
|
|
78
|
+
"@pnpm/workspace.projects-filter": "1100.0.21",
|
|
79
|
+
"@pnpm/network.auth-header": "1101.1.2",
|
|
80
|
+
"@pnpm/types": "1101.3.2",
|
|
76
81
|
"@pnpm/network.git-utils": "1100.0.1",
|
|
77
|
-
"@pnpm/
|
|
78
|
-
"@pnpm/
|
|
79
|
-
"@pnpm/resolving.resolver-base": "1100.4.1",
|
|
80
|
-
"@pnpm/types": "1101.3.1",
|
|
81
|
-
"@pnpm/workspace.projects-filter": "1100.0.20",
|
|
82
|
-
"@pnpm/workspace.projects-sorter": "1100.0.6"
|
|
82
|
+
"@pnpm/fs.packlist": "1100.0.1",
|
|
83
|
+
"@pnpm/workspace.projects-sorter": "1100.0.7"
|
|
83
84
|
},
|
|
84
85
|
"peerDependencies": {
|
|
85
|
-
"@pnpm/logger": "^
|
|
86
|
+
"@pnpm/logger": "^1100.0.0"
|
|
86
87
|
},
|
|
87
88
|
"devDependencies": {
|
|
88
|
-
"@jest/globals": "30.
|
|
89
|
+
"@jest/globals": "30.4.1",
|
|
89
90
|
"@types/cross-spawn": "^6.0.6",
|
|
90
91
|
"@types/is-windows": "^1.0.2",
|
|
91
|
-
"@types/libnpmpublish": "^
|
|
92
|
+
"@types/libnpmpublish": "^11.2.0",
|
|
93
|
+
"@types/npm-registry-fetch": "^8.0.9",
|
|
92
94
|
"@types/proxyquire": "^1.3.31",
|
|
93
95
|
"@types/ramda": "0.31.1",
|
|
94
96
|
"@types/semver": "7.7.1",
|
|
95
|
-
"@types/tar": "^7.0.87",
|
|
96
97
|
"@types/tar-stream": "^3.1.4",
|
|
97
98
|
"@types/validate-npm-package-name": "^4.0.2",
|
|
98
99
|
"ci-info": "^4.4.0",
|
|
@@ -100,18 +101,18 @@
|
|
|
100
101
|
"is-windows": "^1.0.2",
|
|
101
102
|
"load-json-file": "^7.0.1",
|
|
102
103
|
"tar": "^7.5.15",
|
|
103
|
-
"undici": "^7.
|
|
104
|
+
"undici": "^7.27.2",
|
|
104
105
|
"write-yaml-file": "^6.0.0",
|
|
105
|
-
"@pnpm/assert-project": "1100.0.15",
|
|
106
|
-
"@pnpm/catalogs.config": "1100.0.0",
|
|
107
|
-
"@pnpm/hooks.pnpmfile": "1100.0.14",
|
|
108
106
|
"@pnpm/logger": "1100.0.0",
|
|
109
|
-
"@pnpm/
|
|
110
|
-
"@pnpm/
|
|
107
|
+
"@pnpm/hooks.pnpmfile": "1100.0.15",
|
|
108
|
+
"@pnpm/assert-project": "1100.0.16",
|
|
109
|
+
"@pnpm/prepare": "1100.0.16",
|
|
111
110
|
"@pnpm/test-fixtures": "1100.0.0",
|
|
111
|
+
"@pnpm/releasing.commands": "1100.5.0",
|
|
112
112
|
"@pnpm/test-ipc-server": "1100.0.0",
|
|
113
|
-
"@pnpm/testing.command-defaults": "1100.0.
|
|
114
|
-
"@pnpm/testing.registry-mock": "1100.0.
|
|
113
|
+
"@pnpm/testing.command-defaults": "1100.0.6",
|
|
114
|
+
"@pnpm/testing.registry-mock": "1100.0.6",
|
|
115
|
+
"@pnpm/catalogs.config": "1100.0.0"
|
|
115
116
|
},
|
|
116
117
|
"engines": {
|
|
117
118
|
"node": ">=22.13"
|