@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
|
@@ -131,6 +131,18 @@ function setProfileCache(environment, profiles) {
|
|
|
131
131
|
};
|
|
132
132
|
saveGlobalConfig(config);
|
|
133
133
|
}
|
|
134
|
+
function invalidateProfileCache(environment) {
|
|
135
|
+
const config = loadGlobalConfig();
|
|
136
|
+
if (!config.profile_cache) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (environment) {
|
|
140
|
+
delete config.profile_cache[environment];
|
|
141
|
+
} else {
|
|
142
|
+
config.profile_cache = {};
|
|
143
|
+
}
|
|
144
|
+
saveGlobalConfig(config);
|
|
145
|
+
}
|
|
134
146
|
function getOrCreateUserUUID() {
|
|
135
147
|
const config = loadGlobalConfig();
|
|
136
148
|
if (config.user_uuid) {
|
|
@@ -312,7 +324,7 @@ function listApps(environment) {
|
|
|
312
324
|
|
|
313
325
|
// src/utils/version.ts
|
|
314
326
|
function getCliVersion() {
|
|
315
|
-
return true ? "0.
|
|
327
|
+
return true ? "0.5.0-dev.2" : "0.0.0";
|
|
316
328
|
}
|
|
317
329
|
function getClientId() {
|
|
318
330
|
return `ecloud-cli/v${getCliVersion()}`;
|
|
@@ -342,6 +354,13 @@ function addHexPrefix2(value) {
|
|
|
342
354
|
}
|
|
343
355
|
return `0x${value}`;
|
|
344
356
|
}
|
|
357
|
+
function ensureInteractive(missingFlagHint) {
|
|
358
|
+
if (!process.stdin.isTTY) {
|
|
359
|
+
throw new Error(
|
|
360
|
+
`Cannot prompt in non-interactive mode. Provide ${missingFlagHint} via CLI flags or environment variables.`
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
345
364
|
async function getDockerfileInteractive(dockerfilePath) {
|
|
346
365
|
if (dockerfilePath) {
|
|
347
366
|
return dockerfilePath;
|
|
@@ -351,6 +370,7 @@ async function getDockerfileInteractive(dockerfilePath) {
|
|
|
351
370
|
if (!fs3.existsSync(dockerfilePath_resolved)) {
|
|
352
371
|
return "";
|
|
353
372
|
}
|
|
373
|
+
ensureInteractive("--dockerfile or --image-ref");
|
|
354
374
|
console.log(`
|
|
355
375
|
Found Dockerfile in ${cwd}`);
|
|
356
376
|
const choice = await select({
|
|
@@ -397,6 +417,7 @@ async function promptUseVerifiableBuild() {
|
|
|
397
417
|
return confirmWithDefault("Build from verifiable source?", false);
|
|
398
418
|
}
|
|
399
419
|
async function promptVerifiableSourceType() {
|
|
420
|
+
ensureInteractive("--verifiable with --repo/--commit or --image-ref");
|
|
400
421
|
return select({
|
|
401
422
|
message: "Choose verifiable source type:",
|
|
402
423
|
choices: [
|
|
@@ -406,6 +427,7 @@ async function promptVerifiableSourceType() {
|
|
|
406
427
|
});
|
|
407
428
|
}
|
|
408
429
|
async function promptVerifiableGitSourceInputs() {
|
|
430
|
+
ensureInteractive("--repo, --commit");
|
|
409
431
|
const detected = detectGitRepoInfo();
|
|
410
432
|
const repoUrl = (await input({
|
|
411
433
|
message: "Enter public git repository URL:",
|
|
@@ -487,6 +509,7 @@ async function promptVerifiableGitSourceInputs() {
|
|
|
487
509
|
};
|
|
488
510
|
}
|
|
489
511
|
async function promptVerifiablePrebuiltImageRef() {
|
|
512
|
+
ensureInteractive("--image-ref");
|
|
490
513
|
const ref = await input({
|
|
491
514
|
message: "Enter prebuilt verifiable image ref:",
|
|
492
515
|
default: "docker.io/eigenlayer/eigencloud-containers:",
|
|
@@ -577,6 +600,7 @@ async function getAvailableRegistries() {
|
|
|
577
600
|
const auths = config.auths || {};
|
|
578
601
|
const credsStore = config.credsStore;
|
|
579
602
|
const gcrProjects = /* @__PURE__ */ new Map();
|
|
603
|
+
const dockerhubUsers = /* @__PURE__ */ new Map();
|
|
580
604
|
const registries = [];
|
|
581
605
|
for (const [registry, auth] of Object.entries(auths)) {
|
|
582
606
|
const authData = auth;
|
|
@@ -617,8 +641,17 @@ async function getAvailableRegistries() {
|
|
|
617
641
|
}
|
|
618
642
|
continue;
|
|
619
643
|
}
|
|
644
|
+
if (registryType === "dockerhub") {
|
|
645
|
+
if (!dockerhubUsers.has(username)) {
|
|
646
|
+
dockerhubUsers.set(username, info);
|
|
647
|
+
}
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
620
650
|
registries.push(info);
|
|
621
651
|
}
|
|
652
|
+
for (const dhInfo of Array.from(dockerhubUsers.values())) {
|
|
653
|
+
registries.push(dhInfo);
|
|
654
|
+
}
|
|
622
655
|
for (const gcrInfo of Array.from(gcrProjects.values())) {
|
|
623
656
|
registries.push(gcrInfo);
|
|
624
657
|
}
|
|
@@ -724,6 +757,7 @@ async function getImageReferenceInteractive(imageRef, buildFromDockerfile = fals
|
|
|
724
757
|
if (imageRef) {
|
|
725
758
|
return imageRef;
|
|
726
759
|
}
|
|
760
|
+
ensureInteractive("--image-ref");
|
|
727
761
|
const registries = await getAvailableRegistries();
|
|
728
762
|
const appName = getDefaultAppName();
|
|
729
763
|
if (buildFromDockerfile) {
|
|
@@ -759,6 +793,7 @@ async function getEnvFileInteractive(envFilePath) {
|
|
|
759
793
|
if (fs3.existsSync(".env")) {
|
|
760
794
|
return ".env";
|
|
761
795
|
}
|
|
796
|
+
ensureInteractive("--env-file");
|
|
762
797
|
console.log("\nEnvironment file not found.");
|
|
763
798
|
console.log("Environment files contain variables like RPC_URL, etc.");
|
|
764
799
|
const choice = await select({
|
|
@@ -810,14 +845,19 @@ async function getInstanceTypeInteractive(instanceType, defaultSKU, availableTyp
|
|
|
810
845
|
const validSKUs = availableTypes.map((t) => t.sku).join(", ");
|
|
811
846
|
throw new Error(`Invalid instance-type: ${instanceType} (must be one of: ${validSKUs})`);
|
|
812
847
|
}
|
|
848
|
+
ensureInteractive("--instance-type");
|
|
813
849
|
const isCurrentType = defaultSKU !== "";
|
|
814
850
|
const hasPricing = availableTypes.some((t) => t.monthly_price_usd != null);
|
|
815
851
|
if (hasPricing) {
|
|
816
852
|
console.log("\nPay for what you use \u2014 no upfront costs, per-hour billing.\n");
|
|
817
853
|
console.log(` ${chalk.bold("Shielded VM (vTPM)")}: Verified boot and runtime attestation.`);
|
|
818
|
-
console.log(
|
|
819
|
-
|
|
820
|
-
|
|
854
|
+
console.log(
|
|
855
|
+
` ${chalk.bold("SEV-SNP (TEE)")}: Verified boot, runtime attestation, and hardware-encrypted memory (AMD).`
|
|
856
|
+
);
|
|
857
|
+
console.log(
|
|
858
|
+
` ${chalk.bold("TDX (TEE)")}: Verified boot, runtime attestation, and hardware-encrypted memory (Intel).
|
|
859
|
+
`
|
|
860
|
+
);
|
|
821
861
|
}
|
|
822
862
|
if (isCurrentType && defaultSKU) {
|
|
823
863
|
console.log(`Current instance type: ${defaultSKU}
|
|
@@ -851,6 +891,7 @@ async function getLogSettingsInteractive(logVisibility) {
|
|
|
851
891
|
);
|
|
852
892
|
}
|
|
853
893
|
}
|
|
894
|
+
ensureInteractive("--log-visibility");
|
|
854
895
|
const choice = await select({
|
|
855
896
|
message: "Do you want to view your app's logs?",
|
|
856
897
|
choices: [
|
|
@@ -944,9 +985,10 @@ async function getOrPromptAppID(appIDOrOptions, environment) {
|
|
|
944
985
|
return addHexPrefix2(foundAppID);
|
|
945
986
|
}
|
|
946
987
|
throw new Error(
|
|
947
|
-
`App name '${options.appID}' not found in environment '${options.environment}'
|
|
988
|
+
`App name '${options.appID}' not found in environment '${options.environment}'. Name lookup uses a local cache that may be stale. Try using the app ID (0x...) directly, or run 'ecloud compute app list' to refresh the cache.`
|
|
948
989
|
);
|
|
949
990
|
}
|
|
991
|
+
ensureInteractive("app-id argument");
|
|
950
992
|
return getAppIDInteractive(options);
|
|
951
993
|
}
|
|
952
994
|
async function getAppIDInteractive(options) {
|
|
@@ -979,12 +1021,9 @@ Select an app to ${action}:
|
|
|
979
1021
|
let cachedProfiles = getProfileCache(environment);
|
|
980
1022
|
if (!cachedProfiles) {
|
|
981
1023
|
try {
|
|
982
|
-
const userApiClient = new UserApiClient2(
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
publicClient,
|
|
986
|
-
{ clientId: getClientId() }
|
|
987
|
-
);
|
|
1024
|
+
const userApiClient = new UserApiClient2(environmentConfig, walletClient, publicClient, {
|
|
1025
|
+
clientId: getClientId()
|
|
1026
|
+
});
|
|
988
1027
|
const appInfos = await getAppInfosChunked(userApiClient, apps);
|
|
989
1028
|
const freshProfiles = {};
|
|
990
1029
|
for (const info of appInfos) {
|
|
@@ -1184,6 +1223,7 @@ async function getResourceUsageMonitoringInteractive(resourceUsageMonitoring) {
|
|
|
1184
1223
|
);
|
|
1185
1224
|
}
|
|
1186
1225
|
}
|
|
1226
|
+
ensureInteractive("--resource-usage-monitoring");
|
|
1187
1227
|
const choice = await select({
|
|
1188
1228
|
message: "Show resource usage (CPU/memory) for your app?",
|
|
1189
1229
|
choices: [
|
|
@@ -1197,6 +1237,11 @@ async function confirm(prompt) {
|
|
|
1197
1237
|
return confirmWithDefault(prompt, false);
|
|
1198
1238
|
}
|
|
1199
1239
|
async function confirmWithDefault(prompt, defaultValue = false) {
|
|
1240
|
+
if (!process.stdin.isTTY) {
|
|
1241
|
+
throw new Error(
|
|
1242
|
+
`Cannot confirm "${prompt}" in non-interactive mode. Use --force to skip confirmation prompts.`
|
|
1243
|
+
);
|
|
1244
|
+
}
|
|
1200
1245
|
return await inquirerConfirm({
|
|
1201
1246
|
message: prompt,
|
|
1202
1247
|
default: defaultValue
|
|
@@ -1214,6 +1259,7 @@ async function getPrivateKeyInteractive(privateKey) {
|
|
|
1214
1259
|
if (result) {
|
|
1215
1260
|
return result.key;
|
|
1216
1261
|
}
|
|
1262
|
+
ensureInteractive("--private-key or ECLOUD_PRIVATE_KEY");
|
|
1217
1263
|
const key = await password({
|
|
1218
1264
|
message: "Enter private key:",
|
|
1219
1265
|
mask: true,
|
|
@@ -1240,6 +1286,7 @@ async function getEnvironmentInteractive(environment) {
|
|
|
1240
1286
|
} catch {
|
|
1241
1287
|
}
|
|
1242
1288
|
}
|
|
1289
|
+
ensureInteractive("--environment or ECLOUD_ENV");
|
|
1243
1290
|
const availableEnvs = getAvailableEnvironments();
|
|
1244
1291
|
let defaultEnv;
|
|
1245
1292
|
const configDefaultEnv = getDefaultEnvironment();
|
|
@@ -1655,6 +1702,11 @@ var AppUpgrade = class _AppUpgrade extends Command {
|
|
|
1655
1702
|
};
|
|
1656
1703
|
static flags = {
|
|
1657
1704
|
...commonFlags,
|
|
1705
|
+
name: Flags2.string({
|
|
1706
|
+
required: false,
|
|
1707
|
+
description: "Update the app's profile name after upgrade",
|
|
1708
|
+
env: "ECLOUD_NAME"
|
|
1709
|
+
}),
|
|
1658
1710
|
dockerfile: Flags2.string({
|
|
1659
1711
|
required: false,
|
|
1660
1712
|
description: "Path to Dockerfile",
|
|
@@ -1724,6 +1776,10 @@ var AppUpgrade = class _AppUpgrade extends Command {
|
|
|
1724
1776
|
description: "Optional path to Caddyfile inside the repo (relative to build context). If omitted, auto-detected from env file TLS settings",
|
|
1725
1777
|
required: false,
|
|
1726
1778
|
env: "ECLOUD_BUILD_CADDYFILE"
|
|
1779
|
+
}),
|
|
1780
|
+
force: Flags2.boolean({
|
|
1781
|
+
description: "Skip all confirmation prompts",
|
|
1782
|
+
default: false
|
|
1727
1783
|
})
|
|
1728
1784
|
};
|
|
1729
1785
|
async run() {
|
|
@@ -1870,12 +1926,9 @@ var AppUpgrade = class _AppUpgrade extends Command {
|
|
|
1870
1926
|
});
|
|
1871
1927
|
let currentInstanceType = "";
|
|
1872
1928
|
try {
|
|
1873
|
-
const userApiClient = new UserApiClient3(
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
publicClient,
|
|
1877
|
-
{ clientId: getClientId() }
|
|
1878
|
-
);
|
|
1929
|
+
const userApiClient = new UserApiClient3(environmentConfig, walletClient, publicClient, {
|
|
1930
|
+
clientId: getClientId()
|
|
1931
|
+
});
|
|
1879
1932
|
const infos = await userApiClient.getInfos([appID], 1);
|
|
1880
1933
|
if (infos.length > 0) {
|
|
1881
1934
|
currentInstanceType = infos[0].machineType || "";
|
|
@@ -1917,15 +1970,19 @@ var AppUpgrade = class _AppUpgrade extends Command {
|
|
|
1917
1970
|
});
|
|
1918
1971
|
const finalTx = await applyTxOverrides(gasEstimate, flags, { publicClient, address });
|
|
1919
1972
|
if (flags["max-fee-per-gas"] || flags["max-priority-fee"]) {
|
|
1920
|
-
this.log(
|
|
1921
|
-
|
|
1973
|
+
this.log(
|
|
1974
|
+
chalk2.yellow(
|
|
1975
|
+
`
|
|
1976
|
+
Gas override active \u2014 max fee: ${flags["max-fee-per-gas"] || "estimated"} gwei, priority fee: ${flags["max-priority-fee"] || "estimated"} gwei`
|
|
1977
|
+
)
|
|
1978
|
+
);
|
|
1922
1979
|
}
|
|
1923
1980
|
if (finalTx.nonce != null) {
|
|
1924
1981
|
this.log(chalk2.yellow(`Nonce override active \u2014 nonce: ${finalTx.nonce}`));
|
|
1925
1982
|
}
|
|
1926
1983
|
this.log(`
|
|
1927
1984
|
Estimated transaction cost: ${chalk2.cyan(finalTx.maxCostEth)} ETH`);
|
|
1928
|
-
if (isMainnet(environmentConfig)) {
|
|
1985
|
+
if (isMainnet(environmentConfig) && !flags.force) {
|
|
1929
1986
|
const confirmed = await confirm(`Continue with upgrade?`);
|
|
1930
1987
|
if (!confirmed) {
|
|
1931
1988
|
this.log(`
|
|
@@ -1945,9 +2002,39 @@ ${chalk2.gray(`Upgrade cancelled`)}`);
|
|
|
1945
2002
|
`
|
|
1946
2003
|
\u2705 ${chalk2.green(`App upgraded successfully ${chalk2.bold(`(id: ${res.appId}, image: ${res.imageRef})`)}`)}`
|
|
1947
2004
|
);
|
|
2005
|
+
if (flags.name) {
|
|
2006
|
+
try {
|
|
2007
|
+
const { publicClient: publicClient2, walletClient: walletClient2 } = createViemClients({
|
|
2008
|
+
privateKey,
|
|
2009
|
+
rpcUrl,
|
|
2010
|
+
environment
|
|
2011
|
+
});
|
|
2012
|
+
const userApiClient = new UserApiClient3(environmentConfig, walletClient2, publicClient2, {
|
|
2013
|
+
clientId: getClientId()
|
|
2014
|
+
});
|
|
2015
|
+
const infos = await userApiClient.getInfos([res.appId], 1);
|
|
2016
|
+
const existing = infos[0]?.profile;
|
|
2017
|
+
await compute.app.setProfile(res.appId, {
|
|
2018
|
+
name: flags.name,
|
|
2019
|
+
website: existing?.website,
|
|
2020
|
+
description: existing?.description,
|
|
2021
|
+
xURL: existing?.xURL
|
|
2022
|
+
});
|
|
2023
|
+
invalidateProfileCache(environment);
|
|
2024
|
+
this.log(`\u2713 Profile name updated to "${flags.name}"`);
|
|
2025
|
+
} catch (err) {
|
|
2026
|
+
this.warn(`Upgrade succeeded but failed to update profile name: ${err.message}`);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
1948
2029
|
const dashboardUrl = getDashboardUrl(environment, res.appId);
|
|
1949
2030
|
this.log(`
|
|
1950
2031
|
${chalk2.gray("View your app:")} ${chalk2.blue.underline(dashboardUrl)}`);
|
|
2032
|
+
this.log(
|
|
2033
|
+
chalk2.gray(
|
|
2034
|
+
`
|
|
2035
|
+
Note: "Running" means the container started. Verify your app is serving traffic before considering the upgrade complete.`
|
|
2036
|
+
)
|
|
2037
|
+
);
|
|
1951
2038
|
});
|
|
1952
2039
|
}
|
|
1953
2040
|
};
|
|
@@ -1958,7 +2045,9 @@ async function fetchAvailableInstanceTypes(environment, environmentConfig, priva
|
|
|
1958
2045
|
rpcUrl,
|
|
1959
2046
|
environment
|
|
1960
2047
|
});
|
|
1961
|
-
const userApiClient = new UserApiClient3(environmentConfig, walletClient, publicClient, {
|
|
2048
|
+
const userApiClient = new UserApiClient3(environmentConfig, walletClient, publicClient, {
|
|
2049
|
+
clientId: getClientId()
|
|
2050
|
+
});
|
|
1962
2051
|
const skuList = await userApiClient.getSKUs();
|
|
1963
2052
|
if (skuList.skus.length === 0) {
|
|
1964
2053
|
throw new Error("No instance types available from server");
|