@layr-labs/ecloud-cli 0.3.4 → 0.4.0-dev.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.
Files changed (56) hide show
  1. package/dist/commands/auth/whoami.js +1 -0
  2. package/dist/commands/auth/whoami.js.map +1 -1
  3. package/dist/commands/billing/__tests__/status.test.js +552 -0
  4. package/dist/commands/billing/__tests__/status.test.js.map +1 -0
  5. package/dist/commands/billing/__tests__/subscribe.test.js +580 -0
  6. package/dist/commands/billing/__tests__/subscribe.test.js.map +1 -0
  7. package/dist/commands/billing/__tests__/top-up.test.js +729 -0
  8. package/dist/commands/billing/__tests__/top-up.test.js.map +1 -0
  9. package/dist/commands/billing/cancel.js +8 -7
  10. package/dist/commands/billing/cancel.js.map +1 -1
  11. package/dist/commands/billing/status.js +25 -19
  12. package/dist/commands/billing/status.js.map +1 -1
  13. package/dist/commands/billing/subscribe.js +43 -14
  14. package/dist/commands/billing/subscribe.js.map +1 -1
  15. package/dist/commands/billing/top-up.js +491 -0
  16. package/dist/commands/billing/top-up.js.map +1 -0
  17. package/dist/commands/compute/app/create.js +1 -0
  18. package/dist/commands/compute/app/create.js.map +1 -1
  19. package/dist/commands/compute/app/deploy.js +62 -23
  20. package/dist/commands/compute/app/deploy.js.map +1 -1
  21. package/dist/commands/compute/app/info.js +32 -31
  22. package/dist/commands/compute/app/info.js.map +1 -1
  23. package/dist/commands/compute/app/list.js +31 -30
  24. package/dist/commands/compute/app/list.js.map +1 -1
  25. package/dist/commands/compute/app/logs.js +2 -1
  26. package/dist/commands/compute/app/logs.js.map +1 -1
  27. package/dist/commands/compute/app/profile/set.js +6 -5
  28. package/dist/commands/compute/app/profile/set.js.map +1 -1
  29. package/dist/commands/compute/app/releases.js +18 -17
  30. package/dist/commands/compute/app/releases.js.map +1 -1
  31. package/dist/commands/compute/app/start.js +6 -5
  32. package/dist/commands/compute/app/start.js.map +1 -1
  33. package/dist/commands/compute/app/stop.js +6 -5
  34. package/dist/commands/compute/app/stop.js.map +1 -1
  35. package/dist/commands/compute/app/terminate.js +6 -5
  36. package/dist/commands/compute/app/terminate.js.map +1 -1
  37. package/dist/commands/compute/app/upgrade.js +51 -22
  38. package/dist/commands/compute/app/upgrade.js.map +1 -1
  39. package/dist/commands/compute/build/info.js +16 -15
  40. package/dist/commands/compute/build/info.js.map +1 -1
  41. package/dist/commands/compute/build/list.js +13 -12
  42. package/dist/commands/compute/build/list.js.map +1 -1
  43. package/dist/commands/compute/build/logs.js +4 -3
  44. package/dist/commands/compute/build/logs.js.map +1 -1
  45. package/dist/commands/compute/build/status.js +9 -8
  46. package/dist/commands/compute/build/status.js.map +1 -1
  47. package/dist/commands/compute/build/submit.js +16 -15
  48. package/dist/commands/compute/build/submit.js.map +1 -1
  49. package/dist/commands/compute/build/verify.js +10 -9
  50. package/dist/commands/compute/build/verify.js.map +1 -1
  51. package/dist/commands/compute/environment/set.js +1 -0
  52. package/dist/commands/compute/environment/set.js.map +1 -1
  53. package/dist/commands/compute/undelegate.js +6 -5
  54. package/dist/commands/compute/undelegate.js.map +1 -1
  55. package/package.json +3 -2
  56. package/VERSION +0 -2
@@ -181,6 +181,7 @@ import { getBuildType as getBuildType3 } from "@layr-labs/ecloud-sdk";
181
181
 
182
182
  // src/utils/prompts.ts
183
183
  import { input, select, password, confirm as inquirerConfirm } from "@inquirer/prompts";
184
+ import chalk from "chalk";
184
185
  import fs3 from "fs";
185
186
  import path3 from "path";
186
187
  import os3 from "os";
@@ -304,7 +305,7 @@ function findAvailableName(environment, baseName) {
304
305
 
305
306
  // src/utils/version.ts
306
307
  function getCliVersion() {
307
- return true ? "0.3.4" : "0.0.0";
308
+ return true ? "0.4.0-dev.0" : "0.0.0";
308
309
  }
309
310
  function getClientId() {
310
311
  return `ecloud-cli/v${getCliVersion()}`;
@@ -767,6 +768,30 @@ async function getEnvFileInteractive(envFilePath) {
767
768
  throw new Error(`Unexpected choice: ${choice}`);
768
769
  }
769
770
  }
771
+ var SKU_TIER_NAMES = {
772
+ "g1-micro-1v": "Starter 1",
773
+ "g1-small-1v": "Starter 2",
774
+ "g1-custom-2-4096s": "Growth 1",
775
+ "g1-standard-2s": "Growth 2",
776
+ "g1-standard-4t": "Enterprise 1",
777
+ "g1-standard-8t": "Enterprise 2"
778
+ };
779
+ function formatSkuChoice(it) {
780
+ if (it.vcpus != null && it.memory_mb != null && it.monthly_price_usd != null && it.hourly_price_usd != null) {
781
+ const tier = SKU_TIER_NAMES[it.sku] ?? it.sku;
782
+ const isShared = it.description.toLowerCase().includes("shared");
783
+ const vcpuLabel = isShared ? `Shared ${it.vcpus} vCPU` : `${it.vcpus} vCPU`;
784
+ const memLabel = it.memory_mb >= 1024 ? `${it.memory_mb / 1024} GB` : `${it.memory_mb} MB`;
785
+ const specs = `${vcpuLabel} + ${memLabel}`;
786
+ const pricing = `$${it.hourly_price_usd.toFixed(2)}/hr ($${it.monthly_price_usd.toFixed(2)}/mo)`;
787
+ const platform = it.platform ?? "";
788
+ const tierPad = tier.padEnd(14);
789
+ const specsPad = specs.padEnd(22);
790
+ const platformPad = platform.padEnd(20);
791
+ return `${tierPad} ${specsPad} ${platformPad} ${pricing}`.trimEnd();
792
+ }
793
+ return `${it.sku} - ${it.description}`;
794
+ }
770
795
  async function getInstanceTypeInteractive(instanceType, defaultSKU, availableTypes) {
771
796
  if (instanceType) {
772
797
  const valid = availableTypes.find((t) => t.sku === instanceType);
@@ -777,19 +802,22 @@ async function getInstanceTypeInteractive(instanceType, defaultSKU, availableTyp
777
802
  throw new Error(`Invalid instance-type: ${instanceType} (must be one of: ${validSKUs})`);
778
803
  }
779
804
  const isCurrentType = defaultSKU !== "";
780
- if (defaultSKU === "" && availableTypes.length > 0) {
781
- defaultSKU = availableTypes[0].sku;
805
+ const hasPricing = availableTypes.some((t) => t.monthly_price_usd != null);
806
+ if (hasPricing) {
807
+ console.log("\nPay for what you use \u2014 no upfront costs, per-hour billing.\n");
808
+ console.log(` ${chalk.bold("Shielded VM (vTPM)")}: Verified boot and runtime attestation.`);
809
+ console.log(` ${chalk.bold("SEV-SNP (TEE)")}: Verified boot, runtime attestation, and hardware-encrypted memory (AMD).`);
810
+ console.log(` ${chalk.bold("TDX (TEE)")}: Verified boot, runtime attestation, and hardware-encrypted memory (Intel).
811
+ `);
782
812
  }
783
813
  if (isCurrentType && defaultSKU) {
784
- console.log(`
785
- Select instance type (current: ${defaultSKU}):`);
786
- } else {
787
- console.log("\nSelect instance type:");
814
+ console.log(`Current instance type: ${defaultSKU}
815
+ `);
788
816
  }
789
817
  const choices = availableTypes.map((it) => {
790
- let name = `${it.sku} - ${it.description}`;
791
- if (it.sku === defaultSKU) {
792
- name += isCurrentType ? " (current)" : " (default)";
818
+ let name = formatSkuChoice(it);
819
+ if (isCurrentType && it.sku === defaultSKU) {
820
+ name += " (current)";
793
821
  }
794
822
  return { name, value: it.sku };
795
823
  });
@@ -1265,7 +1293,7 @@ async function createBuildClient(flags) {
1265
1293
  }
1266
1294
 
1267
1295
  // src/commands/compute/app/deploy.ts
1268
- import chalk from "chalk";
1296
+ import chalk2 from "chalk";
1269
1297
 
1270
1298
  // src/utils/build.ts
1271
1299
  function formatSourceLink(repoUrl, gitRef) {
@@ -1479,7 +1507,7 @@ var AppDeploy = class _AppDeploy extends Command {
1479
1507
  }),
1480
1508
  "instance-type": Flags2.string({
1481
1509
  required: false,
1482
- description: "Machine instance type to use e.g. g1-standard-4t, g1-standard-8t",
1510
+ description: "Machine instance type (e.g., g1-standard-4t, g1-standard-2s, g1-micro-1v)",
1483
1511
  env: "ECLOUD_INSTANCE_TYPE"
1484
1512
  }),
1485
1513
  "skip-profile": Flags2.boolean({
@@ -1493,6 +1521,13 @@ var AppDeploy = class _AppDeploy extends Command {
1493
1521
  options: ["enable", "disable"],
1494
1522
  env: "ECLOUD_RESOURCE_USAGE_MONITORING"
1495
1523
  }),
1524
+ "bill-to": Flags2.string({
1525
+ required: false,
1526
+ description: "Billing mode: developer (default) or app (isolated billing)",
1527
+ options: ["developer", "app"],
1528
+ default: "developer",
1529
+ env: "ECLOUD_BILL_TO"
1530
+ }),
1496
1531
  website: Flags2.string({
1497
1532
  required: false,
1498
1533
  description: "App website URL (optional)"
@@ -1623,7 +1658,7 @@ var AppDeploy = class _AppDeploy extends Command {
1623
1658
  if (includeTlsCaddyfile && !inputs.caddyfilePath) {
1624
1659
  inputs.caddyfilePath = "Caddyfile";
1625
1660
  }
1626
- this.log(chalk.blue("Building from source with verifiable build..."));
1661
+ this.log(chalk2.blue("Building from source with verifiable build..."));
1627
1662
  this.log("");
1628
1663
  const buildClient2 = await getBuildClient();
1629
1664
  const { build, verified } = await runVerifiableBuildAndVerify(buildClient2, inputs, {
@@ -1656,7 +1691,7 @@ var AppDeploy = class _AppDeploy extends Command {
1656
1691
  } catch (e) {
1657
1692
  this.error(e?.message || String(e));
1658
1693
  }
1659
- this.log(chalk.blue("Resolving and verifying prebuilt verifiable image..."));
1694
+ this.log(chalk2.blue("Resolving and verifying prebuilt verifiable image..."));
1660
1695
  this.log("");
1661
1696
  const digest = await resolveDockerHubImageDigest(imageRef2);
1662
1697
  const buildClient2 = await getBuildClient();
@@ -1692,6 +1727,7 @@ var AppDeploy = class _AppDeploy extends Command {
1692
1727
  );
1693
1728
  envFilePath = envFilePath ?? await getEnvFileInteractive(flags["env-file"]);
1694
1729
  const availableTypes = await fetchAvailableInstanceTypes(
1730
+ environment,
1695
1731
  environmentConfig,
1696
1732
  privateKey,
1697
1733
  rpcUrl
@@ -1709,6 +1745,7 @@ var AppDeploy = class _AppDeploy extends Command {
1709
1745
  flags["resource-usage-monitoring"]
1710
1746
  );
1711
1747
  const logVisibility = logSettings.publicLogs ? "public" : logSettings.logRedirect ? "private" : "off";
1748
+ const billTo = flags["bill-to"];
1712
1749
  const { prepared, gasEstimate } = isVerifiable ? await compute.app.prepareDeployFromVerifiableBuild({
1713
1750
  name: appName,
1714
1751
  imageRef,
@@ -1716,7 +1753,8 @@ var AppDeploy = class _AppDeploy extends Command {
1716
1753
  envFile: envFilePath,
1717
1754
  instanceType,
1718
1755
  logVisibility,
1719
- resourceUsageMonitoring
1756
+ resourceUsageMonitoring,
1757
+ billTo
1720
1758
  }) : await compute.app.prepareDeploy({
1721
1759
  name: appName,
1722
1760
  dockerfile: dockerfilePath,
@@ -1724,15 +1762,16 @@ var AppDeploy = class _AppDeploy extends Command {
1724
1762
  envFile: envFilePath,
1725
1763
  instanceType,
1726
1764
  logVisibility,
1727
- resourceUsageMonitoring
1765
+ resourceUsageMonitoring,
1766
+ billTo
1728
1767
  });
1729
1768
  this.log(`
1730
- Estimated transaction cost: ${chalk.cyan(gasEstimate.maxCostEth)} ETH`);
1769
+ Estimated transaction cost: ${chalk2.cyan(gasEstimate.maxCostEth)} ETH`);
1731
1770
  if (isMainnet(environmentConfig)) {
1732
1771
  const confirmed = await confirm(`Continue with deployment?`);
1733
1772
  if (!confirmed) {
1734
1773
  this.log(`
1735
- ${chalk.gray(`Deployment cancelled`)}`);
1774
+ ${chalk2.gray(`Deployment cancelled`)}`);
1736
1775
  return;
1737
1776
  }
1738
1777
  }
@@ -1788,20 +1827,20 @@ ${chalk.gray(`Deployment cancelled`)}`);
1788
1827
  }
1789
1828
  this.log(
1790
1829
  `
1791
- \u2705 ${chalk.green(`App deployed successfully ${chalk.bold(`(id: ${res.appId}, ip: ${ipAddress})`)}`)}`
1830
+ \u2705 ${chalk2.green(`App deployed successfully ${chalk2.bold(`(id: ${res.appId}, ip: ${ipAddress})`)}`)}`
1792
1831
  );
1793
1832
  const dashboardUrl = getDashboardUrl(environment, res.appId);
1794
1833
  this.log(`
1795
- ${chalk.gray("View your app:")} ${chalk.blue.underline(dashboardUrl)}`);
1834
+ ${chalk2.gray("View your app:")} ${chalk2.blue.underline(dashboardUrl)}`);
1796
1835
  });
1797
1836
  }
1798
1837
  };
1799
- async function fetchAvailableInstanceTypes(environmentConfig, privateKey, rpcUrl) {
1838
+ async function fetchAvailableInstanceTypes(environment, environmentConfig, privateKey, rpcUrl) {
1800
1839
  try {
1801
1840
  const { publicClient, walletClient } = createViemClients({
1802
1841
  privateKey,
1803
1842
  rpcUrl,
1804
- environment: environmentConfig.name
1843
+ environment
1805
1844
  });
1806
1845
  const userApiClient = new UserApiClient3(
1807
1846
  environmentConfig,
@@ -1816,7 +1855,7 @@ async function fetchAvailableInstanceTypes(environmentConfig, privateKey, rpcUrl
1816
1855
  return skuList.skus;
1817
1856
  } catch (err) {
1818
1857
  console.warn(`Failed to fetch instance types: ${err.message}`);
1819
- return [{ sku: "g1-standard-4t", description: "Standard 4-thread instance" }];
1858
+ return [{ sku: "g1-standard-4t", description: "4 vCPUs, 16 GB memory, TDX" }];
1820
1859
  }
1821
1860
  }
1822
1861
  export {