@layr-labs/ecloud-cli 0.1.0-rc.1 → 0.1.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 (53) hide show
  1. package/README.md +6 -4
  2. package/VERSION +2 -2
  3. package/dist/commands/auth/generate.js +184 -46
  4. package/dist/commands/auth/generate.js.map +1 -1
  5. package/dist/commands/auth/login.js +234 -93
  6. package/dist/commands/auth/login.js.map +1 -1
  7. package/dist/commands/auth/logout.js +170 -30
  8. package/dist/commands/auth/logout.js.map +1 -1
  9. package/dist/commands/auth/migrate.js +216 -76
  10. package/dist/commands/auth/migrate.js.map +1 -1
  11. package/dist/commands/auth/whoami.js +145 -17
  12. package/dist/commands/auth/whoami.js.map +1 -1
  13. package/dist/commands/billing/cancel.js +164 -30
  14. package/dist/commands/billing/cancel.js.map +1 -1
  15. package/dist/commands/billing/status.js +213 -80
  16. package/dist/commands/billing/status.js.map +1 -1
  17. package/dist/commands/billing/subscribe.js +179 -45
  18. package/dist/commands/billing/subscribe.js.map +1 -1
  19. package/dist/commands/compute/app/create.js +148 -20
  20. package/dist/commands/compute/app/create.js.map +1 -1
  21. package/dist/commands/compute/app/deploy.js +244 -146
  22. package/dist/commands/compute/app/deploy.js.map +1 -1
  23. package/dist/commands/compute/app/info.js +2 -1
  24. package/dist/commands/compute/app/info.js.map +1 -1
  25. package/dist/commands/compute/app/list.js +194 -111
  26. package/dist/commands/compute/app/list.js.map +1 -1
  27. package/dist/commands/compute/app/logs.js +105 -20
  28. package/dist/commands/compute/app/logs.js.map +1 -1
  29. package/dist/commands/compute/app/profile/set.js +153 -64
  30. package/dist/commands/compute/app/profile/set.js.map +1 -1
  31. package/dist/commands/compute/app/start.js +132 -43
  32. package/dist/commands/compute/app/start.js.map +1 -1
  33. package/dist/commands/compute/app/stop.js +132 -43
  34. package/dist/commands/compute/app/stop.js.map +1 -1
  35. package/dist/commands/compute/app/terminate.js +131 -44
  36. package/dist/commands/compute/app/terminate.js.map +1 -1
  37. package/dist/commands/compute/app/upgrade.js +210 -109
  38. package/dist/commands/compute/app/upgrade.js.map +1 -1
  39. package/dist/commands/compute/environment/list.js +104 -12
  40. package/dist/commands/compute/environment/list.js.map +1 -1
  41. package/dist/commands/compute/environment/set.js +103 -18
  42. package/dist/commands/compute/environment/set.js.map +1 -1
  43. package/dist/commands/compute/environment/show.js +122 -30
  44. package/dist/commands/compute/environment/show.js.map +1 -1
  45. package/dist/commands/compute/undelegate.js +113 -13
  46. package/dist/commands/compute/undelegate.js.map +1 -1
  47. package/dist/commands/telemetry.js +213 -0
  48. package/dist/commands/telemetry.js.map +1 -0
  49. package/dist/commands/upgrade.js +159 -19
  50. package/dist/commands/upgrade.js.map +1 -1
  51. package/dist/commands/version.js +163 -23
  52. package/dist/commands/version.js.map +1 -1
  53. package/package.json +2 -2
@@ -44,6 +44,7 @@ import * as path from "path";
44
44
  import * as os from "os";
45
45
  import { load as loadYaml, dump as dumpYaml } from "js-yaml";
46
46
  import { getBuildType } from "@layr-labs/ecloud-sdk";
47
+ import * as crypto from "crypto";
47
48
  var GLOBAL_CONFIG_FILE = "config.yaml";
48
49
  var PROFILE_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
49
50
  function getGlobalConfigDir() {
@@ -86,6 +87,14 @@ function saveGlobalConfig(config) {
86
87
  const content = dumpYaml(config, { lineWidth: -1 });
87
88
  fs.writeFileSync(configPath, content, { mode: 420 });
88
89
  }
90
+ function getDefaultEnvironment() {
91
+ const config = loadGlobalConfig();
92
+ return config.default_environment;
93
+ }
94
+ function getGlobalTelemetryPreference() {
95
+ const config = loadGlobalConfig();
96
+ return config.telemetry_enabled;
97
+ }
89
98
  function getProfileCache(environment) {
90
99
  const config = loadGlobalConfig();
91
100
  const cacheEntry = config.profile_cache?.[environment];
@@ -137,6 +146,24 @@ function updateProfileCacheEntry(environment, appId, profileName) {
137
146
  config.profile_cache[environment].updated_at = Date.now();
138
147
  saveGlobalConfig(config);
139
148
  }
149
+ function getOrCreateUserUUID() {
150
+ const config = loadGlobalConfig();
151
+ if (config.user_uuid) {
152
+ return config.user_uuid;
153
+ }
154
+ const uuid = generateUUID();
155
+ config.user_uuid = uuid;
156
+ config.first_run = false;
157
+ saveGlobalConfig(config);
158
+ return uuid;
159
+ }
160
+ function generateUUID() {
161
+ const bytes = crypto.randomBytes(16);
162
+ bytes[6] = bytes[6] & 15 | 64;
163
+ bytes[8] = bytes[8] & 63 | 128;
164
+ const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
165
+ return hex.slice(0, 4).join("") + hex.slice(4, 6).join("") + "-" + hex.slice(6, 8).join("") + "-" + hex.slice(8, 10).join("") + "-" + hex.slice(10, 12).join("") + "-" + hex.slice(12, 16).join("");
166
+ }
140
167
 
141
168
  // src/utils/appNames.ts
142
169
  import * as fs2 from "fs";
@@ -205,7 +232,7 @@ function listApps(environment) {
205
232
 
206
233
  // src/utils/version.ts
207
234
  function getCliVersion() {
208
- return true ? "0.1.0-rc.1" : "0.0.0";
235
+ return true ? "0.1.0" : "0.0.0";
209
236
  }
210
237
  function getClientId() {
211
238
  return `ecloud-cli/v${getCliVersion()}`;
@@ -979,6 +1006,66 @@ var commonFlags = {
979
1006
 
980
1007
  // src/commands/compute/app/profile/set.ts
981
1008
  import chalk from "chalk";
1009
+
1010
+ // src/telemetry.ts
1011
+ import {
1012
+ createTelemetryClient,
1013
+ createAppEnvironment,
1014
+ createMetricsContext,
1015
+ addMetric,
1016
+ addMetricWithDimensions,
1017
+ emitMetrics,
1018
+ getBuildType as getBuildType2
1019
+ } from "@layr-labs/ecloud-sdk";
1020
+ function createCLITelemetryClient() {
1021
+ const userUUID = getOrCreateUserUUID();
1022
+ const environment = createAppEnvironment(userUUID);
1023
+ const telemetryEnabled = getGlobalTelemetryPreference();
1024
+ return createTelemetryClient(environment, "ecloud-cli", {
1025
+ telemetryEnabled: telemetryEnabled === true
1026
+ // Only enabled if explicitly set to true
1027
+ });
1028
+ }
1029
+ async function withTelemetry(command, action) {
1030
+ const client = createCLITelemetryClient();
1031
+ const metrics = createMetricsContext();
1032
+ metrics.properties["source"] = "ecloud-cli";
1033
+ metrics.properties["command"] = command.id || command.constructor.name;
1034
+ const environment = getDefaultEnvironment() || "sepolia";
1035
+ metrics.properties["environment"] = environment;
1036
+ const buildType = getBuildType2() || "prod";
1037
+ metrics.properties["build_type"] = buildType;
1038
+ const cliVersion = command.config.version;
1039
+ if (cliVersion) {
1040
+ metrics.properties["cli_version"] = cliVersion;
1041
+ }
1042
+ addMetric(metrics, "Count", 1);
1043
+ let actionError;
1044
+ let result;
1045
+ try {
1046
+ result = await action();
1047
+ return result;
1048
+ } catch (err) {
1049
+ actionError = err instanceof Error ? err : new Error(String(err));
1050
+ throw err;
1051
+ } finally {
1052
+ const resultValue = actionError ? "Failure" : "Success";
1053
+ const dimensions = {};
1054
+ if (actionError) {
1055
+ dimensions["error"] = actionError.message;
1056
+ }
1057
+ addMetricWithDimensions(metrics, resultValue, 1, dimensions);
1058
+ const duration = Date.now() - metrics.startTime.getTime();
1059
+ addMetric(metrics, "DurationMilliseconds", duration);
1060
+ try {
1061
+ await emitMetrics(client, metrics);
1062
+ await client.close();
1063
+ } catch {
1064
+ }
1065
+ }
1066
+ }
1067
+
1068
+ // src/commands/compute/app/profile/set.ts
982
1069
  var ProfileSet = class _ProfileSet extends Command {
983
1070
  static description = "Set public profile information for an app";
984
1071
  static args = {
@@ -1011,73 +1098,75 @@ var ProfileSet = class _ProfileSet extends Command {
1011
1098
  })
1012
1099
  };
1013
1100
  async run() {
1014
- const { args, flags } = await this.parse(_ProfileSet);
1015
- const environment = flags.environment || "sepolia";
1016
- const environmentConfig = getEnvironmentConfig2(environment);
1017
- const rpcUrl = flags["rpc-url"] || environmentConfig.defaultRPCURL;
1018
- const privateKey = await getPrivateKeyInteractive(flags["private-key"]);
1019
- const resolver = createAppResolver(environment, environmentConfig, privateKey, rpcUrl);
1020
- const appId = await getOrPromptAppID({
1021
- appID: args["app-id"],
1022
- environment,
1023
- privateKey,
1024
- rpcUrl,
1025
- action: "set profile for"
1026
- });
1027
- this.log(`
1101
+ return withTelemetry(this, async () => {
1102
+ const { args, flags } = await this.parse(_ProfileSet);
1103
+ const environment = flags.environment || "sepolia";
1104
+ const environmentConfig = getEnvironmentConfig2(environment);
1105
+ const rpcUrl = flags["rpc-url"] || environmentConfig.defaultRPCURL;
1106
+ const privateKey = await getPrivateKeyInteractive(flags["private-key"]);
1107
+ const resolver = createAppResolver(environment, environmentConfig, privateKey, rpcUrl);
1108
+ const appId = await getOrPromptAppID({
1109
+ appID: args["app-id"],
1110
+ environment,
1111
+ privateKey,
1112
+ rpcUrl,
1113
+ action: "set profile for"
1114
+ });
1115
+ this.log(`
1028
1116
  Setting profile for app: ${chalk.cyan(appId)}`);
1029
- let profile;
1030
- if (flags.name) {
1031
- profile = {
1032
- name: flags.name,
1033
- website: flags.website,
1034
- description: flags.description,
1035
- xURL: flags["x-url"],
1036
- imagePath: flags.image
1037
- };
1038
- const validationError = validateAppProfile(profile);
1039
- if (validationError) {
1040
- this.error(validationError);
1041
- }
1042
- this.log("\n\u{1F4CB} Profile Summary:");
1043
- this.log(` Name: ${profile.name}`);
1044
- if (profile.website) this.log(` Website: ${profile.website}`);
1045
- if (profile.description) this.log(` Description: ${profile.description}`);
1046
- if (profile.xURL) this.log(` X URL: ${profile.xURL}`);
1047
- if (profile.imagePath) this.log(` Image: ${profile.imagePath}`);
1048
- } else {
1049
- this.log("\nEnter profile information:");
1050
- profile = await getAppProfileInteractive("", true);
1051
- if (!profile) {
1052
- this.log(`
1117
+ let profile;
1118
+ if (flags.name) {
1119
+ profile = {
1120
+ name: flags.name,
1121
+ website: flags.website,
1122
+ description: flags.description,
1123
+ xURL: flags["x-url"],
1124
+ imagePath: flags.image
1125
+ };
1126
+ const validationError = validateAppProfile(profile);
1127
+ if (validationError) {
1128
+ this.error(validationError);
1129
+ }
1130
+ this.log("\n\u{1F4CB} Profile Summary:");
1131
+ this.log(` Name: ${profile.name}`);
1132
+ if (profile.website) this.log(` Website: ${profile.website}`);
1133
+ if (profile.description) this.log(` Description: ${profile.description}`);
1134
+ if (profile.xURL) this.log(` X URL: ${profile.xURL}`);
1135
+ if (profile.imagePath) this.log(` Image: ${profile.imagePath}`);
1136
+ } else {
1137
+ this.log("\nEnter profile information:");
1138
+ profile = await getAppProfileInteractive("", true);
1139
+ if (!profile) {
1140
+ this.log(`
1053
1141
  ${chalk.gray("Profile setup cancelled")}`);
1054
- return;
1142
+ return;
1143
+ }
1055
1144
  }
1056
- }
1057
- this.log("\nUploading app profile...");
1058
- const userApiClient = new UserApiClient3(environmentConfig, privateKey, rpcUrl, getClientId());
1059
- try {
1060
- const response = await userApiClient.uploadAppProfile(
1061
- appId,
1062
- profile.name,
1063
- profile.website,
1064
- profile.description,
1065
- profile.xURL,
1066
- profile.imagePath
1067
- );
1068
- resolver.updateCacheEntry(appId, response.name);
1069
- invalidateProfileCache(environment);
1070
- this.log(`
1145
+ this.log("\nUploading app profile...");
1146
+ const userApiClient = new UserApiClient3(environmentConfig, privateKey, rpcUrl);
1147
+ try {
1148
+ const response = await userApiClient.uploadAppProfile(
1149
+ appId,
1150
+ profile.name,
1151
+ profile.website,
1152
+ profile.description,
1153
+ profile.xURL,
1154
+ profile.imagePath
1155
+ );
1156
+ resolver.updateCacheEntry(appId, response.name);
1157
+ invalidateProfileCache(environment);
1158
+ this.log(`
1071
1159
  \u2705 ${chalk.green(`Profile updated successfully for app '${response.name}'`)}`);
1072
- this.log("\nUploaded Profile:");
1073
- this.log(` Name: ${response.name}`);
1074
- if (response.website) this.log(` Website: ${response.website}`);
1075
- if (response.description) this.log(` Description: ${response.description}`);
1076
- if (response.xURL) this.log(` X URL: ${response.xURL}`);
1077
- if (response.imageURL) this.log(` Image URL: ${response.imageURL}`);
1078
- } catch (error) {
1079
- this.error(`Failed to upload profile: ${error.message}`);
1080
- }
1160
+ this.log("\nUploaded Profile:");
1161
+ this.log(` Name: ${response.name}`);
1162
+ if (response.website) this.log(` Website: ${response.website}`);
1163
+ if (response.description) this.log(` Description: ${response.description}`);
1164
+ if (response.xURL) this.log(` X URL: ${response.xURL}`);
1165
+ if (response.imageURL) this.log(` Image URL: ${response.imageURL}`);
1166
+ } catch (error) {
1167
+ this.error(`Failed to upload profile: ${error.message}`);
1168
+ }
1169
+ });
1081
1170
  }
1082
1171
  };
1083
1172
  export {