@penvhq/launcher 0.10.0 → 0.11.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.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  httpFetcher,
6
6
  nodeSpawner,
7
7
  runLauncher
8
- } from "./chunk-BNUZ52VN.js";
8
+ } from "./chunk-USYQEKPW.js";
9
9
 
10
10
  // src/bin.ts
11
11
  function readLine() {
@@ -170,6 +170,8 @@ import {
170
170
  PenvError
171
171
  } from "@penvhq/core";
172
172
  var INSTALL_COMMAND = "penv install";
173
+ var UPGRADE_COMMAND = "penv upgrade";
174
+ var YES_FLAG = "--yes";
173
175
  var MIN_PACKAGE_AGE_DAYS = 7;
174
176
  var TRUST_YOUNG_FLAG = "--trust-young";
175
177
  function addCommand(name, version, extra) {
@@ -352,11 +354,11 @@ var OfficialRegistryError = class extends PenvError {
352
354
  };
353
355
  var RegistryUnreadableError = class extends PenvError {
354
356
  name = "RegistryUnreadableError";
355
- constructor(name, url, detail) {
357
+ constructor(name, url, detail, retry = addCommand(name)) {
356
358
  super(
357
359
  "PENV_REGISTRY_UNREADABLE",
358
360
  `Reading ${name} from ${url} failed: ${detail}`,
359
- `Run \`${addCommand(name)}\` again when the registry is reachable.`
361
+ `Run \`${retry}\` again when the registry is reachable.`
360
362
  );
361
363
  }
362
364
  };
@@ -372,11 +374,11 @@ var PackageUnknownError = class extends PenvError {
372
374
  };
373
375
  var VersionUnknownError = class extends PenvError {
374
376
  name = "VersionUnknownError";
375
- constructor(name, version, url) {
377
+ constructor(name, version, url, retry = addCommand(name)) {
376
378
  super(
377
379
  "PENV_VERSION_UNKNOWN",
378
380
  `${url} publishes no ${version} of ${name}`,
379
- `Run \`${addCommand(name)}\` to take the version \`latest\` points at.`
381
+ `Run \`${retry}\` to take the version \`latest\` points at.`
380
382
  );
381
383
  }
382
384
  };
@@ -501,6 +503,66 @@ var EnginePinMismatchError = class extends PenvError {
501
503
  );
502
504
  }
503
505
  };
506
+ var UpgradeSubjectError = class extends PenvError {
507
+ name = "UpgradeSubjectError";
508
+ constructor() {
509
+ super(
510
+ "PENV_UPGRADE_SUBJECT",
511
+ "`penv upgrade` takes one version, or none",
512
+ `Run \`${UPGRADE_COMMAND}\` to move to whatever \`latest\` points at, or \`${UPGRADE_COMMAND} 0.9.6\` to move to an exact release.`
513
+ );
514
+ }
515
+ };
516
+ var UpgradeFlagError = class extends PenvError {
517
+ name = "UpgradeFlagError";
518
+ constructor(flag) {
519
+ super(
520
+ "PENV_UPGRADE_FLAG",
521
+ `\`${UPGRADE_COMMAND}\` does not understand \`${flag}\``,
522
+ `Run \`${UPGRADE_COMMAND} [version]\` with \`${YES_FLAG}\` \u2014 that is the one flag it takes.`
523
+ );
524
+ }
525
+ };
526
+ var UpgradeNoDownloadError = class extends PenvError {
527
+ name = "UpgradeNoDownloadError";
528
+ constructor() {
529
+ super(
530
+ "PENV_UPGRADE_NO_DOWNLOAD",
531
+ `Upgrading means reading the registry for the version and integrity to pin, and \`--no-download\` says this run does not`,
532
+ `Run \`${UPGRADE_COMMAND}\` without \`--no-download\`. Nothing was fetched or written.`
533
+ );
534
+ }
535
+ };
536
+ var UpgradeUnattendedError = class extends PenvError {
537
+ name = "UpgradeUnattendedError";
538
+ constructor() {
539
+ super(
540
+ "PENV_UPGRADE_UNATTENDED",
541
+ `Upgrading rewrites ${MANIFEST_PATH} and package.json, and this run has nobody to decide that`,
542
+ `Run \`${UPGRADE_COMMAND} <version> ${YES_FLAG}\` \u2014 unattended, penv moves the pin only to a version you named. In CI, run \`${INSTALL_COMMAND}\`: it installs what the committed manifest already pins.`
543
+ );
544
+ }
545
+ };
546
+ var UpgradeDeclinedError = class extends PenvError {
547
+ name = "UpgradeDeclinedError";
548
+ constructor(version) {
549
+ super(
550
+ "PENV_UPGRADE_DECLINED",
551
+ `${ENGINE_PACKAGE} ${version} was not installed, so ${MANIFEST_PATH} and package.json are unchanged`,
552
+ `Run \`${UPGRADE_COMMAND} ${version}\` again when you want both of them to move.`
553
+ );
554
+ }
555
+ };
556
+ var UpgradeInstallFailedError = class extends PenvError {
557
+ name = "UpgradeInstallFailedError";
558
+ constructor(command) {
559
+ super(
560
+ "PENV_UPGRADE_INSTALL_FAILED",
561
+ `${command} did not finish, so ${MANIFEST_PATH} still pins the engine it pinned before`,
562
+ `Run \`${command}\` yourself, then run \`${UPGRADE_COMMAND}\` again \u2014 the pin and the dependency move together or not at all.`
563
+ );
564
+ }
565
+ };
504
566
  var EngineEntryError = class extends PenvError {
505
567
  name = "EngineEntryError";
506
568
  constructor(name, version, dir) {
@@ -811,7 +873,8 @@ async function fetchRelease(query) {
811
873
  throw new RegistryUnreadableError(
812
874
  query.name,
813
875
  url,
814
- cause instanceof Error ? cause.message : String(cause)
876
+ cause instanceof Error ? cause.message : String(cause),
877
+ query.retry
815
878
  );
816
879
  }
817
880
  let parsed;
@@ -821,7 +884,8 @@ async function fetchRelease(query) {
821
884
  throw new RegistryUnreadableError(
822
885
  query.name,
823
886
  url,
824
- cause instanceof Error ? cause.message : String(cause)
887
+ cause instanceof Error ? cause.message : String(cause),
888
+ query.retry
825
889
  );
826
890
  }
827
891
  const packument = record(parsed);
@@ -837,7 +901,7 @@ async function fetchRelease(query) {
837
901
  const version = record(at(versions, asked)) === void 0 ? text3(at(tags, asked)) ?? asked : asked;
838
902
  const release = record(at(versions, version));
839
903
  if (release === void 0) {
840
- throw new VersionUnknownError(query.name, asked, url);
904
+ throw new VersionUnknownError(query.name, asked, url, query.retry);
841
905
  }
842
906
  const dist = record(at(release, "dist"));
843
907
  const integrity = text3(at(dist, "integrity"));
@@ -1369,8 +1433,8 @@ var DEV_PIN_INTEGRITY = "sha512-development-build-not-a-published-release";
1369
1433
  var DEV_PIN_VERSION = "0.0.0-dev";
1370
1434
  var BUNDLED_ENGINE_PIN = {
1371
1435
  package: ENGINE_PACKAGE3,
1372
- version: "0.10.0",
1373
- integrity: "sha512-b+U0c3xWbk1ILtMfPjJW8x5XBxSLAaw/IAOLMBmGvT2uuYv41JPED8PrenEj4s3ZJY5BxpWU9mQcJHEBouaw/Q=="
1436
+ version: "0.11.0",
1437
+ integrity: "sha512-Y+WKyuPsX4U8/1j0e+VMUhj0LaGrp67YEoDAWyyinrgA+c8IM4H1blqje/YK4LsQwzQDQQDF9bhWIhfmDAWoxA=="
1374
1438
  };
1375
1439
  function assertReleasePin(pin) {
1376
1440
  if (pin.integrity === DEV_PIN_INTEGRITY || pin.version === DEV_PIN_VERSION) {
@@ -1411,35 +1475,142 @@ function findAdoptedRoot(cwd) {
1411
1475
  return findUp(cwd, (dir) => existsSync3(stateDir(dir)));
1412
1476
  }
1413
1477
 
1478
+ // src/upgrade.ts
1479
+ import { writeFileSync as writeFileSync4 } from "fs";
1480
+ import {
1481
+ installWithPackageManager,
1482
+ planInstall,
1483
+ RUNTIME_PACKAGE,
1484
+ renderInstallPlan
1485
+ } from "@penvhq/cli/install";
1486
+ import { ENGINE_PACKAGE as ENGINE_PACKAGE4, MANIFEST_PATH as MANIFEST_PATH4, serializeManifest as serializeManifest2 } from "@penvhq/core";
1487
+ function parseRequest2(argv) {
1488
+ let version;
1489
+ let yes = false;
1490
+ for (const token of argv) {
1491
+ if (token === YES_FLAG) {
1492
+ yes = true;
1493
+ continue;
1494
+ }
1495
+ if (token.startsWith("-")) {
1496
+ throw new UpgradeFlagError(token);
1497
+ }
1498
+ if (version !== void 0 || token === "") {
1499
+ throw new UpgradeSubjectError();
1500
+ }
1501
+ version = token;
1502
+ }
1503
+ return { version, yes };
1504
+ }
1505
+ function renderPinChange(engine, release) {
1506
+ return [
1507
+ MANIFEST_PATH4,
1508
+ ` - "integrity": "${engine.integrity}"`,
1509
+ ` - "version": "${engine.version}"`,
1510
+ ` + "integrity": "${release.integrity}"`,
1511
+ ` + "version": "${release.version}"`
1512
+ ];
1513
+ }
1514
+ function pinnedElsewhere(manifest, version) {
1515
+ return Object.entries(manifest.extensions).filter(([, entry]) => entry.version !== version).map(([name]) => name);
1516
+ }
1517
+ async function consent(options, release, plan, yes) {
1518
+ const { io, manifest } = options;
1519
+ io.out(`${ENGINE_PACKAGE4} ${manifest.engine.version} \u2192 ${release.version}`);
1520
+ io.out("");
1521
+ for (const line of renderPinChange(manifest.engine, release)) {
1522
+ io.out(line);
1523
+ }
1524
+ for (const line of renderInstallPlan(plan)) {
1525
+ io.out(line);
1526
+ }
1527
+ if (yes) {
1528
+ return;
1529
+ }
1530
+ if (!await io.confirm(`Move this project to ${release.version}?`)) {
1531
+ throw new UpgradeDeclinedError(release.version);
1532
+ }
1533
+ }
1534
+ async function upgrade(options) {
1535
+ const { io, fetcher, home, root, manifest, manifestFile } = options;
1536
+ const request = parseRequest2(options.argv);
1537
+ if (options.noDownload === true) {
1538
+ throw new UpgradeNoDownloadError();
1539
+ }
1540
+ if ((options.ci === true || !io.interactive) && !(request.yes && request.version !== void 0)) {
1541
+ throw new UpgradeUnattendedError();
1542
+ }
1543
+ const release = await fetchRelease({
1544
+ name: ENGINE_PACKAGE4,
1545
+ ...request.version === void 0 ? {} : { version: request.version },
1546
+ retry: UPGRADE_COMMAND,
1547
+ fetcher
1548
+ });
1549
+ const plan = planInstall(root, release.version);
1550
+ if (manifest.engine.version === release.version && plan.satisfied) {
1551
+ io.out(`\u2713 Already on ${ENGINE_PACKAGE4} ${release.version} \u2014 nothing to move`);
1552
+ return;
1553
+ }
1554
+ const manifestText = serializeManifest2({
1555
+ ...manifest,
1556
+ engine: { package: ENGINE_PACKAGE4, version: release.version, integrity: release.integrity }
1557
+ });
1558
+ await consent(options, release, plan, request.yes);
1559
+ await installPin({
1560
+ home,
1561
+ kind: "engines",
1562
+ pin: { name: ENGINE_PACKAGE4, version: release.version, integrity: release.integrity },
1563
+ fetcher
1564
+ });
1565
+ io.out(`\u2713 ${ENGINE_PACKAGE4} ${release.version} installed`);
1566
+ if (!plan.satisfied) {
1567
+ try {
1568
+ await (options.install ?? installWithPackageManager)(plan);
1569
+ } catch {
1570
+ throw new UpgradeInstallFailedError(plan.command.join(" "));
1571
+ }
1572
+ io.out(`\u2713 package.json depends on ${RUNTIME_PACKAGE} ${release.version}`);
1573
+ }
1574
+ writeFileSync4(manifestFile, manifestText);
1575
+ io.out(`\u2713 ${MANIFEST_PATH4} pins ${ENGINE_PACKAGE4} ${release.version}`);
1576
+ const kept = pinnedElsewhere(manifest, release.version);
1577
+ if (kept.length > 0) {
1578
+ const subject = kept.length === 1 ? "keeps its own pin" : "keep their own pins";
1579
+ io.out(`\u2192 ${kept.join(", ")} ${subject} \u2014 \`penv add <package>@<version>\` moves one.`);
1580
+ }
1581
+ }
1582
+
1414
1583
  // src/launcher.ts
1415
- import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
1584
+ import { existsSync as existsSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
1416
1585
  import { join as join7 } from "path";
1417
1586
  import {
1418
1587
  MANIFEST_FORMAT,
1419
- MANIFEST_PATH as MANIFEST_PATH5,
1588
+ MANIFEST_PATH as MANIFEST_PATH6,
1420
1589
  PENV_HOME_VAR,
1421
1590
  PenvError as PenvError3,
1422
1591
  parseManifest as parseManifest2,
1423
1592
  penvHome,
1424
- serializeManifest as serializeManifest2,
1593
+ serializeManifest as serializeManifest3,
1425
1594
  UnsupportedManifestFormatError
1426
1595
  } from "@penvhq/core";
1427
1596
 
1428
1597
  // src/help.ts
1429
- import { EXTENSIONS_PATH as EXTENSIONS_PATH3, MANIFEST_PATH as MANIFEST_PATH4 } from "@penvhq/core";
1598
+ import { RUNTIME_PACKAGE as RUNTIME_PACKAGE2 } from "@penvhq/cli/install";
1599
+ import { ENGINE_PACKAGE as ENGINE_PACKAGE5, EXTENSIONS_PATH as EXTENSIONS_PATH3, MANIFEST_PATH as MANIFEST_PATH5 } from "@penvhq/core";
1430
1600
  function printLauncherCommands(io) {
1431
1601
  io.out("");
1432
1602
  io.out("LAUNCHER COMMANDS (penv itself, whatever engine a project pins)");
1433
1603
  io.out("");
1434
- io.out(` install Installs everything ${MANIFEST_PATH4} pins`);
1604
+ io.out(` install Installs everything ${MANIFEST_PATH5} pins`);
1435
1605
  io.out(" add <package> Pins a provider extension, and commits the decision");
1436
1606
  io.out(` add ${LOCAL_FLAG} <package> Adds the one this repository builds \u2014 nothing is pinned`);
1607
+ io.out(` upgrade [version] Moves the engine pin and ${RUNTIME_PACKAGE2} together`);
1437
1608
  io.out("");
1438
1609
  }
1439
1610
  function printInstallHelp(io) {
1440
1611
  io.out(`${INSTALL_COMMAND}`);
1441
1612
  io.out("");
1442
- io.out(`Downloads, verifies and installs every version ${MANIFEST_PATH4} pins \u2014 the engine and`);
1613
+ io.out(`Downloads, verifies and installs every version ${MANIFEST_PATH5} pins \u2014 the engine and`);
1443
1614
  io.out("every extension \u2014 into $PENV_HOME. The one penv command CI and production run that");
1444
1615
  io.out("may reach the registry.");
1445
1616
  }
@@ -1452,14 +1623,26 @@ function printAddHelp(io) {
1452
1623
  ` ${TRUST_YOUNG_FLAG} Add a release published less than ${MIN_PACKAGE_AGE_DAYS} days ago`
1453
1624
  );
1454
1625
  io.out("");
1455
- io.out(`Pins the release in ${MANIFEST_PATH4} and writes its type declaration to`);
1626
+ io.out(`Pins the release in ${MANIFEST_PATH5} and writes its type declaration to`);
1456
1627
  io.out(`${EXTENSIONS_PATH3}/. Both are committed, so \`${INSTALL_COMMAND}\` gives every machine`);
1457
1628
  io.out(`the bytes you reviewed. \`${LOCAL_FLAG}\` pins nothing and touches no manifest.`);
1458
1629
  }
1630
+ function printUpgradeHelp(io) {
1631
+ io.out("penv upgrade [version]");
1632
+ io.out("");
1633
+ io.out(` ${YES_FLAG} Skip the question \u2014 unattended runs need it and a version`);
1634
+ io.out("");
1635
+ io.out(`Moves the ${ENGINE_PACKAGE5} pin in ${MANIFEST_PATH5} and this project's`);
1636
+ io.out(`${RUNTIME_PACKAGE2} dependency to the same exact version. No version takes whatever`);
1637
+ io.out("`latest` points at; the integrity is the one the registry states, never one penv");
1638
+ io.out("computed. Both files are shown before either moves, and they move together or not");
1639
+ io.out("at all. Extensions keep their own pins.");
1640
+ }
1459
1641
 
1460
1642
  // src/launcher.ts
1461
1643
  var INSTALL = "install";
1462
1644
  var ADD = "add";
1645
+ var UPGRADE = "upgrade";
1463
1646
  var VERSION_FLAGS = /* @__PURE__ */ new Set(["--version", "-v"]);
1464
1647
  var HELP_FLAGS = /* @__PURE__ */ new Set(["--help", "-h"]);
1465
1648
  var NO_DOWNLOAD = "--no-download";
@@ -1555,6 +1738,10 @@ async function launch(options) {
1555
1738
  printAddHelp(io);
1556
1739
  return 0;
1557
1740
  }
1741
+ if (first === UPGRADE) {
1742
+ printUpgradeHelp(io);
1743
+ return 0;
1744
+ }
1558
1745
  }
1559
1746
  const project = findProject(cwd);
1560
1747
  if (project === void 0) {
@@ -1582,6 +1769,20 @@ async function launch(options) {
1582
1769
  io.out(`penv ${manifest.engine.version}`);
1583
1770
  return 0;
1584
1771
  }
1772
+ if (first === UPGRADE) {
1773
+ await upgrade({
1774
+ argv: forwarded.slice(1),
1775
+ root: project.root,
1776
+ manifestFile: project.manifestFile,
1777
+ manifest,
1778
+ home,
1779
+ io,
1780
+ fetcher: options.fetcher,
1781
+ noDownload,
1782
+ ci: isCi(env)
1783
+ });
1784
+ return 0;
1785
+ }
1585
1786
  const enginePin = enginePinOf(manifest);
1586
1787
  const engineDir = await ensure(options, "engines", enginePin, home, noDownload);
1587
1788
  for (const pin of extensionPinsOf(manifest)) {
@@ -1600,16 +1801,16 @@ async function adopt(options, forwarded, home, cwd, noDownload) {
1600
1801
  if (root === void 0) {
1601
1802
  return 0;
1602
1803
  }
1603
- const manifestFile = join7(root, ...MANIFEST_PATH5.split("/"));
1804
+ const manifestFile = join7(root, ...MANIFEST_PATH6.split("/"));
1604
1805
  if (existsSync4(manifestFile)) {
1605
1806
  return 0;
1606
1807
  }
1607
1808
  const pin = releaseEnginePin(options.bundledPin, engine.version);
1608
- writeFileSync4(
1809
+ writeFileSync5(
1609
1810
  manifestFile,
1610
- serializeManifest2({ format: MANIFEST_FORMAT, engine: pin, extensions: {} })
1811
+ serializeManifest3({ format: MANIFEST_FORMAT, engine: pin, extensions: {} })
1611
1812
  );
1612
- options.io.out(`\u2713 ${MANIFEST_PATH5} pins ${pin.package} ${pin.version}`);
1813
+ options.io.out(`\u2713 ${MANIFEST_PATH6} pins ${pin.package} ${pin.version}`);
1613
1814
  await ensureAdoptedEngine(
1614
1815
  options,
1615
1816
  { name: pin.package, version: pin.version, integrity: pin.integrity },
@@ -1709,6 +1910,8 @@ export {
1709
1910
  readProviderEntries,
1710
1911
  setProviderType,
1711
1912
  INSTALL_COMMAND,
1913
+ UPGRADE_COMMAND,
1914
+ YES_FLAG,
1712
1915
  MIN_PACKAGE_AGE_DAYS,
1713
1916
  TRUST_YOUNG_FLAG,
1714
1917
  NoProjectError,
@@ -1743,6 +1946,12 @@ export {
1743
1946
  DeclarationNotSelfContainedError,
1744
1947
  EnginePinUnreleasedError,
1745
1948
  EnginePinMismatchError,
1949
+ UpgradeSubjectError,
1950
+ UpgradeFlagError,
1951
+ UpgradeNoDownloadError,
1952
+ UpgradeUnattendedError,
1953
+ UpgradeDeclinedError,
1954
+ UpgradeInstallFailedError,
1746
1955
  EngineEntryError,
1747
1956
  readExtensionPackage,
1748
1957
  renderDeclaration,
@@ -1773,6 +1982,7 @@ export {
1773
1982
  releaseEnginePin,
1774
1983
  findProject,
1775
1984
  findAdoptedRoot,
1985
+ upgrade,
1776
1986
  runLauncher
1777
1987
  };
1778
- //# sourceMappingURL=chunk-BNUZ52VN.js.map
1988
+ //# sourceMappingURL=chunk-USYQEKPW.js.map