@layr-labs/ecloud-cli 0.1.1 → 0.1.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.
Files changed (44) hide show
  1. package/VERSION +2 -2
  2. package/dist/commands/auth/generate.js +2 -2
  3. package/dist/commands/auth/generate.js.map +1 -1
  4. package/dist/commands/auth/login.js.map +1 -1
  5. package/dist/commands/auth/logout.js.map +1 -1
  6. package/dist/commands/auth/migrate.js.map +1 -1
  7. package/dist/commands/auth/whoami.js +5 -3
  8. package/dist/commands/auth/whoami.js.map +1 -1
  9. package/dist/commands/billing/cancel.js +5 -3
  10. package/dist/commands/billing/cancel.js.map +1 -1
  11. package/dist/commands/billing/status.js +5 -3
  12. package/dist/commands/billing/status.js.map +1 -1
  13. package/dist/commands/billing/subscribe.js +10 -6
  14. package/dist/commands/billing/subscribe.js.map +1 -1
  15. package/dist/commands/compute/app/create.js.map +1 -1
  16. package/dist/commands/compute/app/deploy.js +143 -76
  17. package/dist/commands/compute/app/deploy.js.map +1 -1
  18. package/dist/commands/compute/app/info.js +54 -8
  19. package/dist/commands/compute/app/info.js.map +1 -1
  20. package/dist/commands/compute/app/list.js +6 -7
  21. package/dist/commands/compute/app/list.js.map +1 -1
  22. package/dist/commands/compute/app/logs.js +55 -9
  23. package/dist/commands/compute/app/logs.js.map +1 -1
  24. package/dist/commands/compute/app/profile/set.js +141 -20
  25. package/dist/commands/compute/app/profile/set.js.map +1 -1
  26. package/dist/commands/compute/app/start.js +55 -9
  27. package/dist/commands/compute/app/start.js.map +1 -1
  28. package/dist/commands/compute/app/stop.js +55 -9
  29. package/dist/commands/compute/app/stop.js.map +1 -1
  30. package/dist/commands/compute/app/terminate.js +55 -9
  31. package/dist/commands/compute/app/terminate.js.map +1 -1
  32. package/dist/commands/compute/app/upgrade.js +172 -49
  33. package/dist/commands/compute/app/upgrade.js.map +1 -1
  34. package/dist/commands/compute/environment/list.js.map +1 -1
  35. package/dist/commands/compute/environment/set.js.map +1 -1
  36. package/dist/commands/compute/environment/show.js.map +1 -1
  37. package/dist/commands/compute/undelegate.js +6 -7
  38. package/dist/commands/compute/undelegate.js.map +1 -1
  39. package/dist/commands/telemetry/disable.js.map +1 -1
  40. package/dist/commands/telemetry/enable.js.map +1 -1
  41. package/dist/commands/telemetry/status.js.map +1 -1
  42. package/dist/commands/upgrade.js.map +1 -1
  43. package/dist/commands/version.js.map +1 -1
  44. package/package.json +3 -2
@@ -2,14 +2,7 @@
2
2
 
3
3
  // src/commands/compute/app/upgrade.ts
4
4
  import { Command, Args, Flags as Flags2 } from "@oclif/core";
5
- import {
6
- getEnvironmentConfig as getEnvironmentConfig2,
7
- UserApiClient as UserApiClient3,
8
- isMainnet,
9
- prepareUpgrade,
10
- executeUpgrade,
11
- watchUpgrade
12
- } from "@layr-labs/ecloud-sdk";
5
+ import { getEnvironmentConfig as getEnvironmentConfig3, isMainnet, UserApiClient as UserApiClient3 } from "@layr-labs/ecloud-sdk";
13
6
 
14
7
  // src/telemetry.ts
15
8
  import {
@@ -71,6 +64,42 @@ function saveGlobalConfig(config) {
71
64
  const content = dumpYaml(config, { lineWidth: -1 });
72
65
  fs.writeFileSync(configPath, content, { mode: 420 });
73
66
  }
67
+ function normalizeDirectoryPath(directoryPath) {
68
+ const resolved = path.resolve(directoryPath);
69
+ try {
70
+ return fs.realpathSync(resolved);
71
+ } catch {
72
+ return resolved;
73
+ }
74
+ }
75
+ function getLinkedAppForDirectory(environment, directoryPath) {
76
+ if (!directoryPath) {
77
+ return null;
78
+ }
79
+ const config = loadGlobalConfig();
80
+ const links = config.directory_links?.[environment];
81
+ if (!links) {
82
+ return null;
83
+ }
84
+ const normalizedPath = normalizeDirectoryPath(directoryPath);
85
+ const appId = links[normalizedPath];
86
+ return appId || null;
87
+ }
88
+ function setLinkedAppForDirectory(environment, directoryPath, appId) {
89
+ if (!directoryPath || !environment) {
90
+ return;
91
+ }
92
+ const config = loadGlobalConfig();
93
+ if (!config.directory_links) {
94
+ config.directory_links = {};
95
+ }
96
+ if (!config.directory_links[environment]) {
97
+ config.directory_links[environment] = {};
98
+ }
99
+ const normalizedPath = normalizeDirectoryPath(directoryPath);
100
+ config.directory_links[environment][normalizedPath] = appId.toLowerCase();
101
+ saveGlobalConfig(config);
102
+ }
74
103
  function getDefaultEnvironment() {
75
104
  const config = loadGlobalConfig();
76
105
  return config.default_environment;
@@ -172,6 +201,7 @@ async function withTelemetry(command, action) {
172
201
 
173
202
  // src/flags.ts
174
203
  import { Flags } from "@oclif/core";
204
+ import { getBuildType as getBuildType3 } from "@layr-labs/ecloud-sdk";
175
205
 
176
206
  // src/utils/prompts.ts
177
207
  import { input, select, password, confirm as inquirerConfirm } from "@inquirer/prompts";
@@ -250,7 +280,7 @@ function listApps(environment) {
250
280
 
251
281
  // src/utils/version.ts
252
282
  function getCliVersion() {
253
- return true ? "0.1.1" : "0.0.0";
283
+ return true ? "0.1.2" : "0.0.0";
254
284
  }
255
285
  function getClientId() {
256
286
  return `ecloud-cli/v${getCliVersion()}`;
@@ -445,6 +475,9 @@ function getDefaultAppName() {
445
475
  return "myapp";
446
476
  }
447
477
  }
478
+ function getCurrentProjectPath() {
479
+ return process.env.INIT_CWD || process.cwd();
480
+ }
448
481
  function suggestImageReference(registry, imageName, tag) {
449
482
  imageName = imageName.toLowerCase().replace(/_/g, "-");
450
483
  if (!tag) {
@@ -819,7 +852,19 @@ Select an app to ${action}:
819
852
  index: i
820
853
  });
821
854
  }
855
+ const linkedAppId = getLinkedAppForDirectory(environment, getCurrentProjectPath());
856
+ const normalizedLinkedAppId = linkedAppId ? linkedAppId.toLowerCase() : "";
822
857
  appItems.sort((a, b) => {
858
+ if (normalizedLinkedAppId) {
859
+ const aLinked = String(a.addr).toLowerCase() === normalizedLinkedAppId;
860
+ const bLinked = String(b.addr).toLowerCase() === normalizedLinkedAppId;
861
+ if (aLinked && !bLinked) {
862
+ return -1;
863
+ }
864
+ if (bLinked && !aLinked) {
865
+ return 1;
866
+ }
867
+ }
823
868
  const aPriority = getStatusPriority(a.status, false);
824
869
  const bPriority = getStatusPriority(b.status, false);
825
870
  if (aPriority !== bPriority) {
@@ -885,7 +930,18 @@ async function getAppIDInteractiveFromRegistry(environment, action) {
885
930
  }
886
931
  throw new Error(`Invalid app ID address: ${appIDInput}`);
887
932
  }
888
- const choices = Object.entries(allApps).map(([name, appID]) => {
933
+ const entries = Object.entries(allApps);
934
+ const linkedAppId = getLinkedAppForDirectory(environment, getCurrentProjectPath());
935
+ if (linkedAppId) {
936
+ const linkedIndex = entries.findIndex(
937
+ ([, appId]) => String(appId).toLowerCase() === linkedAppId.toLowerCase()
938
+ );
939
+ if (linkedIndex > 0) {
940
+ const [linkedEntry] = entries.splice(linkedIndex, 1);
941
+ entries.unshift(linkedEntry);
942
+ }
943
+ }
944
+ const choices = entries.map(([name, appID]) => {
889
945
  const displayName = `${name} (${appID})`;
890
946
  return { name: displayName, value: appID };
891
947
  });
@@ -963,8 +1019,8 @@ async function getPrivateKeyInteractive(privateKey) {
963
1019
  }
964
1020
  return privateKey;
965
1021
  }
966
- const { getPrivateKeyWithSource } = await import("@layr-labs/ecloud-sdk");
967
- const result = await getPrivateKeyWithSource({ privateKey: void 0 });
1022
+ const { getPrivateKeyWithSource: getPrivateKeyWithSource2 } = await import("@layr-labs/ecloud-sdk");
1023
+ const result = await getPrivateKeyWithSource2({ privateKey: void 0 });
968
1024
  if (result) {
969
1025
  return result.key;
970
1026
  }
@@ -983,6 +1039,50 @@ async function getPrivateKeyInteractive(privateKey) {
983
1039
  });
984
1040
  return key.trim();
985
1041
  }
1042
+ async function getEnvironmentInteractive(environment) {
1043
+ if (environment) {
1044
+ try {
1045
+ getEnvironmentConfig(environment);
1046
+ if (!isEnvironmentAvailable(environment)) {
1047
+ throw new Error(`Environment ${environment} is not available in this build`);
1048
+ }
1049
+ return environment;
1050
+ } catch {
1051
+ }
1052
+ }
1053
+ const availableEnvs = getAvailableEnvironments();
1054
+ let defaultEnv;
1055
+ const configDefaultEnv = getDefaultEnvironment();
1056
+ if (configDefaultEnv && availableEnvs.includes(configDefaultEnv)) {
1057
+ try {
1058
+ getEnvironmentConfig(configDefaultEnv);
1059
+ defaultEnv = configDefaultEnv;
1060
+ } catch {
1061
+ }
1062
+ }
1063
+ const choices = [];
1064
+ if (availableEnvs.includes("sepolia")) {
1065
+ choices.push({ name: "sepolia - Ethereum Sepolia testnet", value: "sepolia" });
1066
+ }
1067
+ if (availableEnvs.includes("sepolia-dev")) {
1068
+ choices.push({ name: "sepolia-dev - Ethereum Sepolia testnet (dev)", value: "sepolia-dev" });
1069
+ }
1070
+ if (availableEnvs.includes("mainnet-alpha")) {
1071
+ choices.push({
1072
+ name: "mainnet-alpha - Ethereum mainnet (\u26A0\uFE0F uses real funds)",
1073
+ value: "mainnet-alpha"
1074
+ });
1075
+ }
1076
+ if (choices.length === 0) {
1077
+ throw new Error("No environments available in this build");
1078
+ }
1079
+ const env = await select({
1080
+ message: "Select environment:",
1081
+ choices,
1082
+ default: defaultEnv
1083
+ });
1084
+ return env;
1085
+ }
986
1086
  var MAX_IMAGE_SIZE = 4 * 1024 * 1024;
987
1087
 
988
1088
  // src/flags.ts
@@ -990,7 +1090,8 @@ var commonFlags = {
990
1090
  environment: Flags.string({
991
1091
  required: false,
992
1092
  description: "Deployment environment to use",
993
- env: "ECLOUD_ENV"
1093
+ env: "ECLOUD_ENV",
1094
+ default: async () => getDefaultEnvironment() || (getBuildType3() === "dev" ? "sepolia-dev" : "sepolia")
994
1095
  }),
995
1096
  "private-key": Flags.string({
996
1097
  required: false,
@@ -1008,6 +1109,41 @@ var commonFlags = {
1008
1109
  default: false
1009
1110
  })
1010
1111
  };
1112
+ async function validateCommonFlags(flags) {
1113
+ flags["environment"] = await getEnvironmentInteractive(flags["environment"]);
1114
+ flags["private-key"] = await getPrivateKeyInteractive(flags["private-key"]);
1115
+ return flags;
1116
+ }
1117
+
1118
+ // src/client.ts
1119
+ import {
1120
+ createComputeModule,
1121
+ createBillingModule,
1122
+ getEnvironmentConfig as getEnvironmentConfig2,
1123
+ requirePrivateKey,
1124
+ getPrivateKeyWithSource
1125
+ } from "@layr-labs/ecloud-sdk";
1126
+ async function createComputeClient(flags) {
1127
+ flags = await validateCommonFlags(flags);
1128
+ const environment = flags.environment;
1129
+ const environmentConfig = getEnvironmentConfig2(environment);
1130
+ const rpcUrl = flags["rpc-url"] || environmentConfig.defaultRPCURL;
1131
+ const { key: privateKey, source } = await requirePrivateKey({
1132
+ privateKey: flags["private-key"]
1133
+ });
1134
+ if (flags.verbose) {
1135
+ console.log(`Using private key from: ${source}`);
1136
+ }
1137
+ return createComputeModule({
1138
+ verbose: flags.verbose,
1139
+ privateKey,
1140
+ rpcUrl,
1141
+ environment,
1142
+ clientId: getClientId(),
1143
+ skipTelemetry: true
1144
+ // CLI already has telemetry, skip SDK telemetry
1145
+ });
1146
+ }
1011
1147
 
1012
1148
  // src/commands/compute/app/upgrade.ts
1013
1149
  import chalk from "chalk";
@@ -1058,16 +1194,11 @@ var AppUpgrade = class _AppUpgrade extends Command {
1058
1194
  async run() {
1059
1195
  return withTelemetry(this, async () => {
1060
1196
  const { args, flags } = await this.parse(_AppUpgrade);
1061
- const logger = {
1062
- info: (msg) => this.log(msg),
1063
- warn: (msg) => this.warn(msg),
1064
- error: (msg) => this.error(msg),
1065
- debug: (msg) => flags.verbose && this.log(msg)
1066
- };
1067
- const environment = flags.environment || "sepolia";
1068
- const environmentConfig = getEnvironmentConfig2(environment);
1197
+ const compute = await createComputeClient(flags);
1198
+ const environment = flags.environment;
1199
+ const environmentConfig = getEnvironmentConfig3(environment);
1069
1200
  const rpcUrl = flags["rpc-url"] || environmentConfig.defaultRPCURL;
1070
- const privateKey = await getPrivateKeyInteractive(flags["private-key"]);
1201
+ const privateKey = flags["private-key"];
1071
1202
  const appID = await getOrPromptAppID({
1072
1203
  appID: args["app-id"],
1073
1204
  environment,
@@ -1110,22 +1241,14 @@ var AppUpgrade = class _AppUpgrade extends Command {
1110
1241
  flags["resource-usage-monitoring"]
1111
1242
  );
1112
1243
  const logVisibility = logSettings.publicLogs ? "public" : logSettings.logRedirect ? "private" : "off";
1113
- const { prepared, gasEstimate } = await prepareUpgrade(
1114
- {
1115
- appId: appID,
1116
- privateKey,
1117
- rpcUrl,
1118
- environment,
1119
- dockerfilePath,
1120
- imageRef,
1121
- envFilePath,
1122
- instanceType,
1123
- logVisibility,
1124
- resourceUsageMonitoring,
1125
- skipTelemetry: true
1126
- },
1127
- logger
1128
- );
1244
+ const { prepared, gasEstimate } = await compute.app.prepareUpgrade(appID, {
1245
+ dockerfile: dockerfilePath,
1246
+ imageRef,
1247
+ envFile: envFilePath,
1248
+ instanceType,
1249
+ logVisibility,
1250
+ resourceUsageMonitoring
1251
+ });
1129
1252
  this.log(`
1130
1253
  Estimated transaction cost: ${chalk.cyan(gasEstimate.maxCostEth)} ETH`);
1131
1254
  if (isMainnet(environmentConfig)) {
@@ -1136,17 +1259,17 @@ ${chalk.gray(`Upgrade cancelled`)}`);
1136
1259
  return;
1137
1260
  }
1138
1261
  }
1139
- const res = await executeUpgrade(
1140
- prepared,
1141
- {
1142
- maxFeePerGas: gasEstimate.maxFeePerGas,
1143
- maxPriorityFeePerGas: gasEstimate.maxPriorityFeePerGas
1144
- },
1145
- logger,
1146
- true
1147
- // skipTelemetry
1148
- );
1149
- await watchUpgrade(res.appId, privateKey, rpcUrl, environment, logger, getClientId(), true);
1262
+ const res = await compute.app.executeUpgrade(prepared, {
1263
+ maxFeePerGas: gasEstimate.maxFeePerGas,
1264
+ maxPriorityFeePerGas: gasEstimate.maxPriorityFeePerGas
1265
+ });
1266
+ await compute.app.watchUpgrade(res.appId);
1267
+ try {
1268
+ const cwd = process.env.INIT_CWD || process.cwd();
1269
+ setLinkedAppForDirectory(environment, cwd, res.appId);
1270
+ } catch (err) {
1271
+ logger.debug(`Failed to link directory to app: ${err.message}`);
1272
+ }
1150
1273
  this.log(
1151
1274
  `
1152
1275
  \u2705 ${chalk.green(`App upgraded successfully ${chalk.bold(`(id: ${res.appId}, image: ${res.imageRef})`)}`)}`