@layr-labs/ecloud-cli 0.4.3 → 0.5.0-dev.2
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/VERSION +2 -2
- package/dist/commands/auth/login.js +84 -54
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/auth/migrate.js +66 -30
- package/dist/commands/auth/migrate.js.map +1 -1
- package/dist/commands/auth/whoami.js.map +1 -1
- package/dist/commands/billing/__tests__/status.test.js +9 -0
- package/dist/commands/billing/__tests__/status.test.js.map +1 -1
- package/dist/commands/billing/__tests__/subscribe.test.js +9 -0
- package/dist/commands/billing/__tests__/subscribe.test.js.map +1 -1
- package/dist/commands/billing/__tests__/top-up.test.js +9 -0
- package/dist/commands/billing/__tests__/top-up.test.js.map +1 -1
- package/dist/commands/billing/cancel.js +9 -0
- package/dist/commands/billing/cancel.js.map +1 -1
- package/dist/commands/billing/status.js +9 -0
- package/dist/commands/billing/status.js.map +1 -1
- package/dist/commands/billing/subscribe.js +9 -0
- package/dist/commands/billing/subscribe.js.map +1 -1
- package/dist/commands/billing/top-up.js +9 -0
- package/dist/commands/billing/top-up.js.map +1 -1
- package/dist/commands/compute/app/configure/tls.js +138 -50
- package/dist/commands/compute/app/configure/tls.js.map +1 -1
- package/dist/commands/compute/app/create.js.map +1 -1
- package/dist/commands/compute/app/deploy.js +71 -18
- package/dist/commands/compute/app/deploy.js.map +1 -1
- package/dist/commands/compute/app/info.js +15 -8
- package/dist/commands/compute/app/info.js.map +1 -1
- package/dist/commands/compute/app/list.js +10 -1
- package/dist/commands/compute/app/list.js.map +1 -1
- package/dist/commands/compute/app/logs.js +15 -8
- package/dist/commands/compute/app/logs.js.map +1 -1
- package/dist/commands/compute/app/profile/set.js +16 -8
- package/dist/commands/compute/app/profile/set.js.map +1 -1
- package/dist/commands/compute/app/releases.js +15 -8
- package/dist/commands/compute/app/releases.js.map +1 -1
- package/dist/commands/compute/app/start.js +27 -11
- package/dist/commands/compute/app/start.js.map +1 -1
- package/dist/commands/compute/app/stop.js +27 -11
- package/dist/commands/compute/app/stop.js.map +1 -1
- package/dist/commands/compute/app/terminate.js +20 -8
- package/dist/commands/compute/app/terminate.js.map +1 -1
- package/dist/commands/compute/app/upgrade.js +110 -21
- package/dist/commands/compute/app/upgrade.js.map +1 -1
- package/dist/commands/compute/build/info.js +10 -1
- package/dist/commands/compute/build/info.js.map +1 -1
- package/dist/commands/compute/build/list.js +10 -1
- package/dist/commands/compute/build/list.js.map +1 -1
- package/dist/commands/compute/build/logs.js +10 -1
- package/dist/commands/compute/build/logs.js.map +1 -1
- package/dist/commands/compute/build/status.js +10 -1
- package/dist/commands/compute/build/status.js.map +1 -1
- package/dist/commands/compute/build/submit.js +11 -1
- package/dist/commands/compute/build/submit.js.map +1 -1
- package/dist/commands/compute/build/verify.js +10 -1
- package/dist/commands/compute/build/verify.js.map +1 -1
- package/dist/commands/compute/environment/set.js +8 -0
- package/dist/commands/compute/environment/set.js.map +1 -1
- package/dist/commands/compute/undelegate.js +10 -1
- package/dist/commands/compute/undelegate.js.map +1 -1
- package/dist/hooks/init/__tests__/version-check.test.js +1 -1
- package/dist/hooks/init/__tests__/version-check.test.js.map +1 -1
- package/dist/hooks/init/version-check.js +1 -1
- package/dist/hooks/init/version-check.js.map +1 -1
- package/package.json +26 -21
|
@@ -305,7 +305,7 @@ function findAvailableName(environment, baseName) {
|
|
|
305
305
|
|
|
306
306
|
// src/utils/version.ts
|
|
307
307
|
function getCliVersion() {
|
|
308
|
-
return true ? "0.
|
|
308
|
+
return true ? "0.5.0-dev.2" : "0.0.0";
|
|
309
309
|
}
|
|
310
310
|
function getClientId() {
|
|
311
311
|
return `ecloud-cli/v${getCliVersion()}`;
|
|
@@ -313,6 +313,13 @@ function getClientId() {
|
|
|
313
313
|
|
|
314
314
|
// src/utils/prompts.ts
|
|
315
315
|
import { execSync } from "child_process";
|
|
316
|
+
function ensureInteractive(missingFlagHint) {
|
|
317
|
+
if (!process.stdin.isTTY) {
|
|
318
|
+
throw new Error(
|
|
319
|
+
`Cannot prompt in non-interactive mode. Provide ${missingFlagHint} via CLI flags or environment variables.`
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
316
323
|
async function getDockerfileInteractive(dockerfilePath) {
|
|
317
324
|
if (dockerfilePath) {
|
|
318
325
|
return dockerfilePath;
|
|
@@ -322,6 +329,7 @@ async function getDockerfileInteractive(dockerfilePath) {
|
|
|
322
329
|
if (!fs3.existsSync(dockerfilePath_resolved)) {
|
|
323
330
|
return "";
|
|
324
331
|
}
|
|
332
|
+
ensureInteractive("--dockerfile or --image-ref");
|
|
325
333
|
console.log(`
|
|
326
334
|
Found Dockerfile in ${cwd}`);
|
|
327
335
|
const choice = await select({
|
|
@@ -368,6 +376,7 @@ async function promptUseVerifiableBuild() {
|
|
|
368
376
|
return confirmWithDefault("Build from verifiable source?", false);
|
|
369
377
|
}
|
|
370
378
|
async function promptVerifiableSourceType() {
|
|
379
|
+
ensureInteractive("--verifiable with --repo/--commit or --image-ref");
|
|
371
380
|
return select({
|
|
372
381
|
message: "Choose verifiable source type:",
|
|
373
382
|
choices: [
|
|
@@ -377,6 +386,7 @@ async function promptVerifiableSourceType() {
|
|
|
377
386
|
});
|
|
378
387
|
}
|
|
379
388
|
async function promptVerifiableGitSourceInputs() {
|
|
389
|
+
ensureInteractive("--repo, --commit");
|
|
380
390
|
const detected = detectGitRepoInfo();
|
|
381
391
|
const repoUrl = (await input({
|
|
382
392
|
message: "Enter public git repository URL:",
|
|
@@ -458,6 +468,7 @@ async function promptVerifiableGitSourceInputs() {
|
|
|
458
468
|
};
|
|
459
469
|
}
|
|
460
470
|
async function promptVerifiablePrebuiltImageRef() {
|
|
471
|
+
ensureInteractive("--image-ref");
|
|
461
472
|
const ref = await input({
|
|
462
473
|
message: "Enter prebuilt verifiable image ref:",
|
|
463
474
|
default: "docker.io/eigenlayer/eigencloud-containers:",
|
|
@@ -548,6 +559,7 @@ async function getAvailableRegistries() {
|
|
|
548
559
|
const auths = config.auths || {};
|
|
549
560
|
const credsStore = config.credsStore;
|
|
550
561
|
const gcrProjects = /* @__PURE__ */ new Map();
|
|
562
|
+
const dockerhubUsers = /* @__PURE__ */ new Map();
|
|
551
563
|
const registries = [];
|
|
552
564
|
for (const [registry, auth] of Object.entries(auths)) {
|
|
553
565
|
const authData = auth;
|
|
@@ -588,8 +600,17 @@ async function getAvailableRegistries() {
|
|
|
588
600
|
}
|
|
589
601
|
continue;
|
|
590
602
|
}
|
|
603
|
+
if (registryType === "dockerhub") {
|
|
604
|
+
if (!dockerhubUsers.has(username)) {
|
|
605
|
+
dockerhubUsers.set(username, info);
|
|
606
|
+
}
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
591
609
|
registries.push(info);
|
|
592
610
|
}
|
|
611
|
+
for (const dhInfo of Array.from(dockerhubUsers.values())) {
|
|
612
|
+
registries.push(dhInfo);
|
|
613
|
+
}
|
|
593
614
|
for (const gcrInfo of Array.from(gcrProjects.values())) {
|
|
594
615
|
registries.push(gcrInfo);
|
|
595
616
|
}
|
|
@@ -692,6 +713,7 @@ async function getImageReferenceInteractive(imageRef, buildFromDockerfile = fals
|
|
|
692
713
|
if (imageRef) {
|
|
693
714
|
return imageRef;
|
|
694
715
|
}
|
|
716
|
+
ensureInteractive("--image-ref");
|
|
695
717
|
const registries = await getAvailableRegistries();
|
|
696
718
|
const appName = getDefaultAppName();
|
|
697
719
|
if (buildFromDockerfile) {
|
|
@@ -721,6 +743,7 @@ async function getImageReferenceInteractive(imageRef, buildFromDockerfile = fals
|
|
|
721
743
|
return imageRefInput;
|
|
722
744
|
}
|
|
723
745
|
async function getAvailableAppNameInteractive(environment, imageRef, suggestedBaseName, skipDefaultName) {
|
|
746
|
+
ensureInteractive("--name");
|
|
724
747
|
const baseName = skipDefaultName ? void 0 : suggestedBaseName || extractAppNameFromImage(imageRef);
|
|
725
748
|
const suggestedName = baseName ? findAvailableName(environment, baseName) : void 0;
|
|
726
749
|
while (true) {
|
|
@@ -768,6 +791,7 @@ async function getEnvFileInteractive(envFilePath) {
|
|
|
768
791
|
if (fs3.existsSync(".env")) {
|
|
769
792
|
return ".env";
|
|
770
793
|
}
|
|
794
|
+
ensureInteractive("--env-file");
|
|
771
795
|
console.log("\nEnvironment file not found.");
|
|
772
796
|
console.log("Environment files contain variables like RPC_URL, etc.");
|
|
773
797
|
const choice = await select({
|
|
@@ -819,14 +843,19 @@ async function getInstanceTypeInteractive(instanceType, defaultSKU, availableTyp
|
|
|
819
843
|
const validSKUs = availableTypes.map((t) => t.sku).join(", ");
|
|
820
844
|
throw new Error(`Invalid instance-type: ${instanceType} (must be one of: ${validSKUs})`);
|
|
821
845
|
}
|
|
846
|
+
ensureInteractive("--instance-type");
|
|
822
847
|
const isCurrentType = defaultSKU !== "";
|
|
823
848
|
const hasPricing = availableTypes.some((t) => t.monthly_price_usd != null);
|
|
824
849
|
if (hasPricing) {
|
|
825
850
|
console.log("\nPay for what you use \u2014 no upfront costs, per-hour billing.\n");
|
|
826
851
|
console.log(` ${chalk.bold("Shielded VM (vTPM)")}: Verified boot and runtime attestation.`);
|
|
827
|
-
console.log(
|
|
828
|
-
|
|
829
|
-
|
|
852
|
+
console.log(
|
|
853
|
+
` ${chalk.bold("SEV-SNP (TEE)")}: Verified boot, runtime attestation, and hardware-encrypted memory (AMD).`
|
|
854
|
+
);
|
|
855
|
+
console.log(
|
|
856
|
+
` ${chalk.bold("TDX (TEE)")}: Verified boot, runtime attestation, and hardware-encrypted memory (Intel).
|
|
857
|
+
`
|
|
858
|
+
);
|
|
830
859
|
}
|
|
831
860
|
if (isCurrentType && defaultSKU) {
|
|
832
861
|
console.log(`Current instance type: ${defaultSKU}
|
|
@@ -860,6 +889,7 @@ async function getLogSettingsInteractive(logVisibility) {
|
|
|
860
889
|
);
|
|
861
890
|
}
|
|
862
891
|
}
|
|
892
|
+
ensureInteractive("--log-visibility");
|
|
863
893
|
const choice = await select({
|
|
864
894
|
message: "Do you want to view your app's logs?",
|
|
865
895
|
choices: [
|
|
@@ -891,6 +921,7 @@ async function getResourceUsageMonitoringInteractive(resourceUsageMonitoring) {
|
|
|
891
921
|
);
|
|
892
922
|
}
|
|
893
923
|
}
|
|
924
|
+
ensureInteractive("--resource-usage-monitoring");
|
|
894
925
|
const choice = await select({
|
|
895
926
|
message: "Show resource usage (CPU/memory) for your app?",
|
|
896
927
|
choices: [
|
|
@@ -904,6 +935,11 @@ async function confirm(prompt) {
|
|
|
904
935
|
return confirmWithDefault(prompt, false);
|
|
905
936
|
}
|
|
906
937
|
async function confirmWithDefault(prompt, defaultValue = false) {
|
|
938
|
+
if (!process.stdin.isTTY) {
|
|
939
|
+
throw new Error(
|
|
940
|
+
`Cannot confirm "${prompt}" in non-interactive mode. Use --force to skip confirmation prompts.`
|
|
941
|
+
);
|
|
942
|
+
}
|
|
907
943
|
return await inquirerConfirm({
|
|
908
944
|
message: prompt,
|
|
909
945
|
default: defaultValue
|
|
@@ -921,6 +957,7 @@ async function getPrivateKeyInteractive(privateKey) {
|
|
|
921
957
|
if (result) {
|
|
922
958
|
return result.key;
|
|
923
959
|
}
|
|
960
|
+
ensureInteractive("--private-key or ECLOUD_PRIVATE_KEY");
|
|
924
961
|
const key = await password({
|
|
925
962
|
message: "Enter private key:",
|
|
926
963
|
mask: true,
|
|
@@ -947,6 +984,7 @@ async function getEnvironmentInteractive(environment) {
|
|
|
947
984
|
} catch {
|
|
948
985
|
}
|
|
949
986
|
}
|
|
987
|
+
ensureInteractive("--environment or ECLOUD_ENV");
|
|
950
988
|
const availableEnvs = getAvailableEnvironments();
|
|
951
989
|
let defaultEnv;
|
|
952
990
|
const configDefaultEnv = getDefaultEnvironment();
|
|
@@ -1049,6 +1087,7 @@ function validateImagePath(filePath) {
|
|
|
1049
1087
|
return void 0;
|
|
1050
1088
|
}
|
|
1051
1089
|
async function getAppProfileInteractive(defaultName = "", allowRetry = true) {
|
|
1090
|
+
ensureInteractive("--skip-profile or --website/--description/--x-url/--image");
|
|
1052
1091
|
while (true) {
|
|
1053
1092
|
const name = await getAppNameForProfile(defaultName);
|
|
1054
1093
|
const website = await getAppWebsiteInteractive();
|
|
@@ -1686,6 +1725,10 @@ var AppDeploy = class _AppDeploy extends Command {
|
|
|
1686
1725
|
description: "Optional path to Caddyfile inside the repo (relative to build context). If omitted, auto-detected from env file TLS settings",
|
|
1687
1726
|
required: false,
|
|
1688
1727
|
env: "ECLOUD_BUILD_CADDYFILE"
|
|
1728
|
+
}),
|
|
1729
|
+
force: Flags2.boolean({
|
|
1730
|
+
description: "Skip all confirmation prompts",
|
|
1731
|
+
default: false
|
|
1689
1732
|
})
|
|
1690
1733
|
};
|
|
1691
1734
|
async run() {
|
|
@@ -1705,12 +1748,12 @@ var AppDeploy = class _AppDeploy extends Command {
|
|
|
1705
1748
|
if (balance === 0n) {
|
|
1706
1749
|
const isSepolia = environmentConfig.chainID === BigInt(11155111);
|
|
1707
1750
|
this.log(
|
|
1708
|
-
chalk2.yellow(
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
chalk2.yellow(`You will need ETH to pay for deployment gas fees.`)
|
|
1751
|
+
chalk2.yellow(
|
|
1752
|
+
`
|
|
1753
|
+
Warning: Wallet ${chalk2.bold(address)} has zero balance on ${environment}.`
|
|
1754
|
+
)
|
|
1713
1755
|
);
|
|
1756
|
+
this.log(chalk2.yellow(`You will need ETH to pay for deployment gas fees.`));
|
|
1714
1757
|
if (isSepolia) {
|
|
1715
1758
|
this.log(
|
|
1716
1759
|
chalk2.yellow(
|
|
@@ -1909,15 +1952,19 @@ Warning: Wallet ${chalk2.bold(address)} has zero balance on ${environment}.`)
|
|
|
1909
1952
|
});
|
|
1910
1953
|
const finalTx = await applyTxOverrides(gasEstimate, flags, { publicClient, address });
|
|
1911
1954
|
if (flags["max-fee-per-gas"] || flags["max-priority-fee"]) {
|
|
1912
|
-
this.log(
|
|
1913
|
-
|
|
1955
|
+
this.log(
|
|
1956
|
+
chalk2.yellow(
|
|
1957
|
+
`
|
|
1958
|
+
Gas override active \u2014 max fee: ${flags["max-fee-per-gas"] || "estimated"} gwei, priority fee: ${flags["max-priority-fee"] || "estimated"} gwei`
|
|
1959
|
+
)
|
|
1960
|
+
);
|
|
1914
1961
|
}
|
|
1915
1962
|
if (finalTx.nonce != null) {
|
|
1916
1963
|
this.log(chalk2.yellow(`Nonce override active \u2014 nonce: ${finalTx.nonce}`));
|
|
1917
1964
|
}
|
|
1918
1965
|
this.log(`
|
|
1919
1966
|
Estimated transaction cost: ${chalk2.cyan(finalTx.maxCostEth)} ETH`);
|
|
1920
|
-
if (isMainnet(environmentConfig)) {
|
|
1967
|
+
if (isMainnet(environmentConfig) && !flags.force) {
|
|
1921
1968
|
const confirmed = await confirm(`Continue with deployment?`);
|
|
1922
1969
|
if (!confirmed) {
|
|
1923
1970
|
this.log(`
|
|
@@ -1982,6 +2029,15 @@ ${chalk2.gray(`Deployment cancelled`)}`);
|
|
|
1982
2029
|
const dashboardUrl = getDashboardUrl(environment, res.appId);
|
|
1983
2030
|
this.log(`
|
|
1984
2031
|
${chalk2.gray("View your app:")} ${chalk2.blue.underline(dashboardUrl)}`);
|
|
2032
|
+
if (ipAddress) {
|
|
2033
|
+
this.log(
|
|
2034
|
+
chalk2.gray(
|
|
2035
|
+
`
|
|
2036
|
+
Note: "Running" means the container started \u2014 verify it is serving traffic with:`
|
|
2037
|
+
)
|
|
2038
|
+
);
|
|
2039
|
+
this.log(chalk2.gray(` curl -s -o /dev/null -w "%{http_code}" http://${ipAddress}/`));
|
|
2040
|
+
}
|
|
1985
2041
|
});
|
|
1986
2042
|
}
|
|
1987
2043
|
};
|
|
@@ -1992,12 +2048,9 @@ async function fetchAvailableInstanceTypes(environment, environmentConfig, priva
|
|
|
1992
2048
|
rpcUrl,
|
|
1993
2049
|
environment
|
|
1994
2050
|
});
|
|
1995
|
-
const userApiClient = new UserApiClient3(
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
publicClient,
|
|
1999
|
-
{ clientId: getClientId() }
|
|
2000
|
-
);
|
|
2051
|
+
const userApiClient = new UserApiClient3(environmentConfig, walletClient, publicClient, {
|
|
2052
|
+
clientId: getClientId()
|
|
2053
|
+
});
|
|
2001
2054
|
const skuList = await userApiClient.getSKUs();
|
|
2002
2055
|
if (skuList.skus.length === 0) {
|
|
2003
2056
|
throw new Error("No instance types available from server");
|