@pnpm/releasing.commands 1100.6.0 → 1100.6.2
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 +42 -0
- package/package.json +23 -23
- package/lib/change/index.d.ts +0 -41
- package/lib/change/index.js +0 -245
- package/lib/deploy/createDeployFiles.d.ts +0 -26
- package/lib/deploy/createDeployFiles.js +0 -255
- package/lib/deploy/deploy.d.ts +0 -12
- package/lib/deploy/deploy.js +0 -398
- package/lib/deploy/deployHook.d.ts +0 -2
- package/lib/deploy/deployHook.js +0 -15
- package/lib/deploy/index.d.ts +0 -2
- package/lib/deploy/index.js +0 -3
- package/lib/index.d.ts +0 -7
- package/lib/lane/index.d.ts +0 -24
- package/lib/lane/index.js +0 -157
- package/lib/pack-app/index.d.ts +0 -2
- package/lib/pack-app/index.js +0 -3
- package/lib/pack-app/packApp.d.ts +0 -22
- package/lib/pack-app/packApp.js +0 -558
- package/lib/publish/FailedToPublishError.d.ts +0 -22
- package/lib/publish/FailedToPublishError.js +0 -40
- package/lib/publish/batchPublish.d.ts +0 -20
- package/lib/publish/batchPublish.js +0 -201
- package/lib/publish/displayError.d.ts +0 -1
- package/lib/publish/displayError.js +0 -23
- package/lib/publish/executeTokenHelper.d.ts +0 -4
- package/lib/publish/executeTokenHelper.js +0 -17
- package/lib/publish/extractManifestFromPacked.d.ts +0 -19
- package/lib/publish/extractManifestFromPacked.js +0 -110
- package/lib/publish/index.d.ts +0 -3
- package/lib/publish/index.js +0 -4
- package/lib/publish/oidc/authToken.d.ts +0 -73
- package/lib/publish/oidc/authToken.js +0 -97
- package/lib/publish/oidc/idToken.d.ts +0 -76
- package/lib/publish/oidc/idToken.js +0 -90
- package/lib/publish/oidc/provenance.d.ts +0 -73
- package/lib/publish/oidc/provenance.js +0 -91
- package/lib/publish/otp.d.ts +0 -38
- package/lib/publish/otp.js +0 -41
- package/lib/publish/otpEnv.d.ts +0 -7
- package/lib/publish/otpEnv.js +0 -5
- package/lib/publish/pack.d.ts +0 -34
- package/lib/publish/pack.js +0 -408
- package/lib/publish/previousChangelog.d.ts +0 -19
- package/lib/publish/previousChangelog.js +0 -182
- package/lib/publish/publish.d.ts +0 -40
- package/lib/publish/publish.js +0 -256
- package/lib/publish/publishPackedPkg.d.ts +0 -79
- package/lib/publish/publishPackedPkg.js +0 -298
- package/lib/publish/recursivePublish.d.ts +0 -18
- package/lib/publish/recursivePublish.js +0 -132
- package/lib/publish/registryConfigKeys.d.ts +0 -30
- package/lib/publish/registryConfigKeys.js +0 -50
- package/lib/publish/utils/shared-context.d.ts +0 -7
- package/lib/publish/utils/shared-context.js +0 -20
- package/lib/stage/approve.d.ts +0 -2
- package/lib/stage/approve.js +0 -14
- package/lib/stage/context.d.ts +0 -14
- package/lib/stage/context.js +0 -25
- package/lib/stage/download.d.ts +0 -2
- package/lib/stage/download.js +0 -32
- package/lib/stage/errors.d.ts +0 -15
- package/lib/stage/errors.js +0 -17
- package/lib/stage/help.d.ts +0 -1
- package/lib/stage/help.js +0 -84
- package/lib/stage/index.d.ts +0 -13
- package/lib/stage/index.js +0 -57
- package/lib/stage/list.d.ts +0 -2
- package/lib/stage/list.js +0 -49
- package/lib/stage/parsing.d.ts +0 -6
- package/lib/stage/parsing.js +0 -27
- package/lib/stage/publish.d.ts +0 -7
- package/lib/stage/publish.js +0 -38
- package/lib/stage/reject.d.ts +0 -2
- package/lib/stage/reject.js +0 -16
- package/lib/stage/rendering.d.ts +0 -11
- package/lib/stage/rendering.js +0 -50
- package/lib/stage/request.d.ts +0 -29
- package/lib/stage/request.js +0 -110
- package/lib/stage/types.d.ts +0 -38
- package/lib/stage/types.js +0 -3
- package/lib/stage/view.d.ts +0 -2
- package/lib/stage/view.js +0 -14
- package/lib/tarball/index.d.ts +0 -2
- package/lib/tarball/index.js +0 -3
- package/lib/tarball/publishSummary.d.ts +0 -47
- package/lib/tarball/publishSummary.js +0 -36
- package/lib/tarball/safeTarballFilename.d.ts +0 -8
- package/lib/tarball/safeTarballFilename.js +0 -21
- package/lib/tarball/summarizeTarball.d.ts +0 -12
- package/lib/tarball/summarizeTarball.js +0 -84
- package/lib/version/index.d.ts +0 -33
- package/lib/version/index.js +0 -337
package/lib/publish/publish.js
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
|
-
import { confirm } from '@inquirer/prompts';
|
|
3
|
-
import { FILTERING } from '@pnpm/cli.common-cli-options-help';
|
|
4
|
-
import { docsUrl, readProjectManifest } from '@pnpm/cli.utils';
|
|
5
|
-
import { types as allTypes } from '@pnpm/config.reader';
|
|
6
|
-
import { PnpmError } from '@pnpm/error';
|
|
7
|
-
import { runLifecycleHook } from '@pnpm/exec.lifecycle';
|
|
8
|
-
import { getCurrentBranch, isGitRepo, isRemoteHistoryClean, isWorkingTreeClean } from '@pnpm/network.git-utils';
|
|
9
|
-
import { rimraf } from '@zkochan/rimraf';
|
|
10
|
-
import { pick } from 'ramda';
|
|
11
|
-
import { realpathMissing } from 'realpath-missing';
|
|
12
|
-
import { renderHelp } from 'render-help';
|
|
13
|
-
import { temporaryDirectory } from 'tempy';
|
|
14
|
-
import { extractPublishManifestFromPacked, isTarballPath } from './extractManifestFromPacked.js';
|
|
15
|
-
import { optionsWithOtpEnv } from './otpEnv.js';
|
|
16
|
-
import * as pack from './pack.js';
|
|
17
|
-
import { publishPackedPkg } from './publishPackedPkg.js';
|
|
18
|
-
import { recursivePublish } from './recursivePublish.js';
|
|
19
|
-
export function rcOptionsTypes() {
|
|
20
|
-
return pick([
|
|
21
|
-
'access',
|
|
22
|
-
'git-checks',
|
|
23
|
-
'ignore-scripts',
|
|
24
|
-
'skip-manifest-obfuscation',
|
|
25
|
-
'provenance',
|
|
26
|
-
'npm-path',
|
|
27
|
-
'otp',
|
|
28
|
-
'publish-branch',
|
|
29
|
-
'registry',
|
|
30
|
-
'tag',
|
|
31
|
-
'unsafe-perm',
|
|
32
|
-
'embed-readme',
|
|
33
|
-
], allTypes);
|
|
34
|
-
}
|
|
35
|
-
export function cliOptionsTypes() {
|
|
36
|
-
return {
|
|
37
|
-
...rcOptionsTypes(),
|
|
38
|
-
batch: Boolean,
|
|
39
|
-
'dry-run': Boolean,
|
|
40
|
-
force: Boolean,
|
|
41
|
-
json: Boolean,
|
|
42
|
-
otp: String,
|
|
43
|
-
recursive: Boolean,
|
|
44
|
-
'report-summary': Boolean,
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
export const commandNames = ['publish'];
|
|
48
|
-
export function help() {
|
|
49
|
-
return renderHelp({
|
|
50
|
-
description: 'Publishes a package to the npm registry.',
|
|
51
|
-
descriptionLists: [
|
|
52
|
-
{
|
|
53
|
-
title: 'Options',
|
|
54
|
-
list: [
|
|
55
|
-
{
|
|
56
|
-
description: "Don't check if current branch is your publish branch, clean, and up to date",
|
|
57
|
-
name: '--no-git-checks',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
description: 'Sets branch name to publish. Default is master',
|
|
61
|
-
name: '--publish-branch',
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
description: 'Does everything a publish would do except actually publishing to the registry',
|
|
65
|
-
name: '--dry-run',
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
description: 'Show information in JSON format',
|
|
69
|
-
name: '--json',
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
description: 'Registers the published package with the given tag. By default, the "latest" tag is used.',
|
|
73
|
-
name: '--tag <tag>',
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
description: 'Tells the registry whether this package should be published as public or restricted',
|
|
77
|
-
name: '--access <public|restricted>',
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
description: 'Ignores any publish related lifecycle scripts (prepublishOnly, postpublish, and the like)',
|
|
81
|
-
name: '--ignore-scripts',
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
description: 'Skip pnpm\'s manifest obfuscation: keep the original `packageManager` field and publish lifecycle scripts in the published manifest instead of stripping them. The pnpm-specific `pnpm` field is still omitted.',
|
|
85
|
-
name: '--skip-manifest-obfuscation',
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
description: 'Packages are proceeded to be published even if their current version is already in the registry. This is useful when a "prepublishOnly" script bumps the version of the package before it is published',
|
|
89
|
-
name: '--force',
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
description: 'Save the list of the newly published packages to "pnpm-publish-summary.json". Useful when some other tooling is used to report the list of published packages.',
|
|
93
|
-
name: '--report-summary',
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
description: 'When publishing packages that require two-factor authentication, this option can specify a one-time password',
|
|
97
|
-
name: '--otp',
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
description: 'Publish all packages from the workspace',
|
|
101
|
-
name: '--recursive',
|
|
102
|
-
shortAlias: '-r',
|
|
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
|
-
},
|
|
108
|
-
],
|
|
109
|
-
},
|
|
110
|
-
FILTERING,
|
|
111
|
-
],
|
|
112
|
-
url: docsUrl('publish'),
|
|
113
|
-
usages: ['pnpm publish [<tarball>|<dir>] [--tag <tag>] [--access <public|restricted>] [options]'],
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
const GIT_CHECKS_HINT = 'If you want to disable Git checks on publish, set the "git-checks" setting to "false", or run again with "--no-git-checks".';
|
|
117
|
-
export async function handler(opts, params) {
|
|
118
|
-
const result = await publish(opts, params);
|
|
119
|
-
// Emit per-package summaries on stdout when --json is set: single object for a single-package
|
|
120
|
-
// publish, array for recursive publish. Mirrors `pnpm pack --json`'s shape choice.
|
|
121
|
-
if (opts.json) {
|
|
122
|
-
if (result?.publishSummary) {
|
|
123
|
-
return { output: JSON.stringify(result.publishSummary, null, 2), exitCode: 0 };
|
|
124
|
-
}
|
|
125
|
-
if (result?.publishedPackages) {
|
|
126
|
-
return { output: JSON.stringify(result.publishedPackages, null, 2), exitCode: result.exitCode ?? 0 };
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
if (result?.manifest)
|
|
130
|
-
return;
|
|
131
|
-
return result;
|
|
132
|
-
}
|
|
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
|
-
}
|
|
139
|
-
if (opts.gitChecks !== false && await isGitRepo()) {
|
|
140
|
-
if (!(await isWorkingTreeClean())) {
|
|
141
|
-
throw new PnpmError('GIT_UNCLEAN', 'Unclean working tree. Commit or stash changes first.', {
|
|
142
|
-
hint: GIT_CHECKS_HINT,
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
const branches = opts.publishBranch ? [opts.publishBranch] : ['master', 'main'];
|
|
146
|
-
const currentBranch = await getCurrentBranch();
|
|
147
|
-
if (currentBranch === null) {
|
|
148
|
-
throw new PnpmError('GIT_UNKNOWN_BRANCH', `The Git HEAD may not attached to any branch, but your "publish-branch" is set to "${branches.join('|')}".`, {
|
|
149
|
-
hint: GIT_CHECKS_HINT,
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
if (!branches.includes(currentBranch)) {
|
|
153
|
-
let isConfirmed;
|
|
154
|
-
try {
|
|
155
|
-
isConfirmed = await confirm({
|
|
156
|
-
message: `You're on branch "${currentBranch}" but your "publish-branch" is set to "${branches.join('|')}". Do you want to continue?`,
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
catch (err) {
|
|
160
|
-
if (err instanceof Error && err.name === 'ExitPromptError') {
|
|
161
|
-
isConfirmed = false;
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
throw err;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
if (!isConfirmed) {
|
|
168
|
-
throw new PnpmError('GIT_NOT_CORRECT_BRANCH', `Branch is not on '${branches.join('|')}'.`, {
|
|
169
|
-
hint: GIT_CHECKS_HINT,
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
if (!(await isRemoteHistoryClean())) {
|
|
174
|
-
throw new PnpmError('GIT_NOT_LATEST', 'Remote history differs. Please pull changes.', {
|
|
175
|
-
hint: GIT_CHECKS_HINT,
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
if (opts.recursive && (opts.selectedProjectsGraph != null)) {
|
|
180
|
-
const { exitCode, publishedPackages } = await recursivePublish({
|
|
181
|
-
...opts,
|
|
182
|
-
selectedProjectsGraph: opts.selectedProjectsGraph,
|
|
183
|
-
workspaceDir: opts.workspaceDir ?? process.cwd(),
|
|
184
|
-
});
|
|
185
|
-
return { exitCode, publishedPackages };
|
|
186
|
-
}
|
|
187
|
-
opts = optionsWithOtpEnv(opts, process.env);
|
|
188
|
-
const dirInParams = (params.length > 0) ? params[0] : undefined;
|
|
189
|
-
if (dirInParams != null && isTarballPath(dirInParams)) {
|
|
190
|
-
const tarballPath = dirInParams;
|
|
191
|
-
const publishedManifest = await extractPublishManifestFromPacked(tarballPath);
|
|
192
|
-
// Publishing a pre-built tarball bypasses `pack.api()`, so we don't have the file listing
|
|
193
|
-
// or unpacked size — those summary fields are reported as empty/zero.
|
|
194
|
-
const publishSummary = await publishPackedPkg({
|
|
195
|
-
tarballPath,
|
|
196
|
-
publishedManifest,
|
|
197
|
-
contents: [],
|
|
198
|
-
unpackedSize: 0,
|
|
199
|
-
}, opts);
|
|
200
|
-
return { exitCode: 0, publishSummary };
|
|
201
|
-
}
|
|
202
|
-
const dir = dirInParams ?? opts.dir ?? process.cwd();
|
|
203
|
-
const _runScriptsIfPresent = runScriptsIfPresent.bind(null, {
|
|
204
|
-
depPath: dir,
|
|
205
|
-
extraBinPaths: opts.extraBinPaths,
|
|
206
|
-
extraEnv: opts.extraEnv,
|
|
207
|
-
pkgRoot: dir,
|
|
208
|
-
rootModulesDir: await realpathMissing(path.join(dir, 'node_modules')),
|
|
209
|
-
stdio: 'inherit',
|
|
210
|
-
unsafePerm: true, // when running scripts explicitly, assume that they're trusted.
|
|
211
|
-
userAgent: opts.userAgent,
|
|
212
|
-
});
|
|
213
|
-
const { manifest } = await readProjectManifest(dir, opts);
|
|
214
|
-
// Unfortunately, we cannot support postpack at the moment
|
|
215
|
-
if (!opts.ignoreScripts) {
|
|
216
|
-
await _runScriptsIfPresent([
|
|
217
|
-
'prepublishOnly',
|
|
218
|
-
'prepublish',
|
|
219
|
-
], manifest);
|
|
220
|
-
}
|
|
221
|
-
// We have to publish the tarball from another location.
|
|
222
|
-
// Otherwise, npm would publish the package with the package.json file
|
|
223
|
-
// from the current working directory, ignoring the package.json file
|
|
224
|
-
// that was generated and packed to the tarball.
|
|
225
|
-
const packDestination = temporaryDirectory();
|
|
226
|
-
let publishedManifest;
|
|
227
|
-
let publishSummary;
|
|
228
|
-
try {
|
|
229
|
-
const packResult = await pack.api({
|
|
230
|
-
...opts,
|
|
231
|
-
dir,
|
|
232
|
-
packDestination,
|
|
233
|
-
dryRun: false,
|
|
234
|
-
});
|
|
235
|
-
publishSummary = await publishPackedPkg(packResult, opts);
|
|
236
|
-
publishedManifest = packResult.publishedManifest;
|
|
237
|
-
}
|
|
238
|
-
finally {
|
|
239
|
-
await rimraf(packDestination);
|
|
240
|
-
}
|
|
241
|
-
if (!opts.ignoreScripts) {
|
|
242
|
-
await _runScriptsIfPresent([
|
|
243
|
-
'publish',
|
|
244
|
-
'postpublish',
|
|
245
|
-
], manifest);
|
|
246
|
-
}
|
|
247
|
-
return { manifest, publishedManifest, publishSummary };
|
|
248
|
-
}
|
|
249
|
-
export async function runScriptsIfPresent(opts, scriptNames, manifest) {
|
|
250
|
-
for (const scriptName of scriptNames) {
|
|
251
|
-
if (!manifest.scripts?.[scriptName])
|
|
252
|
-
continue;
|
|
253
|
-
await runLifecycleHook(scriptName, manifest, opts); // eslint-disable-line no-await-in-loop
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
//# sourceMappingURL=publish.js.map
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { Config } from '@pnpm/config.reader';
|
|
2
|
-
import { PnpmError } from '@pnpm/error';
|
|
3
|
-
import type { ExportedManifest } from '@pnpm/releasing.exportable-manifest';
|
|
4
|
-
import { type RegistryConfig } from '@pnpm/types';
|
|
5
|
-
import { type PublishSummary } from '../tarball/publishSummary.js';
|
|
6
|
-
import { type OtpContext, type PublishOptionsWithDefaultAccess } from './otp.js';
|
|
7
|
-
import type { PackResult } from './pack.js';
|
|
8
|
-
import { type NormalizedRegistryUrl } from './registryConfigKeys.js';
|
|
9
|
-
export type { PublishSummary };
|
|
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'>> & {
|
|
11
|
-
access?: 'public' | 'restricted';
|
|
12
|
-
ci?: boolean;
|
|
13
|
-
otp?: string;
|
|
14
|
-
provenance?: boolean;
|
|
15
|
-
provenanceFile?: string;
|
|
16
|
-
stage?: boolean;
|
|
17
|
-
};
|
|
18
|
-
export declare function publishPackedPkg(packResult: Pick<PackResult, 'publishedManifest' | 'tarballPath' | 'contents' | 'unpackedSize'>, opts: PublishPackedPkgOptions): Promise<PublishSummary>;
|
|
19
|
-
/**
|
|
20
|
-
* Builds the {@link OtpContext} used to drive the publish. The default fetch
|
|
21
|
-
* is replaced by one that respects proxy / TLS / local-address settings, so
|
|
22
|
-
* the `doneUrl` polling in the web-based authentication flow goes through
|
|
23
|
-
* the same network configuration as the initial publish request (see
|
|
24
|
-
* https://github.com/pnpm/pnpm/issues/11561).
|
|
25
|
-
*/
|
|
26
|
-
export declare function createPublishContext(opts: PublishPackedPkgOptions): OtpContext;
|
|
27
|
-
type StagePublishOptions = PublishOptionsWithDefaultAccess & {
|
|
28
|
-
command?: string;
|
|
29
|
-
stage?: boolean;
|
|
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.
|
|
55
|
-
*/
|
|
56
|
-
export declare function findRegistryInfo({ name }: ExportedManifest, { configByUri, registries }: Pick<Config, 'configByUri' | 'registries'>, publishConfigRegistry?: string): Partial<RegistryInfo>;
|
|
57
|
-
export declare class PublishUnsupportedRegistryProtocolError extends PnpmError {
|
|
58
|
-
readonly registryUrl: string;
|
|
59
|
-
constructor(registryUrl: string);
|
|
60
|
-
}
|
|
61
|
-
interface OidcTokenProvenanceResult {
|
|
62
|
-
authToken: string;
|
|
63
|
-
provenance?: boolean;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Try fetching an authentication token and provenance by OpenID Connect.
|
|
67
|
-
*
|
|
68
|
-
* The result, when defined, is intended to take precedence over any statically configured
|
|
69
|
-
* authentication. This mirrors the npm CLI's OIDC flow, which always attempts the exchange
|
|
70
|
-
* in supported CI environments and overwrites a configured `_authToken` on success.
|
|
71
|
-
*
|
|
72
|
-
* @returns the OIDC-derived authToken (and provenance flag) on success, or `undefined` when
|
|
73
|
-
* OIDC is not applicable / not configured on the registry — in which case callers should
|
|
74
|
-
* fall back to whatever static authentication they already have.
|
|
75
|
-
*
|
|
76
|
-
* @internal Exported for unit testing of the precedence rules. Not part of the package's
|
|
77
|
-
* public API.
|
|
78
|
-
*/
|
|
79
|
-
export declare function fetchTokenAndProvenanceByOidc(packageName: string, registry: string, options: PublishPackedPkgOptions): Promise<OidcTokenProvenanceResult | undefined>;
|
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import { PnpmError, redactUrlCredentials } from '@pnpm/error';
|
|
3
|
-
import { globalInfo, globalWarn } from '@pnpm/logger';
|
|
4
|
-
import { createDispatchedFetch } from '@pnpm/network.fetch';
|
|
5
|
-
import { DEFAULT_REGISTRY_SCOPE } from '@pnpm/types';
|
|
6
|
-
import { createPublishSummary } from '../tarball/publishSummary.js';
|
|
7
|
-
import { displayError } from './displayError.js';
|
|
8
|
-
import { executeTokenHelper } from './executeTokenHelper.js';
|
|
9
|
-
import { createFailedToPublishError } from './FailedToPublishError.js';
|
|
10
|
-
import { AuthTokenError, fetchAuthToken } from './oidc/authToken.js';
|
|
11
|
-
import { getIdToken, IdTokenError } from './oidc/idToken.js';
|
|
12
|
-
import { determineProvenance, ProvenanceError } from './oidc/provenance.js';
|
|
13
|
-
import { publishWithOtpHandling } from './otp.js';
|
|
14
|
-
import { allRegistryConfigKeys, parseSupportedRegistryUrl } from './registryConfigKeys.js';
|
|
15
|
-
import { SHARED_CONTEXT } from './utils/shared-context.js';
|
|
16
|
-
export async function publishPackedPkg(packResult, opts) {
|
|
17
|
-
const { publishedManifest, tarballPath, contents, unpackedSize } = packResult;
|
|
18
|
-
const tarballData = await fs.readFile(tarballPath);
|
|
19
|
-
const publishOptions = await createPublishOptions(publishedManifest, opts);
|
|
20
|
-
const { name, version } = publishedManifest;
|
|
21
|
-
const { registry } = publishOptions;
|
|
22
|
-
const isStage = opts.stage === true;
|
|
23
|
-
// Redact any `user:pass@` credentials a registry= URL may carry so they don't leak into logs.
|
|
24
|
-
globalInfo(`📦 ${name}@${version} → ${registry != null ? redactUrlCredentials(registry) : 'the default registry'}`);
|
|
25
|
-
const summary = createPublishSummary({ publishedManifest, tarballPath, contents, unpackedSize }, tarballData);
|
|
26
|
-
if (opts.dryRun) {
|
|
27
|
-
globalWarn(`Skip ${isStage ? 'staging' : 'publishing'} ${name}@${version} (dry run)`);
|
|
28
|
-
return summary;
|
|
29
|
-
}
|
|
30
|
-
const context = createPublishContext(opts);
|
|
31
|
-
const response = await publishWithOtpHandling({
|
|
32
|
-
context,
|
|
33
|
-
manifest: publishedManifest,
|
|
34
|
-
publishOptions,
|
|
35
|
-
tarballData,
|
|
36
|
-
});
|
|
37
|
-
if (response.ok) {
|
|
38
|
-
if (isStage && response.stageId) {
|
|
39
|
-
summary.stageId = response.stageId;
|
|
40
|
-
}
|
|
41
|
-
globalInfo(`✅ ${isStage ? 'Staged' : 'Published'} package ${name}@${version}`);
|
|
42
|
-
return summary;
|
|
43
|
-
}
|
|
44
|
-
throw await createFailedToPublishError(packResult, response);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Builds the {@link OtpContext} used to drive the publish. The default fetch
|
|
48
|
-
* is replaced by one that respects proxy / TLS / local-address settings, so
|
|
49
|
-
* the `doneUrl` polling in the web-based authentication flow goes through
|
|
50
|
-
* the same network configuration as the initial publish request (see
|
|
51
|
-
* https://github.com/pnpm/pnpm/issues/11561).
|
|
52
|
-
*/
|
|
53
|
-
export function createPublishContext(opts) {
|
|
54
|
-
return {
|
|
55
|
-
...SHARED_CONTEXT,
|
|
56
|
-
fetch: createDispatchedFetch({ ...opts, timeout: opts.fetchTimeout }),
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Build the libnpmpublish / npm-registry-fetch options (registry, auth, headers) for publishing
|
|
61
|
-
* {@link manifest}. When `oidc` is `false`, the per-package OIDC token exchange is skipped and only
|
|
62
|
-
* statically configured credentials are used — batch publish sends many packages in one request,
|
|
63
|
-
* which a package-scoped OIDC token cannot authorize.
|
|
64
|
-
*
|
|
65
|
-
* @internal Exported for unit testing of the access / registry / auth fallback rules and for batch
|
|
66
|
-
* publish. Not part of the package's public API.
|
|
67
|
-
*/
|
|
68
|
-
export async function createPublishOptions(manifest, options, { oidc = true } = {}) {
|
|
69
|
-
const publishConfigRegistry = typeof manifest.publishConfig?.registry === 'string'
|
|
70
|
-
? manifest.publishConfig.registry
|
|
71
|
-
: undefined;
|
|
72
|
-
const { registry, config } = findRegistryInfo(manifest, options, publishConfigRegistry);
|
|
73
|
-
const tls = config?.tls;
|
|
74
|
-
const creds = config?.[DEFAULT_REGISTRY_SCOPE];
|
|
75
|
-
const publishConfigAccess = manifest.publishConfig?.access;
|
|
76
|
-
const access = options.access ?? (isPublishAccess(publishConfigAccess) ? publishConfigAccess : null);
|
|
77
|
-
const { ci: isFromCI, fetchRetries, fetchRetryFactor, fetchRetryMaxtimeout, fetchRetryMintimeout, fetchTimeout: timeout, otp, provenance, provenanceFile, tag: defaultTag, userAgent, } = options;
|
|
78
|
-
const npmCommand = options.stage === true ? 'stage' : 'publish';
|
|
79
|
-
const headers = {
|
|
80
|
-
'npm-auth-type': 'web',
|
|
81
|
-
'npm-command': npmCommand,
|
|
82
|
-
};
|
|
83
|
-
const publishOptions = {
|
|
84
|
-
access,
|
|
85
|
-
defaultTag,
|
|
86
|
-
fetchRetries,
|
|
87
|
-
fetchRetryFactor,
|
|
88
|
-
fetchRetryMaxtimeout,
|
|
89
|
-
fetchRetryMintimeout,
|
|
90
|
-
headers,
|
|
91
|
-
isFromCI,
|
|
92
|
-
otp,
|
|
93
|
-
timeout,
|
|
94
|
-
provenance,
|
|
95
|
-
provenanceFile,
|
|
96
|
-
registry,
|
|
97
|
-
strictSSL: options.strictSsl, // npm-registry-fetch defaults to true; must be set explicitly to honour strictSsl: false
|
|
98
|
-
userAgent,
|
|
99
|
-
// Signal to the registry that the client supports web-based authentication.
|
|
100
|
-
// Without this, the registry would never offer the web auth flow and would
|
|
101
|
-
// always fall back to prompting the user for an OTP code, even when the user
|
|
102
|
-
// has no OTP set up.
|
|
103
|
-
authType: 'web',
|
|
104
|
-
ca: tls?.ca,
|
|
105
|
-
cert: tls?.cert,
|
|
106
|
-
key: tls?.key,
|
|
107
|
-
npmCommand,
|
|
108
|
-
token: creds && extractToken(creds),
|
|
109
|
-
username: creds?.basicAuth?.username,
|
|
110
|
-
password: creds?.basicAuth?.password,
|
|
111
|
-
};
|
|
112
|
-
if (options.stage === true) {
|
|
113
|
-
publishOptions.command = 'stage';
|
|
114
|
-
publishOptions.stage = true;
|
|
115
|
-
}
|
|
116
|
-
if (registry) {
|
|
117
|
-
if (oidc) {
|
|
118
|
-
// OIDC takes precedence over a configured static `_authToken`, mirroring the npm CLI's
|
|
119
|
-
// behavior (see https://github.com/npm/cli/blob/7d900c46/lib/utils/oidc.js). Trusted
|
|
120
|
-
// publishing wins whenever the registry has it configured for the package; the static
|
|
121
|
-
// token is used only as a fallback when OIDC is not applicable.
|
|
122
|
-
const oidcTokenProvenance = await fetchTokenAndProvenanceByOidc(manifest.name, registry, options);
|
|
123
|
-
if (oidcTokenProvenance?.authToken) {
|
|
124
|
-
publishOptions.token = oidcTokenProvenance.authToken;
|
|
125
|
-
}
|
|
126
|
-
publishOptions.provenance ??= oidcTokenProvenance?.provenance;
|
|
127
|
-
}
|
|
128
|
-
appendAuthOptionsForRegistry(publishOptions, registry);
|
|
129
|
-
}
|
|
130
|
-
pruneUndefined(publishOptions);
|
|
131
|
-
return publishOptions;
|
|
132
|
-
}
|
|
133
|
-
export function isPublishAccess(access) {
|
|
134
|
-
return access === 'public' || access === 'restricted';
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Find credentials and SSL info for a package's registry.
|
|
138
|
-
* Follows {@link https://docs.npmjs.com/cli/v10/configuring-npm/npmrc#auth-related-configuration}.
|
|
139
|
-
*
|
|
140
|
-
* The manifest's `publishConfig.registry`, when set, takes precedence over `registries`.
|
|
141
|
-
*
|
|
142
|
-
* @internal Exported for batch publish, which groups packages by their target registry.
|
|
143
|
-
*/
|
|
144
|
-
export function findRegistryInfo({ name }, { configByUri, registries }, publishConfigRegistry) {
|
|
145
|
-
// eslint-disable-next-line regexp/no-unused-capturing-group
|
|
146
|
-
const scopedMatches = /@(?<scope>[^/]+)\/(?<slug>[^/]+)/.exec(name);
|
|
147
|
-
const registryName = scopedMatches?.groups ? `@${scopedMatches.groups.scope}` : 'default';
|
|
148
|
-
const nonNormalizedRegistry = publishConfigRegistry ?? registries[registryName] ?? registries.default;
|
|
149
|
-
const supportedRegistryInfo = parseSupportedRegistryUrl(nonNormalizedRegistry);
|
|
150
|
-
if (!supportedRegistryInfo) {
|
|
151
|
-
throw new PublishUnsupportedRegistryProtocolError(nonNormalizedRegistry);
|
|
152
|
-
}
|
|
153
|
-
const { normalizedUrl: registry, longestConfigKey: initialRegistryConfigKey, } = supportedRegistryInfo;
|
|
154
|
-
const credsScope = registryName === 'default' ? DEFAULT_REGISTRY_SCOPE : registryName;
|
|
155
|
-
let creds;
|
|
156
|
-
let tls = {};
|
|
157
|
-
for (const registryConfigKey of allRegistryConfigKeys(initialRegistryConfigKey)) {
|
|
158
|
-
const entry = configByUri[registryConfigKey];
|
|
159
|
-
if (!entry)
|
|
160
|
-
continue;
|
|
161
|
-
// Auth from longer path collectively overrides shorter path
|
|
162
|
-
creds ??= entry[credsScope] ?? entry[DEFAULT_REGISTRY_SCOPE];
|
|
163
|
-
// TLS from longer path individually overrides shorter path
|
|
164
|
-
tls = { ...entry.tls, ...tls };
|
|
165
|
-
}
|
|
166
|
-
const config = { tls };
|
|
167
|
-
if (creds) {
|
|
168
|
-
config[DEFAULT_REGISTRY_SCOPE] = creds;
|
|
169
|
-
}
|
|
170
|
-
return {
|
|
171
|
-
registry,
|
|
172
|
-
config,
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
function extractToken({ authToken, tokenHelper, }) {
|
|
176
|
-
if (authToken)
|
|
177
|
-
return authToken;
|
|
178
|
-
if (tokenHelper) {
|
|
179
|
-
return executeTokenHelper(tokenHelper, { globalWarn });
|
|
180
|
-
}
|
|
181
|
-
return undefined;
|
|
182
|
-
}
|
|
183
|
-
export class PublishUnsupportedRegistryProtocolError extends PnpmError {
|
|
184
|
-
registryUrl;
|
|
185
|
-
constructor(registryUrl) {
|
|
186
|
-
super('PUBLISH_UNSUPPORTED_REGISTRY_PROTOCOL', `Registry ${registryUrl} has an unsupported protocol`, {
|
|
187
|
-
hint: '`pnpm publish` only supports HTTP and HTTPS registries',
|
|
188
|
-
});
|
|
189
|
-
this.registryUrl = registryUrl;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Try fetching an authentication token and provenance by OpenID Connect.
|
|
194
|
-
*
|
|
195
|
-
* The result, when defined, is intended to take precedence over any statically configured
|
|
196
|
-
* authentication. This mirrors the npm CLI's OIDC flow, which always attempts the exchange
|
|
197
|
-
* in supported CI environments and overwrites a configured `_authToken` on success.
|
|
198
|
-
*
|
|
199
|
-
* @returns the OIDC-derived authToken (and provenance flag) on success, or `undefined` when
|
|
200
|
-
* OIDC is not applicable / not configured on the registry — in which case callers should
|
|
201
|
-
* fall back to whatever static authentication they already have.
|
|
202
|
-
*
|
|
203
|
-
* @internal Exported for unit testing of the precedence rules. Not part of the package's
|
|
204
|
-
* public API.
|
|
205
|
-
*/
|
|
206
|
-
export async function fetchTokenAndProvenanceByOidc(packageName, registry, options) {
|
|
207
|
-
let idToken;
|
|
208
|
-
try {
|
|
209
|
-
idToken = await getIdToken({
|
|
210
|
-
options,
|
|
211
|
-
registry,
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
catch (error) {
|
|
215
|
-
if (error instanceof IdTokenError) {
|
|
216
|
-
globalWarn(`Skipped OIDC: ${displayError(error)}`);
|
|
217
|
-
return undefined;
|
|
218
|
-
}
|
|
219
|
-
throw error;
|
|
220
|
-
}
|
|
221
|
-
if (!idToken) {
|
|
222
|
-
// OIDC is simply not applicable here — either we're outside of CI, or we're in a CI
|
|
223
|
-
// that doesn't natively drive OIDC and the user hasn't forwarded a token via
|
|
224
|
-
// `NPM_ID_TOKEN`. This is the common case for local publishes, so it must stay
|
|
225
|
-
// silent — only configuration *errors* in a supported CI environment surface as
|
|
226
|
-
// warnings, and those come back as `IdTokenError` and are handled above.
|
|
227
|
-
return undefined;
|
|
228
|
-
}
|
|
229
|
-
let authToken;
|
|
230
|
-
try {
|
|
231
|
-
authToken = await fetchAuthToken({
|
|
232
|
-
idToken,
|
|
233
|
-
options,
|
|
234
|
-
packageName,
|
|
235
|
-
registry,
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
catch (error) {
|
|
239
|
-
if (error instanceof AuthTokenError) {
|
|
240
|
-
globalWarn(`Skipped OIDC: ${displayError(error)}`);
|
|
241
|
-
return undefined;
|
|
242
|
-
}
|
|
243
|
-
throw error;
|
|
244
|
-
}
|
|
245
|
-
if (options.provenance != null) {
|
|
246
|
-
return {
|
|
247
|
-
authToken,
|
|
248
|
-
provenance: options.provenance,
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
let provenance;
|
|
252
|
-
try {
|
|
253
|
-
provenance = await determineProvenance({
|
|
254
|
-
authToken,
|
|
255
|
-
idToken,
|
|
256
|
-
options,
|
|
257
|
-
packageName,
|
|
258
|
-
registry,
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
catch (error) {
|
|
262
|
-
if (error instanceof ProvenanceError) {
|
|
263
|
-
// Don't lose the OIDC-derived authToken just because we couldn't determine the
|
|
264
|
-
// provenance flag — the publish itself can still go through, and that's what
|
|
265
|
-
// the npm CLI does too.
|
|
266
|
-
globalWarn(`Skipped setting provenance: ${displayError(error)}`);
|
|
267
|
-
return { authToken };
|
|
268
|
-
}
|
|
269
|
-
throw error;
|
|
270
|
-
}
|
|
271
|
-
return { authToken, provenance };
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Appends authentication information to {@link targetPublishOptions} to explicitly target {@link registry}.
|
|
275
|
-
*
|
|
276
|
-
* `libnpmpublish` has a quirk in which it only read the authentication information from `//<registry>:_authToken`
|
|
277
|
-
* instead of `token`.
|
|
278
|
-
* This function fixes that by making sure the registry specific authentication information exists.
|
|
279
|
-
*/
|
|
280
|
-
function appendAuthOptionsForRegistry(targetPublishOptions, registry) {
|
|
281
|
-
const registryInfo = parseSupportedRegistryUrl(registry);
|
|
282
|
-
if (!registryInfo) {
|
|
283
|
-
globalWarn(`The registry ${registry} cannot be converted into a config key. Supplement is skipped. Subsequent libnpmpublish call may fail.`);
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
const registryConfigKey = registryInfo.longestConfigKey;
|
|
287
|
-
targetPublishOptions[`${registryConfigKey}:_authToken`] ??= targetPublishOptions.token;
|
|
288
|
-
targetPublishOptions[`${registryConfigKey}:username`] ??= targetPublishOptions.username;
|
|
289
|
-
targetPublishOptions[`${registryConfigKey}:_password`] ??= targetPublishOptions.password && btoa(targetPublishOptions.password);
|
|
290
|
-
}
|
|
291
|
-
function pruneUndefined(object) {
|
|
292
|
-
for (const key in object) {
|
|
293
|
-
if (object[key] === undefined) {
|
|
294
|
-
delete object[key];
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
//# sourceMappingURL=publishPackedPkg.js.map
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Config, ConfigContext } from '@pnpm/config.reader';
|
|
2
|
-
import type { PublishPackedPkgOptions, PublishSummary } from './publishPackedPkg.js';
|
|
3
|
-
export type PublishRecursiveOpts = Required<Pick<Config, 'bin' | 'cacheDir' | 'dir' | 'pnpmHomeDir' | 'configByUri' | 'registries' | 'workspaceDir'>> & Required<Pick<ConfigContext, 'cliOptions'>> & Partial<Pick<Config, 'tag' | 'ca' | 'catalogs' | 'cert' | 'fetchTimeout' | 'force' | 'dryRun' | 'extraBinPaths' | 'extraEnv' | 'fetchRetries' | 'fetchRetryFactor' | 'fetchRetryMaxtimeout' | 'fetchRetryMintimeout' | 'key' | 'httpProxy' | 'httpsProxy' | 'localAddress' | 'lockfileDir' | 'noProxy' | 'npmPath' | 'offline' | 'strictSsl' | 'unsafePerm' | 'userAgent' | 'verifyStoreIntegrity' | 'versioning'>> & Partial<Pick<ConfigContext, 'selectedProjectsGraph' | 'allProjectsGraph' | 'prodAllProjectsGraph' | 'prodOnlySelectedProjectDirs'>> & {
|
|
4
|
-
access?: 'public' | 'restricted';
|
|
5
|
-
argv: {
|
|
6
|
-
original: string[];
|
|
7
|
-
};
|
|
8
|
-
batch?: boolean;
|
|
9
|
-
reportSummary?: boolean;
|
|
10
|
-
} & PublishPackedPkgOptions;
|
|
11
|
-
export type RecursivePublishedPackage = PublishSummary | {
|
|
12
|
-
name?: string;
|
|
13
|
-
version?: string;
|
|
14
|
-
};
|
|
15
|
-
export declare function recursivePublish(opts: PublishRecursiveOpts & Required<Pick<ConfigContext, 'selectedProjectsGraph'>>): Promise<{
|
|
16
|
-
exitCode: number;
|
|
17
|
-
publishedPackages: RecursivePublishedPackage[];
|
|
18
|
-
}>;
|