@sparkelf/dsh-plus 0.1.0-rc.38 → 0.1.0-rc.39
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/bin.js
CHANGED
|
@@ -422,6 +422,42 @@ function runPnpm(cwd, args, label) {
|
|
|
422
422
|
if (result.status !== 0) throw new Error(label + " failed with exit code " + String(result.status));
|
|
423
423
|
}
|
|
424
424
|
/**
|
|
425
|
+
* Report whether pnpm can run.
|
|
426
|
+
*
|
|
427
|
+
* The profile installs its own tree so its \`overrides\` apply, and only pnpm reads those
|
|
428
|
+
* from a workspace, so pnpm is a prerequisite the distribution cannot supply. Probing
|
|
429
|
+
* first turns a cryptic failure from the install into a message naming what is missing.
|
|
430
|
+
*
|
|
431
|
+
* @returns \`true\` when pnpm answers with a version.
|
|
432
|
+
*/
|
|
433
|
+
function pnpmAvailable() {
|
|
434
|
+
return spawnSync("pnpm", ["--version"], {
|
|
435
|
+
stdio: "pipe",
|
|
436
|
+
shell: process.platform === "win32",
|
|
437
|
+
encoding: "utf8"
|
|
438
|
+
}).status === 0;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* The commands that install pnpm, in the order worth trying.
|
|
442
|
+
*
|
|
443
|
+
* Corepack ships with Node and needs no download, so it comes first; npm is the fallback
|
|
444
|
+
* for an installation whose Corepack is absent or disabled. Both are the consumer's own
|
|
445
|
+
* toolchain, which is what lets the first start offer to install rather than only report.
|
|
446
|
+
*
|
|
447
|
+
* @returns commands to try in order, stopping at the first that works.
|
|
448
|
+
*/
|
|
449
|
+
function pnpmInstallCommands() {
|
|
450
|
+
return ["corepack enable pnpm", "npm install -g pnpm"];
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* The command to show a consumer who declines the automatic install.
|
|
454
|
+
*
|
|
455
|
+
* @returns the preferred command, which is the one the offer runs first.
|
|
456
|
+
*/
|
|
457
|
+
function pnpmInstallCommand() {
|
|
458
|
+
return pnpmInstallCommands()[0] ?? "npm install -g pnpm";
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
425
461
|
* Expose the distribution's nested packages at the top level the profile searches.
|
|
426
462
|
*
|
|
427
463
|
* The profile resolves a bundle from one directory, so a package npm nested under the
|
|
@@ -698,6 +734,30 @@ async function start(argv) {
|
|
|
698
734
|
const options = parseStartOptions(argv);
|
|
699
735
|
const anchor = installationAnchor();
|
|
700
736
|
const paths = resolvePaths(anchor);
|
|
737
|
+
if (!pnpmAvailable()) {
|
|
738
|
+
const command = pnpmInstallCommand();
|
|
739
|
+
console.log("pnpm is required to install the plus profile, and was not found.");
|
|
740
|
+
console.log("Install it with: " + command);
|
|
741
|
+
if (!await confirm("Install pnpm now?")) {
|
|
742
|
+
console.log("Install pnpm and run dsh-plus start again.");
|
|
743
|
+
return 1;
|
|
744
|
+
}
|
|
745
|
+
let installed = false;
|
|
746
|
+
for (const candidate of pnpmInstallCommands()) if (spawnSync(candidate, {
|
|
747
|
+
stdio: "inherit",
|
|
748
|
+
shell: true
|
|
749
|
+
}).status === 0 && pnpmAvailable()) {
|
|
750
|
+
installed = true;
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
if (!installed) {
|
|
754
|
+
console.log("Could not install pnpm automatically.");
|
|
755
|
+
console.log("Run one of these, then run dsh-plus start again:");
|
|
756
|
+
for (const candidate of pnpmInstallCommands()) console.log(" " + candidate);
|
|
757
|
+
return 1;
|
|
758
|
+
}
|
|
759
|
+
console.log("pnpm installed.");
|
|
760
|
+
}
|
|
701
761
|
const created = ensureProfile(paths, installationRoot());
|
|
702
762
|
console.log(created ? "Created the plus profile at " + paths.profileDirectory : "Using the existing plus profile");
|
|
703
763
|
for (const label of applyProfileNpmPatches(paths.distributionDirectory, paths.profileDirectory)) console.log("Applied the reviewed patch " + label);
|
|
@@ -14,7 +14,7 @@ import { dirname, join } from 'node:path';
|
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { newerVersion } from "./registry-versions.js";
|
|
16
16
|
import { DEFAULT_PORT, STOP_GRACE_MILLISECONDS, choosePort, clearState, isRunning, portAvailable, readState, spawnServer, stateDirectory, waitForAuthenticatedUrl, waitForServer, writeState, } from "./standalone-server.js";
|
|
17
|
-
import { STANDALONE_PROFILE, applyProfileNpmPatches, ensureProfile, readDistributionProfile, resolvePaths, } from "./standalone-profile.js";
|
|
17
|
+
import { STANDALONE_PROFILE, applyProfileNpmPatches, ensureProfile, pnpmAvailable, pnpmInstallCommand, pnpmInstallCommands, readDistributionProfile, resolvePaths, } from "./standalone-profile.js";
|
|
18
18
|
/** Milliseconds a start waits for the server to answer before reporting failure. */
|
|
19
19
|
const READY_TIMEOUT_MILLISECONDS = 90_000;
|
|
20
20
|
function parseStartOptions(argv) {
|
|
@@ -100,6 +100,36 @@ async function start(argv) {
|
|
|
100
100
|
const options = parseStartOptions(argv);
|
|
101
101
|
const anchor = installationAnchor();
|
|
102
102
|
const paths = resolvePaths(anchor);
|
|
103
|
+
// The profile installs its own dependency tree, which needs pnpm. Asking here rather
|
|
104
|
+
// than failing inside the install turns a missing prerequisite into a decision the
|
|
105
|
+
// consumer makes, and the install it can run is the one command that provides it.
|
|
106
|
+
if (!pnpmAvailable()) {
|
|
107
|
+
const command = pnpmInstallCommand();
|
|
108
|
+
console.log('pnpm is required to install the ' + STANDALONE_PROFILE + ' profile, and was not found.');
|
|
109
|
+
console.log('Install it with: ' + command);
|
|
110
|
+
if (!await confirm('Install pnpm now?')) {
|
|
111
|
+
console.log('Install pnpm and run dsh-plus start again.');
|
|
112
|
+
return 1;
|
|
113
|
+
}
|
|
114
|
+
// Try each installer in turn: Corepack is absent on an installation that disabled it,
|
|
115
|
+
// and npm succeeds there. A failure reports the commands rather than a stack trace.
|
|
116
|
+
let installed = false;
|
|
117
|
+
for (const candidate of pnpmInstallCommands()) {
|
|
118
|
+
const attempt = spawnSync(candidate, { stdio: 'inherit', shell: true });
|
|
119
|
+
if (attempt.status === 0 && pnpmAvailable()) {
|
|
120
|
+
installed = true;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (!installed) {
|
|
125
|
+
console.log('Could not install pnpm automatically.');
|
|
126
|
+
console.log('Run one of these, then run dsh-plus start again:');
|
|
127
|
+
for (const candidate of pnpmInstallCommands())
|
|
128
|
+
console.log(' ' + candidate);
|
|
129
|
+
return 1;
|
|
130
|
+
}
|
|
131
|
+
console.log('pnpm installed.');
|
|
132
|
+
}
|
|
103
133
|
const created = ensureProfile(paths, installationRoot());
|
|
104
134
|
console.log(created
|
|
105
135
|
? 'Created the ' + STANDALONE_PROFILE + ' profile at ' + paths.profileDirectory
|
|
@@ -94,6 +94,32 @@ export declare function installProfilePackages(paths: StandalonePaths, consumerD
|
|
|
94
94
|
* @param profileModules - the profile's \`node_modules\` directory.
|
|
95
95
|
*/
|
|
96
96
|
export declare function alignReplacedPackageNames(profileModules: string): void;
|
|
97
|
+
/**
|
|
98
|
+
* Report whether pnpm can run.
|
|
99
|
+
*
|
|
100
|
+
* The profile installs its own tree so its \`overrides\` apply, and only pnpm reads those
|
|
101
|
+
* from a workspace, so pnpm is a prerequisite the distribution cannot supply. Probing
|
|
102
|
+
* first turns a cryptic failure from the install into a message naming what is missing.
|
|
103
|
+
*
|
|
104
|
+
* @returns \`true\` when pnpm answers with a version.
|
|
105
|
+
*/
|
|
106
|
+
export declare function pnpmAvailable(): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* The commands that install pnpm, in the order worth trying.
|
|
109
|
+
*
|
|
110
|
+
* Corepack ships with Node and needs no download, so it comes first; npm is the fallback
|
|
111
|
+
* for an installation whose Corepack is absent or disabled. Both are the consumer's own
|
|
112
|
+
* toolchain, which is what lets the first start offer to install rather than only report.
|
|
113
|
+
*
|
|
114
|
+
* @returns commands to try in order, stopping at the first that works.
|
|
115
|
+
*/
|
|
116
|
+
export declare function pnpmInstallCommands(): readonly string[];
|
|
117
|
+
/**
|
|
118
|
+
* The command to show a consumer who declines the automatic install.
|
|
119
|
+
*
|
|
120
|
+
* @returns the preferred command, which is the one the offer runs first.
|
|
121
|
+
*/
|
|
122
|
+
export declare function pnpmInstallCommand(): string;
|
|
97
123
|
/** Resolve every path a command needs, without creating anything. */
|
|
98
124
|
export declare function resolvePaths(anchor: string, env?: NodeJS.ProcessEnv): StandalonePaths;
|
|
99
125
|
/**
|
|
@@ -219,6 +219,43 @@ function runPnpm(cwd, args, label) {
|
|
|
219
219
|
if (result.status !== 0)
|
|
220
220
|
throw new Error(label + ' failed with exit code ' + String(result.status));
|
|
221
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Report whether pnpm can run.
|
|
224
|
+
*
|
|
225
|
+
* The profile installs its own tree so its \`overrides\` apply, and only pnpm reads those
|
|
226
|
+
* from a workspace, so pnpm is a prerequisite the distribution cannot supply. Probing
|
|
227
|
+
* first turns a cryptic failure from the install into a message naming what is missing.
|
|
228
|
+
*
|
|
229
|
+
* @returns \`true\` when pnpm answers with a version.
|
|
230
|
+
*/
|
|
231
|
+
export function pnpmAvailable() {
|
|
232
|
+
const probe = spawnSync('pnpm', ['--version'], {
|
|
233
|
+
stdio: 'pipe',
|
|
234
|
+
shell: process.platform === 'win32',
|
|
235
|
+
encoding: 'utf8',
|
|
236
|
+
});
|
|
237
|
+
return probe.status === 0;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* The commands that install pnpm, in the order worth trying.
|
|
241
|
+
*
|
|
242
|
+
* Corepack ships with Node and needs no download, so it comes first; npm is the fallback
|
|
243
|
+
* for an installation whose Corepack is absent or disabled. Both are the consumer's own
|
|
244
|
+
* toolchain, which is what lets the first start offer to install rather than only report.
|
|
245
|
+
*
|
|
246
|
+
* @returns commands to try in order, stopping at the first that works.
|
|
247
|
+
*/
|
|
248
|
+
export function pnpmInstallCommands() {
|
|
249
|
+
return ['corepack enable pnpm', 'npm install -g pnpm'];
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* The command to show a consumer who declines the automatic install.
|
|
253
|
+
*
|
|
254
|
+
* @returns the preferred command, which is the one the offer runs first.
|
|
255
|
+
*/
|
|
256
|
+
export function pnpmInstallCommand() {
|
|
257
|
+
return pnpmInstallCommands()[0] ?? 'npm install -g pnpm';
|
|
258
|
+
}
|
|
222
259
|
/**
|
|
223
260
|
* Expose the distribution's nested packages at the top level the profile searches.
|
|
224
261
|
*
|
package/package.json
CHANGED