@pnpm/releasing.commands 1100.1.0 → 1100.2.1
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/pack-app/packApp.d.ts +2 -2
- package/lib/pack-app/packApp.js +64 -26
- package/package.json +22 -22
|
@@ -7,7 +7,7 @@ export declare function help(): string;
|
|
|
7
7
|
export type PackAppOptions = Pick<Config, 'dir' | 'pnpmHomeDir'> & Partial<Pick<Config, 'ca' | 'cert' | 'configByUri' | 'httpProxy' | 'httpsProxy' | 'key' | 'localAddress' | 'nodeDownloadMirrors' | 'noProxy' | 'strictSsl' | 'userAgent'>> & {
|
|
8
8
|
entry?: string;
|
|
9
9
|
target?: string | string[];
|
|
10
|
-
|
|
10
|
+
runtime?: string;
|
|
11
11
|
outputDir?: string;
|
|
12
12
|
outputName?: string;
|
|
13
13
|
};
|
|
@@ -16,7 +16,7 @@ export declare function handler(opts: PackAppOptions, params: string[]): Promise
|
|
|
16
16
|
export interface ProjectAppConfig {
|
|
17
17
|
entry?: string;
|
|
18
18
|
targets?: string[];
|
|
19
|
-
|
|
19
|
+
runtime?: string;
|
|
20
20
|
outputDir?: string;
|
|
21
21
|
outputName?: string;
|
|
22
22
|
}
|
package/lib/pack-app/packApp.js
CHANGED
|
@@ -12,11 +12,6 @@ import { safeExeca as execa } from 'execa';
|
|
|
12
12
|
import { renderHelp } from 'render-help';
|
|
13
13
|
/** Minimum Node.js version that supports `node --build-sea`. */
|
|
14
14
|
const MIN_BUILDER_VERSION = { major: 25, minor: 5 };
|
|
15
|
-
// Range to download when the running Node is too old. Constrained to the
|
|
16
|
-
// current major so we don't silently jump majors across releases, and pinned
|
|
17
|
-
// above MIN_BUILDER_VERSION.minor so older point releases (e.g. 25.0.x) that
|
|
18
|
-
// don't support `--build-sea` aren't picked.
|
|
19
|
-
const DEFAULT_BUILDER_SPEC = `>=${MIN_BUILDER_VERSION.major}.${MIN_BUILDER_VERSION.minor}.0 <${MIN_BUILDER_VERSION.major + 1}.0.0`;
|
|
20
15
|
// Target OS names match `process.platform`. That keeps the CLI surface
|
|
21
16
|
// consistent with pnpm's own `--os` flag (which also takes platform constants)
|
|
22
17
|
// and with `supportedArchitectures.os` in pnpm-workspace.yaml.
|
|
@@ -30,7 +25,7 @@ export function cliOptionsTypes() {
|
|
|
30
25
|
return {
|
|
31
26
|
entry: String,
|
|
32
27
|
target: [String, Array],
|
|
33
|
-
|
|
28
|
+
runtime: String,
|
|
34
29
|
'output-dir': String,
|
|
35
30
|
'output-name': String,
|
|
36
31
|
};
|
|
@@ -44,16 +39,17 @@ export function help() {
|
|
|
44
39
|
description: 'Pack a CommonJS entry file into a standalone executable for one or more target platforms.\n\n' +
|
|
45
40
|
'The executable embeds a Node.js binary via the Node.js Single Executable Applications API.\n' +
|
|
46
41
|
`Requires Node.js v${MIN_BUILDER_VERSION.major}.${MIN_BUILDER_VERSION.minor}+ to perform ` +
|
|
47
|
-
'the injection.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
'
|
|
42
|
+
'the injection. SEA blobs are not compatible across Node.js minor releases, so the ' +
|
|
43
|
+
'builder Node.js must match the embedded runtime version exactly. The running Node.js ' +
|
|
44
|
+
'is used when it already matches; otherwise a host-arch Node.js of the embedded runtime ' +
|
|
45
|
+
'version is downloaded automatically.\n\n' +
|
|
46
|
+
'Defaults for --entry, --target, --runtime, --output-dir, and --output-name can be ' +
|
|
51
47
|
'set in the package.json under "pnpm.app". CLI flags override the config; --target entirely ' +
|
|
52
48
|
'replaces the configured list so you can narrow it at invocation time.',
|
|
53
49
|
url: docsUrl('pack-app'),
|
|
54
50
|
usages: [
|
|
55
51
|
'pnpm pack-app --entry dist/index.cjs --target linux-x64 --target win32-x64',
|
|
56
|
-
|
|
52
|
+
`pnpm pack-app --entry dist/index.cjs --target linux-x64-musl --runtime node@${MIN_BUILDER_VERSION.major}`,
|
|
57
53
|
],
|
|
58
54
|
descriptionLists: [
|
|
59
55
|
{
|
|
@@ -69,9 +65,11 @@ export function help() {
|
|
|
69
65
|
shortAlias: '-t',
|
|
70
66
|
},
|
|
71
67
|
{
|
|
72
|
-
description: '
|
|
68
|
+
description: 'Runtime to embed in the output executables, as a "<name>@<version>" spec ' +
|
|
69
|
+
`(e.g. "node@${MIN_BUILDER_VERSION.major}", "node@${MIN_BUILDER_VERSION.major}.${MIN_BUILDER_VERSION.minor}.0"). ` +
|
|
70
|
+
`Only "node" is supported today, and the version must be >= v${MIN_BUILDER_VERSION.major}.${MIN_BUILDER_VERSION.minor} (the minimum that supports --build-sea). ` +
|
|
73
71
|
'Defaults to the running Node.js version.',
|
|
74
|
-
name: '--
|
|
72
|
+
name: '--runtime',
|
|
75
73
|
},
|
|
76
74
|
{
|
|
77
75
|
description: 'Output directory for the built executables. Defaults to "dist-app".',
|
|
@@ -115,14 +113,27 @@ export async function handler(opts, params) {
|
|
|
115
113
|
throw new PnpmError('PACK_APP_MISSING_TARGET', `"pnpm pack-app" requires at least one target — pass --target <triplet> or set "pnpm.app.targets" in package.json. Supported: ${SUPPORTED_TARGETS}`);
|
|
116
114
|
}
|
|
117
115
|
const targets = rawTargets.map(parseTarget);
|
|
116
|
+
// Parse the runtime before output-name derivation and any network work so
|
|
117
|
+
// that a malformed --runtime fails fast with a clear error instead of being
|
|
118
|
+
// masked by later problems (missing package.json name, registry lookup, etc.).
|
|
119
|
+
const runtimeSpec = opts.runtime ?? project.app?.runtime ?? `node@${process.version.slice(1)}`;
|
|
120
|
+
const { version: requestedNodeSpec } = parseRuntime(runtimeSpec);
|
|
118
121
|
const outputDir = path.resolve(opts.dir, opts.outputDir ?? project.app?.outputDir ?? 'dist-app');
|
|
119
122
|
await mkdir(outputDir, { recursive: true });
|
|
120
123
|
const outputName = validateOutputName(opts.outputName ?? project.app?.outputName ?? deriveOutputNameFromPackage(project, opts.dir));
|
|
121
|
-
const requestedNodeSpec = opts.nodeVersion ?? project.app?.nodeVersion ?? process.version.slice(1);
|
|
122
124
|
const fetch = createFetchFromRegistry(opts);
|
|
123
125
|
const buildRoot = path.join(opts.pnpmHomeDir, 'pack-app');
|
|
124
|
-
|
|
126
|
+
// Resolve the embedded target version first so the builder can be pinned to
|
|
127
|
+
// the same version. SEA blobs carry no version header and the serialized
|
|
128
|
+
// format has changed across Node.js minor releases (e.g. v25.7 added a
|
|
129
|
+
// ModuleFormat byte for ESM entry points), so a blob produced by a builder
|
|
130
|
+
// of a different version than the embedded runtime will fail deserialization
|
|
131
|
+
// at startup with an opaque native assertion.
|
|
125
132
|
const resolvedTargetVersion = await resolveVersion(fetch, requestedNodeSpec, opts.nodeDownloadMirrors);
|
|
133
|
+
const builderBin = await resolveBuilderBinary({
|
|
134
|
+
buildRoot,
|
|
135
|
+
targetVersion: resolvedTargetVersion,
|
|
136
|
+
});
|
|
126
137
|
const results = [];
|
|
127
138
|
for (const target of targets) {
|
|
128
139
|
// eslint-disable-next-line no-await-in-loop
|
|
@@ -170,17 +181,26 @@ export async function handler(opts, params) {
|
|
|
170
181
|
return `Built ${targets.length} executable${targets.length === 1 ? '' : 's'}:\n${results.join('\n')}`;
|
|
171
182
|
}
|
|
172
183
|
/**
|
|
173
|
-
* Returns a Node.js binary that supports `--build-sea
|
|
174
|
-
*
|
|
184
|
+
* Returns a Node.js binary that supports `--build-sea` AND produces a SEA
|
|
185
|
+
* blob the embedded runtime can deserialize. The second constraint forces the
|
|
186
|
+
* builder to match the target runtime version exactly: blobs are versioned by
|
|
187
|
+
* the writer's internal struct layout with no header, and Node bumps that
|
|
188
|
+
* layout in minor releases (e.g. v25.7 added a ModuleFormat byte for ESM
|
|
189
|
+
* entries), so a cross-version blob crashes at startup.
|
|
190
|
+
*
|
|
191
|
+
* Prefers the running interpreter when it already matches the target version;
|
|
192
|
+
* otherwise downloads the target version for the host platform.
|
|
175
193
|
*/
|
|
176
194
|
async function resolveBuilderBinary(ctx) {
|
|
177
|
-
if (runningNodeCanBuildSea()) {
|
|
195
|
+
if (runningNodeCanBuildSea() && process.version === `v${ctx.targetVersion}`) {
|
|
178
196
|
return process.execPath;
|
|
179
197
|
}
|
|
180
|
-
|
|
198
|
+
if (!builderVersionCanBuildSea(ctx.targetVersion)) {
|
|
199
|
+
throw new PnpmError('PACK_APP_RUNTIME_TOO_OLD', `The embedded runtime "node@${ctx.targetVersion}" is older than Node.js v${MIN_BUILDER_VERSION.major}.${MIN_BUILDER_VERSION.minor}, which is the minimum version that supports --build-sea.`, { hint: `Pass --runtime node@${MIN_BUILDER_VERSION.major}.${MIN_BUILDER_VERSION.minor}.0 (or newer) or set "pnpm.app.runtime" in package.json.` });
|
|
200
|
+
}
|
|
181
201
|
return ensureNodeRuntime({
|
|
182
202
|
buildRoot: ctx.buildRoot,
|
|
183
|
-
version,
|
|
203
|
+
version: ctx.targetVersion,
|
|
184
204
|
platform: process.platform,
|
|
185
205
|
arch: process.arch,
|
|
186
206
|
// Pin libc to the host's. Otherwise a caller that had set
|
|
@@ -196,7 +216,10 @@ function hostLinuxLibc() {
|
|
|
196
216
|
return family === 'musl' ? 'musl' : 'glibc';
|
|
197
217
|
}
|
|
198
218
|
function runningNodeCanBuildSea() {
|
|
199
|
-
|
|
219
|
+
return builderVersionCanBuildSea(process.version.slice(1));
|
|
220
|
+
}
|
|
221
|
+
function builderVersionCanBuildSea(version) {
|
|
222
|
+
const [majorStr, minorStr] = version.split('.');
|
|
200
223
|
const major = Number(majorStr);
|
|
201
224
|
const minor = Number(minorStr);
|
|
202
225
|
return (major > MIN_BUILDER_VERSION.major ||
|
|
@@ -270,6 +293,21 @@ function parseTarget(raw) {
|
|
|
270
293
|
}
|
|
271
294
|
return { raw, platform, arch, libc: libc || undefined };
|
|
272
295
|
}
|
|
296
|
+
// Runtime spec is "<name>@<version>". Only "node" is supported today; the
|
|
297
|
+
// prefix is kept so future runtimes (bun, deno) can share the same flag
|
|
298
|
+
// without a breaking change. Reading the runtime name rather than a bare
|
|
299
|
+
// version also avoids shadowing pnpm's global `node-version` rc setting,
|
|
300
|
+
// whose value would otherwise leak into Config['nodeVersion'] and override
|
|
301
|
+
// `pnpm.app.runtime`.
|
|
302
|
+
const SUPPORTED_RUNTIMES = ['node'];
|
|
303
|
+
const RUNTIME_PATTERN = /^(node)@(.+)$/;
|
|
304
|
+
function parseRuntime(spec) {
|
|
305
|
+
const match = RUNTIME_PATTERN.exec(spec);
|
|
306
|
+
if (!match) {
|
|
307
|
+
throw new PnpmError('PACK_APP_INVALID_RUNTIME', `Invalid runtime "${spec}". Expected format: <name>@<version> (supported runtimes: ${SUPPORTED_RUNTIMES.join(', ')}; e.g. "node@${MIN_BUILDER_VERSION.major}.${MIN_BUILDER_VERSION.minor}.0").`);
|
|
308
|
+
}
|
|
309
|
+
return { name: match[1], version: match[2] };
|
|
310
|
+
}
|
|
273
311
|
// Characters that Win32 rejects in filenames, plus NUL. Path separators are
|
|
274
312
|
// checked separately via `path.basename` so the message is crisp.
|
|
275
313
|
const INVALID_FILENAME_CHARS = /[<>:"|?*\0]/;
|
|
@@ -319,7 +357,7 @@ async function readProjectAppConfig(dir) {
|
|
|
319
357
|
return { name, app: validateAppConfig(appField) };
|
|
320
358
|
}
|
|
321
359
|
function validateAppConfig(raw) {
|
|
322
|
-
const known = new Set(['entry', 'targets', '
|
|
360
|
+
const known = new Set(['entry', 'targets', 'runtime', 'outputDir', 'outputName']);
|
|
323
361
|
for (const key of Object.keys(raw)) {
|
|
324
362
|
if (!known.has(key)) {
|
|
325
363
|
throw new PnpmError('PACK_APP_INVALID_CONFIG', `Unknown "pnpm.app.${key}" setting in package.json. Allowed keys: ${Array.from(known).join(', ')}.`);
|
|
@@ -338,11 +376,11 @@ function validateAppConfig(raw) {
|
|
|
338
376
|
}
|
|
339
377
|
config.targets = raw.targets;
|
|
340
378
|
}
|
|
341
|
-
if (raw.
|
|
342
|
-
if (typeof raw.
|
|
343
|
-
throw new PnpmError('PACK_APP_INVALID_CONFIG', '"pnpm.app.
|
|
379
|
+
if (raw.runtime != null) {
|
|
380
|
+
if (typeof raw.runtime !== 'string') {
|
|
381
|
+
throw new PnpmError('PACK_APP_INVALID_CONFIG', '"pnpm.app.runtime" must be a string.');
|
|
344
382
|
}
|
|
345
|
-
config.
|
|
383
|
+
config.runtime = raw.runtime;
|
|
346
384
|
}
|
|
347
385
|
if (raw.outputDir != null) {
|
|
348
386
|
if (typeof raw.outputDir !== 'string') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/releasing.commands",
|
|
3
|
-
"version": "1100.1
|
|
3
|
+
"version": "1100.2.1",
|
|
4
4
|
"description": "Commands for deploy, pack, and publish",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -47,35 +47,35 @@
|
|
|
47
47
|
"validate-npm-package-name": "7.0.2",
|
|
48
48
|
"write-json-file": "^7.0.0",
|
|
49
49
|
"write-yaml-file": "^6.0.0",
|
|
50
|
+
"@pnpm/catalogs.types": "1100.0.0",
|
|
51
|
+
"@pnpm/cli.common-cli-options-help": "1100.0.0",
|
|
50
52
|
"@pnpm/bins.resolver": "1100.0.1",
|
|
51
53
|
"@pnpm/cli.utils": "1101.0.0",
|
|
52
|
-
"@pnpm/cli.common-cli-options-help": "1100.0.0",
|
|
53
54
|
"@pnpm/config.pick-registry-for-package": "1100.0.1",
|
|
54
55
|
"@pnpm/constants": "1100.0.0",
|
|
55
|
-
"@pnpm/
|
|
56
|
+
"@pnpm/deps.path": "1100.0.1",
|
|
57
|
+
"@pnpm/engine.runtime.node-resolver": "1101.0.0",
|
|
58
|
+
"@pnpm/engine.runtime.commands": "1100.0.4",
|
|
56
59
|
"@pnpm/error": "1100.0.0",
|
|
57
|
-
"@pnpm/
|
|
60
|
+
"@pnpm/config.reader": "1101.1.1",
|
|
61
|
+
"@pnpm/exec.lifecycle": "1100.0.4",
|
|
58
62
|
"@pnpm/exec.pnpm-cli-runner": "1100.0.0",
|
|
59
|
-
"@pnpm/
|
|
60
|
-
"@pnpm/deps.path": "1100.0.1",
|
|
61
|
-
"@pnpm/installing.client": "1100.0.3",
|
|
63
|
+
"@pnpm/fetching.directory-fetcher": "1100.0.4",
|
|
62
64
|
"@pnpm/fs.is-empty-dir-or-nothing": "1100.0.0",
|
|
65
|
+
"@pnpm/fs.indexed-pkg-importer": "1100.0.3",
|
|
63
66
|
"@pnpm/fs.packlist": "1100.0.0",
|
|
64
|
-
"@pnpm/
|
|
65
|
-
"@pnpm/
|
|
66
|
-
"@pnpm/
|
|
67
|
+
"@pnpm/installing.client": "1100.0.4",
|
|
68
|
+
"@pnpm/installing.commands": "1100.1.2",
|
|
69
|
+
"@pnpm/lockfile.fs": "1100.0.3",
|
|
67
70
|
"@pnpm/lockfile.types": "1100.0.2",
|
|
68
|
-
"@pnpm/network.web-auth": "1101.0.0",
|
|
69
71
|
"@pnpm/network.git-utils": "1100.0.0",
|
|
72
|
+
"@pnpm/network.web-auth": "1101.0.0",
|
|
70
73
|
"@pnpm/releasing.exportable-manifest": "1100.0.2",
|
|
71
|
-
"@pnpm/types": "1101.0.0",
|
|
72
74
|
"@pnpm/resolving.resolver-base": "1100.1.0",
|
|
73
|
-
"@pnpm/
|
|
74
|
-
"@pnpm/workspace.projects-filter": "1100.0.3",
|
|
75
|
-
"@pnpm/workspace.projects-sorter": "1100.0.1",
|
|
75
|
+
"@pnpm/types": "1101.0.0",
|
|
76
76
|
"@pnpm/network.fetch": "1100.0.1",
|
|
77
|
-
"@pnpm/
|
|
78
|
-
"@pnpm/
|
|
77
|
+
"@pnpm/workspace.projects-filter": "1100.0.4",
|
|
78
|
+
"@pnpm/workspace.projects-sorter": "1100.0.1"
|
|
79
79
|
},
|
|
80
80
|
"peerDependencies": {
|
|
81
81
|
"@pnpm/logger": ">=1001.0.0 <1002.0.0"
|
|
@@ -98,14 +98,14 @@
|
|
|
98
98
|
"load-json-file": "^7.0.1",
|
|
99
99
|
"tar": "^7.5.10",
|
|
100
100
|
"write-yaml-file": "^6.0.0",
|
|
101
|
-
"@pnpm/
|
|
102
|
-
"@pnpm/
|
|
103
|
-
"@pnpm/
|
|
104
|
-
"@pnpm/
|
|
101
|
+
"@pnpm/catalogs.config": "1100.0.0",
|
|
102
|
+
"@pnpm/hooks.pnpmfile": "1100.0.3",
|
|
103
|
+
"@pnpm/prepare": "1100.0.3",
|
|
104
|
+
"@pnpm/assert-project": "1100.0.3",
|
|
105
105
|
"@pnpm/logger": "1100.0.0",
|
|
106
|
+
"@pnpm/releasing.commands": "1100.2.1",
|
|
106
107
|
"@pnpm/test-fixtures": "1100.0.0",
|
|
107
108
|
"@pnpm/testing.command-defaults": "1100.0.1",
|
|
108
|
-
"@pnpm/catalogs.config": "1100.0.0",
|
|
109
109
|
"@pnpm/test-ipc-server": "1100.0.0"
|
|
110
110
|
},
|
|
111
111
|
"engines": {
|