@penvhq/launcher 0.11.0 → 0.12.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/dist/bin.cjs +87 -41
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-USYQEKPW.js → chunk-A5LJQPYS.js} +98 -51
- package/dist/chunk-A5LJQPYS.js.map +1 -0
- package/dist/index.cjs +89 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -20
- package/dist/index.d.ts +28 -20
- package/dist/index.js +3 -3
- package/package.json +9 -3
- package/dist/chunk-USYQEKPW.js.map +0 -1
package/dist/bin.cjs
CHANGED
|
@@ -160,7 +160,7 @@ var AddFlagError = class extends import_core.PenvError {
|
|
|
160
160
|
super(
|
|
161
161
|
"PENV_ADD_FLAG",
|
|
162
162
|
`\`penv add\` does not understand \`${flag}\``,
|
|
163
|
-
`Run \`penv add <package>\` with \`${TRUST_YOUNG_FLAG}\`, \`--registry <url>\`, or \`${
|
|
163
|
+
`Run \`penv add <package>\` with \`${TRUST_YOUNG_FLAG}\`, \`--registry <url>\`, \`${LOCAL_FLAG}\`, or \`${YES_FLAG}\` \u2014 those are the four it takes.`
|
|
164
164
|
);
|
|
165
165
|
}
|
|
166
166
|
};
|
|
@@ -306,13 +306,13 @@ var AddNoDownloadError = class extends import_core.PenvError {
|
|
|
306
306
|
);
|
|
307
307
|
}
|
|
308
308
|
};
|
|
309
|
-
var
|
|
310
|
-
name = "
|
|
311
|
-
constructor(name) {
|
|
309
|
+
var AddTrustUnattendedError = class extends import_core.PenvError {
|
|
310
|
+
name = "AddTrustUnattendedError";
|
|
311
|
+
constructor(name, ceremony) {
|
|
312
312
|
super(
|
|
313
|
-
"
|
|
314
|
-
`Adding ${name}
|
|
315
|
-
`Run \`${addCommand(name)}\` from a terminal
|
|
313
|
+
"PENV_ADD_TRUST_UNATTENDED",
|
|
314
|
+
`Adding ${name} records ${ceremony}, and this run has nobody to write it`,
|
|
315
|
+
`Run \`${addCommand(name)}\` from a terminal, without \`${YES_FLAG}\` \u2014 the trust block is a line only a person can write. In CI, run \`${INSTALL_COMMAND}\`: it installs the versions the committed manifest already pins.`
|
|
316
316
|
);
|
|
317
317
|
}
|
|
318
318
|
};
|
|
@@ -438,11 +438,11 @@ var UpgradeDeclinedError = class extends import_core.PenvError {
|
|
|
438
438
|
};
|
|
439
439
|
var UpgradeInstallFailedError = class extends import_core.PenvError {
|
|
440
440
|
name = "UpgradeInstallFailedError";
|
|
441
|
-
constructor(
|
|
441
|
+
constructor(manager, version) {
|
|
442
442
|
super(
|
|
443
443
|
"PENV_UPGRADE_INSTALL_FAILED",
|
|
444
|
-
`${
|
|
445
|
-
`
|
|
444
|
+
`${manager} did not finish moving this project to ${import_core.ENGINE_PACKAGE} ${version}, so ${import_core.MANIFEST_PATH} still pins the engine it pinned before`,
|
|
445
|
+
`Read what ${manager} printed above \u2014 it names what it refused. Fix that and run \`${UPGRADE_COMMAND} ${version}\` again; the pin and the dependency move together or not at all.`
|
|
446
446
|
);
|
|
447
447
|
}
|
|
448
448
|
};
|
|
@@ -1100,12 +1100,17 @@ function parseRequest(argv) {
|
|
|
1100
1100
|
let registry;
|
|
1101
1101
|
let trustYoung = false;
|
|
1102
1102
|
let local = false;
|
|
1103
|
+
let yes = false;
|
|
1103
1104
|
for (let index = 0; index < argv.length; index += 1) {
|
|
1104
1105
|
const token = argv[index] ?? "";
|
|
1105
1106
|
if (token === LOCAL_FLAG) {
|
|
1106
1107
|
local = true;
|
|
1107
1108
|
continue;
|
|
1108
1109
|
}
|
|
1110
|
+
if (token === YES_FLAG) {
|
|
1111
|
+
yes = true;
|
|
1112
|
+
continue;
|
|
1113
|
+
}
|
|
1109
1114
|
if (token === TRUST_YOUNG_FLAG) {
|
|
1110
1115
|
trustYoung = true;
|
|
1111
1116
|
continue;
|
|
@@ -1145,7 +1150,10 @@ function parseRequest(argv) {
|
|
|
1145
1150
|
throw new AddLocalFlagError(`\`${TRUST_YOUNG_FLAG}\``);
|
|
1146
1151
|
}
|
|
1147
1152
|
}
|
|
1148
|
-
return { name, version, registry, trustYoung, local };
|
|
1153
|
+
return { name, version, registry, trustYoung, local, yes };
|
|
1154
|
+
}
|
|
1155
|
+
function ceremonyFor(tier) {
|
|
1156
|
+
return tier === "official" ? void 0 : "who publishes it and why you trust it";
|
|
1149
1157
|
}
|
|
1150
1158
|
function tierOf(request) {
|
|
1151
1159
|
if (request.name.startsWith(import_core6.OFFICIAL_SCOPE)) {
|
|
@@ -1224,7 +1232,29 @@ function recordExtension(manifestFile, name, entry) {
|
|
|
1224
1232
|
};
|
|
1225
1233
|
return (0, import_core6.serializeManifest)(next);
|
|
1226
1234
|
}
|
|
1227
|
-
|
|
1235
|
+
var NONE = /* @__PURE__ */ new Set(["", "none", "no", "n"]);
|
|
1236
|
+
var ALL = /* @__PURE__ */ new Set(["all", "a", "yes", "y"]);
|
|
1237
|
+
function chooseEnvironments(answer, offered) {
|
|
1238
|
+
const normalized = answer.trim().toLowerCase();
|
|
1239
|
+
if (NONE.has(normalized)) {
|
|
1240
|
+
return { chosen: [], unknown: [] };
|
|
1241
|
+
}
|
|
1242
|
+
if (ALL.has(normalized)) {
|
|
1243
|
+
return { chosen: offered, unknown: [] };
|
|
1244
|
+
}
|
|
1245
|
+
const chosen = [];
|
|
1246
|
+
const unknown = [];
|
|
1247
|
+
for (const token of normalized.split(/[\s,]+/).filter((part) => part !== "")) {
|
|
1248
|
+
const match = offered.find((environment) => environment.toLowerCase() === token);
|
|
1249
|
+
if (match === void 0) {
|
|
1250
|
+
unknown.push(token);
|
|
1251
|
+
} else {
|
|
1252
|
+
chosen.push(match);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
return { chosen, unknown };
|
|
1256
|
+
}
|
|
1257
|
+
async function offerConfigEdit(options, name, ask) {
|
|
1228
1258
|
const { io: io2, root } = options;
|
|
1229
1259
|
const configFile = (0, import_core6.findConfigFile)(root);
|
|
1230
1260
|
const line = `Add \`type: ${JSON.stringify(name)}\` to an environment in penv.config.ts.`;
|
|
@@ -1239,31 +1269,35 @@ async function offerConfigEdit(options, name) {
|
|
|
1239
1269
|
io2.out(line);
|
|
1240
1270
|
return;
|
|
1241
1271
|
}
|
|
1242
|
-
|
|
1272
|
+
const offered = entries.filter((entry) => entry.type !== name).map((entry) => entry.environment);
|
|
1273
|
+
if (offered.length === 0) {
|
|
1243
1274
|
return;
|
|
1244
1275
|
}
|
|
1245
|
-
if (!
|
|
1276
|
+
if (!ask) {
|
|
1246
1277
|
io2.out(line);
|
|
1247
1278
|
return;
|
|
1248
1279
|
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1280
|
+
const { chosen, unknown } = chooseEnvironments(
|
|
1281
|
+
await io2.ask(`Point which of ${offered.join(", ")} at ${name} in ${shown}? all / none / names`),
|
|
1282
|
+
offered
|
|
1283
|
+
);
|
|
1284
|
+
if (unknown.length > 0) {
|
|
1285
|
+
io2.out(`${shown} declares no ${unknown.join(", ")}, so nothing was repointed.`);
|
|
1286
|
+
io2.out(line);
|
|
1287
|
+
return;
|
|
1288
|
+
}
|
|
1289
|
+
for (const environment of chosen) {
|
|
1290
|
+
const next = setProviderType(current, environment, name);
|
|
1257
1291
|
if (next === void 0) {
|
|
1258
|
-
io2.out(`Add \`type: ${JSON.stringify(name)}\` to \`${
|
|
1292
|
+
io2.out(`Add \`type: ${JSON.stringify(name)}\` to \`${environment}\` in ${shown}.`);
|
|
1259
1293
|
continue;
|
|
1260
1294
|
}
|
|
1261
1295
|
current = next;
|
|
1262
1296
|
(0, import_node_fs5.writeFileSync)(configFile, current);
|
|
1263
|
-
io2.out(`\u2713 ${shown} points \`${
|
|
1297
|
+
io2.out(`\u2713 ${shown} points \`${environment}\` at ${name}`);
|
|
1264
1298
|
}
|
|
1265
1299
|
}
|
|
1266
|
-
async function offerOnboarding(io2, name, onboard) {
|
|
1300
|
+
async function offerOnboarding(io2, name, onboard, ask) {
|
|
1267
1301
|
if (onboard === void 0) {
|
|
1268
1302
|
return void 0;
|
|
1269
1303
|
}
|
|
@@ -1272,7 +1306,7 @@ async function offerOnboarding(io2, name, onboard) {
|
|
|
1272
1306
|
return void 0;
|
|
1273
1307
|
}
|
|
1274
1308
|
const command = `penv ${args.join(" ")}`;
|
|
1275
|
-
if (
|
|
1309
|
+
if (ask && await io2.confirm(`Run \`${command}\` now?`)) {
|
|
1276
1310
|
return args;
|
|
1277
1311
|
}
|
|
1278
1312
|
io2.out(`Run \`${command}\` to finish setting ${name} up.`);
|
|
@@ -1353,8 +1387,9 @@ async function addLocal(options, request) {
|
|
|
1353
1387
|
io2.out(`\u2713 ${request.name} resolves from this project and imports \u2014 nothing is pinned`);
|
|
1354
1388
|
io2.out(`\u2713 ${import_core6.LOCAL_EXTENSIONS_PATH} records it`);
|
|
1355
1389
|
io2.out(`\u2713 ${declaration} declares its config type`);
|
|
1356
|
-
|
|
1357
|
-
|
|
1390
|
+
const ask = io2.interactive && !request.yes;
|
|
1391
|
+
await offerConfigEdit(options, request.name, ask);
|
|
1392
|
+
return { onboard: await offerOnboarding(io2, request.name, installed.onboard, ask) };
|
|
1358
1393
|
}
|
|
1359
1394
|
async function add(options) {
|
|
1360
1395
|
const { io: io2, fetcher, home, root, manifestFile } = options;
|
|
@@ -1364,11 +1399,13 @@ async function add(options) {
|
|
|
1364
1399
|
}
|
|
1365
1400
|
const tier = tierOf(request);
|
|
1366
1401
|
const now = (options.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
1402
|
+
const ask = io2.interactive && !request.yes;
|
|
1367
1403
|
if (options.noDownload === true) {
|
|
1368
1404
|
throw new AddNoDownloadError(request.name);
|
|
1369
1405
|
}
|
|
1370
|
-
|
|
1371
|
-
|
|
1406
|
+
const ceremony = ceremonyFor(tier);
|
|
1407
|
+
if (ceremony !== void 0 && (options.ci === true || !ask)) {
|
|
1408
|
+
throw new AddTrustUnattendedError(request.name, ceremony);
|
|
1372
1409
|
}
|
|
1373
1410
|
const release = await fetchRelease({
|
|
1374
1411
|
name: request.name,
|
|
@@ -1410,8 +1447,8 @@ async function add(options) {
|
|
|
1410
1447
|
io2.out(`\u2713 ${release.name} ${release.version} installed \u2014 ${provenance}`);
|
|
1411
1448
|
io2.out(`\u2713 ${import_core6.MANIFEST_PATH} pins it`);
|
|
1412
1449
|
io2.out(`\u2713 ${declaration} declares its config type`);
|
|
1413
|
-
await offerConfigEdit(options, release.name);
|
|
1414
|
-
return { onboard: await offerOnboarding(io2, release.name, installed.onboard) };
|
|
1450
|
+
await offerConfigEdit(options, release.name, ask);
|
|
1451
|
+
return { onboard: await offerOnboarding(io2, release.name, installed.onboard, ask) };
|
|
1415
1452
|
}
|
|
1416
1453
|
|
|
1417
1454
|
// src/help.ts
|
|
@@ -1442,10 +1479,15 @@ function printAddHelp(io2) {
|
|
|
1442
1479
|
io2.out(
|
|
1443
1480
|
` ${TRUST_YOUNG_FLAG} Add a release published less than ${MIN_PACKAGE_AGE_DAYS} days ago`
|
|
1444
1481
|
);
|
|
1482
|
+
io2.out(` ${YES_FLAG} Ask nothing \u2014 the config and onboarding offers print instead`);
|
|
1445
1483
|
io2.out("");
|
|
1446
1484
|
io2.out(`Pins the release in ${import_core7.MANIFEST_PATH} and writes its type declaration to`);
|
|
1447
1485
|
io2.out(`${import_core7.EXTENSIONS_PATH}/. Both are committed, so \`${INSTALL_COMMAND}\` gives every machine`);
|
|
1448
1486
|
io2.out(`the bytes you reviewed. \`${LOCAL_FLAG}\` pins nothing and touches no manifest.`);
|
|
1487
|
+
io2.out("");
|
|
1488
|
+
io2.out(`An \`${import_core7.OFFICIAL_SCOPE}*\` package asks nothing, so it adds unattended. Anything else`);
|
|
1489
|
+
io2.out("records who publishes it and why you trust it, which needs a person at a terminal \u2014");
|
|
1490
|
+
io2.out(`\`${YES_FLAG}\` cannot write that line for you.`);
|
|
1449
1491
|
}
|
|
1450
1492
|
function printUpgradeHelp(io2) {
|
|
1451
1493
|
io2.out("penv upgrade [version]");
|
|
@@ -1465,8 +1507,8 @@ var DEV_PIN_INTEGRITY = "sha512-development-build-not-a-published-release";
|
|
|
1465
1507
|
var DEV_PIN_VERSION = "0.0.0-dev";
|
|
1466
1508
|
var BUNDLED_ENGINE_PIN = {
|
|
1467
1509
|
package: import_core8.ENGINE_PACKAGE,
|
|
1468
|
-
version: "0.
|
|
1469
|
-
integrity: "sha512-
|
|
1510
|
+
version: "0.12.0",
|
|
1511
|
+
integrity: "sha512-9HUylEIbFq0BGTOW54Vxhkzv8AvuB7H3bImTFP5J+dfglkR7udP2KUsr8b0I2mf45YMTQO5xsYpI5+nhLERGtA=="
|
|
1470
1512
|
};
|
|
1471
1513
|
function assertReleasePin(pin) {
|
|
1472
1514
|
if (pin.integrity === DEV_PIN_INTEGRITY || pin.version === DEV_PIN_VERSION) {
|
|
@@ -1594,9 +1636,11 @@ async function upgrade(options) {
|
|
|
1594
1636
|
try {
|
|
1595
1637
|
await (options.install ?? import_install2.installWithPackageManager)(plan);
|
|
1596
1638
|
} catch {
|
|
1597
|
-
throw new UpgradeInstallFailedError(plan.
|
|
1639
|
+
throw new UpgradeInstallFailedError(plan.manager, release.version);
|
|
1640
|
+
}
|
|
1641
|
+
for (const step of plan.steps.filter((entry) => !entry.satisfied)) {
|
|
1642
|
+
io2.out(`\u2713 ${step.manifest} depends on ${import_install2.RUNTIME_PACKAGE} ${release.version}`);
|
|
1598
1643
|
}
|
|
1599
|
-
io2.out(`\u2713 package.json depends on ${import_install2.RUNTIME_PACKAGE} ${release.version}`);
|
|
1600
1644
|
}
|
|
1601
1645
|
(0, import_node_fs7.writeFileSync)(manifestFile, manifestText);
|
|
1602
1646
|
io2.out(`\u2713 ${import_core10.MANIFEST_PATH} pins ${import_core10.ENGINE_PACKAGE} ${release.version}`);
|
|
@@ -1825,12 +1869,14 @@ async function install(options, pins, home, broken) {
|
|
|
1825
1869
|
if (state === "corrupt") {
|
|
1826
1870
|
throw new PackageCorruptError(pin.name, pin.version, dir);
|
|
1827
1871
|
}
|
|
1828
|
-
if (state === "
|
|
1829
|
-
|
|
1830
|
-
|
|
1872
|
+
if (state === "absent") {
|
|
1873
|
+
await installPin({ home, kind, pin, fetcher: options.fetcher });
|
|
1874
|
+
}
|
|
1875
|
+
if (kind === "extensions") {
|
|
1876
|
+
await assertLoadable(pin.name, (0, import_core11.packageEntry)(dir), false);
|
|
1831
1877
|
}
|
|
1832
|
-
|
|
1833
|
-
options.io.out(`\u2713 ${pin.name} ${pin.version}
|
|
1878
|
+
const verb = state === "absent" ? "installed" : "already installed";
|
|
1879
|
+
options.io.out(`\u2713 ${pin.name} ${pin.version} ${verb}`);
|
|
1834
1880
|
}
|
|
1835
1881
|
if (broken.length > 0) {
|
|
1836
1882
|
report(new ManifestEntriesUnreadableError(broken), options.io);
|