@pnpm/releasing.commands 1100.2.17 → 1100.3.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/deploy.js +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/publish/otp.d.ts +2 -0
- package/lib/publish/pack.d.ts +1 -1
- package/lib/publish/pack.js +9 -1
- package/lib/publish/publish.d.ts +2 -2
- package/lib/publish/publish.js +5 -0
- package/lib/publish/publishPackedPkg.d.ts +3 -29
- package/lib/publish/publishPackedPkg.js +16 -20
- package/lib/publish/recursivePublish.js +2 -1
- package/lib/stage/approve.d.ts +2 -0
- package/lib/stage/approve.js +14 -0
- package/lib/stage/context.d.ts +14 -0
- package/lib/stage/context.js +25 -0
- package/lib/stage/download.d.ts +2 -0
- package/lib/stage/download.js +25 -0
- package/lib/stage/errors.d.ts +15 -0
- package/lib/stage/errors.js +17 -0
- package/lib/stage/help.d.ts +1 -0
- package/lib/stage/help.js +84 -0
- package/lib/stage/index.d.ts +13 -0
- package/lib/stage/index.js +57 -0
- package/lib/stage/list.d.ts +2 -0
- package/lib/stage/list.js +44 -0
- package/lib/stage/parsing.d.ts +6 -0
- package/lib/stage/parsing.js +27 -0
- package/lib/stage/publish.d.ts +7 -0
- package/lib/stage/publish.js +38 -0
- package/lib/stage/reject.d.ts +2 -0
- package/lib/stage/reject.js +16 -0
- package/lib/stage/rendering.d.ts +11 -0
- package/lib/stage/rendering.js +52 -0
- package/lib/stage/request.d.ts +29 -0
- package/lib/stage/request.js +110 -0
- package/lib/stage/types.d.ts +38 -0
- package/lib/stage/types.js +3 -0
- package/lib/stage/view.d.ts +2 -0
- package/lib/stage/view.js +14 -0
- package/lib/tarball/index.d.ts +2 -0
- package/lib/tarball/index.js +3 -0
- package/lib/tarball/publishSummary.d.ts +39 -0
- package/lib/tarball/publishSummary.js +16 -0
- package/lib/tarball/summarizeTarball.d.ts +12 -0
- package/lib/tarball/summarizeTarball.js +86 -0
- package/package.json +24 -23
package/lib/deploy/deploy.js
CHANGED
|
@@ -240,6 +240,7 @@ async function deployFromSharedLockfile(opts, selectedProject, deployDir) {
|
|
|
240
240
|
injectWorkspacePackages: undefined, // the effects of injecting workspace packages should already be part of the package snapshots
|
|
241
241
|
overrides: undefined, // the effects of the overrides should already be part of the package snapshots
|
|
242
242
|
packageExtensions: undefined, // the effects of the package extensions should already be part of the package snapshots
|
|
243
|
+
configDependencies: undefined, // configDependencies (e.g. pacquet) are not installed into the deploy dir, so the install engine they designate isn't on disk to invoke
|
|
243
244
|
hooks: {
|
|
244
245
|
...opts.hooks,
|
|
245
246
|
readPackage: [
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { deploy } from './deploy/index.js';
|
|
2
2
|
export { packApp } from './pack-app/index.js';
|
|
3
3
|
export { pack, publish } from './publish/index.js';
|
|
4
|
+
export * as stage from './stage/index.js';
|
|
4
5
|
export { version } from './version/index.js';
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
package/lib/publish/otp.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface OtpPublishResponse {
|
|
|
6
6
|
readonly status: number;
|
|
7
7
|
readonly statusText: string;
|
|
8
8
|
readonly text: () => Promise<string>;
|
|
9
|
+
/** Set by the registry only when the publish was staged (i.e. `stage: true` was sent). */
|
|
10
|
+
readonly stageId?: string;
|
|
9
11
|
}
|
|
10
12
|
export type OtpPublishFn = (manifest: ExportedManifest, tarballData: Buffer, options: PublishOptions) => Promise<OtpPublishResponse>;
|
|
11
13
|
export interface OtpContext extends BaseOtpContext {
|
package/lib/publish/pack.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare function rcOptionsTypes(): Record<string, unknown>;
|
|
|
4
4
|
export declare function cliOptionsTypes(): Record<string, unknown>;
|
|
5
5
|
export declare const commandNames: string[];
|
|
6
6
|
export declare function help(): string;
|
|
7
|
-
export type PackOptions = Pick<UniversalOptions, 'dir'> & Pick<Config, 'catalogs' | 'ignoreScripts' | 'embedReadme' | 'packGzipLevel' | 'nodeLinker' | 'userAgent'> & Partial<Pick<Config, 'extraBinPaths' | 'extraEnv' | 'recursive' | 'workspaceConcurrency' | 'workspaceDir'>> & Partial<Pick<ConfigContext, 'hooks' | 'selectedProjectsGraph'>> & {
|
|
7
|
+
export type PackOptions = Pick<UniversalOptions, 'dir'> & Pick<Config, 'catalogs' | 'ignoreScripts' | 'embedReadme' | 'packGzipLevel' | 'nodeLinker' | 'skipManifestObfuscation' | 'userAgent'> & Partial<Pick<Config, 'extraBinPaths' | 'extraEnv' | 'recursive' | 'workspaceConcurrency' | 'workspaceDir'>> & Partial<Pick<ConfigContext, 'hooks' | 'selectedProjectsGraph'>> & {
|
|
8
8
|
argv: {
|
|
9
9
|
original: string[];
|
|
10
10
|
};
|
package/lib/publish/pack.js
CHANGED
|
@@ -25,6 +25,7 @@ export function rcOptionsTypes() {
|
|
|
25
25
|
...cliOptionsTypes(),
|
|
26
26
|
...pick([
|
|
27
27
|
'npm-path',
|
|
28
|
+
'skip-manifest-obfuscation',
|
|
28
29
|
], allTypes),
|
|
29
30
|
};
|
|
30
31
|
}
|
|
@@ -37,6 +38,7 @@ export function cliOptionsTypes() {
|
|
|
37
38
|
'pack-destination',
|
|
38
39
|
'pack-gzip-level',
|
|
39
40
|
'json',
|
|
41
|
+
'skip-manifest-obfuscation',
|
|
40
42
|
'workspace-concurrency',
|
|
41
43
|
], allTypes),
|
|
42
44
|
};
|
|
@@ -71,6 +73,10 @@ export function help() {
|
|
|
71
73
|
name: '--recursive',
|
|
72
74
|
shortAlias: '-r',
|
|
73
75
|
},
|
|
76
|
+
{
|
|
77
|
+
description: 'Skip pnpm\'s manifest obfuscation: keep the original `packageManager` field and publish lifecycle scripts in the packed manifest instead of stripping them. The pnpm-specific `pnpm` field is still omitted.',
|
|
78
|
+
name: '--skip-manifest-obfuscation',
|
|
79
|
+
},
|
|
74
80
|
{
|
|
75
81
|
description: `Set the maximum number of concurrency. Default is ${getDefaultWorkspaceConcurrency()}. For unlimited concurrency use Infinity.`,
|
|
76
82
|
name: '--workspace-concurrency <number>',
|
|
@@ -178,6 +184,7 @@ export async function api(opts) {
|
|
|
178
184
|
embedReadme: opts.embedReadme,
|
|
179
185
|
catalogs: opts.catalogs ?? {},
|
|
180
186
|
hooks: opts.hooks,
|
|
187
|
+
skipManifestObfuscation: opts.skipManifestObfuscation,
|
|
181
188
|
});
|
|
182
189
|
// Strip semver build metadata (the `+<build>` segment) from the published version so that
|
|
183
190
|
// the tarball, the manifest packed inside it, and the metadata sent to the registry all agree.
|
|
@@ -309,13 +316,14 @@ async function packPkg(opts) {
|
|
|
309
316
|
});
|
|
310
317
|
}
|
|
311
318
|
async function createPublishManifest(opts) {
|
|
312
|
-
const { projectDir, embedReadme, modulesDir, manifest, catalogs, hooks } = opts;
|
|
319
|
+
const { projectDir, embedReadme, modulesDir, manifest, catalogs, hooks, skipManifestObfuscation } = opts;
|
|
313
320
|
const readmeFile = embedReadme ? await readReadmeFile(projectDir) : undefined;
|
|
314
321
|
return createExportableManifest(projectDir, manifest, {
|
|
315
322
|
catalogs,
|
|
316
323
|
hooks,
|
|
317
324
|
readmeFile,
|
|
318
325
|
modulesDir,
|
|
326
|
+
skipManifestObfuscation,
|
|
319
327
|
});
|
|
320
328
|
}
|
|
321
329
|
function toPackResultJson(packResult) {
|
package/lib/publish/publish.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export declare function handler(opts: Omit<PublishRecursiveOpts, 'workspaceDir'>
|
|
|
16
16
|
json?: boolean;
|
|
17
17
|
recursive?: boolean;
|
|
18
18
|
workspaceDir?: string;
|
|
19
|
-
} & Pick<Config, 'bin' | 'gitChecks' | 'ignoreScripts' | 'pnpmHomeDir' | 'publishBranch' | 'embedReadme'> & Pick<ConfigContext, 'allProjects'>, params: string[]): Promise<{
|
|
19
|
+
} & Pick<Config, 'bin' | 'gitChecks' | 'ignoreScripts' | 'pnpmHomeDir' | 'publishBranch' | 'embedReadme' | 'skipManifestObfuscation'> & Pick<ConfigContext, 'allProjects'>, params: string[]): Promise<{
|
|
20
20
|
exitCode?: number;
|
|
21
21
|
output?: string;
|
|
22
22
|
} | undefined>;
|
|
@@ -36,5 +36,5 @@ export declare function publish(opts: Omit<PublishRecursiveOpts, 'workspaceDir'>
|
|
|
36
36
|
engineStrict?: boolean;
|
|
37
37
|
recursive?: boolean;
|
|
38
38
|
workspaceDir?: string;
|
|
39
|
-
} & Pick<Config, 'bin' | 'gitChecks' | 'ignoreScripts' | 'pnpmHomeDir' | 'publishBranch' | 'embedReadme' | 'packGzipLevel'> & Pick<ConfigContext, 'allProjects'>, params: string[]): Promise<PublishResult>;
|
|
39
|
+
} & Pick<Config, 'bin' | 'gitChecks' | 'ignoreScripts' | 'pnpmHomeDir' | 'publishBranch' | 'embedReadme' | 'packGzipLevel' | 'skipManifestObfuscation'> & Pick<ConfigContext, 'allProjects'>, params: string[]): Promise<PublishResult>;
|
|
40
40
|
export declare function runScriptsIfPresent(opts: RunLifecycleHookOptions, scriptNames: string[], manifest: ProjectManifest): Promise<void>;
|
package/lib/publish/publish.js
CHANGED
|
@@ -21,6 +21,7 @@ export function rcOptionsTypes() {
|
|
|
21
21
|
'access',
|
|
22
22
|
'git-checks',
|
|
23
23
|
'ignore-scripts',
|
|
24
|
+
'skip-manifest-obfuscation',
|
|
24
25
|
'provenance',
|
|
25
26
|
'npm-path',
|
|
26
27
|
'otp',
|
|
@@ -78,6 +79,10 @@ export function help() {
|
|
|
78
79
|
description: 'Ignores any publish related lifecycle scripts (prepublishOnly, postpublish, and the like)',
|
|
79
80
|
name: '--ignore-scripts',
|
|
80
81
|
},
|
|
82
|
+
{
|
|
83
|
+
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.',
|
|
84
|
+
name: '--skip-manifest-obfuscation',
|
|
85
|
+
},
|
|
81
86
|
{
|
|
82
87
|
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',
|
|
83
88
|
name: '--force',
|
|
@@ -2,43 +2,18 @@ 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
4
|
import type { PublishOptions } from 'libnpmpublish';
|
|
5
|
+
import { type PublishSummary } from '../tarball/publishSummary.js';
|
|
5
6
|
import { type OtpContext } from './otp.js';
|
|
6
7
|
import type { PackResult } from './pack.js';
|
|
8
|
+
export type { PublishSummary };
|
|
7
9
|
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'>> & {
|
|
8
10
|
access?: 'public' | 'restricted';
|
|
9
11
|
ci?: boolean;
|
|
10
12
|
otp?: string;
|
|
11
13
|
provenance?: boolean;
|
|
12
14
|
provenanceFile?: string;
|
|
15
|
+
stage?: boolean;
|
|
13
16
|
};
|
|
14
|
-
/**
|
|
15
|
-
* Per-package summary describing a successful publish, modeled after `npm publish --json`.
|
|
16
|
-
* Returned to callers and serialized to stdout when `pnpm publish --json` is used.
|
|
17
|
-
*/
|
|
18
|
-
export interface PublishSummary {
|
|
19
|
-
/** Human-readable identifier `${name}@${version}`. */
|
|
20
|
-
id: string;
|
|
21
|
-
name: string;
|
|
22
|
-
version: string;
|
|
23
|
-
/** Compressed tarball size in bytes. */
|
|
24
|
-
size: number;
|
|
25
|
-
/** Total uncompressed size of all files in the tarball, in bytes. */
|
|
26
|
-
unpackedSize: number;
|
|
27
|
-
/** Lowercase hex SHA-1 digest of the tarball. */
|
|
28
|
-
shasum: string;
|
|
29
|
-
/** SRI-formatted SHA-512 digest of the tarball (e.g. `sha512-...`). */
|
|
30
|
-
integrity: string;
|
|
31
|
-
/** Tarball file basename (e.g. `pkg-1.0.0.tgz`). */
|
|
32
|
-
filename: string;
|
|
33
|
-
/** Files inside the tarball, in the same shape `pnpm pack --json` emits. */
|
|
34
|
-
files: Array<{
|
|
35
|
-
path: string;
|
|
36
|
-
}>;
|
|
37
|
-
/** Number of files inside the tarball. */
|
|
38
|
-
entryCount: number;
|
|
39
|
-
/** Names of bundled dependencies included in the tarball (typically empty). */
|
|
40
|
-
bundled: string[];
|
|
41
|
-
}
|
|
42
17
|
export declare function publishPackedPkg(packResult: Pick<PackResult, 'publishedManifest' | 'tarballPath' | 'contents' | 'unpackedSize'>, opts: PublishPackedPkgOptions): Promise<PublishSummary>;
|
|
43
18
|
/**
|
|
44
19
|
* Builds the {@link OtpContext} used to drive the publish. The default fetch
|
|
@@ -76,4 +51,3 @@ interface OidcTokenProvenanceResult {
|
|
|
76
51
|
* public API.
|
|
77
52
|
*/
|
|
78
53
|
export declare function fetchTokenAndProvenanceByOidc(packageName: string, registry: string, options: PublishPackedPkgOptions): Promise<OidcTokenProvenanceResult | undefined>;
|
|
79
|
-
export {};
|
|
@@ -4,6 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import { PnpmError } from '@pnpm/error';
|
|
5
5
|
import { globalInfo, globalWarn } from '@pnpm/logger';
|
|
6
6
|
import { createDispatchedFetch } from '@pnpm/network.fetch';
|
|
7
|
+
import { extractBundledDependencies } from '../tarball/publishSummary.js';
|
|
7
8
|
import { displayError } from './displayError.js';
|
|
8
9
|
import { executeTokenHelper } from './executeTokenHelper.js';
|
|
9
10
|
import { createFailedToPublishError } from './FailedToPublishError.js';
|
|
@@ -19,6 +20,7 @@ export async function publishPackedPkg(packResult, opts) {
|
|
|
19
20
|
const publishOptions = await createPublishOptions(publishedManifest, opts);
|
|
20
21
|
const { name, version } = publishedManifest;
|
|
21
22
|
const { registry } = publishOptions;
|
|
23
|
+
const isStage = opts.stage === true;
|
|
22
24
|
globalInfo(`📦 ${name}@${version} → ${registry ?? 'the default registry'}`);
|
|
23
25
|
const summary = {
|
|
24
26
|
id: `${name}@${version}`,
|
|
@@ -36,17 +38,21 @@ export async function publishPackedPkg(packResult, opts) {
|
|
|
36
38
|
bundled: extractBundledDependencies(publishedManifest),
|
|
37
39
|
};
|
|
38
40
|
if (opts.dryRun) {
|
|
39
|
-
globalWarn(`Skip publishing ${name}@${version} (dry run)`);
|
|
41
|
+
globalWarn(`Skip ${isStage ? 'staging' : 'publishing'} ${name}@${version} (dry run)`);
|
|
40
42
|
return summary;
|
|
41
43
|
}
|
|
44
|
+
const context = createPublishContext(opts);
|
|
42
45
|
const response = await publishWithOtpHandling({
|
|
43
|
-
context
|
|
46
|
+
context,
|
|
44
47
|
manifest: publishedManifest,
|
|
45
48
|
publishOptions,
|
|
46
49
|
tarballData,
|
|
47
50
|
});
|
|
48
51
|
if (response.ok) {
|
|
49
|
-
|
|
52
|
+
if (isStage && response.stageId) {
|
|
53
|
+
summary.stageId = response.stageId;
|
|
54
|
+
}
|
|
55
|
+
globalInfo(`✅ ${isStage ? 'Staged' : 'Published'} package ${name}@${version}`);
|
|
50
56
|
return summary;
|
|
51
57
|
}
|
|
52
58
|
throw await createFailedToPublishError(packResult, response);
|
|
@@ -64,21 +70,6 @@ export function createPublishContext(opts) {
|
|
|
64
70
|
fetch: createDispatchedFetch({ ...opts, timeout: opts.fetchTimeout }),
|
|
65
71
|
};
|
|
66
72
|
}
|
|
67
|
-
/**
|
|
68
|
-
* npm accepts both `bundledDependencies` and `bundleDependencies` in package.json and normalizes
|
|
69
|
-
* to a list of dependency names. We mirror that normalization so consumers see a consistent array.
|
|
70
|
-
*/
|
|
71
|
-
function extractBundledDependencies(manifest) {
|
|
72
|
-
const raw = manifest.bundledDependencies ?? manifest.bundleDependencies;
|
|
73
|
-
if (!raw)
|
|
74
|
-
return [];
|
|
75
|
-
if (Array.isArray(raw))
|
|
76
|
-
return raw;
|
|
77
|
-
// `true` means "bundle every dependency" per npm's semantics; expand it to the dependency names.
|
|
78
|
-
if (raw === true)
|
|
79
|
-
return Object.keys(manifest.dependencies ?? {});
|
|
80
|
-
return [];
|
|
81
|
-
}
|
|
82
73
|
/**
|
|
83
74
|
* @internal Exported for unit testing of the access / registry / auth fallback rules. Not part of the package's
|
|
84
75
|
* public API.
|
|
@@ -92,9 +83,10 @@ export async function createPublishOptions(manifest, options) {
|
|
|
92
83
|
const publishConfigAccess = manifest.publishConfig?.access;
|
|
93
84
|
const access = options.access ?? (isPublishAccess(publishConfigAccess) ? publishConfigAccess : undefined);
|
|
94
85
|
const { ci: isFromCI, fetchRetries, fetchRetryFactor, fetchRetryMaxtimeout, fetchRetryMintimeout, fetchTimeout: timeout, otp, provenance, provenanceFile, tag: defaultTag, userAgent, } = options;
|
|
86
|
+
const npmCommand = options.stage === true ? 'stage' : 'publish';
|
|
95
87
|
const headers = {
|
|
96
88
|
'npm-auth-type': 'web',
|
|
97
|
-
'npm-command':
|
|
89
|
+
'npm-command': npmCommand,
|
|
98
90
|
};
|
|
99
91
|
const publishOptions = {
|
|
100
92
|
access,
|
|
@@ -119,11 +111,15 @@ export async function createPublishOptions(manifest, options) {
|
|
|
119
111
|
ca: tls?.ca,
|
|
120
112
|
cert: tls?.cert,
|
|
121
113
|
key: tls?.key,
|
|
122
|
-
npmCommand
|
|
114
|
+
npmCommand,
|
|
123
115
|
token: creds && extractToken(creds),
|
|
124
116
|
username: creds?.basicAuth?.username,
|
|
125
117
|
password: creds?.basicAuth?.password,
|
|
126
118
|
};
|
|
119
|
+
if (options.stage === true) {
|
|
120
|
+
publishOptions.command = 'stage';
|
|
121
|
+
publishOptions.stage = true;
|
|
122
|
+
}
|
|
127
123
|
if (registry) {
|
|
128
124
|
// OIDC takes precedence over a configured static `_authToken`, mirroring the npm CLI's
|
|
129
125
|
// behavior (see https://github.com/npm/cli/blob/7d900c46/lib/utils/oidc.js). Trusted
|
|
@@ -56,6 +56,7 @@ export async function recursivePublish(opts) {
|
|
|
56
56
|
}
|
|
57
57
|
const chunks = sortProjects(opts.selectedProjectsGraph);
|
|
58
58
|
const tag = opts.tag ?? 'latest';
|
|
59
|
+
const commandArgs = opts.stage ? ['stage', 'publish'] : ['publish'];
|
|
59
60
|
for (const chunk of chunks) {
|
|
60
61
|
// We can't run publish concurrently due to the npm CLI asking for OTP.
|
|
61
62
|
// NOTE: If we solve the OTP issue, we still need to limit packages concurrency.
|
|
@@ -72,7 +73,7 @@ export async function recursivePublish(opts) {
|
|
|
72
73
|
dir: pkg.rootDir,
|
|
73
74
|
argv: {
|
|
74
75
|
original: [
|
|
75
|
-
|
|
76
|
+
...commandArgs,
|
|
76
77
|
'--tag',
|
|
77
78
|
tag,
|
|
78
79
|
'--registry',
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createStageContext } from './context.js';
|
|
2
|
+
import { requireStageId } from './parsing.js';
|
|
3
|
+
import { stageRequestWithOtp } from './request.js';
|
|
4
|
+
export async function stageApprove(opts, params) {
|
|
5
|
+
const stageId = requireStageId(params, 'approve');
|
|
6
|
+
const context = createStageContext(opts);
|
|
7
|
+
await stageRequestWithOtp(context, {
|
|
8
|
+
url: new URL(`-/stage/${stageId}/approve`, context.registry).href,
|
|
9
|
+
init: { method: 'POST' },
|
|
10
|
+
action: `approve staged package ${stageId}`,
|
|
11
|
+
});
|
|
12
|
+
return `Staged package ${stageId} approved and published successfully.`;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=approve.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createFetchFromRegistry } from '@pnpm/network.fetch';
|
|
2
|
+
import type { StageOptions } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Shared per-subcommand request context. Created once at the entry of each stage
|
|
5
|
+
* subcommand so that paginated calls (e.g. `stageList`) reuse a single
|
|
6
|
+
* `fetchFromRegistry` instance and a precomputed auth header.
|
|
7
|
+
*/
|
|
8
|
+
export interface StageContext {
|
|
9
|
+
opts: StageOptions;
|
|
10
|
+
registry: string;
|
|
11
|
+
authHeaderValue: string | undefined;
|
|
12
|
+
fetchFromRegistry: ReturnType<typeof createFetchFromRegistry>;
|
|
13
|
+
}
|
|
14
|
+
export declare function createStageContext(opts: StageOptions, packageName?: string): StageContext;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { pickRegistryForPackage } from '@pnpm/config.pick-registry-for-package';
|
|
2
|
+
import { createGetAuthHeaderByURI } from '@pnpm/network.auth-header';
|
|
3
|
+
import { createFetchFromRegistry } from '@pnpm/network.fetch';
|
|
4
|
+
const DEFAULT_REGISTRY = 'https://registry.npmjs.org/';
|
|
5
|
+
export function createStageContext(opts, packageName) {
|
|
6
|
+
const registry = getStageRegistry(opts, packageName);
|
|
7
|
+
const getAuthHeaderByUri = createGetAuthHeaderByURI(opts.configByUri ?? {}, registry);
|
|
8
|
+
return {
|
|
9
|
+
opts,
|
|
10
|
+
registry,
|
|
11
|
+
authHeaderValue: getAuthHeaderByUri(registry),
|
|
12
|
+
fetchFromRegistry: createFetchFromRegistry(opts),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function getStageRegistry(opts, packageName) {
|
|
16
|
+
const registries = getRegistries(opts);
|
|
17
|
+
const registry = packageName
|
|
18
|
+
? pickRegistryForPackage(registries, packageName)
|
|
19
|
+
: registries.default;
|
|
20
|
+
return registry.endsWith('/') ? registry : `${registry}/`;
|
|
21
|
+
}
|
|
22
|
+
function getRegistries(opts) {
|
|
23
|
+
return opts.registries ?? { default: opts.registry ?? DEFAULT_REGISTRY };
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { summarizeTarball } from '../tarball/summarizeTarball.js';
|
|
4
|
+
import { createStageContext } from './context.js';
|
|
5
|
+
import { requireStageId } from './parsing.js';
|
|
6
|
+
import { normalizePackageName, renderTarballSummary } from './rendering.js';
|
|
7
|
+
import { stageRequest } from './request.js';
|
|
8
|
+
export async function stageDownload(opts, params) {
|
|
9
|
+
const stageId = requireStageId(params, 'download');
|
|
10
|
+
const context = createStageContext(opts);
|
|
11
|
+
const response = await stageRequest(context, {
|
|
12
|
+
url: new URL(`-/stage/${stageId}/tarball`, context.registry).href,
|
|
13
|
+
init: { method: 'GET' },
|
|
14
|
+
action: `download staged package ${stageId}`,
|
|
15
|
+
});
|
|
16
|
+
const tarballData = Buffer.from(await response.arrayBuffer());
|
|
17
|
+
const summary = await summarizeTarball(tarballData);
|
|
18
|
+
const filename = `${normalizePackageName(summary.name)}-${summary.version}-${stageId}.tgz`;
|
|
19
|
+
const downloadedSummary = { ...summary, filename };
|
|
20
|
+
await fs.writeFile(path.resolve(opts.dir ?? process.cwd(), filename), tarballData);
|
|
21
|
+
if (opts.json)
|
|
22
|
+
return JSON.stringify({ [summary.name]: downloadedSummary }, null, 2);
|
|
23
|
+
return `${renderTarballSummary(downloadedSummary)}\n${filename}`;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=download.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PnpmError } from '@pnpm/error';
|
|
2
|
+
interface StageRegistryErrorProperties {
|
|
3
|
+
readonly action: string;
|
|
4
|
+
readonly status: number;
|
|
5
|
+
readonly statusText: string;
|
|
6
|
+
readonly text: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class StageRegistryError extends PnpmError implements StageRegistryErrorProperties {
|
|
9
|
+
readonly action: string;
|
|
10
|
+
readonly status: number;
|
|
11
|
+
readonly statusText: string;
|
|
12
|
+
readonly text: string;
|
|
13
|
+
constructor(opts: StageRegistryErrorProperties);
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PnpmError } from '@pnpm/error';
|
|
2
|
+
export class StageRegistryError extends PnpmError {
|
|
3
|
+
action;
|
|
4
|
+
status;
|
|
5
|
+
statusText;
|
|
6
|
+
text;
|
|
7
|
+
constructor(opts) {
|
|
8
|
+
const statusDisplay = opts.statusText ? `${opts.status} ${opts.statusText}` : opts.status.toString();
|
|
9
|
+
const trimmedText = opts.text.trim();
|
|
10
|
+
super('STAGE_REGISTRY_ERROR', `Failed to ${opts.action} (status ${statusDisplay})${trimmedText ? `: ${trimmedText}` : ''}`);
|
|
11
|
+
this.action = opts.action;
|
|
12
|
+
this.status = opts.status;
|
|
13
|
+
this.statusText = opts.statusText;
|
|
14
|
+
this.text = opts.text;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function help(): string;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { FILTERING } from '@pnpm/cli.common-cli-options-help';
|
|
2
|
+
import { docsUrl } from '@pnpm/cli.utils';
|
|
3
|
+
import { renderHelp } from 'render-help';
|
|
4
|
+
export function help() {
|
|
5
|
+
return renderHelp({
|
|
6
|
+
description: 'Stage packages for publishing, deferring proof-of-presence (2FA) to a later point in time.',
|
|
7
|
+
descriptionLists: [
|
|
8
|
+
{
|
|
9
|
+
title: 'Subcommands',
|
|
10
|
+
list: [
|
|
11
|
+
{
|
|
12
|
+
description: 'Stage a package for publishing.',
|
|
13
|
+
name: 'publish',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
description: 'List all staged package versions.',
|
|
17
|
+
name: 'list',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
description: 'View details of a specific staged package.',
|
|
21
|
+
name: 'view',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
description: 'Approve a staged package, publishing it to the npm registry.',
|
|
25
|
+
name: 'approve',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
description: 'Reject a staged package, removing it from the registry.',
|
|
29
|
+
name: 'reject',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
description: 'Download the tarball of a staged package for inspection.',
|
|
33
|
+
name: 'download',
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
title: 'Options',
|
|
39
|
+
list: [
|
|
40
|
+
{
|
|
41
|
+
description: 'The base URL of the npm registry.',
|
|
42
|
+
name: '--registry <url>',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
description: 'Show information in JSON format for list, view, publish, and download.',
|
|
46
|
+
name: '--json',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
description: 'Registers the staged package with the given tag. By default, the "latest" tag is used.',
|
|
50
|
+
name: '--tag <tag>',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
description: 'Tells the registry whether the staged package should be public or restricted.',
|
|
54
|
+
name: '--access <public|restricted>',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
description: 'Does everything stage publish would do except uploading to the registry.',
|
|
58
|
+
name: '--dry-run',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
description: 'One-time password for approve and reject.',
|
|
62
|
+
name: '--otp',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
description: 'Stage all publishable packages from the workspace.',
|
|
66
|
+
name: '--recursive',
|
|
67
|
+
shortAlias: '-r',
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
FILTERING,
|
|
72
|
+
],
|
|
73
|
+
url: docsUrl('stage'),
|
|
74
|
+
usages: [
|
|
75
|
+
'pnpm stage publish [<tarball>|<dir>] [--tag <tag>] [--access <public|restricted>] [options]',
|
|
76
|
+
'pnpm stage list [<package-spec>]',
|
|
77
|
+
'pnpm stage view <stage-id>',
|
|
78
|
+
'pnpm stage approve <stage-id>',
|
|
79
|
+
'pnpm stage reject <stage-id>',
|
|
80
|
+
'pnpm stage download <stage-id>',
|
|
81
|
+
],
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=help.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { help } from './help.js';
|
|
2
|
+
import { type StageOptions } from './types.js';
|
|
3
|
+
export { help };
|
|
4
|
+
export declare function rcOptionsTypes(): Record<string, unknown>;
|
|
5
|
+
export declare function cliOptionsTypes(): Record<string, unknown>;
|
|
6
|
+
export declare const commandNames: string[];
|
|
7
|
+
export declare const completion: (_cliOpts: Record<string, unknown>, params: string[]) => Promise<Array<{
|
|
8
|
+
name: string;
|
|
9
|
+
}>>;
|
|
10
|
+
export declare function handler(opts: StageOptions, params: string[]): Promise<{
|
|
11
|
+
exitCode?: number;
|
|
12
|
+
output?: string;
|
|
13
|
+
} | string | undefined>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { types as allTypes } from '@pnpm/config.reader';
|
|
2
|
+
import { PnpmError } from '@pnpm/error';
|
|
3
|
+
import { pick } from 'ramda';
|
|
4
|
+
import * as publishCommand from '../publish/publish.js';
|
|
5
|
+
import { stageApprove } from './approve.js';
|
|
6
|
+
import { stageDownload } from './download.js';
|
|
7
|
+
import { help } from './help.js';
|
|
8
|
+
import { stageList } from './list.js';
|
|
9
|
+
import { stagePublish } from './publish.js';
|
|
10
|
+
import { stageReject } from './reject.js';
|
|
11
|
+
import { STAGE_SUBCOMMANDS } from './types.js';
|
|
12
|
+
import { stageView } from './view.js';
|
|
13
|
+
export { help };
|
|
14
|
+
export function rcOptionsTypes() {
|
|
15
|
+
return {
|
|
16
|
+
...publishCommand.rcOptionsTypes(),
|
|
17
|
+
...pick([
|
|
18
|
+
'registry',
|
|
19
|
+
], allTypes),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function cliOptionsTypes() {
|
|
23
|
+
return publishCommand.cliOptionsTypes();
|
|
24
|
+
}
|
|
25
|
+
export const commandNames = ['stage'];
|
|
26
|
+
export const completion = async (_cliOpts, params) => {
|
|
27
|
+
if (params.length > 0)
|
|
28
|
+
return [];
|
|
29
|
+
return STAGE_SUBCOMMANDS.map((name) => ({ name }));
|
|
30
|
+
};
|
|
31
|
+
export async function handler(opts, params) {
|
|
32
|
+
const subcommand = params[0];
|
|
33
|
+
const subcommandParams = params.slice(1);
|
|
34
|
+
switch (subcommand) {
|
|
35
|
+
case 'publish':
|
|
36
|
+
return stagePublish(opts, subcommandParams);
|
|
37
|
+
case 'list':
|
|
38
|
+
return stageList(opts, subcommandParams);
|
|
39
|
+
case 'view':
|
|
40
|
+
return stageView(opts, subcommandParams);
|
|
41
|
+
case 'approve':
|
|
42
|
+
return stageApprove(opts, subcommandParams);
|
|
43
|
+
case 'reject':
|
|
44
|
+
return stageReject(opts, subcommandParams);
|
|
45
|
+
case 'download':
|
|
46
|
+
return stageDownload(opts, subcommandParams);
|
|
47
|
+
case undefined:
|
|
48
|
+
throw new PnpmError('STAGE_SUBCOMMAND_REQUIRED', 'Stage subcommand is required', {
|
|
49
|
+
hint: `Use one of: ${STAGE_SUBCOMMANDS.join(', ')}`,
|
|
50
|
+
});
|
|
51
|
+
default:
|
|
52
|
+
throw new PnpmError('STAGE_UNKNOWN_SUBCOMMAND', `Unknown stage subcommand "${subcommand}"`, {
|
|
53
|
+
hint: `Use one of: ${STAGE_SUBCOMMANDS.join(', ')}`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { PnpmError } from '@pnpm/error';
|
|
2
|
+
import { createStageContext } from './context.js';
|
|
3
|
+
import { parseStagePackageSpec } from './parsing.js';
|
|
4
|
+
import { renderStageItem } from './rendering.js';
|
|
5
|
+
import { stageJsonRequest } from './request.js';
|
|
6
|
+
const PER_PAGE = 100;
|
|
7
|
+
export async function stageList(opts, params) {
|
|
8
|
+
const packageFilter = parsePackageFilter(params[0]);
|
|
9
|
+
const context = createStageContext(opts, packageFilter);
|
|
10
|
+
const items = [];
|
|
11
|
+
let page = 0;
|
|
12
|
+
while (true) {
|
|
13
|
+
const url = new URL('-/stage', context.registry);
|
|
14
|
+
url.searchParams.set('page', page.toString());
|
|
15
|
+
url.searchParams.set('perPage', PER_PAGE.toString());
|
|
16
|
+
if (packageFilter) {
|
|
17
|
+
url.searchParams.set('package', packageFilter);
|
|
18
|
+
}
|
|
19
|
+
// eslint-disable-next-line no-await-in-loop
|
|
20
|
+
const res = await stageJsonRequest(context, { url: url.href, action: 'list staged packages' });
|
|
21
|
+
items.push(...res.items);
|
|
22
|
+
if (items.length >= res.total || res.items.length < PER_PAGE)
|
|
23
|
+
break;
|
|
24
|
+
page++;
|
|
25
|
+
}
|
|
26
|
+
if (opts.json)
|
|
27
|
+
return JSON.stringify(items, null, 2);
|
|
28
|
+
if (items.length === 0) {
|
|
29
|
+
return packageFilter
|
|
30
|
+
? `No staged versions of package name "${packageFilter}".`
|
|
31
|
+
: 'No staged packages found.';
|
|
32
|
+
}
|
|
33
|
+
return items.map(renderStageItem).join('\n\n');
|
|
34
|
+
}
|
|
35
|
+
function parsePackageFilter(rawSpec) {
|
|
36
|
+
if (!rawSpec)
|
|
37
|
+
return undefined;
|
|
38
|
+
const spec = parseStagePackageSpec(rawSpec);
|
|
39
|
+
if (spec.rawSpec !== '' && spec.rawSpec !== '*') {
|
|
40
|
+
throw new PnpmError('STAGE_VERSION_SPECIFIER_UNSUPPORTED', 'Version specifiers are not supported for listing staged packages');
|
|
41
|
+
}
|
|
42
|
+
return spec.name;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=list.js.map
|